Skip to content

Commit

Permalink
Added manifests to data resources providing a map for for_each usage (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
gavinbunney committed Oct 11, 2021
1 parent 1dfa7b0 commit 02b422d
Show file tree
Hide file tree
Showing 13 changed files with 248 additions and 28 deletions.
16 changes: 16 additions & 0 deletions .run/Template Go Test.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<component name="ProjectRunConfigurationManager">
<configuration default="true" type="GoTestRunConfiguration" factoryName="Go Test">
<module name="terraform-provider-kubectl" />
<working_directory value="$PROJECT_DIR$" />
<envs>
<env name="TF_ACC" value="1" />
<env name="KUBECONFIG" value="$PROJECT_DIR$/scripts/kubeconfig.yaml" />
</envs>
<kind value="DIRECTORY" />
<package value="github.com/gavinbunney/terraform-provider-kubectl" />
<directory value="$PROJECT_DIR$" />
<filePath value="$PROJECT_DIR$" />
<framework value="gotest" />
<method v="2" />
</configuration>
</component>
1 change: 1 addition & 0 deletions _examples/manifests/directives-templated.yaml
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
kind: MyAwesomeCRD
MyYaml: Hello, %{ if name != "" }${name}%{ else }unnamed%{ endif }!
30 changes: 30 additions & 0 deletions _examples/manifests/duplicates/multiple.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
name: name-here-crd
spec:
cronSpec: "* * * * /5"
image: my-awesome-cron-image
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: name-here-crontabs.stable.example.com
spec:
group: stable.example.com
conversion:
strategy: None
scope: Namespaced
names:
plural: name-here-crontabs
singular: crontab
kind: CronTab
shortNames:
- ct
version: v1
versions:
- name: v1
served: true
storage: true
---
30 changes: 30 additions & 0 deletions _examples/manifests/duplicates/multiple2.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
name: name-here-crd
spec:
cronSpec: "* * * * /5"
image: my-awesome-cron-image
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: name-here-crontabs.stable.example.com
spec:
group: stable.example.com
conversion:
strategy: None
scope: Namespaced
names:
plural: name-here-crontabs
singular: crontab
kind: CronTab
shortNames:
- ct
version: v1
versions:
- name: v1
served: true
storage: true
---
4 changes: 2 additions & 2 deletions _examples/manifests/multiple-templated.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
name: name-here-crd
name: name-here-crd-templated
spec:
cronSpec: "* * * * /5"
image: my-awesome-cron-image
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: name-here-crontabs.stable.example.com
name: name-here-templated-crontabs.stable.example.com
spec:
group: stable.example.com
conversion:
Expand Down
2 changes: 1 addition & 1 deletion _examples/manifests/single-templated.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
apiVersion: "stable.example.com/v1"
kind: ${the_kind}
metadata:
name: name-here-crd
name: name-here-crd-single-templated
spec:
cronSpec: "* * * * /5"
image: my-awesome-cron-image
2 changes: 1 addition & 1 deletion _examples/manifests/single.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
name: name-here-crd
name: name-here-crd-single
spec:
cronSpec: "* * * * /5"
image: my-awesome-cron-image
29 changes: 25 additions & 4 deletions docs/data-sources/kubectl_file_documents.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,38 @@ This provider provides a `data` resource `kubectl_file_documents` to enable ease

## Example Usage

### Example Usage with for_each

The recommended approach is to use the `manifests` attribute and a `for_each` expression to apply the found manifests.
This ensures that any additional yaml documents or removals do not cause a large amount of terraform changes.

```hcl
data "kubectl_file_documents" "docs" {
content = file("multi-doc-manifest.yaml")
}
resource "kubectl_manifest" "test" {
for_each = data.kubectl_file_documents.docs.manifests
yaml_body = each.value
}
```

### Example Usage via count

Raw documents can also be accessed via the `documents` attribute.

```hcl
data "kubectl_file_documents" "manifests" {
data "kubectl_file_documents" "docs" {
content = file("multi-doc-manifest.yaml")
}
resource "kubectl_manifest" "test" {
count = length(data.kubectl_file_documents.manifests.documents)
yaml_body = element(data.kubectl_file_documents.manifests.documents, count.index)
count = length(data.kubectl_file_documents.docs.documents)
yaml_body = element(data.kubectl_file_documents.docs.documents, count.index)
}
```

## Attribute Reference

* `documents` - List of YAML documents (string).
* `manifests` - Map of YAML documents with key being the document id, and value being the document yaml. Best used with `for_each` expressions.
* `documents` - List of raw YAML documents (string). Best used with `count` expressions.
29 changes: 24 additions & 5 deletions docs/data-sources/kubectl_path_documents.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,34 @@ This gives you the flexibility of parameterizing your manifests, and loading & t

## Example Usage

### Load all manifest documents
### Load all manifest documents via for_each (recommended)

The recommended approach is to use the `manifests` attribute and a `for_each` expression to apply the found manifests.
This ensures that any additional yaml documents or removals do not cause a large amount of terraform changes.

```hcl
data "kubectl_path_documents" "manifests" {
data "kubectl_path_documents" "docs" {
pattern = "./manifests/*.yaml"
}
resource "kubectl_manifest" "test" {
for_each = data.kubectl_file_documents.docs.manifests
yaml_body = each.value
}
```

### Load all manifest documents via count

Raw documents can also be accessed via the `documents` attribute.

```hcl
data "kubectl_path_documents" "docs" {
pattern = "./manifests/*.yaml"
}
resource "kubectl_manifest" "test" {
count = length(data.kubectl_path_documents.manifests.documents)
yaml_body = element(data.kubectl_path_documents.manifests.documents, count.index)
count = length(data.kubectl_path_documents.docs.documents)
yaml_body = element(data.kubectl_path_documents.docs.documents, count.index)
}
```

Expand Down Expand Up @@ -152,4 +170,5 @@ metadata:

## Attribute Reference

* `documents` - List of YAML documents (list[string]).
* `manifests` - Map of YAML documents with key being the document id, and value being the document yaml. Best used with `for_each` expressions.
* `documents` - List of YAML documents (list[string]). Best used with `count` expressions.
29 changes: 28 additions & 1 deletion kubernetes/data_source_kubectl_file_documents.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ func dataSourceKubectlFileDocuments() *schema.Resource {
Elem: &schema.Schema{Type: schema.TypeString},
Computed: true,
},
"manifests": &schema.Schema{
Type: schema.TypeMap,
Elem: &schema.Schema{
Type: schema.TypeString,
},
Computed: true,
},
},
}
}
Expand All @@ -33,7 +40,27 @@ func dataSourceKubectlFileDocumentsRead(ctx context.Context, d *schema.ResourceD
return diag.FromErr(err)
}

