Skip to content

Commit

Permalink
Clean flatten metadata (#2413)
Browse files Browse the repository at this point in the history
  • Loading branch information
arybolovlev authored Feb 5, 2024
1 parent 50773e4 commit e08bb8e
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 11 deletions.
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.

0 comments on commit e08bb8e

Please sign in to comment.