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

🐛 clusterctl to show config provider without setting env vars #2905

Merged
merged 1 commit into from
Apr 17, 2020

Conversation

nader-ziada
Copy link
Contributor

@nader-ziada nader-ziada commented Apr 14, 2020

What this PR does / why we need it:

  • the clusterctl config provider now can show the configuration without any env vars being set
  • change the code path so we don't have to replace variables as part of this informational command

Which issue(s) this PR fixes
Fixes #2876

Release Notes:

  • ⚠️ ComponentsClient.Get method definition changed from func(string, string, string) (Components, error) to func(ComponentsOptions) (Components, error)
  • ⚠️ NewComponents method definition changed from func(sigs.k8s.io/cluster-api/cmd/clusterctl/client/config.Provider, string, []byte, sigs.k8s.io/cluster-api/cmd/clusterctl/client/config.Client, string, string) (*components, error) to func(sigs.k8s.io/cluster-api/cmd/clusterctl/client/config.Provider, sigs.k8s.io/cluster-api/cmd/clusterctl/client/config.Client, []byte, ComponentsOptions) (*components, error)

@k8s-ci-robot k8s-ci-robot added the cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. label Apr 14, 2020
@k8s-ci-robot k8s-ci-robot added the size/L Denotes a PR that changes 100-499 lines, ignoring generated files. label Apr 14, 2020
@nader-ziada
Copy link
Contributor Author

@wfernandes @JoelSpeed when you get a chance to review this, let me know what you think about which tests are missing. thanks

cmd/clusterctl/client/config_test.go Outdated Show resolved Hide resolved
cmd/clusterctl/client/config_test.go Outdated Show resolved Hide resolved
cmd/clusterctl/client/repository/components_client.go Outdated Show resolved Hide resolved
cmd/clusterctl/client/repository/components_client.go Outdated Show resolved Hide resolved
cmd/clusterctl/client/repository/components_client.go Outdated Show resolved Hide resolved
cmd/clusterctl/client/config_test.go Outdated Show resolved Hide resolved
cmd/clusterctl/client/common.go Outdated Show resolved Hide resolved
cmd/clusterctl/client/common.go Outdated Show resolved Hide resolved
cmd/clusterctl/client/common.go Outdated Show resolved Hide resolved
cmd/clusterctl/client/common.go Outdated Show resolved Hide resolved
Copy link
Member

@vincepri vincepri left a comment

Choose a reason for hiding this comment

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

/approve
/assign @fabriziopandini
/milestone v0.3.4

