Skip to content

Commit

Permalink
feat: template lagoonenv configmap
Browse files Browse the repository at this point in the history
  • Loading branch information
shreddedbacon committed Oct 13, 2024
1 parent ac5c193 commit 1b57fb0
Show file tree
Hide file tree
Showing 18 changed files with 866 additions and 312 deletions.
4 changes: 1 addition & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,11 @@ RUN apk add -U --repository http://dl-cdn.alpinelinux.org/alpine/edge/testing au
&& apk upgrade --no-cache openssh openssh-keygen openssh-client-common openssh-client-default \
&& apk add --no-cache openssl curl jq parallel bash git py-pip skopeo \
&& git config --global user.email "[email protected]" && git config --global user.name lagoon \
&& pip install --break-system-packages shyaml yq
&& pip install --break-system-packages yq

RUN architecture=$(case $(uname -m) in x86_64 | amd64) echo "amd64" ;; aarch64 | arm64 | armv8) echo "arm64" ;; *) echo "amd64" ;; esac) \
&& curl -Lo /usr/bin/kubectl https://dl.k8s.io/release/$KUBECTL_VERSION/bin/linux/${architecture}/kubectl \
&& chmod +x /usr/bin/kubectl \
&& curl -Lo /usr/bin/yq3 https://github.com/mikefarah/yq/releases/download/3.3.2/yq_linux_${architecture} \
&& chmod +x /usr/bin/yq3 \
&& curl -Lo /usr/bin/yq https://github.com/mikefarah/yq/releases/download/v4.35.2/yq_linux_${architecture} \
&& chmod +x /usr/bin/yq \
&& curl -Lo /tmp/helm.tar.gz https://get.helm.sh/helm-${HELM_VERSION}-linux-${architecture}.tar.gz \
Expand Down
2 changes: 2 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@ func init() {
"Ignore missing env_file files (true by default, subject to change).")
rootCmd.PersistentFlags().StringP("images", "", "",
"JSON representation of service:image reference")
rootCmd.PersistentFlags().StringP("dbaas-creds", "", "",
"JSON representation of dbaas credential references")
}

// initConfig reads in config file and ENV variables if set.
Expand Down
103 changes: 103 additions & 0 deletions cmd/template_lagoonenv.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package cmd

import (
"encoding/json"
"fmt"
"os"
"strings"

"github.com/spf13/cobra"
generator "github.com/uselagoon/build-deploy-tool/internal/generator"
"github.com/uselagoon/build-deploy-tool/internal/helpers"
"github.com/uselagoon/build-deploy-tool/internal/templating/lagoonenv"
"sigs.k8s.io/yaml"
)

type DBaaSCredRefs []map[string]string

var lagoonEnvGeneration = &cobra.Command{
Use: "lagoon-env",
Aliases: []string{"le"},
Short: "Generate the lagoon-env configmap template for a Lagoon build",
RunE: func(cmd *cobra.Command, args []string) error {
generator, err := generator.GenerateInput(*rootCmd, true)
if err != nil {
return err
}
routes, err := cmd.Flags().GetString("routes")
if err != nil {
return fmt.Errorf("error reading routes flag: %v", err)
}
dbaasCreds, err := rootCmd.PersistentFlags().GetString("dbaas-creds")
if err != nil {
return fmt.Errorf("error reading images flag: %v", err)
}
dbaasCredRefs, err := loadCredsFromFile(dbaasCreds)
if err != nil {
return err
}
dbCreds := map[string]string{}
for _, v := range *dbaasCredRefs {
for k, v1 := range v {
dbCreds[k] = v1
}
}
generator.DBaaSVariables = dbCreds
return LagoonEnvTemplateGeneration(generator, routes)
},
}

func loadCredsFromFile(file string) (*DBaaSCredRefs, error) {
dbaasCredRefs := &DBaaSCredRefs{}
dbaasCredJSON, err := os.ReadFile(file)
if err != nil {
return nil, fmt.Errorf("couldn't read file %v: %v", file, err)
}
if err := json.Unmarshal(dbaasCredJSON, dbaasCredRefs); err != nil {
return nil, fmt.Errorf("error unmarshalling images payload: %v", err)
}
return dbaasCredRefs, nil
}

// LagoonEnvTemplateGeneration .
func LagoonEnvTemplateGeneration(
g generator.GeneratorInput,
routes string,
) error {
lagoonBuild, err := generator.NewGenerator(
g,
)
if err != nil {
return err
}
savedTemplates := g.SavedTemplatesPath
// if the routes have been passed from the command line, use them instead. we do this since lagoon currently doesn't enforce route state to match
// what is in the `.lagoon.yml` file, so there may be items that exist in the cluster that don't exist in yaml
// eventually once route state enforcement is enforced, or the tool can reconcile what is in the cluster itself rather than in bash
// then this can be removed
// https://github.com/uselagoon/build-deploy-tool/blob/f527a89ad5efb46e19a2f59d9ff3ffbff541e2a2/legacy/build-deploy-docker-compose.sh#L1090
if routes != "" {
lagoonBuild.BuildValues.Routes = strings.Split(routes, ",")
}
cm, err := lagoonenv.GenerateLagoonEnvConfigMap(*lagoonBuild.BuildValues)
if err != nil {
return fmt.Errorf("couldn't generate template: %v", err)
}
cmBytes, err := yaml.Marshal(cm)
if err != nil {
return fmt.Errorf("couldn't generate template: %v", err)
}
if len(cmBytes) > 0 {
if g.Debug {
fmt.Printf("Templating lagoon-env configmap %s\n", fmt.Sprintf("%s/%s.yaml", savedTemplates, "lagoon-env-configmap"))
}
helpers.WriteTemplateFile(fmt.Sprintf("%s/%s.yaml", savedTemplates, "lagoon-env-configmap"), cmBytes)
}
return nil
}

func init() {
templateCmd.AddCommand(lagoonEnvGeneration)
lagoonEnvGeneration.Flags().StringP("routes", "R", "",
"The routes from the environment")
}
240 changes: 240 additions & 0 deletions cmd/template_lagoonenv_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
package cmd

import (
"fmt"
"os"
"reflect"
"testing"

"github.com/andreyvit/diff"
"github.com/uselagoon/build-deploy-tool/internal/dbaasclient"
"github.com/uselagoon/build-deploy-tool/internal/helpers"
"github.com/uselagoon/build-deploy-tool/internal/lagoon"
"github.com/uselagoon/build-deploy-tool/internal/testdata"
)

