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  }