Skip to content

Commit 7747bd9

Browse files
authored
Merge pull request #196 from kbst/fail-incorrect-namespace
Error when namespace set but not allowed or not set when required
2 parents e605d47 + 5bf205e commit 7747bd9

File tree

7 files changed

+138
-10
lines changed

7 files changed

+138
-10
lines changed

kustomize/manifest.go

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,19 @@ func (km *kManifest) namespace() string {
121121
return km.id().namespace
122122
}
123123

124+
func (km *kManifest) isNamespaced() (bool, error) {
125+
m, err := km.mapping()
126+
if err != nil {
127+
return false, km.fmtErr(fmt.Errorf("api error: %s", err))
128+
}
129+
130+
if m.Scope.Name() == k8smeta.RESTScopeNameNamespace {
131+
return true, nil
132+
}
133+
134+
return false, nil
135+
}
136+
124137
func (km *kManifest) name() string {
125138
return km.id().name
126139
}
@@ -137,10 +150,21 @@ func (km *kManifest) id() (id kManifestId) {
137150
func (km *kManifest) api() (api k8sdynamic.ResourceInterface, err error) {
138151
gvr, err := km.gvr()
139152
if err != nil {
140-
return api, nil
153+
return api, km.fmtErr(fmt.Errorf("api error: %s", err))
154+
}
155+
156+
api = km.client.Resource(gvr)
157+
158+
isNamespaced, err := km.isNamespaced()
159+
if err != nil {
160+
return api, km.fmtErr(fmt.Errorf("api error: %s", err))
161+
}
162+
163+
if isNamespaced {
164+
api = km.client.Resource(gvr).Namespace(km.namespace())
141165
}
142166

143-
return km.client.Resource(gvr).Namespace(km.namespace()), nil
167+
return api, nil
144168
}
145169

146170
func (km *kManifest) apiGet(opts k8smetav1.GetOptions) (resp *k8sunstructured.Unstructured, err error) {

kustomize/resource_kustomization.go

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -179,15 +179,28 @@ func kustomizationResourceDiff(ctx context.Context, d *schema.ResourceDiff, m in
179179
}
180180
setLastAppliedConfig(kmm, gzipLastAppliedConfig)
181181

182+
_, err = kmm.mappings()
183+
if err != nil {
184+
// if there are no mappings we can't dry-run
185+
// this is for CRDs that do not exist yet
186+
return nil
187+
}
188+
189+
isNamespaced, err := kmm.isNamespaced()
190+
if err != nil {
191+
return logError(err)
192+
}
193+
if isNamespaced && kmm.namespace() == "" {
194+
err = kmm.fmtErr(fmt.Errorf("is namespace scoped and must set metadata.namespace"))
195+
return logError(err)
196+
}
197+
if !isNamespaced && kmm.namespace() != "" {
198+
err = kmm.fmtErr(fmt.Errorf("is not namespace scoped but has metadata.namespace set"))
199+
return logError(err)
200+
}
201+
182202
if do.(string) == "" {
183203
// diffing for create
184-
_, err := kmm.mappings()
185-
if err != nil {
186-
// if there are no mappings we can't dry-run
187-
// this is for CRDs that do not exist yet
188-
return nil
189-
}
190-
191204
_, err = kmm.apiCreate(k8smetav1.CreateOptions{DryRun: []string{k8smetav1.DryRunAll}})
192205
if err != nil {
193206
if k8serrors.IsAlreadyExists(err) {
@@ -334,7 +347,7 @@ func kustomizationResourceDelete(d *schema.ResourceData, m interface{}) error {
334347
// the resource can't exist either
335348
return nil
336349
}
337-
return logError(err)
350+
return logError(km.fmtErr(err))
338351
}
339352

340353
err = km.apiDelete(k8smetav1.DeleteOptions{})

kustomize/resource_kustomization_test.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,60 @@ resource "kustomization_resource" "ns" {
604604
`
605605
}
606606

607+
//
608+
//
609+
// Fail namespace not allowed
610+
func TestAccResourceKustomization_failPlanInvalidNamespaceNotAllowed(t *testing.T) {
611+
612+
resource.Test(t, resource.TestCase{
613+
Providers: testAccProviders,
614+
Steps: []resource.TestStep{
615+
//
616+
//
617+
// Expect plan to fail due to namespace not allowed
618+
{
619+
Config: testAccResourceKustomizationConfig_failNamespaceNotAllowed("test_kustomizations/fail_namespace_not_allowed"),
620+
ExpectError: regexp.MustCompile("Error: github.com/kbst/terraform-provider-kustomize/kustomize.kustomizationResourceDiff: \"rbac.authorization.k8s.io/ClusterRoleBinding/default/invalid\": is not namespace scoped but has metadata.namespace set"),
621+
},
622+
},
623+
})
624+
}
625+
626+
func testAccResourceKustomizationConfig_failNamespaceNotAllowed(path string) string {
627+
return testAccDataSourceKustomizationConfig_basic(path) + `
628+
resource "kustomization_resource" "crb" {
629+
manifest = data.kustomization_build.test.manifests["rbac.authorization.k8s.io/ClusterRoleBinding/default/invalid"]
630+
}
631+
`
632+
}
633+
634+
//
635+
//
636+
// Fail namespace required
637+
func TestAccResourceKustomization_failNamespaceRequired(t *testing.T) {
638+
639+
resource.Test(t, resource.TestCase{
640+
Providers: testAccProviders,
641+
Steps: []resource.TestStep{
642+
//
643+
//
644+
// Expect plan to fail due to missing namespace
645+
{
646+
Config: testAccResourceKustomizationConfig_failNamespaceRequired("test_kustomizations/fail_namespace_required"),
647+
ExpectError: regexp.MustCompile("Error: github.com/kbst/terraform-provider-kustomize/kustomize.kustomizationResourceDiff: \"rbac.authorization.k8s.io/RoleBinding/_/invalid\": is namespace scoped and must set metadata.namespace"),
648+
},
649+
},
650+
})
651+
}
652+
653+
func testAccResourceKustomizationConfig_failNamespaceRequired(path string) string {
654+
return testAccDataSourceKustomizationConfig_basic(path) + `
655+
resource "kustomization_resource" "crb" {
656+
manifest = data.kustomization_build.test.manifests["rbac.authorization.k8s.io/RoleBinding/_/invalid"]
657+
}
658+
`
659+
}
660+
607661
//
608662
//
609663
// Fail plan invalid manifest
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
apiVersion: rbac.authorization.k8s.io/v1
2+
kind: ClusterRoleBinding
3+
metadata:
4+
name: invalid
5+
# invalid not namespace scoped
6+
namespace: default
7+
subjects:
8+
- kind: Group
9+
name: admins
10+
apiGroup: rbac.authorization.k8s.io
11+
roleRef:
12+
kind: ClusterRole
13+
name: admin
14+
apiGroup: rbac.authorization.k8s.io
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
apiVersion: kustomize.config.k8s.io/v1beta1
2+
kind: Kustomization
3+
4+
resources:
5+
- invalid_cluster_role_binding.yaml
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
apiVersion: rbac.authorization.k8s.io/v1
2+
kind: RoleBinding
3+
metadata:
4+
name: invalid
5+
# invalid namespace scoped but no namespace
6+
subjects:
7+
- kind: Group
8+
name: admins
9+
apiGroup: rbac.authorization.k8s.io
10+
roleRef:
11+
kind: ClusterRole
12+
name: admin
13+
apiGroup: rbac.authorization.k8s.io
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
apiVersion: kustomize.config.k8s.io/v1beta1
2+
kind: Kustomization
3+
4+
resources:
5+
- invalid_role_binding.yaml

0 commit comments

Comments
 (0)