diff --git a/README.md b/README.md index 33cc43e..20a180c 100644 --- a/README.md +++ b/README.md @@ -93,3 +93,4 @@ services: - `katenary.io/to-service` binds the given (coma separated) variables names to {{ .Release.Name }}-value - `katenary.io/expose-ingress`: create an ingress and bind it to the service +- `katenary.io/as-secret`: force the creation of a secret for the given coma separated list of "env_file" diff --git a/generator/main.go b/generator/main.go index d0725e9..21e5440 100644 --- a/generator/main.go +++ b/generator/main.go @@ -42,23 +42,42 @@ func CreateReplicaObject(name string, s compose.Service) (ret []interface{}) { container := helm.NewContainer(name, s.Image, s.Environment, s.Labels) + secretsFiles := make([]string, 0) + + if v, ok := s.Labels[helm.K+"/as-secret"]; ok { + secretsFiles = strings.Split(v, ",") + } + for _, envfile := range s.EnvFiles { f := strings.ReplaceAll(envfile, "_", "-") f = strings.ReplaceAll(f, ".env", "") + f = strings.ReplaceAll(f, ".", "-") cf := f + "-" + name - Bluef("Generating configMap %s\n", cf) - configMap := helm.NewConfigMap(cf) - if err := configMap.AddEnvFile(envfile); err != nil { + isSecret := false + for _, s := range secretsFiles { + if s == envfile { + isSecret = true + } + } + var store helm.InlineConfig + if !isSecret { + Bluef("Generating configMap %s\n", cf) + store = helm.NewConfigMap(cf) + } else { + Bluef("Generating secret %s\n", cf) + store = helm.NewSecret(cf) + } + if err := store.AddEnvFile(envfile); err != nil { Red(err.Error()) os.Exit(2) } container.EnvFrom = append(container.EnvFrom, map[string]map[string]string{ "configMapRef": { - "name": configMap.Metadata.Name, + "name": store.Metadata().Name, }, }) - ret = append(ret, configMap) + ret = append(ret, store) Greenf("Done configMap %s\n", cf) } diff --git a/helm/configMap.go b/helm/configMap.go index 33481eb..4ae14fd 100644 --- a/helm/configMap.go +++ b/helm/configMap.go @@ -2,10 +2,17 @@ package helm import ( "errors" + "fmt" "io/ioutil" "strings" ) +// InlineConfig is made to represent a configMap or a secret +type InlineConfig interface { + AddEnvFile(filename string) error + Metadata() *Metadata +} + type ConfigMap struct { *K8sBase `yaml:",inline"` Data map[string]string `yaml:"data"` @@ -22,6 +29,10 @@ func NewConfigMap(name string) *ConfigMap { } } +func (c *ConfigMap) Metadata() *Metadata { + return c.K8sBase.Metadata +} + func (c *ConfigMap) AddEnvFile(file string) error { content, err := ioutil.ReadFile(file) if err != nil { @@ -44,3 +55,45 @@ func (c *ConfigMap) AddEnvFile(file string) error { return nil } + +type Secret struct { + *K8sBase `yaml:",inline"` + Data map[string]string `yaml:"data"` +} + +func NewSecret(name string) *Secret { + base := NewBase() + base.ApiVersion = "v1" + base.Kind = "Secret" + base.Metadata.Name = "{{ .Release.Name }}-" + name + return &Secret{ + K8sBase: base, + Data: make(map[string]string), + } +} + +func (s *Secret) AddEnvFile(file string) error { + content, err := ioutil.ReadFile(file) + if err != nil { + return err + } + + lines := strings.Split(string(content), "\n") + for _, l := range lines { + l = strings.TrimSpace(l) + if len(l) == 0 { + continue + } + parts := strings.SplitN(l, "=", 2) + if len(parts) < 2 { + return errors.New("The environment file " + file + " is not valid") + } + s.Data[parts[0]] = fmt.Sprintf(`{{ "%s" | b64enc }}`, parts[1]) + } + + return nil + +} +func (s *Secret) Metadata() *Metadata { + return s.K8sBase.Metadata +}