Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

restore default port 8500 for CONSUL_HTTP_ADDR (#394) #395

Conversation

larrytamnjong
Copy link
Contributor

Restore default port 8500 for CONSUL_HTTP_ADDR when no port is specif…ied (#394)

@larrytamnjong
Copy link
Contributor Author

@marcin-krystianc I made a tiny adjustment to default the port to 8500 if it isn’t specified in CONSUL_HTTP_ADDR. Please let me know if this makes sense.

Copy link
Contributor

@marcin-krystianc marcin-krystianc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @larrytamnjong,

implementation seems legit, please add tests for following cases:

CONSUL_HTTP_ADDR=127.0.0.1 => protocol: http, host: 127.0.0.1, port: 8500
CONSUL_HTTP_ADDR=http://127.0.0.1/ => protocol: http, host: 127.0.0.1, port: 8500 
CONSUL_HTTP_ADDR=http://127.0.0.1:8500/ => protocol: http, host: 127.0.0.1, port: 8500
CONSUL_HTTP_ADDR=http://127.0.0.1:80/ => protocol: http, host: 127.0.0.1, port: 80

Please also verify the test results are the same for your implementation and the version before the ef310c2.

@larrytamnjong
Copy link
Contributor Author

Hi @marcin-krystianc
I create a test method and for my implementation

 public void ConsulClient_BaseUri_Parses_ConsulHttpAddr_Correctly()
 {
     Environment.SetEnvironmentVariable("CONSUL_HTTP_ADDR", "127.0.0.1");
     var client1 = new ConsulClient();
     var config1 = client1.Config;


     Environment.SetEnvironmentVariable("CONSUL_HTTP_ADDR", "http://127.0.0.1/");
     var client2 = new ConsulClient();
     var config2 = client2.Config;


     Environment.SetEnvironmentVariable("CONSUL_HTTP_ADDR", "http://127.0.0.1:8500/");
     var client3 = new ConsulClient();
     var config3 = client3.Config;


     Environment.SetEnvironmentVariable("CONSUL_HTTP_ADDR", "http://127.0.0.1:80/");
     var client4 = new ConsulClient();
     var config4 = client4.Config;

     Assert.Equal("127.0.0.1", config1.Address.Host);  //Passes
     Assert.Equal("127.0.0.1", config2.Address.Host);  //Passes
     Assert.Equal("127.0.0.1", config4.Address.Host);  //Passes
     Assert.Equal("127.0.0.1", config3.Address.Host); //Passes
     Assert.Equal(8500, config1.Address.Port);  //Passes
     Assert.Equal(8500, config2.Address.Port); //Passes
     Assert.Equal(8500, config3.Address.Port);  //Passes
     Assert.Equal(80, config4.Address.Port);  //It fails here because the port returns 8500
 }

However, when I run this test on commit f6a8038, I encounter exceptions with certain values of CONSUL_HTTP_ADDR:

 public void ConsulClient_BaseUri_Parses_ConsulHttpAddr_Correctly()
 {
     Environment.SetEnvironmentVariable("CONSUL_HTTP_ADDR", "127.0.0.1");
     var client1 = new ConsulClient();
     var config1 = client1.Config;


     Environment.SetEnvironmentVariable("CONSUL_HTTP_ADDR", "http://127.0.0.1/");  //An exception is thrown here "Failed parsing port from environment variable CONSUL_HTTP_ADDR"
     var client2 = new ConsulClient();
     var config2 = client2.Config;


     Environment.SetEnvironmentVariable("CONSUL_HTTP_ADDR", "http://127.0.0.1:8500/"); //An exception is thrown here "Failed parsing port from environment variable CONSUL_HTTP_ADDR"
     var client3 = new ConsulClient();
     var config3 = client3.Config;


     Environment.SetEnvironmentVariable("CONSUL_HTTP_ADDR", "http://127.0.0.1:80/"); //An exception is thrown here "Failed parsing port from environment variable CONSUL_HTTP_ADDR"
     var client4 = new ConsulClient();
     var config4 = client4.Config;

     Assert.Equal("127.0.0.1", config1.Address.Host);  
     Assert.Equal("127.0.0.1", config2.Address.Host);  
     Assert.Equal("127.0.0.1", config4.Address.Host);  
     Assert.Equal("127.0.0.1", config3.Address.Host); 
     Assert.Equal(8500, config1.Address.Port);  
     Assert.Equal(8500, config2.Address.Port); 
     Assert.Equal(8500, config3.Address.Port);  
     Assert.Equal(80, config4.Address.Port);  
 }

I'm not sure if this is the expected way to test it. Could you provide some guidance on how to proceed?

@orange-puff
Copy link

This seems to not be quite right. Uri.IsDefaultPort will return true if the specified port matches the scheme. So,
new Uri("http://mysite.com").IsDefaultPort and new Uri("http://mysite.com:80").IsDefaultPort will both resolve to true.
It seems dumb, but what if the consumer has their consul agent listening on port 80? This logic would overwrite their port with 8500

For determining if the original string contains a port, I'd suggest either

envAddr.Contains($"{uri.Host}:{uri.Port}");

or
Regex.IsMatch(envAddr, ":[0-9]+");

@orange-puff
Copy link

orange-puff commented Nov 13, 2024

Unit tests before ef310c2 never included scheme, which was not supported properly previously.

It looks like f6a8038 breaks if the client specifies a scheme http or https, or any other for that matter. There is an environment variable driven way of determining scheme

It will split the address into 3 parts for http://127.0.0.1:80
which would be ["http", "//127.0.0.1", "80"]
which means

consulAddress.Port = ushort.Parse(addrParts[1]);
will try to parse "//127.0.0.1" as an int causing this to be thrown
throw new ConsulConfigurationException("Failed parsing port from environment variable CONSUL_HTTP_ADDR", ex);

if (!string.IsNullOrEmpty(envAddr))
            {
                var addrParts = envAddr.Split(':');
                for (int i = 0; i < addrParts.Length; i++)
                {
                    addrParts[i] = addrParts[i].Trim();
                }
                if (!string.IsNullOrEmpty(addrParts[0]))
                {
                    consulAddress.Host = addrParts[0];
                }
                if (addrParts.Length > 1 && !string.IsNullOrEmpty(addrParts[1]))
                {
                    try
                    {
                        consulAddress.Port = ushort.Parse(addrParts[1]);
                    }
                    catch (Exception ex)
                    {
                        throw new ConsulConfigurationException("Failed parsing port from environment variable CONSUL_HTTP_ADDR", ex);
                    }
                }
            }

@marcin-krystianc
Copy link
Contributor

Hi @marcin-krystianc I create a test method and for my implementation

 public void ConsulClient_BaseUri_Parses_ConsulHttpAddr_Correctly()
 {
     Environment.SetEnvironmentVariable("CONSUL_HTTP_ADDR", "127.0.0.1");
     var client1 = new ConsulClient();
     var config1 = client1.Config;


     Environment.SetEnvironmentVariable("CONSUL_HTTP_ADDR", "http://127.0.0.1/");
     var client2 = new ConsulClient();
     var config2 = client2.Config;


     Environment.SetEnvironmentVariable("CONSUL_HTTP_ADDR", "http://127.0.0.1:8500/");
     var client3 = new ConsulClient();
     var config3 = client3.Config;


     Environment.SetEnvironmentVariable("CONSUL_HTTP_ADDR", "http://127.0.0.1:80/");
     var client4 = new ConsulClient();
     var config4 = client4.Config;

     Assert.Equal("127.0.0.1", config1.Address.Host);  //Passes
     Assert.Equal("127.0.0.1", config2.Address.Host);  //Passes
     Assert.Equal("127.0.0.1", config4.Address.Host);  //Passes
     Assert.Equal("127.0.0.1", config3.Address.Host); //Passes
     Assert.Equal(8500, config1.Address.Port);  //Passes
     Assert.Equal(8500, config2.Address.Port); //Passes
     Assert.Equal(8500, config3.Address.Port);  //Passes
     Assert.Equal(80, config4.Address.Port);  //It fails here because the port returns 8500
 }

However, when I run this test on commit f6a8038, I encounter exceptions with certain values of CONSUL_HTTP_ADDR:

 public void ConsulClient_BaseUri_Parses_ConsulHttpAddr_Correctly()
 {
     Environment.SetEnvironmentVariable("CONSUL_HTTP_ADDR", "127.0.0.1");
     var client1 = new ConsulClient();
     var config1 = client1.Config;


     Environment.SetEnvironmentVariable("CONSUL_HTTP_ADDR", "http://127.0.0.1/");  //An exception is thrown here "Failed parsing port from environment variable CONSUL_HTTP_ADDR"
     var client2 = new ConsulClient();
     var config2 = client2.Config;


     Environment.SetEnvironmentVariable("CONSUL_HTTP_ADDR", "http://127.0.0.1:8500/"); //An exception is thrown here "Failed parsing port from environment variable CONSUL_HTTP_ADDR"
     var client3 = new ConsulClient();
     var config3 = client3.Config;


     Environment.SetEnvironmentVariable("CONSUL_HTTP_ADDR", "http://127.0.0.1:80/"); //An exception is thrown here "Failed parsing port from environment variable CONSUL_HTTP_ADDR"
     var client4 = new ConsulClient();
     var config4 = client4.Config;

     Assert.Equal("127.0.0.1", config1.Address.Host);  
     Assert.Equal("127.0.0.1", config2.Address.Host);  
     Assert.Equal("127.0.0.1", config4.Address.Host);  
     Assert.Equal("127.0.0.1", config3.Address.Host); 
     Assert.Equal(8500, config1.Address.Port);  
     Assert.Equal(8500, config2.Address.Port); 
     Assert.Equal(8500, config3.Address.Port);  
     Assert.Equal(80, config4.Address.Port);  
 }

I'm not sure if this is the expected way to test it. Could you provide some guidance on how to proceed?

@larrytamnjong , we have already a parametrised test Client_DefaultConfig_env, just add more cases to that test instead of implementing a new test method.
As per @orange-puff comment, the old version didn't support parsing of all possible combination of scheme, address and port so in such cases we do not have to worry about backwards compatibility. What we care about is that if an CONSUL_HTTP_ADDR value was valid in the old version it should be also valid in the new version and it should produce the same consul URL.

@larrytamnjong
Copy link
Contributor Author

Hi @marcin-krystianc,

I've added tests for the scenarios you mentioned and adjusted the check for the default port. The tests pass in both my implementation and commit f6a8038. The main difference is that in previous versions, we can't specify an HTTP scheme when adding the address, as noted by @orange-puff.

I believe it’s ready now. Let me know your thoughts!

@larrytamnjong
Copy link
Contributor Author

Hi @marcin-krystianc I create a test method and for my implementation

 public void ConsulClient_BaseUri_Parses_ConsulHttpAddr_Correctly()
 {
     Environment.SetEnvironmentVariable("CONSUL_HTTP_ADDR", "127.0.0.1");
     var client1 = new ConsulClient();
     var config1 = client1.Config;


     Environment.SetEnvironmentVariable("CONSUL_HTTP_ADDR", "http://127.0.0.1/");
     var client2 = new ConsulClient();
     var config2 = client2.Config;


     Environment.SetEnvironmentVariable("CONSUL_HTTP_ADDR", "http://127.0.0.1:8500/");
     var client3 = new ConsulClient();
     var config3 = client3.Config;


     Environment.SetEnvironmentVariable("CONSUL_HTTP_ADDR", "http://127.0.0.1:80/");
     var client4 = new ConsulClient();
     var config4 = client4.Config;

     Assert.Equal("127.0.0.1", config1.Address.Host);  //Passes
     Assert.Equal("127.0.0.1", config2.Address.Host);  //Passes
     Assert.Equal("127.0.0.1", config4.Address.Host);  //Passes
     Assert.Equal("127.0.0.1", config3.Address.Host); //Passes
     Assert.Equal(8500, config1.Address.Port);  //Passes
     Assert.Equal(8500, config2.Address.Port); //Passes
     Assert.Equal(8500, config3.Address.Port);  //Passes
     Assert.Equal(80, config4.Address.Port);  //It fails here because the port returns 8500
 }

However, when I run this test on commit f6a8038, I encounter exceptions with certain values of CONSUL_HTTP_ADDR:

 public void ConsulClient_BaseUri_Parses_ConsulHttpAddr_Correctly()
 {
     Environment.SetEnvironmentVariable("CONSUL_HTTP_ADDR", "127.0.0.1");
     var client1 = new ConsulClient();
     var config1 = client1.Config;


     Environment.SetEnvironmentVariable("CONSUL_HTTP_ADDR", "http://127.0.0.1/");  //An exception is thrown here "Failed parsing port from environment variable CONSUL_HTTP_ADDR"
     var client2 = new ConsulClient();
     var config2 = client2.Config;


     Environment.SetEnvironmentVariable("CONSUL_HTTP_ADDR", "http://127.0.0.1:8500/"); //An exception is thrown here "Failed parsing port from environment variable CONSUL_HTTP_ADDR"
     var client3 = new ConsulClient();
     var config3 = client3.Config;


     Environment.SetEnvironmentVariable("CONSUL_HTTP_ADDR", "http://127.0.0.1:80/"); //An exception is thrown here "Failed parsing port from environment variable CONSUL_HTTP_ADDR"
     var client4 = new ConsulClient();
     var config4 = client4.Config;

     Assert.Equal("127.0.0.1", config1.Address.Host);  
     Assert.Equal("127.0.0.1", config2.Address.Host);  
     Assert.Equal("127.0.0.1", config4.Address.Host);  
     Assert.Equal("127.0.0.1", config3.Address.Host); 
     Assert.Equal(8500, config1.Address.Port);  
     Assert.Equal(8500, config2.Address.Port); 
     Assert.Equal(8500, config3.Address.Port);  
     Assert.Equal(80, config4.Address.Port);  
 }

I'm not sure if this is the expected way to test it. Could you provide some guidance on how to proceed?

@larrytamnjong , we have already a parametrised test Client_DefaultConfig_env, just add more cases to that test instead of implementing a new test method. As per @orange-puff comment, the old version didn't support parsing of all possible combination of scheme, address and port so in such cases we do not have to worry about backwards compatibility. What we care about is that if an CONSUL_HTTP_ADDR value was valid in the old version it should be also valid in the new version and it should produce the same consul URL.

@marcin-krystianc thanks.. please have a look and let me know if it's okay.

Consul/Client.cs Outdated
Comment on lines 181 to 184
else
{
consulAddress.Port = 8500;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assigning the default 8500 here is redundant as the consulAddress variable already has the default port pre-assigned. You can remove the else block entirely.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@marcin-krystianc thanks. Done ✅

@@ -174,8 +174,14 @@ private void ConfigureFromEnvironment(UriBuilder consulAddress)
{
consulAddress.Host = uri.Host;
}

consulAddress.Port = uri.Port;
if (envAddr.Contains($"{uri.Host}:{uri.Port}"))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 I'm not a fan of this, but it does the job and I don't see how we can do it differently.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:)

@marcin-krystianc marcin-krystianc merged commit 39a598d into G-Research:master Nov 15, 2024
242 of 243 checks passed
@larrytamnjong larrytamnjong deleted the bugfix/consul-http-addr-default-port-8500 branch November 15, 2024 12:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants