diff --git a/cmd/config_fastly.go b/cmd/config_fastly.go index af496910..fcd3879d 100644 --- a/cmd/config_fastly.go +++ b/cmd/config_fastly.go @@ -40,6 +40,10 @@ func FastlyConfigGeneration(debug bool, domain string) (lagoon.Fastly, error) { if err != nil { return lagoon.Fastly{}, fmt.Errorf("error reading fastly-service-id flag: %v", err) } + organizationVariables, err := rootCmd.PersistentFlags().GetString("organization-variables") + if err != nil { + return lagoon.Fastly{}, fmt.Errorf("error reading organization-variables flag: %v", err) + } projectVariables, err := rootCmd.PersistentFlags().GetString("project-variables") if err != nil { return lagoon.Fastly{}, fmt.Errorf("error reading project-variables flag: %v", err) @@ -53,15 +57,18 @@ func FastlyConfigGeneration(debug bool, domain string) (lagoon.Fastly, error) { fastlyServiceID = helpers.GetEnv("ROUTE_FASTLY_SERVICE_ID", fastlyServiceID, debug) // get the project and environment variables + organizationVariables = helpers.GetEnv("LAGOON_ORGANIZATION_VARIABLES", organizationVariables, debug) projectVariables = helpers.GetEnv("LAGOON_PROJECT_VARIABLES", projectVariables, debug) environmentVariables = helpers.GetEnv("LAGOON_ENVIRONMENT_VARIABLES", environmentVariables, debug) // unmarshal and then merge the two so there is only 1 set of variables to iterate over + orgVars := []lagoon.EnvironmentVariable{} projectVars := []lagoon.EnvironmentVariable{} envVars := []lagoon.EnvironmentVariable{} + json.Unmarshal([]byte(organizationVariables), &orgVars) json.Unmarshal([]byte(projectVariables), &projectVars) json.Unmarshal([]byte(environmentVariables), &envVars) - lagoonEnvVars := lagoon.MergeVariables(projectVars, envVars) + lagoonEnvVars := lagoon.MergeVariables(orgVars, projectVars, envVars, []lagoon.EnvironmentVariable{}) // generate the fastly configuration from the provided flags/variables f := &lagoon.Fastly{} diff --git a/cmd/identify_feature_test.go b/cmd/identify_feature_test.go index 7868ffe0..4f727d5f 100644 --- a/cmd/identify_feature_test.go +++ b/cmd/identify_feature_test.go @@ -158,6 +158,26 @@ func TestIdentifyFeatureFlag(t *testing.T) { }, want: "enabled", }, + { + name: "test7 check if flag is defined in lagoon organization variables", + varName: "ROOTLESS_WORKLOAD", + args: testdata.GetSeedData( + testdata.TestData{ + ProjectName: "example-project", + EnvironmentName: "main", + Branch: "main", + LagoonYAML: "internal/testdata/node/lagoon.yml", + OrganizationVariables: []lagoon.EnvironmentVariable{ + { + Name: "LAGOON_FEATURE_FLAG_ROOTLESS_WORKLOAD", + Value: "enabled", + Scope: "build", + }, + }, + }, true), + templatePath: "testoutput", + want: "enabled", + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/cmd/root.go b/cmd/root.go index e88ae3cc..2f8f1096 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -124,6 +124,8 @@ func init() { "The pullrequest base branch") rootCmd.PersistentFlags().StringP("lagoon-version", "L", "", "The lagoon version") + rootCmd.PersistentFlags().StringP("organization-variables", "", "", + "The JSON payload for organization scope variables") rootCmd.PersistentFlags().StringP("project-variables", "", "", "The JSON payload for project scope variables") rootCmd.PersistentFlags().StringP("environment-variables", "", "", diff --git a/docs/buildrequirements.md b/docs/buildrequirements.md index 0b80a0bd..a2b99768 100644 --- a/docs/buildrequirements.md +++ b/docs/buildrequirements.md @@ -39,6 +39,7 @@ These are variables that are injected into a build pod by `remote-controller`, s * `PROMOTION_SOURCE_ENVIRONMENT` contains the source environment name if this is a promotion type build #### Environment Variables +* `LAGOON_ORGANIZATION_VARIABLES` contains any organization specific environment variables * `LAGOON_PROJECT_VARIABLES` contains any project specific environment variables * `LAGOON_ENVIRONMENT_VARIABLES` contains any environment specific environment variables diff --git a/internal/generator/generator.go b/internal/generator/generator.go index df8ed8b0..89b0d04b 100644 --- a/internal/generator/generator.go +++ b/internal/generator/generator.go @@ -33,6 +33,7 @@ type GeneratorInput struct { EnvironmentType string ActiveEnvironment string StandbyEnvironment string + OrganizationVariables string ProjectVariables string EnvironmentVariables string BuildType string @@ -139,6 +140,7 @@ func NewGenerator( buildValues.Backup.K8upVersion = helpers.GetEnv("K8UP_VERSION", generator.BackupConfiguration.K8upVersion, generator.Debug) // get the project and environment variables + organizationVariables := helpers.GetEnv("LAGOON_ORGANIZATION_VARIABLES", generator.OrganizationVariables, generator.Debug) projectVariables := helpers.GetEnv("LAGOON_PROJECT_VARIABLES", generator.ProjectVariables, generator.Debug) environmentVariables := helpers.GetEnv("LAGOON_ENVIRONMENT_VARIABLES", generator.EnvironmentVariables, generator.Debug) @@ -245,16 +247,15 @@ func NewGenerator( } // unmarshal and then merge the two so there is only 1 set of variables to iterate over + orgVars := []lagoon.EnvironmentVariable{} projectVars := []lagoon.EnvironmentVariable{} envVars := []lagoon.EnvironmentVariable{} + json.Unmarshal([]byte(organizationVariables), &orgVars) json.Unmarshal([]byte(projectVariables), &projectVars) json.Unmarshal([]byte(environmentVariables), &envVars) - mergedVariables := lagoon.MergeVariables(projectVars, envVars) // collect a bunch of the default LAGOON_X based build variables that are injected into `lagoon-env` and make them available configVars := collectBuildVariables(buildValues) - // add the calculated build runtime variables into the existing variable slice - // this will later be used to add `runtime|global` scope into the `lagoon-env` configmap - buildValues.EnvironmentVariables = lagoon.MergeVariables(mergedVariables, configVars) + buildValues.EnvironmentVariables = lagoon.MergeVariables(orgVars, projectVars, envVars, configVars) // if the core version is provided from the API, set the buildvalues LagoonVersion to this instead lagoonCoreVersion, _ := lagoon.GetLagoonVariable("LAGOON_SYSTEM_CORE_VERSION", []string{"internal_system"}, buildValues.EnvironmentVariables) diff --git a/internal/helpers/helpers.go b/internal/helpers/helpers.go index 8a01db88..38f5b1c7 100644 --- a/internal/helpers/helpers.go +++ b/internal/helpers/helpers.go @@ -218,6 +218,7 @@ func UnsetEnvVars(localVars []EnvironmentVariable) { "ACTIVE_ENVIRONMENT", "STANDBY_ENVIRONMENT", "LAGOON_FASTLY_NOCACHE_SERVICE_ID", + "LAGOON_ORGANIZATION_VARIABLES", "LAGOON_PROJECT_VARIABLES", "LAGOON_ENVIRONMENT_VARIABLES", "LAGOON_VERSION", diff --git a/internal/lagoon/variables.go b/internal/lagoon/variables.go index b3c642fa..ac070634 100644 --- a/internal/lagoon/variables.go +++ b/internal/lagoon/variables.go @@ -2,6 +2,7 @@ package lagoon import ( "fmt" + "slices" "github.com/uselagoon/build-deploy-tool/internal/helpers" ) @@ -14,44 +15,51 @@ type EnvironmentVariable struct { } // MergeVariables merges lagoon environment variables. -func MergeVariables(project, environment []EnvironmentVariable) []EnvironmentVariable { - allVars := []EnvironmentVariable{} - existsInEnvironment := false - // replace any variables from the project with ones from the environment - // this only modifies ones that exist in project - for _, pVar := range project { - add := EnvironmentVariable{} - for _, eVar := range environment { - // internal_system scoped variables are only added to the projects variabled during a build - // this make sure that any that may exist in the environment variables are not merged - // and also makes sure that internal_system variables are not replaced by other scopes - if eVar.Name == pVar.Name && pVar.Scope != "internal_system" && eVar.Scope != "internal_system" { - existsInEnvironment = true - add = eVar - } +func MergeVariables(organization, project, environment, config []EnvironmentVariable) []EnvironmentVariable { + + // Helper function to compare environment variable names. + findByName := func(name string) func(EnvironmentVariable) bool { + return func(eVar EnvironmentVariable) bool { return eVar.Name == name } + } + + // Start with config variables since they are most specific. + allVars := make([]EnvironmentVariable, len(config)) + copy(allVars, config) + + for _, eVar := range environment { + idx := slices.IndexFunc(allVars, findByName(eVar.Name)) + + // Append environment variables that are distinct. + if idx == -1 { + allVars = append(allVars, eVar) } - if existsInEnvironment { - allVars = append(allVars, add) - existsInEnvironment = false - } else { + } + + for _, pVar := range project { + idx := slices.IndexFunc(allVars, findByName(pVar.Name)) + + // Append project variables that are distinct. + if idx == -1 { allVars = append(allVars, pVar) + continue } - } - // add any that exist in the environment only to the final variables list - existsInProject := false - for _, eVar := range environment { - add := eVar - for _, aVar := range allVars { - if eVar.Name == aVar.Name { - existsInProject = true - } + + // Overwrite environment variables if they are suppossed to be internally + // scoped. + if pVar.Scope == "internal_system" { + allVars[idx] = pVar } - if existsInProject { - existsInProject = false - } else { - allVars = append(allVars, add) + } + + for _, oVar := range organization { + idx := slices.IndexFunc(allVars, findByName(oVar.Name)) + + // Append organization variables that are distinct. + if idx == -1 { + allVars = append(allVars, oVar) } } + return allVars } diff --git a/internal/lagoon/variables_test.go b/internal/lagoon/variables_test.go index 339ea24e..9bc98cb7 100644 --- a/internal/lagoon/variables_test.go +++ b/internal/lagoon/variables_test.go @@ -7,8 +7,10 @@ import ( func TestMergeVariables(t *testing.T) { type args struct { - project []EnvironmentVariable - environment []EnvironmentVariable + organization []EnvironmentVariable + project []EnvironmentVariable + environment []EnvironmentVariable + config []EnvironmentVariable } tests := []struct { name string @@ -18,6 +20,7 @@ func TestMergeVariables(t *testing.T) { { name: "test1", args: args{ + organization: []EnvironmentVariable{}, project: []EnvironmentVariable{ { Name: "PROJECT_SPECIFIC_VARIABLE", @@ -37,16 +40,17 @@ func TestMergeVariables(t *testing.T) { Scope: "global", }, }, + config: []EnvironmentVariable{}, }, want: []EnvironmentVariable{ { - Name: "PROJECT_SPECIFIC_VARIABLE", - Value: "projectvariable", + Name: "LAGOON_FASTLY_SERVICE_ID", + Value: "1234567", Scope: "global", }, { - Name: "LAGOON_FASTLY_SERVICE_ID", - Value: "1234567", + Name: "PROJECT_SPECIFIC_VARIABLE", + Value: "projectvariable", Scope: "global", }, }, @@ -54,6 +58,7 @@ func TestMergeVariables(t *testing.T) { { name: "test2", args: args{ + organization: []EnvironmentVariable{}, project: []EnvironmentVariable{ { Name: "PROJECT_SPECIFIC_VARIABLE", @@ -68,24 +73,26 @@ func TestMergeVariables(t *testing.T) { Scope: "build", }, }, + config: []EnvironmentVariable{}, }, want: []EnvironmentVariable{ - { - Name: "PROJECT_SPECIFIC_VARIABLE", - Value: "projectvariable", - Scope: "global", - }, { Name: "LAGOON_ROUTES_JSON", Value: "eyJyb3V0ZXMiOlt7ImRvbWFpbiI6InRlc3QxLmV4YW1wbGUuY29tIiwic2VydmljZSI6Im5naW54IiwidGxzLWFjbWUiOmZhbHNlLCJtb25pdG9yaW5nLXBhdGgiOiIvYnlwYXNzLWNhY2hlIn1dfQo=", Scope: "build", }, + { + Name: "PROJECT_SPECIFIC_VARIABLE", + Value: "projectvariable", + Scope: "global", + }, }, }, { name: "test3", args: args{ - project: []EnvironmentVariable{}, + organization: []EnvironmentVariable{}, + project: []EnvironmentVariable{}, environment: []EnvironmentVariable{ { Name: "LAGOON_ROUTES_JSON", @@ -93,6 +100,7 @@ func TestMergeVariables(t *testing.T) { Scope: "build", }, }, + config: []EnvironmentVariable{}, }, want: []EnvironmentVariable{ { @@ -123,13 +131,8 @@ func TestMergeVariables(t *testing.T) { Value: "123", Scope: "build", }, - { - // this will be ignored - Name: "LAGOON_ROUTE_QUOTA", - Value: "321", - Scope: "internal_system", - }, }, + config: []EnvironmentVariable{}, }, want: []EnvironmentVariable{ { @@ -137,17 +140,200 @@ func TestMergeVariables(t *testing.T) { Value: "1234", Scope: "internal_system", }, + }, + }, + { + name: "test5", + args: args{ + organization: []EnvironmentVariable{}, + project: []EnvironmentVariable{{ + Name: "LAGOON_ROUTES_JSON", + Value: "eyJyb3V0ZXMiOlt7ImRvbWFpbiI6InRlc3QxLmV4YW1wbGUuY29tIiwic2VydmljZSI6Im5naW54IiwidGxzLWFjbWUiOmZhbHNlLCJtb25pdG9yaW5nLXBhdGgiOiIvYnlwYXNzLWNhY2hlIn1dfQo=", + Scope: "build", + }}, + environment: []EnvironmentVariable{}, + config: []EnvironmentVariable{}, + }, + want: []EnvironmentVariable{ { - Name: "LAGOON_ROUTE_QUOTA", - Value: "123", + Name: "LAGOON_ROUTES_JSON", + Value: "eyJyb3V0ZXMiOlt7ImRvbWFpbiI6InRlc3QxLmV4YW1wbGUuY29tIiwic2VydmljZSI6Im5naW54IiwidGxzLWFjbWUiOmZhbHNlLCJtb25pdG9yaW5nLXBhdGgiOiIvYnlwYXNzLWNhY2hlIn1dfQo=", + Scope: "build", + }, + }, + }, + { + name: "test6", + args: args{ + organization: []EnvironmentVariable{{ + Name: "LAGOON_ROUTES_JSON", + Value: "eyJyb3V0ZXMiOlt7ImRvbWFpbiI6InRlc3QxLmV4YW1wbGUuY29tIiwic2VydmljZSI6Im5naW54IiwidGxzLWFjbWUiOmZhbHNlLCJtb25pdG9yaW5nLXBhdGgiOiIvYnlwYXNzLWNhY2hlIn1dfQo=", + Scope: "build", + }}, + project: []EnvironmentVariable{}, + environment: []EnvironmentVariable{}, + config: []EnvironmentVariable{}, + }, + want: []EnvironmentVariable{ + { + Name: "LAGOON_ROUTES_JSON", + Value: "eyJyb3V0ZXMiOlt7ImRvbWFpbiI6InRlc3QxLmV4YW1wbGUuY29tIiwic2VydmljZSI6Im5naW54IiwidGxzLWFjbWUiOmZhbHNlLCJtb25pdG9yaW5nLXBhdGgiOiIvYnlwYXNzLWNhY2hlIn1dfQo=", + Scope: "build", + }, + }, + }, + { + name: "test7", + args: args{ + organization: []EnvironmentVariable{}, + project: []EnvironmentVariable{}, + environment: []EnvironmentVariable{}, + config: []EnvironmentVariable{{ + Name: "LAGOON_ROUTES_JSON", + Value: "eyJyb3V0ZXMiOlt7ImRvbWFpbiI6InRlc3QxLmV4YW1wbGUuY29tIiwic2VydmljZSI6Im5naW54IiwidGxzLWFjbWUiOmZhbHNlLCJtb25pdG9yaW5nLXBhdGgiOiIvYnlwYXNzLWNhY2hlIn1dfQo=", Scope: "build", + }}, + }, + want: []EnvironmentVariable{ + { + Name: "LAGOON_ROUTES_JSON", + Value: "eyJyb3V0ZXMiOlt7ImRvbWFpbiI6InRlc3QxLmV4YW1wbGUuY29tIiwic2VydmljZSI6Im5naW54IiwidGxzLWFjbWUiOmZhbHNlLCJtb25pdG9yaW5nLXBhdGgiOiIvYnlwYXNzLWNhY2hlIn1dfQo=", + Scope: "build", + }, + }, + }, + { + name: "test8", + args: args{ + organization: []EnvironmentVariable{{ + Name: "ORG_KEEP", + Value: "ORG_KEEP", + Scope: "global", + }, { + Name: "OVERRIDE_1", + Value: "org", + Scope: "global", + }, { + Name: "OVERRIDE_2", + Value: "org", + Scope: "global", + }, { + Name: "OVERRIDE_3", + Value: "org", + Scope: "global", + }}, + project: []EnvironmentVariable{{ + Name: "PROJ_KEEP", + Value: "PROJ_KEEP", + Scope: "global", + }, { + Name: "OVERRIDE_1", + Value: "proj", + Scope: "global", + }, { + Name: "OVERRIDE_2", + Value: "proj", + Scope: "global", + }, { + Name: "OVERRIDE_3", + Value: "proj", + Scope: "global", + }, { + Name: "OVERRIDE_4", + Value: "proj", + Scope: "global", + }}, + environment: []EnvironmentVariable{{ + Name: "ENV_KEEP", + Value: "ENV_KEEP", + Scope: "global", + }, { + Name: "OVERRIDE_1", + Value: "env", + Scope: "global", + }, { + Name: "OVERRIDE_2", + Value: "env", + Scope: "global", + }, { + Name: "OVERRIDE_4", + Value: "env", + Scope: "global", + }, { + Name: "OVERRIDE_5", + Value: "env", + Scope: "global", + }}, + config: []EnvironmentVariable{{ + Name: "CONFIG_KEEP", + Value: "CONFIG_KEEP", + Scope: "global", + }, { + Name: "OVERRIDE_1", + Value: "config", + Scope: "global", + }, { + Name: "OVERRIDE_4", + Value: "config", + Scope: "global", + }, { + Name: "OVERRIDE_5", + Value: "config", + Scope: "global", + }}, + }, + want: []EnvironmentVariable{ + { + Name: "CONFIG_KEEP", + Value: "CONFIG_KEEP", + Scope: "global", + }, + { + Name: "OVERRIDE_1", + Value: "config", + Scope: "global", + }, + { + Name: "OVERRIDE_4", + Value: "config", + Scope: "global", + }, + { + Name: "OVERRIDE_5", + Value: "config", + Scope: "global", + }, + { + Name: "ENV_KEEP", + Value: "ENV_KEEP", + Scope: "global", + }, + { + Name: "OVERRIDE_2", + Value: "env", + Scope: "global", + }, + { + Name: "PROJ_KEEP", + Value: "PROJ_KEEP", + Scope: "global", + }, + { + Name: "OVERRIDE_3", + Value: "proj", + Scope: "global", + }, + { + Name: "ORG_KEEP", + Value: "ORG_KEEP", + Scope: "global", }, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := MergeVariables(tt.args.project, tt.args.environment); !reflect.DeepEqual(got, tt.want) { + if got := MergeVariables(tt.args.organization, tt.args.project, tt.args.environment, tt.args.config); !reflect.DeepEqual(got, tt.want) { t.Errorf("MergeVariables() = %v, want %v", got, tt.want) } }) diff --git a/internal/testdata/testdata.go b/internal/testdata/testdata.go index 06cbd2f7..62a6e8ae 100644 --- a/internal/testdata/testdata.go +++ b/internal/testdata/testdata.go @@ -41,6 +41,7 @@ type TestData struct { IngressClass string ProjectVars string EnvVars string + OrganizationVariables []lagoon.EnvironmentVariable ProjectVariables []lagoon.EnvironmentVariable EnvVariables []lagoon.EnvironmentVariable LagoonVersion string @@ -121,6 +122,11 @@ func SetupEnvironment(rootCmd cobra.Command, templatePath string, t TestData) (g if err != nil { return generator.GeneratorInput{}, err } + ov, _ := json.Marshal(t.OrganizationVariables) + err = os.Setenv("LAGOON_ORGANIZATION_VARIABLES", string(ov)) + if err != nil { + return generator.GeneratorInput{}, err + } pv, _ := json.Marshal(t.ProjectVariables) err = os.Setenv("LAGOON_PROJECT_VARIABLES", string(pv)) if err != nil { @@ -297,6 +303,9 @@ func GetSeedData(t TestData, defaultProjectVariables bool) TestData { if t.LagoonYAML != "" { rt.LagoonYAML = t.LagoonYAML } + if t.OrganizationVariables != nil { + rt.OrganizationVariables = append(rt.OrganizationVariables, t.OrganizationVariables...) + } if t.ProjectVariables != nil && defaultProjectVariables { rt.ProjectVariables = append(rt.ProjectVariables, t.ProjectVariables...) } else if !defaultProjectVariables { diff --git a/legacy/build-deploy-docker-compose.sh b/legacy/build-deploy-docker-compose.sh index 9a3f510b..cb39f478 100755 --- a/legacy/build-deploy-docker-compose.sh +++ b/legacy/build-deploy-docker-compose.sh @@ -47,7 +47,11 @@ function contains() { # Lagoon project global scoped env-vars. This allows policy control at the # project level. # -# 4. The cluster-default feature flag, prefixed with +# 4. The regular feature flag, prefixed with LAGOON_FEATURE_FLAG_, in the Lagoon +# organization global scoped env-vars. This allows policy control at the +# organization level. +# +# 5. The cluster-default feature flag, prefixed with # LAGOON_FEATURE_FLAG_DEFAULT_, as a build pod environment variable. This is # set via a flag on the build-deploy controller. This allows default policy # to be set at the cluster level, but maintains the ability to selectively @@ -72,27 +76,34 @@ function featureFlag() { # check Lagoon project variables flagValue=$(jq -r '.[] | select(.scope == "global" and .name == "'"$flagVar"'") | .value' <<<"$LAGOON_PROJECT_VARIABLES") [ "$flagValue" ] && echo "$flagValue" && return + # check Lagoon organization variables + flagValue=$(jq -r '.[] | select(.scope == "global" and .name == "'"$flagVar"'") | .value' <<<"$LAGOON_ORGANIZATION_VARIABLES") + [ "$flagValue" ] && echo "$flagValue" && return # fall back to the default, if set. defaultFlagVar="LAGOON_FEATURE_FLAG_DEFAULT_$1" echo "${!defaultFlagVar}" } -function projectEnvironmentVariableCheck() { - # check for argument - [ "$1" ] || return - - local flagVar - - flagVar="$1" - # check Lagoon environment variables - flagValue=$(jq -r '.[] | select(.name == "'"$flagVar"'") | .value' <<<"$LAGOON_ENVIRONMENT_VARIABLES") - [ "$flagValue" ] && echo "$flagValue" && return - # check Lagoon project variables - flagValue=$(jq -r '.[] | select(.name == "'"$flagVar"'") | .value' <<<"$LAGOON_PROJECT_VARIABLES") - [ "$flagValue" ] && echo "$flagValue" && return - - echo "$2" +# Checks for an environment variable from Lagoon API +function apiEnvironmentVariableCheck() { + # check for argument + [ "$1" ] || return + + local flagVar + + flagVar="$1" + # check Lagoon environment variables + flagValue=$(jq -r '.[] | select(.name == "'"$flagVar"'") | .value' <<<"$LAGOON_ENVIRONMENT_VARIABLES") + [ "$flagValue" ] && echo "$flagValue" && return + # check Lagoon project variables + flagValue=$(jq -r '.[] | select(.name == "'"$flagVar"'") | .value' <<<"$LAGOON_PROJECT_VARIABLES") + [ "$flagValue" ] && echo "$flagValue" && return + # check Lagoon organization variables + flagValue=$(jq -r '.[] | select(.name == "'"$flagVar"'") | .value' <<<"$LAGOON_ORGANIZATION_VARIABLES") + [ "$flagValue" ] && echo "$flagValue" && return + + echo "$2" } SCC_CHECK=$(kubectl -n ${NAMESPACE} get pod ${LAGOON_BUILD_NAME} -o json | jq -r '.metadata.annotations."openshift.io/scc" // false') @@ -422,28 +433,9 @@ declare -A IMAGE_HASHES # separated by commas # Example 1: mariadb:mariadb-dbaas < tells any docker-compose services named mariadb to use the mariadb-dbaas service type # Example 2: mariadb:mariadb-dbaas,nginx:nginx-persistent -if [ ! -z "$LAGOON_PROJECT_VARIABLES" ]; then - LAGOON_SERVICE_TYPES=($(echo $LAGOON_PROJECT_VARIABLES | jq -r '.[] | select(.name == "LAGOON_SERVICE_TYPES") | "\(.value)"')) -fi -if [ ! -z "$LAGOON_ENVIRONMENT_VARIABLES" ]; then - TEMP_LAGOON_SERVICE_TYPES=($(echo $LAGOON_ENVIRONMENT_VARIABLES | jq -r '.[] | select(.name == "LAGOON_SERVICE_TYPES") | "\(.value)"')) - if [ ! -z $TEMP_LAGOON_SERVICE_TYPES ]; then - LAGOON_SERVICE_TYPES=$TEMP_LAGOON_SERVICE_TYPES - fi -fi -# Allow the dbaas environment type to be overridden by the lagoon API -# This accepts colon separated values like so `SERVICE_NAME:DBAAS_ENVIRONMENT_TYPE`, and multiple overrides -# separated by commas -# Example 1: mariadb:production < tells any docker-compose services named mariadb to use the production dbaas environment type -# Example 2: mariadb:production,mariadb-test:development -if [ ! -z "$LAGOON_PROJECT_VARIABLES" ]; then - LAGOON_DBAAS_ENVIRONMENT_TYPES=($(echo $LAGOON_PROJECT_VARIABLES | jq -r '.[] | select(.name == "LAGOON_DBAAS_ENVIRONMENT_TYPES") | "\(.value)"')) -fi -if [ ! -z "$LAGOON_ENVIRONMENT_VARIABLES" ]; then - TEMP_LAGOON_DBAAS_ENVIRONMENT_TYPES=($(echo $LAGOON_ENVIRONMENT_VARIABLES | jq -r '.[] | select(.name == "LAGOON_DBAAS_ENVIRONMENT_TYPES") | "\(.value)"')) - if [ ! -z $TEMP_LAGOON_DBAAS_ENVIRONMENT_TYPES ]; then - LAGOON_DBAAS_ENVIRONMENT_TYPES=$TEMP_LAGOON_DBAAS_ENVIRONMENT_TYPES - fi +TEMP_LAGOON_SERVICE_TYPES=$(apiEnvironmentVariableCheck LAGOON_SERVICE_TYPES) +if [ ! -z "$TEMP_LAGOON_SERVICE_TYPES" ]; then + LAGOON_SERVICE_TYPES=$TEMP_LAGOON_SERVICE_TYPES fi # loop through created DBAAS templates @@ -555,20 +547,8 @@ do done # Get the pre-rollout and post-rollout vars -if [ ! -z "$LAGOON_PROJECT_VARIABLES" ]; then - LAGOON_PREROLLOUT_DISABLED=($(echo $LAGOON_PROJECT_VARIABLES | jq -r '.[] | select(.name == "LAGOON_PREROLLOUT_DISABLED") | "\(.value)"')) - LAGOON_POSTROLLOUT_DISABLED=($(echo $LAGOON_PROJECT_VARIABLES | jq -r '.[] | select(.name == "LAGOON_POSTROLLOUT_DISABLED") | "\(.value)"')) -fi -if [ ! -z "$LAGOON_ENVIRONMENT_VARIABLES" ]; then - TEMP_LAGOON_PREROLLOUT_DISABLED=($(echo $LAGOON_ENVIRONMENT_VARIABLES | jq -r '.[] | select(.name == "LAGOON_PREROLLOUT_DISABLED") | "\(.value)"')) - TEMP_LAGOON_POSTROLLOUT_DISABLED=($(echo $LAGOON_ENVIRONMENT_VARIABLES | jq -r '.[] | select(.name == "LAGOON_POSTROLLOUT_DISABLED") | "\(.value)"')) - if [ ! -z $TEMP_LAGOON_PREROLLOUT_DISABLED ]; then - LAGOON_PREROLLOUT_DISABLED=$TEMP_LAGOON_PREROLLOUT_DISABLED - fi - if [ ! -z $TEMP_LAGOON_POSTROLLOUT_DISABLED ]; then - LAGOON_POSTROLLOUT_DISABLED=$TEMP_LAGOON_POSTROLLOUT_DISABLED - fi -fi +LAGOON_PREROLLOUT_DISABLED=$(apiEnvironmentVariableCheck LAGOON_PREROLLOUT_DISABLED "false") +LAGOON_POSTROLLOUT_DISABLED=$(apiEnvironmentVariableCheck LAGOON_POSTROLLOUT_DISABLED "false") currentStepEnd="$(date +"%Y-%m-%d %H:%M:%S")" patchBuildStep "${buildStartTime}" "${buildStartTime}" "${currentStepEnd}" "${NAMESPACE}" "configureVars" "Configure Variables" "false" @@ -800,43 +780,12 @@ patchBuildStep "${buildStartTime}" "${previousStepEnd}" "${currentStepEnd}" "${N previousStepEnd=${currentStepEnd} beginBuildStep "Service Configuration Phase 2" "serviceConfigurationPhase2" -# FASTLY SERVICE ID PER INGRESS OVERRIDE FROM LAGOON API VARIABLE -# Allow the fastly serviceid for specific ingress to be overridden by the lagoon API -# This accepts colon separated values like so `INGRESS_DOMAIN:FASTLY_SERVICE_ID:WATCH_STATUS:SECRET_NAME(OPTIONAL)`, and multiple overrides -# separated by commas -# Example 1: www.example.com:x1s8asfafasf7ssf:true -# ^^^ tells the ingress creation to use the service id x1s8asfafasf7ssf for ingress www.example.com, with the watch status of true -# Example 2: www.example.com:x1s8asfafasf7ssf:true,www.not-example.com:fa23rsdgsdgas:false -# ^^^ same as above, but also tells the ingress creation to use the service id fa23rsdgsdgas for ingress www.not-example.com, with the watch status of false -# Example 3: www.example.com:x1s8asfafasf7ssf:true:examplecom -# ^^^ tells the ingress creation to use the service id x1s8asfafasf7ssf for ingress www.example.com, with the watch status of true -# but it will also be annotated to be told to use the secret named `examplecom` that could be defined elsewhere -if [ ! -z "$LAGOON_PROJECT_VARIABLES" ]; then - LAGOON_FASTLY_SERVICE_IDS=($(echo $LAGOON_PROJECT_VARIABLES | jq -r '.[] | select(.name == "LAGOON_FASTLY_SERVICE_IDS") | "\(.value)"')) -fi -if [ ! -z "$LAGOON_ENVIRONMENT_VARIABLES" ]; then - TEMP_LAGOON_FASTLY_SERVICE_IDS=($(echo $LAGOON_ENVIRONMENT_VARIABLES | jq -r '.[] | select(.name == "LAGOON_FASTLY_SERVICE_IDS") | "\(.value)"')) - if [ ! -z $TEMP_LAGOON_FASTLY_SERVICE_IDS ]; then - LAGOON_FASTLY_SERVICE_IDS=$TEMP_LAGOON_FASTLY_SERVICE_IDS - fi -fi - ############################################## ### CREATE SERVICES, AUTOGENERATED ROUTES AND DBAAS CONFIG ############################################## -# start custom routes disabled -AUTOGEN_ROUTES_DISABLED=false -if [ ! -z "$LAGOON_PROJECT_VARIABLES" ]; then - AUTOGEN_ROUTES_DISABLED=($(echo $LAGOON_PROJECT_VARIABLES | jq -r '.[] | select(.scope == "build") | select(.name == "LAGOON_AUTOGEN_ROUTES_DISABLED") | "\(.value)"')) -fi -if [ ! -z "$LAGOON_ENVIRONMENT_VARIABLES" ]; then - TEMP_AUTOGEN_ROUTES_DISABLED=($(echo $LAGOON_ENVIRONMENT_VARIABLES | jq -r '.[] | select(.scope == "build") | select(.name == "LAGOON_AUTOGEN_ROUTES_DISABLED") | "\(.value)"')) - if [ ! -z $TEMP_AUTOGEN_ROUTES_DISABLED ]; then - AUTOGEN_ROUTES_DISABLED=$TEMP_AUTOGEN_ROUTES_DISABLED - fi -fi # generate the autogenerated ingress +AUTOGEN_ROUTES_DISABLED=$(apiEnvironmentVariableCheck LAGOON_AUTOGEN_ROUTES_DISABLED false) if [ ! "$AUTOGEN_ROUTES_DISABLED" == true ]; then LAGOON_AUTOGEN_YAML_FOLDER="/kubectl-build-deploy/lagoon/autogen-routes" mkdir -p $LAGOON_AUTOGEN_YAML_FOLDER @@ -913,20 +862,7 @@ TEMPLATE_PARAMETERS=() ### CUSTOM ROUTES ############################################## -# Run the route generation process - -# start custom routes disabled -CUSTOM_ROUTES_DISABLED=false -if [ ! -z "$LAGOON_PROJECT_VARIABLES" ]; then - CUSTOM_ROUTES_DISABLED=($(echo $LAGOON_PROJECT_VARIABLES | jq -r '.[] | select(.scope == "build") | select(.name == "LAGOON_CUSTOM_ROUTES_DISABLED") | "\(.value)"')) -fi -if [ ! -z "$LAGOON_ENVIRONMENT_VARIABLES" ]; then - TEMP_CUSTOM_ROUTES_DISABLED=($(echo $LAGOON_ENVIRONMENT_VARIABLES | jq -r '.[] | select(.scope == "build") | select(.name == "LAGOON_CUSTOM_ROUTES_DISABLED") | "\(.value)"')) - if [ ! -z $TEMP_CUSTOM_ROUTES_DISABLED ]; then - CUSTOM_ROUTES_DISABLED=$TEMP_CUSTOM_ROUTES_DISABLED - fi -fi - +CUSTOM_ROUTES_DISABLED=$(apiEnvironmentVariableCheck LAGOON_CUSTOM_ROUTES_DISABLED false) if [ ! "$CUSTOM_ROUTES_DISABLED" == true ]; then LAGOON_ROUTES_YAML_FOLDER="/kubectl-build-deploy/lagoon/routes" mkdir -p $LAGOON_ROUTES_YAML_FOLDER @@ -1143,6 +1079,16 @@ LAGOON_AUTOGENERATED_ROUTES=${AUTOGENERATED_ROUTES}\n\ kubectl -n ${NAMESPACE} create configmap lagoon-env -o yaml --dry-run=client --from-env-file=/kubectl-build-deploy/values.env | kubectl apply -n ${NAMESPACE} -f - # Add environment variables from lagoon API +if [ ! -z "$LAGOON_ORGANIZATION_VARIABLES" ]; then + HAS_ORGANIZATION_RUNTIME_VARS=$(echo $LAGOON_ORGANIZATION_VARIABLES | jq -r 'map( select(.scope == "runtime" or .scope == "global") )') + + if [ ! "$HAS_ORGANIZATION_RUNTIME_VARS" = "[]" ]; then + kubectl patch \ + -n ${NAMESPACE} \ + configmap lagoon-env \ + -p "{\"data\":$(echo $LAGOON_ORGANIZATION_VARIABLES | jq -r 'map( select(.scope == "runtime" or .scope == "global") ) | map( { (.name) : .value } ) | add | tostring')}" + fi +fi if [ ! -z "$LAGOON_PROJECT_VARIABLES" ]; then HAS_PROJECT_RUNTIME_VARS=$(echo $LAGOON_PROJECT_VARIABLES | jq -r 'map( select(.scope == "runtime" or .scope == "global") )') @@ -1351,17 +1297,7 @@ beginBuildStep "Backup Configuration" "configuringBackups" # Run the backup generation script -BACKUPS_DISABLED=false -if [ ! -z "$LAGOON_PROJECT_VARIABLES" ]; then - BACKUPS_DISABLED=($(echo $LAGOON_PROJECT_VARIABLES | jq -r '.[] | select(.scope == "build") | select(.name == "LAGOON_BACKUPS_DISABLED") | "\(.value)"')) -fi -if [ ! -z "$LAGOON_ENVIRONMENT_VARIABLES" ]; then - TEMP_BACKUPS_DISABLED=($(echo $LAGOON_ENVIRONMENT_VARIABLES | jq -r '.[] | select(.scope == "build") | select(.name == "LAGOON_BACKUPS_DISABLED") | "\(.value)"')) - if [ ! -z $TEMP_BACKUPS_DISABLED ]; then - BACKUPS_DISABLED=$TEMP_BACKUPS_DISABLED - fi -fi - +BACKUPS_DISABLED=$(apiEnvironmentVariableCheck LAGOON_BACKUPS_DISABLED false) if [ ! "$BACKUPS_DISABLED" == true ]; then # check if k8up v2 feature flag is enabled LAGOON_BACKUP_YAML_FOLDER="/kubectl-build-deploy/lagoon/backup"