github.com/oam-dev/kubevela@v1.9.11/references/common/workload.go (about)

     1  /*
     2  Copyright 2021 The KubeVela Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package common
    18  
    19  import (
    20  	"fmt"
    21  	"strconv"
    22  	"strings"
    23  
    24  	"github.com/oam-dev/kubevela/pkg/utils/common"
    25  
    26  	"cuelang.org/go/cue"
    27  	"github.com/spf13/pflag"
    28  
    29  	"github.com/oam-dev/kubevela/references/appfile"
    30  	"github.com/oam-dev/kubevela/references/appfile/api"
    31  	"github.com/oam-dev/kubevela/references/docgen"
    32  )
    33  
    34  // InitApplication will load Application from cluster
    35  func InitApplication(namespace string, c common.Args, workloadName string, appGroup string) (*api.Application, error) {
    36  	var appName string
    37  	if appGroup != "" {
    38  		appName = appGroup
    39  	} else {
    40  		appName = workloadName
    41  	}
    42  	// TODO(wonderflow): we should load the existing application from cluster and convert to appfile
    43  	// app, err := appfile.LoadApplication(env.Namespace, appName, c)
    44  	// compatible application not found
    45  	app, err := appfile.NewEmptyApplication(namespace, c)
    46  	if err != nil {
    47  		return nil, err
    48  	}
    49  	app.Name = appName
    50  
    51  	return app, nil
    52  }
    53  
    54  // BaseComplete will construct an Application from cli parameters.
    55  func BaseComplete(namespace string, c common.Args, workloadName string, appName string, flagSet *pflag.FlagSet, workloadType string) (*api.Application, error) {
    56  	app, err := InitApplication(namespace, c, workloadName, appName)
    57  	if err != nil {
    58  		return nil, err
    59  	}
    60  	tp, workloadData := appfile.GetWorkload(app, workloadName)
    61  	if tp == "" {
    62  		if workloadType == "" {
    63  			return nil, fmt.Errorf("must specify workload type for application %s", workloadName)
    64  		}
    65  		// Not exist
    66  		tp = workloadType
    67  	}
    68  	template, err := docgen.LoadCapabilityByName(tp, namespace, c)
    69  	if err != nil {
    70  		return nil, err
    71  	}
    72  
    73  	for _, v := range template.Parameters {
    74  		name := v.Name
    75  		if v.Alias != "" {
    76  			name = v.Alias
    77  		}
    78  		// Cli can check required flag before make a request to backend, but API itself could not, so validate flags here
    79  		flag := flagSet.Lookup(name)
    80  		if name == "name" {
    81  			continue
    82  		}
    83  		if flag == nil || flag.Value.String() == "" {
    84  			if v.Required {
    85  				return nil, fmt.Errorf("required flag(s) \"%s\" not set", name)
    86  			}
    87  			continue
    88  		}
    89  		// nolint:exhaustive
    90  		switch v.Type {
    91  		case cue.IntKind:
    92  			workloadData[v.Name], err = flagSet.GetInt64(name)
    93  		case cue.StringKind:
    94  			workloadData[v.Name], err = flagSet.GetString(name)
    95  		case cue.BoolKind:
    96  			workloadData[v.Name], err = flagSet.GetBool(name)
    97  		case cue.NumberKind, cue.FloatKind:
    98  			workloadData[v.Name], err = flagSet.GetFloat64(name)
    99  		default:
   100  			// Currently we don't support get value from complex type
   101  			continue
   102  		}
   103  		if err != nil {
   104  			if strings.Contains(err.Error(), "of flag of type string") {
   105  				data, _ := flagSet.GetString(name)
   106  				// nolint:exhaustive
   107  				switch v.Type {
   108  				case cue.IntKind:
   109  					workloadData[v.Name], err = strconv.ParseInt(data, 10, 64)
   110  				case cue.BoolKind:
   111  					workloadData[v.Name], err = strconv.ParseBool(data)
   112  				case cue.NumberKind, cue.FloatKind:
   113  					workloadData[v.Name], err = strconv.ParseFloat(data, 64)
   114  				default:
   115  					return nil, fmt.Errorf("should not get string from type(%s) for parameter \"%s\"", v.Type.String(), name)
   116  				}
   117  				if err != nil {
   118  					return nil, fmt.Errorf("get flag(s) \"%s\" err %w", v.Name, err)
   119  				}
   120  				continue
   121  			}
   122  			return nil, fmt.Errorf("get flag(s) \"%s\" err %w", v.Name, err)
   123  		}
   124  	}
   125  	if err = appfile.SetWorkload(app, workloadName, tp, workloadData); err != nil {
   126  		return app, err
   127  	}
   128  	return app, nil
   129  }