terraform-provider-kubernetes icon indicating copy to clipboard operation
terraform-provider-kubernetes copied to clipboard

--from-env-file Implementation to kubernetes_secret resource

Open albertorm95 opened this issue 5 years ago • 11 comments

Description

I want to be able to use kubectl functionality when creating a secret with flag --from-env-file what does this do is to iterate over the input file and line by line (Code) split the = from the line (Code) so you can have the key-value pair and use those values as the data map[string][]byte.

Potential Terraform Configuration

Code in resource_kubernetes_secret.go should be modify so now it can accept an env-file field.

Schema: map[string]*schema.Schema{
    "metadata": namespacedMetadataSchema("secret", true),
    "data": {
        Type:        schema.TypeMap,
        Description: "A map of the secret data.",
        Optional:    true,
        Sensitive:   true,
    },
    "type": {
        Type:        schema.TypeString,
        Description: "Type of secret",
        Default:     "Opaque",
        Optional:    true,
        ForceNew:    true,
    },
    "from_env_file": {
        Type:        schema.TypeMap,
        Description: "Path to a file to read lines of key=val pairs to create a secret.",
        Optional:    true,
        Sensitive:   true,
    }
}

So then we can use:

resource "kubernetes_secret" "foo-env" {
  metadata {
    name = "foo-env"
  }
  from_env_file = {
    "foo-env" = "${file("foo.env")}"
  }
}

References

I did study how kubectl does this solution and I might be able to apply that in Terraform, the process in kubectl is:

Input foo.env:

TEST=teststring
NODE_ENV=development
kubectl create secret generic foo-env --from-env-file=foo.env

Then -> create_secret.go Complete() -> secret.go StructuredGenerate() -> secret.go handleFromEnvFileSource() -> env_file.go addFromEnvFile() -> env_file.go proccessEnvFileLine() -> secret.go addKeyFromLiteralToSecret()

Output Kubernetes secret object created with flag --from-env-file:

apiVersion: v1
data:
  TEST: base64string
  NODE_ENV: base64string
kind: Secret
metadata:
  name: foo-env
  namespace: default
type: Opaque

Community Note

  • Please vote on this issue by adding a 👍 reaction to the original issue to help the community and maintainers prioritize this request
  • If you are interested in working on this issue or have submitted a pull request, please leave a comment

albertorm95 avatar Jun 17 '20 21:06 albertorm95

Thanks for opening this @albertorm95 this is an interesting issue, and I think there are a few paths forward here:

  1. It's possible to do this purely with Terraform's built-in functions, as the data field of secret is of type map:
resource "kubernetes_secret" "test" {
  metadata {
    name = "test"
  }

  data = {
    for line in compact(split("\n", file("vars.env"))):
      split("=",line)[0] => split("=",line)[1]
  }
}

This will work for now, but it's pretty ugly and will lead to copypasta if you use this a lot. This approach also has a few gotaches, i.e if the values in your dotenv contain = or spread across multiple lines.

  1. Like you suggested, we could add support for this in the provider by adding a from_env_file attribute that will parse the env file format for us. We're open to accepting a PR that implements this feature so we can do something like this:
from_env_file = file("vars.env")

We will have to add this to both ConfigMap and Secret.

  1. Adding envdecode() to Terraform's set of functions for encoding/decoding files. This would mean we could do something like this:
data = envdecode(file("path.env"))

This feels like the most reusable way to enable this sort of behaviour, but for this we would have to open a PR against Terraform's core repo.

jrhouston avatar Jun 29 '20 19:06 jrhouston

Ok, so let me then create an Issue in the core repo in order te add the envdecode() function to Terraform's set of functions for encoding/decoding files.

So once thats done I could use it to resolve this issue!

albertorm95 avatar Jun 29 '20 20:06 albertorm95

So once thats done I could use it to resolve this issue!

It takes a fair bit of time to get something into Terraform core (if they are willing to accept it) so I am happy to help add this to this provider in the mean time.

jrhouston avatar Jun 29 '20 22:06 jrhouston

Looks like there is already an open issue about this on the main Terraform repo, see here: https://github.com/hashicorp/terraform/issues/23906

jrhouston avatar Jun 30 '20 10:06 jrhouston

Any progress toward this? I've got the for loop in my terraform files but would be nice to simplify that!

cameronspeakflash avatar Oct 12 '20 02:10 cameronspeakflash

I would be interested in that feature as well.

hadim avatar Nov 23 '20 23:11 hadim

I have an open PR for this on the core repo, add your 👍 there if you want to see this feature.

jrhouston avatar Jul 27 '21 21:07 jrhouston

It occurred to me that we could solve this use case by creating a utility provider with a data source that can read the .env format. As there is some contention about adding a dotenvdecode function to terraform core I've created a dotenv utility provider here: https://registry.terraform.io/providers/jrhouston/dotenv/latest/docs that can be used to feed .env files into configmaps and secrets.

Here is an example:

terraform {
  required_providers {
    dotenv = {
      source  = "jrhouston/dotenv"
      version = "~> 1.0"
    }
  }
}

provider kubernetes {
  config_path = "~/.kube/config"
}

data dotenv dev_config {
  # NOTE there must be a file called `dev.env` in the same directory as the .tf config
  filename = "dev.env"
}

resource kubernetes_config_map cm {
  metadata {
    name = "example"
  }

  data = data.dotenv.dev_config.env
}

jrhouston avatar Nov 03 '21 22:11 jrhouston

Marking this issue as stale due to inactivity. If this issue receives no comments in the next 30 days it will automatically be closed. If this issue was automatically closed and you feel this issue should be reopened, we encourage creating a new issue linking back to this one for added context. This helps our maintainers find and focus on the active issues. Maintainers may also remove the stale label at their discretion. Thank you!

github-actions[bot] avatar Nov 04 '22 00:11 github-actions[bot]

Marking this issue as stale due to inactivity. If this issue receives no comments in the next 30 days it will automatically be closed. If this issue was automatically closed and you feel this issue should be reopened, we encourage creating a new issue linking back to this one for added context. This helps our maintainers find and focus on the active issues. Maintainers may also remove the stale label at their discretion. Thank you!

github-actions[bot] avatar Nov 24 '23 00:11 github-actions[bot]

I'm reopening this one as we could now add this to the provider as a Provider Defined Function.

We could add a envdecode function that replicates the functionality of the --from-env-file logic here: https://github.com/kubernetes/kubectl/blob/8d3b6cf1408476c8421eb5d4bf26b1d7badec47c/pkg/generate/versioned/env_file.go#L35-L70

jrhouston avatar Mar 29 '24 03:03 jrhouston