@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: nader-ziada, vincepri

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Apr 14, 2020
// 3. Ensure all the ClusterRoleBinding which are referencing namespaced objects have the name prefixed with the namespace name
// 4. Set the watching namespace for the provider controller
// 5. Adds labels to all the components in order to allow easy identification of the provider objects
func NewComponents(provider config.Provider, version string, rawyaml []byte, configClient config.Client, targetNamespace, watchingNamespace string) (*components, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggestion: I'm wondering if we could refactor and collapse the two methods NewComponents and NewComponentsWithValues into one method takes a struct like ComponentsInput that contains all the required arguments and one more called replaceVariables bool. If replaceVariables is set, then we call replaceVariables(...).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I tried at first adding a bool like you are suggesting, but all kinds of tests broke because these functions are called from a bunch of places at different levels, so some places call replace variables directly and other places call NewComponents. It would have been a real big refactor

Copy link
Contributor

@wfernandes wfernandes Apr 14, 2020

Choose a reason for hiding this comment

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

Hmm...yes it would be a sizeable change across the layers of clusterctl from getComponentsByName -> ComponentsClient.Get -> NewComponents.
But I'm leaning more towards that because currently the clusterctl API is subject to change regardless and I'd prefer not having extra methods in the interfaces that we may have to support in the future.
I'll let the others weigh in.
/cc @fabriziopandini

Copy link
Contributor Author

Choose a reason for hiding this comment

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

these are different methods that are used for different use cases, adding the bool won't change that, it would just make header to read

Copy link
Member

Choose a reason for hiding this comment

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

As per comment #2876 (comment), I don't see such a clear distinction between the two use cases because variable substitution could provide value to users also in clusterctl config cluster with the -o yaml option.

Said that I like the idea of avoiding duplicating methods, even if I fully understand the pain of fixing the chain of calls (I experimented also some refactoring to get rid of this, but this is invasive).

@@ -234,7 +234,7 @@ func Test_componentsClient_Get(t *testing.T) {
gs := NewWithT(t)

f := newComponentsClient(tt.fields.provider, tt.fields.repository, configClient)
got, err := f.Get(tt.args.version, tt.args.targetNamespace, tt.args.watchingNamespace)
Copy link
Contributor

Choose a reason for hiding this comment

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

Changing this means that we don't have tests for Get. If we share the logic this might be fine, or we can add a test specifically for the Get without values? WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

how about I refactor the func to share the common code so I don't just duplicate the tests?

@@ -47,18 +48,53 @@ func newComponentsClient(provider config.Provider, repository Repository, config
}
}

func (f *componentsClient) GetWithValues(version, targetNamespace, watchingNamespace string) (Components, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggestion:

Suggested change
func (f *componentsClient) GetWithValues(version, targetNamespace, watchingNamespace string) (Components, error) {
type ComponentsClientInput struct {
version, targetNamespace, watchingNamespace string
withValues bool // Feel free to choose a more appropriate name
}
func (f *componentsClient) Get(input ComponentsClientInput) (Components, error) {
}

Then we can pass in the withValues to NewComponents.

Copy link
Contributor

Choose a reason for hiding this comment

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

I also noticed that we are missing the godoc for these methods. Maybe we can add them in here now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

will add godoc

Comment on lines 28 to 30
// getComponentsByNameAndValue is a utility method that returns components
// for a given provider, targetNamespace, and watchingNamespace.
func (c *clusterctlClient) getComponentsByNameAndValue(provider string, providerType clusterctlv1.ProviderType, targetNamespace string, watchingNamespace string) (repository.Components, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: The godoc for this is the same as getComponentsByName, can we differentiate them or say something like it is the same as getComponentsByName except for variables being filled in.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

what if the user only looks at one of them? I can change it if you feel strongly about it :D

@nader-ziada nader-ziada force-pushed the config-provider branch 2 times, most recently from d8fa0cc to 7fae5de Compare April 14, 2020 18:12
Copy link
Member

@fabriziopandini fabriziopandini left a comment

Choose a reason for hiding this comment

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

@nader-ziada sorry for jumping on this Issue with some delay
As per #2876 (comment), I'm personally for a slightly different solution, but I reviewed the PR as it is now

return nil, err
}

return NewComponents(f.provider, version, file, f.configClient, targetNamespace, watchingNamespace)
Copy link
Member

Choose a reason for hiding this comment

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

Changing the behavior of an existing method should be clearly advised to the users.
Also, get in clusterctl Get is used for upgrades

components, err := providerRepository.Components().Get(provider.NextVersion, provider.Namespace, provider.WatchedNamespace)

And this should be replaced with GetWithValues

// 3. Ensure all the ClusterRoleBinding which are referencing namespaced objects have the name prefixed with the namespace name
// 4. Set the watching namespace for the provider controller
// 5. Adds labels to all the components in order to allow easy identification of the provider objects
func NewComponents(provider config.Provider, version string, rawyaml []byte, configClient config.Client, targetNamespace, watchingNamespace string) (*components, error) {
Copy link
Member

Choose a reason for hiding this comment

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

As per comment #2876 (comment), I don't see such a clear distinction between the two use cases because variable substitution could provide value to users also in clusterctl config cluster with the -o yaml option.

Said that I like the idea of avoiding duplicating methods, even if I fully understand the pain of fixing the chain of calls (I experimented also some refactoring to get rid of this, but this is invasive).

@nader-ziada
Copy link
Contributor Author

@wfernandes @fabriziopandini added a 2nd commit with the flag approach, let me know what you think. Thanks

@vincepri
Copy link
Member

/test pull-cluster-api-apidiff

@nader-ziada
Copy link
Contributor Author

The api-apidiff is failing because I had to change a clusterctl method signature to fix this issue @vincepri

@wfernandes
Copy link
Contributor

This lgtm. Handing off to @fabriziopandini for final lgtm.

Copy link
Member

@fabriziopandini fabriziopandini left a comment

Choose a reason for hiding this comment

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

@nader-ziada thanks for this new version! really appreciated
Two nits and then lgtm from my side

// GetProviderComponents returns the provider components for a given provider, targetNamespace, watchingNamespace.
GetProviderComponents(provider string, providerType clusterctlv1.ProviderType, targetNameSpace, watchingNamespace string) (Components, error)
// GetProviderComponents returns the provider components for a given provider with options including targetNamespace, watchingNamespace.
GetProviderComponents(provider string, providerType clusterctlv1.ProviderType, options repository.ComponentsOptions) (Components, error)
Copy link
Member

Choose a reason for hiding this comment

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

Is it possible to define an alias for repository.ComponentsOptions in cmd/clusterctl/client/alias.go so we are not forcing to import the repository package to the consumer

Such alias should be used in all client the public methods

Copy link
Contributor Author

Choose a reason for hiding this comment

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

will add the alias

func (c *clusterctlClient) GetProviderComponents(provider string, providerType clusterctlv1.ProviderType, targetNameSpace, watchingNamespace string) (Components, error) {
components, err := c.getComponentsByName(provider, providerType, targetNameSpace, watchingNamespace)
func (c *clusterctlClient) GetProviderComponents(provider string, providerType clusterctlv1.ProviderType, options repository.ComponentsOptions) (Components, error) {
options.SkipVariables = true
Copy link
Member

Choose a reason for hiding this comment

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

Given that we are exponing options, should we leave to choose if to set this flag or not to the CLI/Library consumers?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Maybe this can be in a follow up PR

@k8s-ci-robot
Copy link
Contributor

@nader-ziada: The following test failed, say /retest to rerun all failed tests:

Test name Commit Details Rerun command
pull-cluster-api-apidiff 8103e29 link /test pull-cluster-api-apidiff

Full PR test history. Your PR dashboard. Please help us cut down on flakes by linking to an open issue when you hit one in your PR.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here.

@fabriziopandini
Copy link
Member

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Apr 17, 2020
@k8s-ci-robot k8s-ci-robot merged commit 62b7a1d into kubernetes-sigs:master Apr 17, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[clusterctl] "clusterctl config provider" fails to show AWS, VSphere, and Azure info
5 participants