-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
🐛 clusterctl to show config provider without setting env vars #2905
Conversation
@wfernandes @JoelSpeed when you get a chance to review this, let me know what you think about which tests are missing. thanks |
ae41205
to
5c2df9f
Compare
There was a problem hiding this 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
[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 |
// 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) { |
There was a problem hiding this comment.
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(...)
.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion:
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
.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will add godoc
cmd/clusterctl/client/common.go
Outdated
// 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) { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
d8fa0cc
to
7fae5de
Compare
There was a problem hiding this 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) |
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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).
7fae5de
to
1fd9cea
Compare
@wfernandes @fabriziopandini added a 2nd commit with the flag approach, let me know what you think. Thanks |
1fd9cea
to
ee99878
Compare
/test pull-cluster-api-apidiff |
The |
This lgtm. Handing off to @fabriziopandini for final lgtm. |
ee99878
to
f2013dd
Compare
There was a problem hiding this 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
cmd/clusterctl/client/client.go
Outdated
// 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) |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will add the alias
cmd/clusterctl/client/config.go
Outdated
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 |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
f2013dd
to
79df486
Compare
79df486
to
8103e29
Compare
@nader-ziada: The following test failed, say
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. |
/lgtm |
What this PR does / why we need it:
Which issue(s) this PR fixes
Fixes #2876
Release Notes:
func(string, string, string) (Components, error)
tofunc(ComponentsOptions) (Components, error)
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)
tofunc(sigs.k8s.io/cluster-api/cmd/clusterctl/client/config.Provider, sigs.k8s.io/cluster-api/cmd/clusterctl/client/config.Client, []byte, ComponentsOptions) (*components, error)