Skip to content

Commit

Permalink
Merge pull request #16 from kbst/resiliency
Browse files Browse the repository at this point in the history
Improve resiliency of kustomization_resource create and delete
  • Loading branch information
pst authored Feb 22, 2020
2 parents 7383937 + 666f3a2 commit 63f903f
Show file tree
Hide file tree
Showing 6 changed files with 186 additions and 5 deletions.
74 changes: 69 additions & 5 deletions resource_kustomization.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,17 @@ func kustomizationResource() *schema.Resource {
}

func getGVR(gvk k8sschema.GroupVersionKind, cs *kubernetes.Clientset) (gvr k8sschema.GroupVersionResource, err error) {
gk := k8sschema.GroupKind{Group: gvk.Group, Kind: gvk.Kind}
agr, err := restmapper.GetAPIGroupResources(cs.Discovery())
if err != nil {
return gvr, fmt.Errorf("discovering API group resources failed: %s", err)
}

rm := restmapper.NewDiscoveryRESTMapper(agr)

gk := k8sschema.GroupKind{Group: gvk.Group, Kind: gvk.Kind}
mapping, err := rm.RESTMapping(gk, gvk.Version)
if err != nil {
return gvr, fmt.Errorf("mapping GroupKind failed: %s", err)
return gvr, fmt.Errorf("mapping GroupKind failed for '%s': %s", gvk, err)
}

gvr = mapping.Resource
Expand Down Expand Up @@ -82,14 +83,71 @@ func kustomizationResourceCreate(d *schema.ResourceData, m interface{}) error {
return fmt.Errorf("ResourceCreate: %s", err)
}

gvr, err := getGVR(u.GroupVersionKind(), clientset)
stateConf := &resource.StateChangeConf{
Target: []string{"existing"},
Pending: []string{"pending"},
Timeout: d.Timeout(schema.TimeoutCreate),
Refresh: func() (interface{}, string, error) {
// CRDs: wait for GroupVersionKind to exist
gvr, err := getGVR(u.GroupVersionKind(), clientset)
if err != nil {
return nil, "pending", nil
}

return gvr, "existing", nil
},
}
gvrResp, err := stateConf.WaitForState()
if err != nil {
return fmt.Errorf("ResourceCreate: %s", err)
return fmt.Errorf(
"ResourceCreate: GroupVersionKind '%s' %s",
u.GroupVersionKind(),
err)
}

gvr := gvrResp.(k8sschema.GroupVersionResource)
namespace := u.GetNamespace()

setLastAppliedConfig(u, srcJSON)

if namespace != "" {
// wait for the namespace to exist
nsGvk := k8sschema.GroupVersionKind{
Group: "",
Version: "",
Kind: "Namespace"}
nsGvr, err := getGVR(nsGvk, clientset)
if err != nil {
return fmt.Errorf("ResourceCreate: %s", err)
}

stateConf := &resource.StateChangeConf{
Target: []string{"existing"},
Pending: []string{"pending"},
Timeout: d.Timeout(schema.TimeoutCreate),
Refresh: func() (interface{}, string, error) {
resp, err := client.
Resource(nsGvr).
Get(namespace, k8smetav1.GetOptions{})
if err != nil {
if k8serrors.IsNotFound(err) {
return nil, "pending", nil
}
return nil, "", err
}

return resp, "existing", nil
},
}
_, err = stateConf.WaitForState()
if err != nil {
return fmt.Errorf(
"ResourceCreate: namespace '%s' %s",
namespace,
err)
}
}

resp, err := client.
Resource(gvr).
Namespace(namespace).
Expand Down Expand Up @@ -361,6 +419,12 @@ func kustomizationResourceDelete(d *schema.ResourceData, m interface{}) error {
Namespace(namespace).
Delete(name, nil)
if err != nil {
// Consider not found during deletion a success
if k8serrors.IsNotFound(err) {
d.SetId("")
return nil
}

return fmt.Errorf("ResourceDelete: deleting '%s' failed: %s", gvr, err)
}

Expand All @@ -377,7 +441,7 @@ func kustomizationResourceDelete(d *schema.ResourceData, m interface{}) error {
if k8serrors.IsNotFound(err) {
return nil, "", nil
}
return nil, "", fmt.Errorf("ResourceDelete: refreshing '%s' state failed: %s", gvr, err)
return nil, "", fmt.Errorf("refreshing '%s' state failed: %s", gvr, err)
}

return resp, "deleting", nil
Expand Down
70 changes: 70 additions & 0 deletions resource_kustomization_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,76 @@ resource "kustomization_resource" "dep1" {
`
}

//
//
// CRD Test
func TestAccResourceKustomization_crd(t *testing.T) {

resource.Test(t, resource.TestCase{
//PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
//
//
// Applying both namespaced and cluster wide CRD
// and one custom object of each CRD
{
Config: testAccResourceKustomizationConfig_crd("test_kustomizations/crd"),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttrSet(
"kustomization_resource.clusteredcrd",
"id"),
resource.TestCheckResourceAttrSet(
"kustomization_resource.namespacedcrd",
"id"),
resource.TestCheckResourceAttrSet(
"kustomization_resource.clusteredco",
"id"),
resource.TestCheckResourceAttrSet(
"kustomization_resource.namespacedco",
"id"),
resource.TestCheckResourceAttrSet(
"kustomization_resource.ns",
"id"),
),
},
//
//
// Test state import
{
ResourceName: "kustomization_resource.test[\"apiextensions.k8s.io_v1beta1_CustomResourceDefinition|~X|clusteredcrds.test.example.com\"]",
ImportStateId: "apiextensions.k8s.io_v1beta1_CustomResourceDefinition|~X|clusteredcrds.test.example.com",
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func testAccResourceKustomizationConfig_crd(path string) string {
return testAccDataSourceKustomizationConfig_basic(path) + `
resource "kustomization_resource" "clusteredcrd" {
manifest = data.kustomization.test.manifests["apiextensions.k8s.io_v1beta1_CustomResourceDefinition|~X|clusteredcrds.test.example.com"]
}
resource "kustomization_resource" "namespacedcrd" {
manifest = data.kustomization.test.manifests["apiextensions.k8s.io_v1beta1_CustomResourceDefinition|~X|namespacedcrds.test.example.com"]
}
resource "kustomization_resource" "clusteredco" {
manifest = data.kustomization.test.manifests["test.example.com_v1alpha1_Clusteredcrd|~X|clusteredco"]
}
resource "kustomization_resource" "namespacedco" {
manifest = data.kustomization.test.manifests["test.example.com_v1alpha1_Namespacedcrd|test-crd|namespacedco"]
}
resource "kustomization_resource" "ns" {
manifest = data.kustomization.test.manifests["~G_v1_Namespace|~X|test-crd"]
}
`
}

//
//
// Test check functions
Expand Down
12 changes: 12 additions & 0 deletions test_kustomizations/crd/co.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
apiVersion: test.example.com/v1alpha1
kind: Namespacedcrd
metadata:
name: namespacedco
namespace: test-crd
spec: {}
---
apiVersion: test.example.com/v1alpha1
kind: Clusteredcrd
metadata:
name: clusteredco
spec: {}
27 changes: 27 additions & 0 deletions test_kustomizations/crd/crd.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: namespacedcrds.test.example.com
spec:
group: test.example.com
names:
kind: Namespacedcrd
plural: namespacedcrds
shortNames:
- ncrds
scope: Namespaced
version: v1alpha1
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: clusteredcrds.test.example.com
spec:
group: test.example.com
names:
kind: Clusteredcrd
plural: clusteredcrds
shortNames:
- ccrds
scope: Cluster
version: v1alpha1
4 changes: 4 additions & 0 deletions test_kustomizations/crd/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
resources:
- namespace.yaml
- crd.yaml
- co.yaml
4 changes: 4 additions & 0 deletions test_kustomizations/crd/namespace.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: test-crd

0 comments on commit 63f903f

Please sign in to comment.