github.com/apache/incubator-kie-tools/packages/kn-plugin-workflow@v0.28.1-0.20240311201729-34c6856b157f/pkg/command/deploy.go (about) 1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 */ 19 20 package command 21 22 import ( 23 "fmt" 24 "os" 25 "path" 26 27 "github.com/apache/incubator-kie-tools/packages/kn-plugin-workflow/pkg/metadata" 28 29 "github.com/apache/incubator-kie-tools/packages/kn-plugin-workflow/pkg/common" 30 "github.com/ory/viper" 31 "github.com/spf13/cobra" 32 ) 33 34 func NewDeployCommand() *cobra.Command { 35 var cmd = &cobra.Command{ 36 Use: "deploy", 37 Short: "Deploy a SonataFlow project on Kubernetes via SonataFlow Operator", 38 Long: ` 39 Deploy a SonataFlow project in Kubernetes via the SonataFlow Operator. 40 By default, the deploy command will generate the Operator manifests and apply them to the cluster. 41 You can also provide a custom manifest directory with the --custom-manifests-dir option. 42 `, 43 Example: ` 44 # Deploy the workflow project from the current directory's project. 45 # You must provide target namespace. 46 {{.Name}} deploy --namespace <your_namespace> 47 48 # Persist the generated Operator manifests on a given path and deploy the 49 # workflow from the current directory's project. 50 {{.Name}} deploy --custom-generated-manifests-dir=<full_directory_path> 51 52 # Specify a custom manifest files directory. 53 # This option *will not* automatically generate the manifest files, but will use the existing ones. 54 {{.Name}} deploy --custom-manifests-dir=<full_directory_path> 55 56 # Specify a custom subflows files directory. (default: ./subflows) 57 {{.Name}} deploy --subflows-dir=<full_directory_path> 58 59 # Specify a custom support specs directory. (default: ./specs) 60 {{.Name}} deploy --specs-dir=<full_directory_path> 61 62 # Specify a custom support schemas directory. (default: ./schemas) 63 {{.Name}} deploy --schemas-dir=<full_directory_path> 64 65 `, 66 67 PreRunE: common.BindEnv("namespace", "custom-manifests-dir", "custom-generated-manifests-dir", "specs-dir", "schemas-dir", "subflows-dir"), 68 SuggestFor: []string{"delpoy", "deplyo"}, 69 } 70 71 cmd.RunE = func(cmd *cobra.Command, args []string) error { 72 return runDeployUndeploy(cmd, args) 73 } 74 75 cmd.Flags().StringP("namespace", "n", "", "Target namespace of your deployment.") 76 cmd.Flags().StringP("custom-generated-manifests-dir", "c", "", "Target directory of your generated Operator manifests.") 77 cmd.Flags().StringP("custom-manifests-dir", "m", "", "Specify a custom manifest files directory. This option will not automatically generate the manifest files, but will use the existing ones.") 78 cmd.Flags().StringP("specs-dir", "p", "", "Specify a custom specs files directory") 79 cmd.Flags().StringP("subflows-dir", "s", "", "Specify a custom subflows files directory") 80 cmd.Flags().StringP("schemas-dir", "t", "", "Specify a custom schemas files directory") 81 82 cmd.SetHelpFunc(common.DefaultTemplatedHelp) 83 84 return cmd 85 } 86 87 func runDeployUndeploy(cmd *cobra.Command, args []string) error { 88 89 cfg, err := runDeployCmdConfig(cmd) 90 //temp dir cleanup 91 defer func(cfg *DeployUndeployCmdConfig) { 92 if cfg.TempDir != "" { 93 if err := os.RemoveAll(cfg.TempDir); err != nil { 94 fmt.Errorf("ā ERROR: failed to remove temp dir: %v", err) 95 } 96 } 97 }(&cfg) 98 99 if err != nil { 100 return fmt.Errorf("ā ERROR: initializing deploy config: %w", err) 101 } 102 103 fmt.Println("š ļøļø Deploy a SonataFlow project on Kubernetes via the SonataFlow Operator...") 104 105 if err := checkEnvironment(&cfg); err != nil { 106 return fmt.Errorf("ā ERROR: checking deploy environment: %w", err) 107 } 108 109 if len(cfg.CustomManifestsFileDir) == 0 { 110 if err := generateManifests(&cfg); err != nil { 111 return fmt.Errorf("ā ERROR: generating deploy environment: %w", err) 112 } 113 } else { 114 fmt.Printf("š Using manifests located at %s\n", cfg.CustomManifestsFileDir) 115 } 116 117 if err = deploy(&cfg); err != nil { 118 return fmt.Errorf("ā ERROR: applying deploy: %w", err) 119 } 120 121 fmt.Printf("\nš SonataFlow project successfully deployed.\n") 122 123 return nil 124 } 125 126 func deploy(cfg *DeployUndeployCmdConfig) error { 127 fmt.Printf("š Deploying your SonataFlow project in namespace %s\n", cfg.NameSpace) 128 129 manifestExtension := []string{metadata.YAMLExtension} 130 131 manifestPath := cfg.CustomGeneratedManifestDir 132 if len(cfg.CustomManifestsFileDir) != 0 { 133 manifestPath = cfg.CustomManifestsFileDir 134 } 135 136 files, err := common.FindFilesWithExtensions(manifestPath, manifestExtension) 137 if err != nil { 138 return fmt.Errorf("ā ERROR: failed to get manifest directory and files: %w", err) 139 } 140 for _, file := range files { 141 if err = common.ExecuteKubectlApply(file, cfg.NameSpace); err != nil { 142 return fmt.Errorf("ā ERROR: failed to deploy manifest %s, %w", file, err) 143 } 144 fmt.Printf(" - ā Manifest %s successfully deployed in namespace %s\n", path.Base(file), cfg.NameSpace) 145 146 } 147 return nil 148 } 149 150 func runDeployCmdConfig(cmd *cobra.Command) (cfg DeployUndeployCmdConfig, err error) { 151 152 cfg = DeployUndeployCmdConfig{ 153 NameSpace: viper.GetString("namespace"), 154 CustomManifestsFileDir: viper.GetString("custom-manifests-dir"), 155 CustomGeneratedManifestDir: viper.GetString("custom-generated-manifests-dir"), 156 SpecsDir: viper.GetString("specs-dir"), 157 SchemasDir: viper.GetString("schemas-dir"), 158 SubflowsDir: viper.GetString("subflows-dir"), 159 } 160 161 if len(cfg.SubflowsDir) == 0 { 162 dir, err := os.Getwd() 163 cfg.SubflowsDir = dir + "/subflows" 164 if err != nil { 165 return cfg, fmt.Errorf("ā ERROR: failed to get default subflows workflow files folder: %w", err) 166 } 167 } 168 169 if len(cfg.SpecsDir) == 0 { 170 dir, err := os.Getwd() 171 cfg.SpecsDir = dir + "/specs" 172 if err != nil { 173 return cfg, fmt.Errorf("ā ERROR: failed to get default specs files folder: %w", err) 174 } 175 } 176 177 if len(cfg.SchemasDir) == 0 { 178 dir, err := os.Getwd() 179 cfg.SchemasDir = dir + "/schemas" 180 if err != nil { 181 return cfg, fmt.Errorf("ā ERROR: failed to get default schemas files folder: %w", err) 182 } 183 } 184 185 dir, err := os.Getwd() 186 cfg.DefaultDashboardsFolder = dir + "/" + metadata.DashboardsDefaultDirName 187 if err != nil { 188 return cfg, fmt.Errorf("ā ERROR: failed to get default dashboards files folder: %w", err) 189 } 190 191 //setup manifest path 192 if err := setupConfigManifestPath(&cfg); err != nil { 193 return cfg, err 194 } 195 196 return cfg, nil 197 }