-
Notifications
You must be signed in to change notification settings - Fork 982
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 ConflictsWith
to provider authentication config
#1141
Conversation
242f7b1
to
9b2e03a
Compare
6dca5d8
to
c30a64f
Compare
command = "aws" | ||
} | ||
} | ||
|
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 moved the provider blocks into the root module, since that's best practice.
c30a64f
to
e1ad2e2
Compare
token = data.google_client_config.default.access_token | ||
cluster_ca_certificate = base64decode(var.cluster_ca_cert) | ||
} | ||
|
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 moved this provider config into the root module.
_examples/gke/gke-cluster/main.tf
Outdated
# This can be set statically, if preferred. See docs for details. | ||
# https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/provider_reference#full-reference | ||
} | ||
|
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.
This provider config was moved into the root module.
002dc63
to
72a16df
Compare
if err := checkConfigurationValid(k.configData); err != nil { | ||
return nil, err | ||
} | ||
|
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 did a bunch of Progressive Apply testing and I wasn't able to find a difference between having this check enabled vs disabled.
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.
Did you do your testing across different versions of Terraform and can you share your testing strategy? I'm still pretty uncertain about reliably reproducing the illusive progressive apply issue.
You can look at the issue that caused us to revert this change in the Helm provider for context: hashicorp/terraform-provider-helm#647
} else if v := os.Getenv("KUBE_CONFIG_PATHS"); v != "" { | ||
// NOTE we have to do this here because the schema | ||
// does not yet allow you to set a default for a TypeList | ||
configPaths = filepath.SplitList(v) |
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.
The SDK now seems to allow us to set a default for TypeList! 🎉 I didn't see the feature added, but it worked for me when I defined my own function of type schema.EnvDefaultFunc
.
@@ -334,16 +434,16 @@ func initializeConfiguration(d *schema.ResourceData) (*restclient.Config, error) | |||
} | |||
|
|||
// Overriding with static configuration | |||
if v, ok := d.GetOk("insecure"); ok { | |||
if v, ok := d.GetOk("insecure"); ok && v != "" { |
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 checks are just meant to ensure the various configuration attributes are not initialized with any default/empty values. For example, if the provider thinks we've set host = ""
, it won't let us set config_path = "~/.kube/config"
because of the ConflictsWith.
d5b9d54
to
c706a16
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.
Thanks for doing this @dak1n1 – this mostly looks great, especially all the tests you've added and config examples you've tidied up.
I added a few questions about the conflicts with stuff, and there seems to be a problem with sourcing the KUBE_CONFIG_PATHS
environment variable.
Optional: true, | ||
Description: "A list of paths to kube config files. Can be set with KUBE_CONFIG_PATHS environment variable.", | ||
// config_paths conflicts with every attribute except for "insecure", since all of these options will be read from the kubeconfig. |
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.
It seems like the insecure
option can actually be part of the kubeconfig file but is called insecure-skip-tls-verify
https://github.com/kubernetes/kubernetes/blob/f4a156eb29d51b73f52d69ab4c5f96e440eebc41/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1beta1/types.go#L86
Is there a good reason to also have it here when using config_path
in that case?
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.
Nope, my mistake! I thought it was a command-line override that works anywhere. I'll have to fix that. But I'm going to hold off doing anything with this PR until we have that meeting next week.
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.
Just to give you a status update: I'll fix the things you mentioned as soon as I can get the needed functionality into the SDK. (Since we don't want to enable ConflictsWith in "fatal error" mode, the SDK work will be needed before this PR can progress).
kubernetes/provider.go
Outdated
Optional: true, | ||
DefaultFunc: schema.EnvDefaultFunc("KUBE_CTX", nil), | ||
Description: "Context to choose from the kube config file. ", | ||
ConflictsWith: []string{"exec", "token", "client_certificate", "client_key", "username", "password"}, |
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.
Wouldn't this also conflict with cluster_ca_certificate
since it's just for when using a kubeconfig file?
// configPathsEnv fetches the value of the environment variable KUBE_CONFIG_PATHS, if defined. | ||
func configPathsEnv() (interface{}, error) { | ||
value, exists := os.LookupEnv("KUBE_CONFIG_PATHS") | ||
if exists { |
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.
Just a nit but because there's a bunch of stuff inside this conditional i would invert it so that if !exists
returns early so the rest of the logic is just the body of the function.
}, | ||
"config_paths": { | ||
Type: schema.TypeList, | ||
Elem: &schema.Schema{Type: schema.TypeString}, | ||
DefaultFunc: configPathsEnv, |
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.
This doesn't actually seem to be working for me on your branch:
When I use KUBE_CONFIG_PATH
it works fine:
KUBE_CONFIG_PATH=~/.kube/config terraform plan ✘ 1 conflictswith ✱ ◼
kubernetes_config_map.testy: Refreshing state... [id=default/testo]
No changes. Infrastructure is up-to-date.
That Terraform did not detect any differences between your configuration and the remote system(s). As a result, there
are no actions to take.
But when I try to use KUBE_CONFIG_PATHS
:
KUBE_CONFIG_PATHS=~/.kube/config terraform plan ✘ 1 conflictswith ✱ ◼
kubernetes_config_map.testy: Refreshing state... [id=default/testo]
╷
│ Error: Get "http://localhost/api/v1/namespaces/default/configmaps/testo": dial tcp [::1]:80: connect: connection refused
│
│
╵
However if I set config_paths
in the config it works fine. So I suspect something isn't right with the default function here.
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.
Nice, thanks for testing! I'll have to check this out.
if err := checkConfigurationValid(k.configData); err != nil { | ||
return nil, err | ||
} | ||
|
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.
Did you do your testing across different versions of Terraform and can you share your testing strategy? I'm still pretty uncertain about reliably reproducing the illusive progressive apply issue.
You can look at the issue that caused us to revert this change in the Helm provider for context: hashicorp/terraform-provider-helm#647
}) | ||
} | ||
|
||
func TestAccKubernetesProviderConfig_config_paths_env(t *testing.T) { |
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 I couldn't get KUBE_CONFIG_PATHS
to work locally as mentioned above, I'm confused by how this test passes 🤯
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.
Ah, I see this probably passes because the validation on the provider block doesn't error but terraform breaks gives an error at apply time because the list is empty.
I added some logging to the provider block where I can see that configPathsEnv
is being called, but when I do a d.Get("config_paths")
in the providerConfigure function it comes up empty. 😢
}, | ||
{ | ||
Config: testAccKubernetesProviderConfig( | ||
providerConfig_host("https://test-host") + |
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 found the nesting of functions here a bit confusing to read – I think I would have preferred just one big string with the provider block in it so I can see exactly what is being tested. I see you are trying not to repeat yourself here and avoid copypasta though.
There's a PR that I tested out today, which gives us the conflictsWith warning level messages. It's working, but it will take some time for it to be reviewed and released. Probably sometime in June. hashicorp/terraform-plugin-sdk#745 |
In order to create a more explicit configuration, and more predictable behavior, this PR adds ConflictsWith to specific provider authentication attributes, effectively disallowing the use of conflicting methods of authentication, such as config_path and token. The provider now generates an error to tell the user that these options are mutually exclusive.
Description
In the past, we relied on Kubernetes client-go to determine the order of precedence when given a list of mutually-exclusive parameters for authenticating to the Kubernetes cluster. This lead to some confusion, since client-go's decision could override even an explicit provider configuration. For example, if a
token
were specified in the Kubernetes provider config, and the environment variableKUBE_CONFIG_PATH
was present, client-go would silently decide to use theKUBE_CONFIG_PATH
to authenticate to the cluster.In order to create a more explicit configuration, and more predictable behavior, this PR adds
ConflictsWith
to specific provider authentication attributes, effectively disallowing the use of conflicting methods of authentication, such asconfig_path
andtoken
. The provider now generates an error to tell the user that these options are mutually exclusive.Acceptance tests
Output from acceptance testing:
Release Note
Release note for CHANGELOG:
References
Community Note