func TestLagoonEnvTemplateGeneration(t *testing.T) {
tests := []struct {
name string
description string
args testdata.TestData
templatePath string
want string
dbaasCreds string
vars []helpers.EnvironmentVariable
}{
{
name: "test1 basic deployment",
args: testdata.GetSeedData(
testdata.TestData{
ProjectName: "example-project",
EnvironmentName: "main",
Branch: "main",
LagoonYAML: "internal/testdata/basic/lagoon.yml",
ProjectVariables: []lagoon.EnvironmentVariable{
{
Name: "MY_SPECIAL_VARIABLE1",
Value: "myspecialvariable1",
Scope: "global",
},
{
Name: "MY_SPECIAL_VARIABLE2",
Value: "myspecialvariable2",
Scope: "runtime",
},
{
Name: "MY_SPECIAL_VARIABLE3",
Value: "myspecialvariable3",
Scope: "build",
},
{
Name: "MY_SPECIAL_VARIABLE",
Value: "myspecialvariable",
Scope: "global",
},
{
Name: "LAGOON_SYSTEM_CORE_VERSION",
Value: "v2.19.0",
Scope: "internal_system",
},
{
Name: "REGISTRY_PASSWORD",
Value: "myenvvarregistrypassword",
Scope: "container_registry",
},
},
EnvVariables: []lagoon.EnvironmentVariable{
{
Name: "MY_SPECIAL_VARIABLE2",
Value: "myspecialvariable2-env-override",
Scope: "global",
},
{
Name: "MY_SPECIAL_VARIABLE4",
Value: "myspecialvariable4",
Scope: "runtime",
},
},
}, true),
templatePath: "testoutput",
want: "internal/testdata/basic/configmap-templates/lagoonenv1",
},
{
name: "test1 basic deployment with mariadb creds",
args: testdata.GetSeedData(
testdata.TestData{
ProjectName: "example-project",
EnvironmentName: "main",
Branch: "main",
LagoonYAML: "internal/testdata/basic/lagoon.yml",
ProjectVariables: []lagoon.EnvironmentVariable{
{
Name: "MY_SPECIAL_VARIABLE1",
Value: "myspecialvariable1",
Scope: "global",
},
{
Name: "MY_SPECIAL_VARIABLE2",
Value: "myspecialvariable2",
Scope: "runtime",
},
{
Name: "MY_SPECIAL_VARIABLE3",
Value: "myspecialvariable3",
Scope: "build",
},
{
Name: "MY_SPECIAL_VARIABLE",
Value: "myspecialvariable",
Scope: "global",
},
{
Name: "LAGOON_SYSTEM_CORE_VERSION",
Value: "v2.19.0",
Scope: "internal_system",
},
{
Name: "REGISTRY_PASSWORD",
Value: "myenvvarregistrypassword",
Scope: "container_registry",
},
},
EnvVariables: []lagoon.EnvironmentVariable{
{
Name: "MY_SPECIAL_VARIABLE2",
Value: "myspecialvariable2-env-override",
Scope: "global",
},
{
Name: "MY_SPECIAL_VARIABLE4",
Value: "myspecialvariable4",
Scope: "runtime",
},
},
}, true),
dbaasCreds: "internal/testdata/basic/lagoonenv2-creds.json",
templatePath: "testoutput",
want: "internal/testdata/basic/configmap-templates/lagoonenv2",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
helpers.UnsetEnvVars(tt.vars) //unset variables before running tests
for _, envVar := range tt.vars {
err := os.Setenv(envVar.Name, envVar.Value)
if err != nil {
t.Errorf("%v", err)
}
}
// set the environment variables from args
savedTemplates := tt.templatePath
generator, err := testdata.SetupEnvironment(*rootCmd, savedTemplates, tt.args)
if err != nil {
t.Errorf("%v", err)
}

err = os.MkdirAll(savedTemplates, 0755)
if err != nil {
t.Errorf("couldn't create directory %v: %v", savedTemplates, err)
}

defer os.RemoveAll(savedTemplates)

ts := dbaasclient.TestDBaaSHTTPServer()
defer ts.Close()
err = os.Setenv("DBAAS_OPERATOR_HTTP", ts.URL)
if err != nil {
t.Errorf("%v", err)
}
dbaasCreds := &DBaaSCredRefs{}
if tt.dbaasCreds != "" {
dbaasCreds, err = loadCredsFromFile(tt.dbaasCreds)
if err != nil {
t.Errorf("%v", err)
}
dbCreds := map[string]string{}
for _, v := range *dbaasCreds {
for k, v1 := range v {
dbCreds[k] = v1
}
}
generator.DBaaSVariables = dbCreds
}
err = LagoonEnvTemplateGeneration(generator, "")
if err != nil {
t.Errorf("%v", err)
}

files, err := os.ReadDir(savedTemplates)
if err != nil {
t.Errorf("couldn't read directory %v: %v", savedTemplates, err)
}
results, err := os.ReadDir(tt.want)
if err != nil {
t.Errorf("couldn't read directory %v: %v", tt.want, err)
}
if len(files) != len(results) {
for _, f := range files {
f1, err := os.ReadFile(fmt.Sprintf("%s/%s", savedTemplates, f.Name()))
if err != nil {
t.Errorf("couldn't read file %v: %v", savedTemplates, err)
}
fmt.Println(string(f1))
}
t.Errorf("number of generated templates doesn't match results %v/%v: %v", len(files), len(results), err)
}
fCount := 0
for _, f := range files {
for _, r := range results {
if f.Name() == r.Name() {
fCount++
f1, err := os.ReadFile(fmt.Sprintf("%s/%s", savedTemplates, f.Name()))
if err != nil {
t.Errorf("couldn't read file %v: %v", savedTemplates, err)
}
r1, err := os.ReadFile(fmt.Sprintf("%s/%s", tt.want, f.Name()))
if err != nil {
t.Errorf("couldn't read file %v: %v", tt.want, err)
}
if !reflect.DeepEqual(f1, r1) {
t.Errorf("LagoonEnvTemplateGeneration() = \n%v", diff.LineDiff(string(r1), string(f1)))
}
}
}
}
if fCount != len(files) {
for _, f := range files {
f1, err := os.ReadFile(fmt.Sprintf("%s/%s", savedTemplates, f.Name()))
if err != nil {
t.Errorf("couldn't read file %v: %v", savedTemplates, err)
}
fmt.Println(string(f1))
}
t.Errorf("resulting templates do not match")
}
t.Cleanup(func() {
helpers.UnsetEnvVars(tt.vars)
})
})
}
}
Loading

0 comments on commit 1b57fb0

Please sign in to comment.