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

Clean flatten metadata #2413

Merged
merged 5 commits into from
Feb 5, 2024
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
17 changes: 9 additions & 8 deletions kubernetes/structures.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,20 +135,21 @@ func flattenMetadataFields(meta metav1.ObjectMeta) []interface{} {
}

func flattenMetadata(meta metav1.ObjectMeta, d *schema.ResourceData, providerMetadata interface{}) []interface{} {
metadata := expandMetadata(d.Get("metadata").([]interface{}))
metadataAnnotations := d.Get("metadata.0.annotations").(map[string]interface{})
metadataLabels := d.Get("metadata.0.labels").(map[string]interface{})

ignoreAnnotations := providerMetadata.(kubeClientsets).IgnoreAnnotations
removeInternalKeys(meta.Annotations, metadata.Annotations)
removeKeys(meta.Annotations, metadata.Annotations, ignoreAnnotations)
removeInternalKeys(meta.Annotations, metadataAnnotations)
removeKeys(meta.Annotations, metadataAnnotations, ignoreAnnotations)

ignoreLabels := providerMetadata.(kubeClientsets).IgnoreLabels
removeInternalKeys(meta.Labels, metadata.Labels)
removeKeys(meta.Labels, metadata.Labels, ignoreLabels)
removeInternalKeys(meta.Labels, metadataLabels)
removeKeys(meta.Labels, metadataLabels, ignoreLabels)

return flattenMetadataFields(meta)
}

func removeInternalKeys(m map[string]string, d map[string]string) {
func removeInternalKeys(m map[string]string, d map[string]interface{}) {
for k := range m {
if isInternalKey(k) && !isKeyInMap(k, d) {
delete(m, k)
Expand All @@ -158,15 +159,15 @@ func removeInternalKeys(m map[string]string, d map[string]string) {

// removeKeys removes given Kubernetes metadata(annotations and labels) keys.
// In that case, they won't be available in the TF state file and will be ignored during apply/plan operations.
func removeKeys(m map[string]string, d map[string]string, ignoreKubernetesMetadataKeys []string) {
func removeKeys(m map[string]string, d map[string]interface{}, ignoreKubernetesMetadataKeys []string) {
for k := range m {
if ignoreKey(k, ignoreKubernetesMetadataKeys) && !isKeyInMap(k, d) {
delete(m, k)
}
}
}

func isKeyInMap(key string, d map[string]string) bool {
func isKeyInMap(key string, d map[string]interface{}) bool {
_, ok := d[key]
return ok
}
Expand Down
21 changes: 18 additions & 3 deletions website/docs/index.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -136,12 +136,27 @@ For further reading, see these examples which demonstrate different approaches t

## Ignore Kubernetes annotations and labels

In certain cases, external systems can add and modify resources annotations and labels for their own purposes. However, Terraform will remove them since they are not presented in the code. It also might be hard to update code accordingly to stay tuned with the changes that come outside. In order to address this `ignore_annotations` and `ignore_labels` attributes were introduced on the provider level. They allow Terraform to ignore certain annotations and labels across all resources. Please bear in mind, that all data sources remain unaffected and the provider always returns all labels and annotations, in spite of the `ignore_annotations` and `ignore_labels` settings. The same is applicable for the pod and job definitions that fall under templates.
In certain cases, external systems can add and modify resources annotations and labels for their own purposes. However, Terraform will remove them since they are not presented in the code. It also might be hard to update code accordingly to stay tuned with the changes that come outside. In order to address this `ignore_annotations` and `ignore_labels` attributes were introduced on the provider level. They allow Terraform to ignore certain annotations and labels across all resources.

Both attributes support RegExp to match metadata objects more effectively.

Please keep in mind that all data sources remain unaffected, and the provider always returns all labels and annotations, despite the `ignore_annotations` and `ignore_labels` settings. The same applies to the pod and job definitions that fall under templates. To ignore certain annotations and/or labels on the template level, please use the `ignore_changes` feature of the [lifecycle](https://developer.hashicorp.com/terraform/language/meta-arguments/lifecycle) meta-argument.

### Examples

The following example demonstrates how to ignore changes related to the `kubectl.kubernetes.io/restartedAt` annotation that were made in the upstream Kubernetes object:

```hcl
resource "kubernetes_deployment_v1" "this" {
// omit the resource config
lifecycle {
ignore_changes = [
spec[0].template[0].metadata[0].annotations["kubectl.kubernetes.io/restartedAt"],
]
}
}
```

The following example demonstrates how to ignore particular annotation keys:

```hcl
Expand Down Expand Up @@ -189,5 +204,5 @@ The following arguments are supported:
* `command` - (Required) Command to execute.
* `args` - (Optional) List of arguments to pass when executing the plugin.
* `env` - (Optional) Map of environment variables to set when executing the plugin.
* `ignore_annotations` - (Optional) List of Kubernetes metadata annotations to ignore across all resources handled by this provider for situations where external systems are managing certain resource annotations. Each item is a regular expression.
* `ignore_labels` - (Optional) List of Kubernetes metadata labels to ignore across all resources handled by this provider for situations where external systems are managing certain resource labels. Each item is a regular expression.
* `ignore_annotations` - (Optional) List of Kubernetes metadata annotations to ignore across all resources handled by this provider for situations where external systems are managing certain resource annotations. This option does not affect annotations within a template block. Each item is a regular expression.
* `ignore_labels` - (Optional) List of Kubernetes metadata labels to ignore across all resources handled by this provider for situations where external systems are managing certain resource labels. This option does not affect annotations within a template block. Each item is a regular expression.
Loading