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

add default subscription or sensu server will crash #23

Merged
merged 4 commits into from
Mar 28, 2017

Conversation

gbolo
Copy link
Contributor

@gbolo gbolo commented Feb 22, 2017

This PR fixes #22

Basically this PR forces the client to send at least one subscription in the form: client:name. Testing and works with both configuration file and environment variables. this default subscription will be appended to subscription slice even if none are specified. This matches the default behaviour of the official ruby sensu client.

Can be tested like:

git clone https://github.com/gbolo/dockerfiles.git
cd dockerfiles/sensu/
docker-compose up -d
docker logs sensu_sensu-client-go-fix_1 -f

Dashboard can be seen: http://127.0.0.1:3000/#/clients

Copy link
Member

@AlexisMontagne AlexisMontagne left a comment

Choose a reason for hiding this comment

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

Good work! I gave you some syntax feedbacks

sensu/config.go Outdated
} else {
// if we get a Name, let's also add the default subscription - client:name
// without at least one subscription sensu server will crash
cfg.Client().Subscriptions = append(cfg.Client().Subscriptions, "client:"+cfg.Client().Name)
Copy link
Member

Choose a reason for hiding this comment

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

  • prefer fmt.Sprintf over string concat: fmt.Sprintf("client:%s", cfg.Client().Name)
  • try to keep your line smaller than 80chars

Copy link
Member

Choose a reason for hiding this comment

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

PS: because you already added this subscription in the Client() method, you don't need to add it again here

sensu/config.go Outdated
return &client.Client{
Name: os.Getenv("SENSU_CLIENT_NAME"),
Address: fetchEnv("SENSU_CLIENT_ADDRESS", "SENSU_ADDRESS"),
Subscriptions: split(os.Getenv("SENSU_CLIENT_SUBSCRIPTIONS"), ","),
Subscriptions: cs,
Copy link
Member

Choose a reason for hiding this comment

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

you don't need to assign all these variables assignations you can easily build all the subscriptions in here:

Subscriptions: append(
    split(os.Getenv("SENSU_CLIENT_SUBSCRIPTIONS"), ","),
    fmt.Sprintf("client:%s", cfg.Client().Name),
)

@gbolo
Copy link
Contributor Author

gbolo commented Feb 22, 2017

hi @AlexisMontagne

Thank you for your review. My apologies for the bad code, as I am completely new to golang and not a developer. I will clean it up when I get home later, I think I understand the flow better now. This a great learning opportunity for me. Thanks for a great go sensu client btw.

@gbolo gbolo force-pushed the master branch 2 times, most recently from 83633e0 to e0aed7d Compare February 23, 2017 03:33
@gbolo
Copy link
Contributor Author

gbolo commented Feb 23, 2017

hi @AlexisMontagne

I have amended my last commit. I now do the following:

Upon determining that our client section of the configuration has a name and after client() method is called which finally determines the final state of the Subscriptions slice from user input (config file or env vars), I then append the Subscriptions slice and also remove any duplicate slices that may occur due to user error or introduced by the append. This duplicates the behaviour of the ruby client which also seems to remove duplicate subscriptions

sensu/config.go Outdated
// If we reached this point, we have a client name.
// Let's also add the default subscription - client:name
// Without at least one subscription sensu server will crash.
cfg.config.Client.Subscriptions = append(cfg.config.Client.Subscriptions,
Copy link
Member

Choose a reason for hiding this comment

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

To write multi line method call, please write it as:

append(
  arg1,
  arg2,
)

Copy link
Member

Choose a reason for hiding this comment

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

if you need at least one subscriptions you don't need to add the value all the time just ensure len(cfg.config.Client.Subscriptions) == 0

Copy link
Contributor Author

@gbolo gbolo Feb 23, 2017

Choose a reason for hiding this comment

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

hi @AlexisMontagne,
the requirement for at least one subscription comes from the sensu server crashing, but if we want to duplicate the behaviour of the ruby client we must always add this subscription client:name. I tested a config with other subscriptions and it appears like the ruby client still adds it.

The choice is yours if you would like to copy the behaviour of the ruby client. Please let me know before I amend my commit later. In my opinion we should behave similarly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed

@AlexisMontagne
Copy link
Member

Hey @gbolo,

Could you also add some test to ensure the behavour of your feature? ( https://github.com/upfluence/sensu-client-go/blob/master/sensu/config_test.go ) It would be great!

@gbolo
Copy link
Contributor Author

gbolo commented Feb 23, 2017

hi @AlexisMontagne,

I will amend the commit later to fix the styling error you described for append(). I will also add a second commit to address the lack of test. Thanks for you patience

sensu/config.go Outdated
@@ -131,3 +141,17 @@ func (c *Config) Checks() []*check.Check {

return []*check.Check{}
}

// Removes duplicates from string slices
func RemoveDuplicates(xs *[]string) {
Copy link
Member

Choose a reason for hiding this comment

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

Could you rewrite this function and make it something immutable. removeDuplicates([]string) []string

And it does not need to be public, please use a lowercase for the first letter of the function

Copy link
Contributor Author

@gbolo gbolo Feb 23, 2017

Choose a reason for hiding this comment

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

done

sensu/config.go Outdated

// Removes duplicates from string slices
func removeDuplicates(xs []string) []string {
found := make(map[string]bool)
Copy link
Member

Choose a reason for hiding this comment

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

a simpler implementation would be:

var (
  temp  = map[string]bool{}
  result = []string
)

for _, x := range xs {
   temp[x] = true
}

for k, _ := range temp {
  result = append(result, k)
}

return result

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added your preferred function logic

sensu/config.go Outdated
// If we reached this point, we have a client name.
// Let's also add the default subscription - client:name
// Without at least one subscription sensu server will crash.
cfg.config.Client.Subscriptions = append(
Copy link
Member

Choose a reason for hiding this comment

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

do you really need to re assign cfg.config.Client.Subscriptions twice?

you could do both at the same time:

cfg.config.Client.Subscriptions = removeDuplicates(
    append(
        cfg.config.Client.Subscriptions, 
        fmt.Sprintf("client:%s", cfg.config.Client.Name),
    ),
)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed

@AlexisMontagne
Copy link
Member

@gbolo The code looks good to me, could you add some tests to assert it?

@gbolo
Copy link
Contributor Author

gbolo commented Feb 27, 2017

@AlexisMontagne thanks for comment. I was thinking about how to test. Since the additional code only exists in NewConfigFromFile function, the usual test cases which call Client() method won't apply. Can you suggest what the best way to test this is? I am totally new to this and would appreciate some guidance. Thanks

@AlexisMontagne
Copy link
Member

@gbolo you should write some configuration fixtures (json files) in a directory ( something like testdata/ ) and the idea is to assert the client built out of it.

write some test case with the following format:

for _, tCase := range []struct{
   in string
   out client.Client
}{
  {"testdata/fixtures1.json", client.Client{...}},
} {
  cfg, err := NewConfigFromFile(nil, tCase.in)

  if err ...
 
  if !reflet.DeepEqual(cfg.Client(), tCase.out) ...
}

@gbolo
Copy link
Contributor Author

gbolo commented Feb 28, 2017

Hi @AlexisMontagne, I have added a working test case.

@AlexisMontagne
Copy link
Member

@gbolo could you test multiple cases:

  • empty subscriptions case
  • uniq subscriptions
  • duplicaticates

@gbolo
Copy link
Contributor Author

gbolo commented Feb 28, 2017

@AlexisMontagne sure, I will add these additional cases tonight.

@gbolo
Copy link
Contributor Author

gbolo commented Mar 1, 2017

@AlexisMontagne the additional test cases have been added.

@AlexisMontagne
Copy link
Member

@gbolo One of the best practice to write test in Go, is to write some structured test cases ( input + output ) and test it consistently. cf. https://github.com/golang/go/wiki/TableDrivenTests

could you update your tests according to it.

PS: in my last comment i gave you an example of what the tests could look like.

@gbolo
Copy link
Contributor Author

gbolo commented Mar 2, 2017

Hi @AlexisMontagne,

Thanks for the link, I read over it and redesigned the test cases. Good learning experience. Hopefully we are done with this PR so I can begin working on adding the much needed TLS support.

@gbolo
Copy link
Contributor Author

gbolo commented Mar 6, 2017

Hi @AlexisMontagne, are any other modifications needed, or can this be merged?

@mihaitodor
Copy link
Contributor

@AlexisMontagne Do you think we can merge this? I am adding some code for upfluence/sensu-go#1 and it would be great to get this merged first.

@AlexisMontagne
Copy link
Member

@mihaitodor I totally forgot about this PR, i'm sorry! I will merge it right away

@AlexisMontagne AlexisMontagne merged commit 3b96af2 into upfluence:master Mar 28, 2017
@mihaitodor
Copy link
Contributor

Thanks a lot :)

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.

this go client seems to crash the sensu server
3 participants