manifests := make(map[string]string, 0)
for _, doc := range documents {
manifest, err := yaml.ParseYAML(doc)
if err != nil {
return diag.FromErr(fmt.Errorf("failed to parse yaml as a kubernetes yaml manifest: %v", err))
}

parsed, err := manifest.AsYAML()
if err != nil {
return diag.FromErr(fmt.Errorf("failed to parse convert manifest to yaml: %v", err))
}

if _, exists := manifests[manifest.GetSelfLink()]; exists {
return diag.FromErr(fmt.Errorf("duplicate manifest found with id: %v", manifest.GetSelfLink()))
}

manifests[manifest.GetSelfLink()] = parsed
}

d.SetId(fmt.Sprintf("%x", sha256.Sum256([]byte(content))))
d.Set("documents", documents)
_ = d.Set("documents", documents)
_ = d.Set("manifests", manifests)
return nil
}
8 changes: 8 additions & 0 deletions kubernetes/data_source_kubectl_file_documents_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ func TestAccKubectlDataSourceFileDocuments_single(t *testing.T) {
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("data.kubectl_file_documents.test", "documents.#", "1"),
resource.TestCheckResourceAttr("data.kubectl_file_documents.test", "documents.0", "kind: Service1"),
resource.TestCheckResourceAttr("data.kubectl_file_documents.test", "manifests.%", "1"),
resource.TestCheckResourceAttr("data.kubectl_file_documents.test", "manifests./apis/service1s", "kind: Service1\n"),
),
},
},
Expand All @@ -33,6 +35,9 @@ func TestAccKubectlDataSourceFileDocuments_basic(t *testing.T) {
resource.TestCheckResourceAttr("data.kubectl_file_documents.test", "documents.#", "2"),
resource.TestCheckResourceAttr("data.kubectl_file_documents.test", "documents.0", "kind: Service1"),
resource.TestCheckResourceAttr("data.kubectl_file_documents.test", "documents.1", "kind: Service2"),
resource.TestCheckResourceAttr("data.kubectl_file_documents.test", "manifests.%", "2"),
resource.TestCheckResourceAttr("data.kubectl_file_documents.test", "manifests./apis/service1s", "kind: Service1\n"),
resource.TestCheckResourceAttr("data.kubectl_file_documents.test", "manifests./apis/service2s", "kind: Service2\n"),
),
},
},
Expand Down Expand Up @@ -61,6 +66,9 @@ YAML
resource.TestCheckResourceAttr("data.kubectl_file_documents.test", "documents.#", "2"),
resource.TestCheckResourceAttr("data.kubectl_file_documents.test", "documents.0", "kind: Service1"),
resource.TestCheckResourceAttr("data.kubectl_file_documents.test", "documents.1", "kind: Service2"),
resource.TestCheckResourceAttr("data.kubectl_file_documents.test", "manifests.%", "2"),
resource.TestCheckResourceAttr("data.kubectl_file_documents.test", "manifests./apis/service1s", "kind: Service1\n"),
resource.TestCheckResourceAttr("data.kubectl_file_documents.test", "manifests./apis/service2s", "kind: Service2\n"),
),
},
},
Expand Down
27 changes: 27 additions & 0 deletions kubernetes/data_source_kubectl_path_documents.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ func dataSourceKubectlPathDocuments() *schema.Resource {
Elem: &schema.Schema{Type: schema.TypeString},
Computed: true,
},
"manifests": &schema.Schema{
Type: schema.TypeMap,
Elem: &schema.Schema{
Type: schema.TypeString,
},
Computed: true,
},
"vars": {
Type: schema.TypeMap,
Optional: true,
Expand Down Expand Up @@ -99,8 +106,28 @@ func dataSourceKubectlPathDocumentsRead(ctx context.Context, d *schema.ResourceD
allDocuments = append(allDocuments, documents...)
}

manifests := make(map[string]string, 0)
for _, doc := range allDocuments {
manifest, err := yaml.ParseYAML(doc)
if err != nil {
return diag.FromErr(fmt.Errorf("failed to parse yaml as a kubernetes yaml manifest: %v", err))
}

parsed, err := manifest.AsYAML()
if err != nil {
return diag.FromErr(fmt.Errorf("failed to parse convert manifest to yaml: %v", err))
}

if _, exists := manifests[manifest.GetSelfLink()]; exists {
return diag.FromErr(fmt.Errorf("duplicate manifest found with id: %v", manifest.GetSelfLink()))
}

manifests[manifest.GetSelfLink()] = parsed
}

d.SetId(fmt.Sprintf("%x", sha256.Sum256([]byte(strings.Join(allDocuments, "")))))
_ = d.Set("documents", allDocuments)
_ = d.Set("manifests", manifests)
return nil
}

Expand Down
Loading

0 comments on commit 02b422d

Please sign in to comment.