|
|
@@ -0,0 +1,231 @@
|
|
|
+package v2
|
|
|
+
|
|
|
+import (
|
|
|
+ "fmt"
|
|
|
+
|
|
|
+ porterv1 "github.com/porter-dev/api-contracts/generated/go/porter/v1"
|
|
|
+)
|
|
|
+
|
|
|
+// Env is a list of env variable definitions
|
|
|
+type Env []EnvVariableDefinition
|
|
|
+
|
|
|
+// EnvVariableSource indicates how to set an env variable
|
|
|
+type EnvVariableSource string
|
|
|
+
|
|
|
+const (
|
|
|
+ // EnvVariableSource_Value indicates that the env variable should be set to an explicitly provided value
|
|
|
+ EnvVariableSource_Value EnvVariableSource = "value"
|
|
|
+ // EnvVariableSource_FromApp indicates that the env variable should be set to a value from another app
|
|
|
+ EnvVariableSource_FromApp EnvVariableSource = "app"
|
|
|
+)
|
|
|
+
|
|
|
+// EnvVariableDefinition is a struct containing information about how to set an env variable
|
|
|
+type EnvVariableDefinition struct {
|
|
|
+ Key string
|
|
|
+ Source EnvVariableSource
|
|
|
+ Value EnvValueOptional
|
|
|
+ FromApp EnvVariableFromAppOptional
|
|
|
+}
|
|
|
+
|
|
|
+// EnvValueOptional is a struct wrapping an optional string value to be set as an env variable
|
|
|
+type EnvValueOptional struct {
|
|
|
+ // Value is the actual value of the env variable
|
|
|
+ Value string
|
|
|
+
|
|
|
+ IsSet bool
|
|
|
+}
|
|
|
+
|
|
|
+// EnvValueFromApp indicates which value to pull from the app
|
|
|
+type EnvValueFromApp string
|
|
|
+
|
|
|
+const (
|
|
|
+ // EnvValueFromApp_InternalDomain indicates that the internal domain should be pulled from the app
|
|
|
+ EnvValueFromApp_InternalDomain EnvValueFromApp = "internal_domain"
|
|
|
+ // EnvValueFromApp_PublicDomain indicates that the first found public domain should be pulled from the app
|
|
|
+ EnvValueFromApp_PublicDomain EnvValueFromApp = "public_domain"
|
|
|
+)
|
|
|
+
|
|
|
+// EnvVariableFromApp is a struct containing information about how to set an env variable from another app
|
|
|
+type EnvVariableFromApp struct {
|
|
|
+ // AppName is the name of the app to pull the value from
|
|
|
+ AppName string
|
|
|
+ // Value indicates which value to pull from the app
|
|
|
+ Value EnvValueFromApp
|
|
|
+ // ServiceName is the name of the service to pull the value from, if applicable
|
|
|
+ ServiceName string
|
|
|
+}
|
|
|
+
|
|
|
+// EnvVariableFromAppOptional is an optional value indicating how to resolve an env variable from another app
|
|
|
+type EnvVariableFromAppOptional struct {
|
|
|
+ Value EnvVariableFromApp
|
|
|
+
|
|
|
+ IsSet bool
|
|
|
+}
|
|
|
+
|
|
|
+// UnmarshalYAML implements the yaml.Unmarshaler interface for Env in order to support both a list of env variables and a map of env variables
|
|
|
+func (e *Env) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|
|
+ var asList []EnvVariableDefinition
|
|
|
+ if err := unmarshal(&asList); err == nil {
|
|
|
+ *e = asList
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+
|
|
|
+ var asMap map[string]string
|
|
|
+ if err := unmarshal(&asMap); err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
+ for key, value := range asMap {
|
|
|
+ *e = append(*e, EnvVariableDefinition{
|
|
|
+ Key: key,
|
|
|
+ Source: EnvVariableSource_Value,
|
|
|
+ Value: EnvValueOptional{
|
|
|
+ Value: value,
|
|
|
+ IsSet: true,
|
|
|
+ },
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+// MarshalYAML implements the yaml.Marshaler interface for Env in order to convert from the internal representation to the yaml representation
|
|
|
+func (e Env) MarshalYAML() (interface{}, error) {
|
|
|
+ var rawList []rawEnvVarDef
|
|
|
+
|
|
|
+ for _, def := range e {
|
|
|
+ switch def.Source {
|
|
|
+ case EnvVariableSource_Value:
|
|
|
+ rawList = append(rawList, rawEnvVarDef{
|
|
|
+ Key: def.Key,
|
|
|
+ Value: def.Value.Value,
|
|
|
+ })
|
|
|
+ case EnvVariableSource_FromApp:
|
|
|
+ rawList = append(rawList, rawEnvVarDef{
|
|
|
+ Key: def.Key,
|
|
|
+ From: rawEnvVariableReference{
|
|
|
+ Source: EnvVariableSource_FromApp,
|
|
|
+ Name: def.FromApp.Value.AppName,
|
|
|
+ Value: string(def.FromApp.Value.Value),
|
|
|
+ ServiceName: def.FromApp.Value.ServiceName,
|
|
|
+ },
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return rawList, nil
|
|
|
+}
|
|
|
+
|
|
|
+// rawEnvVarDef is a struct used to unmarshal the yaml representation of an env variable
|
|
|
+// this represents the structure of an env variable in the yaml file
|
|
|
+type rawEnvVarDef struct {
|
|
|
+ Key string `yaml:"key"`
|
|
|
+ Value string `yaml:"value,omitempty"`
|
|
|
+ From rawEnvVariableReference `yaml:"from,omitempty"`
|
|
|
+}
|
|
|
+
|
|
|
+// rawEnvVariableReference is a struct used to unmarshal the yaml representation of an env variable reference
|
|
|
+type rawEnvVariableReference struct {
|
|
|
+ // source for the value. right now only "app" is supported
|
|
|
+ Source EnvVariableSource `yaml:"source,omitempty"`
|
|
|
+ // name of the app to get the value from
|
|
|
+ Name string `yaml:"name,omitempty"`
|
|
|
+ // value to pull from the app, right now only public_domain or internal_domain are supported
|
|
|
+ Value string `yaml:"value,omitempty"`
|
|
|
+ // name of the source to get the value from. only set if source is "app"
|
|
|
+ ServiceName string `yaml:"service,omitempty"`
|
|
|
+}
|
|
|
+
|
|
|
+// UnmarshalYAML implements the yaml.Unmarshaler interface for EnvVariableDefinition in order to support both a string value and a reference to another app
|
|
|
+func (def *EnvVariableDefinition) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|
|
+ var raw rawEnvVarDef
|
|
|
+ if err := unmarshal(&raw); err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
+ def.Key = raw.Key
|
|
|
+ if raw.Value != "" {
|
|
|
+ def.Source = EnvVariableSource_Value
|
|
|
+ def.Value = EnvValueOptional{
|
|
|
+ Value: raw.Value,
|
|
|
+ IsSet: true,
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if !def.Value.IsSet {
|
|
|
+ switch raw.From.Source {
|
|
|
+ case EnvVariableSource_FromApp:
|
|
|
+ def.Source = EnvVariableSource_FromApp
|
|
|
+
|
|
|
+ value, err := fromAppValue(raw.From.Value)
|
|
|
+ if err != nil {
|
|
|
+ return fmt.Errorf("unknown app value provided: %w", err)
|
|
|
+ }
|
|
|
+
|
|
|
+ def.FromApp = EnvVariableFromAppOptional{
|
|
|
+ Value: EnvVariableFromApp{
|
|
|
+ AppName: raw.From.Name,
|
|
|
+ Value: value,
|
|
|
+ ServiceName: raw.From.ServiceName,
|
|
|
+ },
|
|
|
+ IsSet: true,
|
|
|
+ }
|
|
|
+ default:
|
|
|
+ return fmt.Errorf("invalid source %s for env variable", raw.From.Source)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+// EnvVarFromAppToProto converts an env variable from app to the proto representation
|
|
|
+func EnvVarFromAppToProto(value EnvVariableFromApp) (*porterv1.EnvVariableFromApp, error) {
|
|
|
+ variable := &porterv1.EnvVariableFromApp{
|
|
|
+ AppName: value.AppName,
|
|
|
+ ServiceName: value.ServiceName,
|
|
|
+ }
|
|
|
+
|
|
|
+ switch value.Value {
|
|
|
+ case EnvValueFromApp_InternalDomain:
|
|
|
+ variable.Value = porterv1.EnvValueFromApp_ENV_VALUE_FROM_APP_INTERNAL_DOMAIN
|
|
|
+ case EnvValueFromApp_PublicDomain:
|
|
|
+ variable.Value = porterv1.EnvValueFromApp_ENV_VALUE_FROM_APP_PUBLIC_DOMAIN
|
|
|
+ default:
|
|
|
+ return nil, fmt.Errorf("invalid value %s for env variable from app", value.Value)
|
|
|
+ }
|
|
|
+
|
|
|
+ return variable, nil
|
|
|
+}
|
|
|
+
|
|
|
+// EnvVarFromAppFromProto converts a proto env variable from app to the internal representation
|
|
|
+func EnvVarFromAppFromProto(value *porterv1.EnvVariableFromApp) (EnvVariableFromAppOptional, error) {
|
|
|
+ variable := EnvVariableFromAppOptional{
|
|
|
+ Value: EnvVariableFromApp{
|
|
|
+ AppName: value.AppName,
|
|
|
+ ServiceName: value.ServiceName,
|
|
|
+ },
|
|
|
+ IsSet: true,
|
|
|
+ }
|
|
|
+
|
|
|
+ switch value.Value {
|
|
|
+ case porterv1.EnvValueFromApp_ENV_VALUE_FROM_APP_INTERNAL_DOMAIN:
|
|
|
+ variable.Value.Value = EnvValueFromApp_InternalDomain
|
|
|
+ case porterv1.EnvValueFromApp_ENV_VALUE_FROM_APP_PUBLIC_DOMAIN:
|
|
|
+ variable.Value.Value = EnvValueFromApp_PublicDomain
|
|
|
+ default:
|
|
|
+ return variable, fmt.Errorf("invalid value %s for env variable from app", value.Value)
|
|
|
+ }
|
|
|
+
|
|
|
+ return variable, nil
|
|
|
+}
|
|
|
+
|
|
|
+func fromAppValue(raw string) (EnvValueFromApp, error) {
|
|
|
+ switch raw {
|
|
|
+ case string(EnvValueFromApp_InternalDomain):
|
|
|
+ return EnvValueFromApp_InternalDomain, nil
|
|
|
+ case string(EnvValueFromApp_PublicDomain):
|
|
|
+ return EnvValueFromApp_PublicDomain, nil
|
|
|
+ default:
|
|
|
+ return "", fmt.Errorf("invalid value %s for env variable from app", raw)
|
|
|
+ }
|
|
|
+}
|