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

Change provider namespace from override to default #585

Merged
merged 4 commits into from
Jun 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
## 0.23.2 (Unreleased)

### Important

This release changes the behavior of the provider namespace flag introduced in `0.23.0`.
Previously, this flag was treated as an override, which ignored namespace values set
directly on resources. Now, the flag is a default, and will only set the namespace if one
is not already set. **This may cause resources to be recreated!**

lblackstone marked this conversation as resolved.
Show resolved Hide resolved
### Major changes

- BREAKING: Change the recently added `transformations` callback in Python to match JavaScript API (https://github.com/pulumi/pulumi-kubernetes/pull/575)
- BREAKING: Remove `getInputs` from Kubernetes resource implementations.
- BREAKING: Remove `getInputs` from Kubernetes resource implementations. (https://github.com/pulumi/pulumi-kubernetes/pull/580)
- BREAKING: Change provider namespace from override to default. (https://github.com/pulumi/pulumi-kubernetes/pull/585)
lblackstone marked this conversation as resolved.
Show resolved Hide resolved

### Improvements

Expand Down
57 changes: 1 addition & 56 deletions go.sum

Large diffs are not rendered by default.

28 changes: 13 additions & 15 deletions pkg/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,13 @@ type kubeOpts struct {
}

type kubeProvider struct {
host *provider.HostClient
canceler *cancellationContext
name string
version string
providerPrefix string
opts kubeOpts
overrideNamespace string
host *provider.HostClient
canceler *cancellationContext
name string
version string
providerPrefix string
opts kubeOpts
defaultNamespace string

clientSet *clients.DynamicClientSet
}
Expand Down Expand Up @@ -219,13 +219,12 @@ func (k *kubeProvider) Configure(_ context.Context, req *pulumirpc.ConfigureRequ
overrides := &clientcmd.ConfigOverrides{
Context: clientapi.Context{
Cluster: vars["kubernetes:config:cluster"],
Namespace: vars["kubernetes:config:namespace"],
},
CurrentContext: vars["kubernetes:config:context"],
}

if overrides.Context.Namespace != "" {
k.overrideNamespace = overrides.Context.Namespace
if defaultNamespace := vars["kubernetes:config:namespace"]; defaultNamespace != "" {
k.defaultNamespace = defaultNamespace
}

var kubeconfig clientcmd.ClientConfig
Expand Down Expand Up @@ -406,10 +405,9 @@ func (k *kubeProvider) Check(ctx context.Context, req *pulumirpc.CheckRequest) (
return nil, err
}

// If an override namespace is set on the provider for this resource, check if the resource has Namespaced
// or Global scope. For namespaced resources, set the namespace to the override value, ignoring any value
// currently set on the resource. Global-scope resources are unaffected by the override.
if k.overrideNamespace != "" {
// If a default namespace is set on the provider for this resource, check if the resource has Namespaced
// or Global scope. For namespaced resources, set the namespace to the default value if unset.
if k.defaultNamespace != "" && len(newInputs.GetNamespace()) == 0 {
namespacedKind, err := k.clientSet.IsNamespacedKind(gvk)
if err != nil {
if clients.IsNoNamespaceInfoErr(err) {
Expand All @@ -423,7 +421,7 @@ func (k *kubeProvider) Check(ctx context.Context, req *pulumirpc.CheckRequest) (
}

if namespacedKind {
newInputs.SetNamespace(k.overrideNamespace)
newInputs.SetNamespace(k.defaultNamespace)
}
}

Expand Down
3 changes: 2 additions & 1 deletion sdk/nodejs/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ export interface ProviderArgs {
*/
readonly kubeconfig?: pulumi.Input<string>;
/**
* If present, the namespace scope to use.
* If present, the default namespace to use. This flag is ignored for cluster-scoped resources.
lblackstone marked this conversation as resolved.
Show resolved Hide resolved
* Note: if .metadata.namespace is set on a resource, that value takes precedence over the provider default.
*/
readonly namespace?: pulumi.Input<string>;
}
9 changes: 6 additions & 3 deletions sdk/python/pulumi_kubernetes/provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,12 @@ def __init__(self,
:param pulumi.ResourceOptions __opts__: An optional bag of options that controls this resource's behavior.
:param pulumi.Input[str] cluster: If present, the name of the kubeconfig cluster to use.
:param pulumi.Input[str] context: If present, the name of the kubeconfig context to use.
:param pulumi.Input[str] kubeconfig: The contents of a kubeconfig file. If this is set, this config will be used instead
of $KUBECONFIG.
:param pulumi.Input[str] namespace: If present, the namespace scope to use.
:param pulumi.Input[str] kubeconfig: The contents of a kubeconfig file.
If this is set, this config will be used instead of $KUBECONFIG.
:param pulumi.Input[str] namespace: If present, the default namespace to use.
This flag is ignored for cluster-scoped resources.
Note: if .metadata.namespace is set on a resource, that value takes
precedence over the provider default.
"""
__props__ = {
"cluster": cluster,
Expand Down
40 changes: 23 additions & 17 deletions tests/integration/provider/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,41 +41,47 @@ func TestProvider(t *testing.T) {
Quick: true,
ExtraRuntimeValidation: func(t *testing.T, stackInfo integration.RuntimeValidationStackInfo) {
assert.NotNil(t, stackInfo.Deployment)
assert.Equal(t, 7, len(stackInfo.Deployment.Resources))
assert.Equal(t, 8, len(stackInfo.Deployment.Resources))

tests.SortResourcesByURN(stackInfo)

stackRes := stackInfo.Deployment.Resources[6]
stackRes := stackInfo.Deployment.Resources[7]
assert.Equal(t, resource.RootStackType, stackRes.URN.Type())

k8sProvider := stackInfo.Deployment.Resources[5]
k8sProvider := stackInfo.Deployment.Resources[6]
assert.True(t, providers.IsProviderType(k8sProvider.URN.Type()))

defaultProvider := stackInfo.Deployment.Resources[4]
defaultProvider := stackInfo.Deployment.Resources[5]
assert.True(t, providers.IsProviderType(defaultProvider.URN.Type()))

// Assert the provider Namespace was created
providerNamespace := stackInfo.Deployment.Resources[0]
assert.Equal(t, tokens.Type("kubernetes:core/v1:Namespace"), providerNamespace.URN.Type())
providerNsName, _ := openapi.Pluck(providerNamespace.Outputs, "metadata", "name")
// Assert the provider default Namespace (ns1) was created
ns1 := stackInfo.Deployment.Resources[0]
assert.Equal(t, tokens.Type("kubernetes:core/v1:Namespace"), ns1.URN.Type())
providerNsName, _ := openapi.Pluck(ns1.Outputs, "metadata", "name")

// Assert the other Namespace was created despite the provider override.
otherNamespace := stackInfo.Deployment.Resources[1]
// Assert the ns2 Namespace was created
ns2 := stackInfo.Deployment.Resources[1]
assert.Equal(t, tokens.Type("kubernetes:core/v1:Namespace"), ns2.URN.Type())
ns2Name, _ := openapi.Pluck(ns2.Outputs, "metadata", "name")

// Assert the other Namespace was created and doesn't use the provider default.
otherNamespace := stackInfo.Deployment.Resources[2]
assert.Equal(t, tokens.Type("kubernetes:core/v1:Namespace"), otherNamespace.URN.Type())
nsName, _ := openapi.Pluck(otherNamespace.Outputs, "metadata", "name")
assert.NotEqual(t, nsName, providerNsName)
assert.NotEqual(t, nsName.(string), providerNsName.(string))

// Assert the Pod was created in the provider namespace.
pod := stackInfo.Deployment.Resources[3]
// Assert the first Pod was created in the provider default namespace.
pod := stackInfo.Deployment.Resources[4]
assert.Equal(t, "nginx", string(pod.URN.Name()))
podNamespace, _ := openapi.Pluck(pod.Outputs, "metadata", "namespace")
assert.Equal(t, providerNamespace.ID.String(), podNamespace.(string))
assert.Equal(t, providerNsName.(string), podNamespace.(string))

// Assert the Pod was created in the provider namespace rather than the specified namespace.
namespacedPod := stackInfo.Deployment.Resources[2]
// Assert the Pod was created in the specified namespace rather than the provider default namespace.
namespacedPod := stackInfo.Deployment.Resources[3]
assert.Equal(t, "namespaced-nginx", string(namespacedPod.URN.Name()))
namespacedPodNamespace, _ := openapi.Pluck(namespacedPod.Outputs, "metadata", "namespace")
assert.Equal(t, providerNamespace.ID.String(), namespacedPodNamespace.(string))
assert.NotEqual(t, providerNsName.(string), namespacedPodNamespace.(string))
assert.Equal(t, ns2Name.(string), namespacedPodNamespace.(string))
},
})
}
15 changes: 8 additions & 7 deletions tests/integration/provider/step1/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,17 @@ import * as path from "path";
// Use the existing ~/.kube/config kubeconfig
const kubeconfig = fs.readFileSync(path.join(os.homedir(), ".kube", "config")).toString();

const ns = new k8s.core.v1.Namespace("ns");
const ns1 = new k8s.core.v1.Namespace("ns1");
const ns2 = new k8s.core.v1.Namespace("ns2");

// Create a new provider
const myk8s = new k8s.Provider("myk8s", {
kubeconfig: kubeconfig,
namespace: ns.metadata.name,
namespace: ns1.metadata.name,
});

// Create a Pod using the custom provider.
// The namespace should be automatically set by the provider override.
// The namespace should be automatically set by the provider default.
new k8s.core.v1.Pod("nginx", {
spec: {
containers: [{
Expand All @@ -40,10 +41,10 @@ new k8s.core.v1.Pod("nginx", {
},
}, { provider: myk8s });

// Create a Pod using the custom provider with a specified namespace.
// The namespace should be overridden by the provider override.
// Create a Pod using the custom provider with a specified default namespace.
// The namespace should not be overridden by the provider default.
new k8s.core.v1.Pod("namespaced-nginx", {
metadata: { namespace: ns.metadata.name },
metadata: { namespace: ns2.metadata.name },
spec: {
containers: [{
image: "nginx:1.7.9",
Expand All @@ -54,7 +55,7 @@ new k8s.core.v1.Pod("namespaced-nginx", {
}, { provider: myk8s });

// Create a Namespace using the custom provider
// The namespace should not be affected by the provider override since it is a non-namespaceable kind.
// The namespace should not be affected by the provider override since it is a cluster-scoped kind.
new k8s.core.v1.Namespace("other-ns",
{},
{ provider: myk8s });