github.com/vshn/k8ify@v1.1.2-0.20240502214202-6c9ed3ef0bf4/main.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "os" 6 "time" 7 8 composeLoader "github.com/compose-spec/compose-go/loader" 9 composeTypes "github.com/compose-spec/compose-go/types" 10 "github.com/joho/godotenv" 11 "github.com/sirupsen/logrus" 12 "github.com/spf13/pflag" 13 "github.com/vshn/k8ify/internal" 14 "github.com/vshn/k8ify/pkg/converter" 15 "github.com/vshn/k8ify/pkg/ir" 16 "github.com/vshn/k8ify/pkg/provider" 17 "github.com/vshn/k8ify/pkg/util" 18 ) 19 20 var ( 21 defaultConfig = internal.Config{ 22 OutputDir: "manifests", 23 Env: "dev", 24 Ref: "", 25 } 26 modifiedImages internal.ModifiedImagesFlag 27 shellEnvFiles internal.ShellEnvFilesFlag 28 pflagInitialized = false 29 ) 30 31 func InitPflag() { 32 // Main() may be called multiple times from tests, hence this kludge 33 if !pflagInitialized { 34 pflag.Var(&modifiedImages, "modified-image", "Image that has been modified during the build. Can be repeated.") 35 pflag.Var(&shellEnvFiles, "shell-env-file", "Shell environment file ('key=value' format) to be used in addition to the current shell environment. Can be repeated.") 36 pflagInitialized = true 37 } 38 } 39 40 func main() { 41 code := Main(os.Args) 42 os.Exit(code) 43 } 44 45 func Main(args []string) int { 46 InitPflag() 47 err := pflag.CommandLine.Parse(args[1:]) 48 if err != nil { 49 logrus.Error(err) 50 return 1 51 } 52 plainArgs := pflag.Args() 53 54 config := defaultConfig // this code may run multiple times during testing, thus we can't modify the defaults and must create a copy 55 if len(plainArgs) > 0 { 56 config.Env = plainArgs[0] 57 } 58 if len(plainArgs) > 1 { 59 config.Ref = plainArgs[1] 60 } 61 62 if config.ConfigFiles == nil || len(config.ConfigFiles) == 0 { 63 config.ConfigFiles = []string{"compose.yml", "docker-compose.yml", "compose-" + config.Env + ".yml", "docker-compose-" + config.Env + ".yml"} 64 } 65 66 // Load the additional shell environment files. This will merge everything into the existing shell environment and 67 // all values can later be retrieved using os.Environ() 68 for _, shellEnvFile := range shellEnvFiles.Values { 69 err := godotenv.Load(shellEnvFile) 70 if err != nil { 71 logrus.Error(err) 72 return 1 73 } 74 } 75 76 composeConfigFiles := []composeTypes.ConfigFile{} 77 for _, configFile := range config.ConfigFiles { 78 if _, err := os.Stat(configFile); err == nil { 79 composeConfigFiles = append(composeConfigFiles, composeTypes.ConfigFile{ 80 Filename: configFile, 81 }) 82 } 83 } 84 env := util.GetEnv() 85 if _, ok := env["_ref_"]; ok { 86 logrus.Error("The environment variable '_ref_' must not be defined as it is needed for internal purposes") 87 return 1 88 } 89 env["_ref_"] = converter.SecretRefMagic 90 configDetails := composeTypes.ConfigDetails{ 91 ConfigFiles: composeConfigFiles, 92 Environment: env, 93 } 94 project, err := composeLoader.Load(configDetails) 95 if err != nil { 96 logrus.Error(err) 97 return 1 98 } 99 100 inputs := ir.FromCompose(project) 101 internal.ComposeServicePrecheck(inputs) 102 internal.VolumesPrecheck(inputs) 103 internal.DomainLengthPrecheck(inputs) 104 105 objects := converter.Objects{} 106 107 for _, service := range inputs.Services { 108 objects = objects.Append(converter.ComposeServiceToK8s(config.Ref, service, inputs.Volumes, inputs.TargetCfg)) 109 } 110 111 forceRestartAnnotation := make(map[string]string) 112 forceRestartAnnotation["k8ify.restart-trigger"] = fmt.Sprintf("%d", time.Now().Unix()) 113 converter.PatchDeployments(objects.Deployments, modifiedImages.Values, forceRestartAnnotation) 114 converter.PatchStatefulSets(objects.StatefulSets, modifiedImages.Values, forceRestartAnnotation) 115 116 objects = provider.PatchEncryptedVolumeSchemeAppuioCloudscale(inputs.TargetCfg, config, objects) 117 118 err = internal.WriteManifests(config.OutputDir, objects) 119 if err != nil { 120 logrus.Error(err) 121 return 1 122 } 123 124 return 0 125 }