mirror of
https://github.com/kubevela/kubevela.git
synced 2026-08-19 04:26:39 +00:00
Merge pull request #216 from wonderflow/scope
support scopes in appfile and make health scope as default
This commit is contained in:
@@ -24,6 +24,6 @@ var _ = ginkgo.Describe("Application", func() {
|
||||
e2e.TraitManualScalerAttachContext("vela attach trait", traitAlias, applicationName)
|
||||
//e2e.ApplicationListContext("app ls", applicationName, traitAlias)
|
||||
e2e.ApplicationShowContext("app show", applicationName, workloadType)
|
||||
e2e.ApplicationStatusContext("app status", applicationName, workloadType)
|
||||
e2e.ApplicationStatusContext("comp status", applicationName, workloadType)
|
||||
e2e.WorkloadDeleteContext("delete", applicationName)
|
||||
})
|
||||
|
||||
@@ -177,13 +177,11 @@ var (
|
||||
ApplicationStatusContext = func(context string, applicationName string, workloadType string) bool {
|
||||
return ginkgo.Context(context, func() {
|
||||
ginkgo.It("should get status for the application", func() {
|
||||
cli := fmt.Sprintf("vela app status %s", applicationName)
|
||||
cli := fmt.Sprintf("vela comp status %s", applicationName)
|
||||
output, err := Exec(cli)
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
gomega.Expect(output).To(gomega.ContainSubstring(applicationName))
|
||||
// TODO(zzxwill) need to check workloadType after app status is refined
|
||||
//gomega.Expect(output).To(gomega.ContainSubstring(workloadType))
|
||||
gomega.Expect(output).To(gomega.ContainSubstring("Workload"))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
+29
-7
@@ -12,6 +12,10 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/crossplane/oam-kubernetes-runtime/pkg/oam"
|
||||
|
||||
"github.com/crossplane/crossplane-runtime/apis/core/v1alpha1"
|
||||
|
||||
"cuelang.org/go/cue"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
@@ -39,7 +43,7 @@ type Application struct {
|
||||
// key of map is component name
|
||||
Components map[string]map[string]interface{} `json:"components"`
|
||||
Secrets map[string]map[string]interface{} `json:"secrets"`
|
||||
Scopes map[string]map[string]interface{} `json:"appScopes"`
|
||||
Scopes map[string]map[string]interface{} `json:"globalScopes"`
|
||||
CreateTime time.Time `json:"createTime,omitempty"`
|
||||
UpdateTime time.Time `json:"updateTime,omitempty"`
|
||||
}
|
||||
@@ -166,6 +170,7 @@ func (app *Application) Validate() error {
|
||||
if !ok {
|
||||
return fmt.Errorf("format of scopes in '%s' must be string array", name)
|
||||
}
|
||||
//TODO(wonderflow) check scope exist
|
||||
}
|
||||
if lenth != 1 {
|
||||
return fmt.Errorf("you must have only one workload in component '%s'", name)
|
||||
@@ -340,17 +345,25 @@ func (app *Application) GetComponentTraits(componentName string) ([]v1alpha2.Com
|
||||
return traits, nil
|
||||
}
|
||||
|
||||
func FormatDefaultHealthScopeName(appName string) string {
|
||||
return appName + "-default-health"
|
||||
}
|
||||
|
||||
//TODO(wonderflow) add scope support here
|
||||
func (app *Application) OAM(env *types.EnvMeta) ([]v1alpha2.Component, v1alpha2.ApplicationConfiguration, error) {
|
||||
func (app *Application) OAM(env *types.EnvMeta) ([]v1alpha2.Component, v1alpha2.ApplicationConfiguration, []oam.Object, error) {
|
||||
var appConfig v1alpha2.ApplicationConfiguration
|
||||
if err := app.Validate(); err != nil {
|
||||
return nil, appConfig, err
|
||||
return nil, appConfig, nil, err
|
||||
}
|
||||
appConfig.Name = app.Name
|
||||
appConfig.Namespace = env.Namespace
|
||||
|
||||
var components []v1alpha2.Component
|
||||
var health v1alpha2.HealthScope
|
||||
health.Name = FormatDefaultHealthScopeName(app.Name)
|
||||
health.Namespace = env.Namespace
|
||||
health.Spec.WorkloadReferences = make([]v1alpha1.TypedReference, 0)
|
||||
|
||||
var components []v1alpha2.Component
|
||||
for name := range app.Components {
|
||||
// fulfill component
|
||||
var component v1alpha2.Component
|
||||
@@ -358,7 +371,7 @@ func (app *Application) OAM(env *types.EnvMeta) ([]v1alpha2.Component, v1alpha2.
|
||||
component.Namespace = env.Namespace
|
||||
obj, workloadType, err := app.GetWorkloadObject(name)
|
||||
if err != nil {
|
||||
return nil, v1alpha2.ApplicationConfiguration{}, err
|
||||
return nil, v1alpha2.ApplicationConfiguration{}, nil, err
|
||||
}
|
||||
anns := component.Annotations
|
||||
if anns == nil {
|
||||
@@ -372,13 +385,22 @@ func (app *Application) OAM(env *types.EnvMeta) ([]v1alpha2.Component, v1alpha2.
|
||||
|
||||
var appConfigComp v1alpha2.ApplicationConfigurationComponent
|
||||
appConfigComp.ComponentName = name
|
||||
|
||||
//TODO(wonderflow): Temporarily we add health scope here, should change to use scope framework
|
||||
appConfigComp.Scopes = append(appConfigComp.Scopes, v1alpha2.ComponentScope{ScopeReference: v1alpha1.TypedReference{
|
||||
APIVersion: v1alpha2.SchemeGroupVersion.String(),
|
||||
Kind: v1alpha2.HealthScopeKind,
|
||||
Name: health.Name,
|
||||
}})
|
||||
|
||||
//TODO(wonderflow): handle component data input/output here
|
||||
compTraits, err := app.GetComponentTraits(name)
|
||||
if err != nil {
|
||||
return nil, v1alpha2.ApplicationConfiguration{}, err
|
||||
return nil, v1alpha2.ApplicationConfiguration{}, nil, err
|
||||
}
|
||||
appConfigComp.Traits = compTraits
|
||||
appConfig.Spec.Components = append(appConfig.Spec.Components, appConfigComp)
|
||||
}
|
||||
return components, appConfig, nil
|
||||
|
||||
return components, appConfig, []oam.Object{&health}, nil
|
||||
}
|
||||
|
||||
+23
-1
@@ -3,6 +3,8 @@ package application
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/crossplane/oam-kubernetes-runtime/pkg/oam"
|
||||
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
|
||||
"github.com/crossplane/oam-kubernetes-runtime/apis/core/v1alpha2"
|
||||
@@ -13,7 +15,7 @@ import (
|
||||
)
|
||||
|
||||
func (app *Application) Run(ctx context.Context, client client.Client, env *types.EnvMeta) error {
|
||||
components, appconfig, err := app.OAM(env)
|
||||
components, appconfig, scopes, err := app.OAM(env)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -22,6 +24,9 @@ func (app *Application) Run(ctx context.Context, client client.Client, env *type
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err = CreateScopes(ctx, client, scopes); err != nil {
|
||||
return err
|
||||
}
|
||||
return CreateOrUpdateAppConfig(ctx, client, appconfig)
|
||||
}
|
||||
|
||||
@@ -58,3 +63,20 @@ func CreateOrUpdateAppConfig(ctx context.Context, client client.Client, appConfi
|
||||
appConfig.ResourceVersion = geta.ResourceVersion
|
||||
return client.Update(ctx, &appConfig)
|
||||
}
|
||||
|
||||
func CreateScopes(ctx context.Context, client client.Client, scopes []oam.Object) error {
|
||||
for _, obj := range scopes {
|
||||
key := ctypes.NamespacedName{Name: obj.GetName(), Namespace: obj.GetNamespace()}
|
||||
err := client.Get(ctx, key, obj)
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
if !apierrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
if err = client.Create(ctx, obj); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Vendored
+9
-5
@@ -20,11 +20,15 @@ components:
|
||||
container_port: 8080
|
||||
scopes:
|
||||
- public-scope
|
||||
- myapp-default-health
|
||||
secrets:
|
||||
secret-foo:
|
||||
key1: 'pass-word'
|
||||
appScopes:
|
||||
public-scope:
|
||||
networkPolicy: public
|
||||
private-scope:
|
||||
networkPolicy: private
|
||||
globalScopes:
|
||||
network:
|
||||
public-scope:
|
||||
networkPolicy: public
|
||||
private-scope:
|
||||
networkPolicy: private
|
||||
health:
|
||||
myapp-default-health: {}
|
||||
@@ -1,26 +0,0 @@
|
||||
package builtin
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/cloud-native-application/rudrx/pkg/builtin/traitdefinition"
|
||||
"github.com/cloud-native-application/rudrx/pkg/builtin/workloaddefinition"
|
||||
)
|
||||
|
||||
func TestValidYaml(t *testing.T) {
|
||||
cases := map[string]string{
|
||||
"scale": traitdefinition.ManualScaler,
|
||||
"rollout": traitdefinition.SimpleRollout,
|
||||
"containerized": workloaddefinition.ContainerizedWorkload,
|
||||
"deployment": workloaddefinition.Deployment,
|
||||
}
|
||||
for name, val := range cases {
|
||||
data := unstructured.Unstructured{}
|
||||
assert.NoError(t, yaml.Unmarshal([]byte(val), &data), name)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package traitdefinition
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/crossplane/oam-kubernetes-runtime/apis/core/v1alpha2"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestValidTraitDefinition(t *testing.T) {
|
||||
cases := map[string]string{
|
||||
"scale": ManualScaler,
|
||||
"rollout": SimpleRollout,
|
||||
}
|
||||
for name, val := range cases {
|
||||
data := v1alpha2.TraitDefinition{}
|
||||
assert.NoError(t, yaml.Unmarshal([]byte(val), &data), name)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package workloaddefinition
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/crossplane/oam-kubernetes-runtime/apis/core/v1alpha2"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestValidWorkloadDefinition(t *testing.T) {
|
||||
cases := map[string]string{
|
||||
"containerized": ContainerizedWorkload,
|
||||
"deployment": Deployment,
|
||||
}
|
||||
for name, val := range cases {
|
||||
data := v1alpha2.WorkloadDefinition{}
|
||||
assert.NoError(t, yaml.Unmarshal([]byte(val), &data), name)
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,6 @@ func NewAppsCommand(c types.Args, ioStreams cmdutil.IOStreams) *cobra.Command {
|
||||
|
||||
cmd.AddCommand(NewAppListCommand(c, ioStreams),
|
||||
NewDeleteCommand(c, ioStreams),
|
||||
NewAppStatusCommand(c, ioStreams),
|
||||
NewAppShowCommand(ioStreams),
|
||||
NewRunCommand(c, ioStreams))
|
||||
return cmd
|
||||
|
||||
+2
-3
@@ -43,6 +43,7 @@ func AddCompCommands(c types.Args, ioStreams util.IOStreams) *cobra.Command {
|
||||
NewCompListCommand(c, ioStreams),
|
||||
NewCompRunCommands(c, ioStreams),
|
||||
NewCompShowCommand(ioStreams),
|
||||
NewCompStatusCommand(c, ioStreams),
|
||||
NewCompDeleteCommand(c, ioStreams),
|
||||
)
|
||||
return compCommands
|
||||
@@ -132,9 +133,7 @@ func (o *runOptions) Complete(cmd *cobra.Command, args []string, ctx context.Con
|
||||
if err = flags.Parse(args); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var flagSet = cmd.Flags()
|
||||
app, err := oam.BaseComplete(envName, workloadName, appGroup, flagSet, workloadType)
|
||||
app, err := oam.BaseComplete(envName, workloadName, appGroup, flags, workloadType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
+11
-1
@@ -77,8 +77,9 @@ func (o *deleteOptions) DeleteApp() error {
|
||||
}
|
||||
return fmt.Errorf("delete appconfig err %s", err)
|
||||
}
|
||||
for _, comp := range appConfig.Status.Workloads {
|
||||
for _, comp := range appConfig.Spec.Components {
|
||||
var c corev1alpha2.Component
|
||||
//TODO(wonderflow): what if we use componentRevision here?
|
||||
c.Name = comp.ComponentName
|
||||
c.Namespace = o.Env.Namespace
|
||||
err = o.client.Delete(ctx, &c)
|
||||
@@ -90,6 +91,15 @@ func (o *deleteOptions) DeleteApp() error {
|
||||
if err != nil && !apierrors.IsNotFound(err) {
|
||||
return fmt.Errorf("delete appconfig err %s", err)
|
||||
}
|
||||
|
||||
var healthscope corev1alpha2.HealthScope
|
||||
healthscope.Name = application.FormatDefaultHealthScopeName(o.appName)
|
||||
healthscope.Namespace = o.Env.Namespace
|
||||
err = o.client.Delete(ctx, &healthscope)
|
||||
if err != nil && !apierrors.IsNotFound(err) {
|
||||
return fmt.Errorf("delete health scope %s err %v", healthscope.Name, err)
|
||||
}
|
||||
|
||||
o.Info("DELETE SUCCEED")
|
||||
return nil
|
||||
}
|
||||
|
||||
+1
-1
@@ -116,7 +116,7 @@ func mergeStagingComponents(deployed []oam.ComponentMeta, env *types.EnvMeta, io
|
||||
}
|
||||
var all []oam.ComponentMeta
|
||||
for _, app := range apps {
|
||||
comps, appConfig, err := app.OAM(env)
|
||||
comps, appConfig, _, err := app.OAM(env)
|
||||
if err != nil {
|
||||
ioStreams.Errorf("convert app %s err %v\n", app.Name, err)
|
||||
continue
|
||||
|
||||
+32
-12
@@ -3,18 +3,20 @@ package cmd
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/crossplane/oam-kubernetes-runtime/apis/core/v1alpha2"
|
||||
|
||||
"github.com/cloud-native-application/rudrx/pkg/application"
|
||||
|
||||
"github.com/cloud-native-application/rudrx/api/types"
|
||||
|
||||
cmdutil "github.com/cloud-native-application/rudrx/pkg/cmd/util"
|
||||
"github.com/cloud-native-application/rudrx/pkg/oam"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
func NewAppStatusCommand(c types.Args, ioStreams cmdutil.IOStreams) *cobra.Command {
|
||||
func NewCompStatusCommand(c types.Args, ioStreams cmdutil.IOStreams) *cobra.Command {
|
||||
ctx := context.Background()
|
||||
cmd := &cobra.Command{
|
||||
Use: "status <APPLICATION-NAME>",
|
||||
@@ -27,18 +29,18 @@ func NewAppStatusCommand(c types.Args, ioStreams cmdutil.IOStreams) *cobra.Comma
|
||||
ioStreams.Errorf("Hint: please specify an application")
|
||||
os.Exit(1)
|
||||
}
|
||||
appName := args[0]
|
||||
compName := args[0]
|
||||
env, err := GetEnv(cmd)
|
||||
if err != nil {
|
||||
ioStreams.Errorf("Error: failed to get Env: %s", err)
|
||||
return err
|
||||
}
|
||||
namespace := env.Namespace
|
||||
newClient, err := client.New(c.Config, client.Options{Scheme: c.Schema})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return printApplicationStatus(ctx, newClient, ioStreams, appName, namespace)
|
||||
appName, _ := cmd.Flags().GetString(App)
|
||||
return printComponentStatus(ctx, newClient, ioStreams, compName, appName, env)
|
||||
},
|
||||
Annotations: map[string]string{
|
||||
types.TagCommandType: types.TypeApp,
|
||||
@@ -48,15 +50,33 @@ func NewAppStatusCommand(c types.Args, ioStreams cmdutil.IOStreams) *cobra.Comma
|
||||
return cmd
|
||||
}
|
||||
|
||||
func printApplicationStatus(ctx context.Context, c client.Client, ioStreams cmdutil.IOStreams, appName string, namespace string) error {
|
||||
application, err := oam.RetrieveApplicationStatusByName(ctx, c, appName, namespace)
|
||||
func printComponentStatus(ctx context.Context, c client.Client, ioStreams cmdutil.IOStreams, compName, appName string, env *types.EnvMeta) error {
|
||||
ioStreams.Infof("Showing status of Component %s deployed in Environment %s\n", compName, env.Name)
|
||||
var app *application.Application
|
||||
var err error
|
||||
if appName != "" {
|
||||
app, err = application.Load(env.Name, appName)
|
||||
} else {
|
||||
app, err = application.MatchAppByComp(env.Name, compName)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
out, err := yaml.Marshal(application)
|
||||
if err != nil {
|
||||
|
||||
var health v1alpha2.HealthScope
|
||||
if err = c.Get(ctx, client.ObjectKey{Namespace: env.Namespace, Name: application.FormatDefaultHealthScopeName(app.Name)}, &health); err != nil {
|
||||
return err
|
||||
}
|
||||
ioStreams.Info(string(out))
|
||||
ioStreams.Info("Component Status:")
|
||||
//TODO(wonderflow): add more information from health scope
|
||||
ioStreams.Infof("\n %s \n\n", health.Status.Health)
|
||||
|
||||
var appConfig v1alpha2.ApplicationConfiguration
|
||||
if err = c.Get(ctx, client.ObjectKey{Namespace: env.Namespace, Name: app.Name}, &appConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
ioStreams.Infof("Last Deployment:\n\n")
|
||||
ioStreams.Infof("\tCreated at:\t%v\n", appConfig.CreationTimestamp)
|
||||
ioStreams.Infof("\tUpdated at:\t%v\n", app.UpdateTime.Format(time.RFC3339))
|
||||
return nil
|
||||
}
|
||||
|
||||
+31
-27
@@ -189,51 +189,55 @@ func GetOAMReleaseVersion() (string, error) {
|
||||
|
||||
func GenNativeResourceDefinition(c client.Client) error {
|
||||
var capabilities []string
|
||||
ctx := context.Background()
|
||||
for name, manifest := range workloadResource {
|
||||
workloadDefinition, err := NewWorkloadDefinition(manifest)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
err = c.Get(context.Background(), client.ObjectKey{Name: name}, &workloadDefinition)
|
||||
if kubeerrors.IsNotFound(err) {
|
||||
if err := c.Create(context.Background(), &workloadDefinition); err != nil {
|
||||
wd := NewWorkloadDefinition(manifest)
|
||||
capabilities = append(capabilities, name)
|
||||
nwd := &oamv1.WorkloadDefinition{}
|
||||
err := c.Get(ctx, client.ObjectKey{Name: name}, nwd)
|
||||
if err != nil && kubeerrors.IsNotFound(err) {
|
||||
if err := c.Create(context.Background(), &wd); err != nil {
|
||||
return fmt.Errorf("create workload definition %s hit an issue: %v", name, err)
|
||||
}
|
||||
} else if err != nil {
|
||||
return fmt.Errorf("get workload definition hit an issue: %v", err)
|
||||
continue
|
||||
}
|
||||
wd.ResourceVersion = nwd.ResourceVersion
|
||||
if err := c.Update(ctx, &wd); err != nil {
|
||||
return fmt.Errorf("update workload definition %s err %v", wd.Name, err)
|
||||
}
|
||||
capabilities = append(capabilities, name)
|
||||
}
|
||||
|
||||
for name, manifest := range traitResource {
|
||||
traitDefinition, err := NewTraitDefinition(manifest)
|
||||
if err != nil {
|
||||
fmt.Printf("creating local definition %s err %v", name, err)
|
||||
td := NewTraitDefinition(manifest)
|
||||
capabilities = append(capabilities, name)
|
||||
ntd := &oamv1.TraitDefinition{}
|
||||
err := c.Get(context.Background(), client.ObjectKey{Name: name}, ntd)
|
||||
if err != nil && kubeerrors.IsNotFound(err) {
|
||||
if err := c.Create(context.Background(), &td); err != nil {
|
||||
return fmt.Errorf("create trait definition %s hit an issue: %v", name, err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
err = c.Get(context.Background(), client.ObjectKey{Name: name}, &traitDefinition)
|
||||
if kubeerrors.IsNotFound(err) {
|
||||
if err := c.Create(context.Background(), &traitDefinition); err != nil {
|
||||
return fmt.Errorf("create workload definition %s hit an issue: %v", name, err)
|
||||
}
|
||||
} else if err != nil {
|
||||
return fmt.Errorf("get workload definition hit an issue: %v", err)
|
||||
td.ResourceVersion = ntd.ResourceVersion
|
||||
if err := c.Update(ctx, &td); err != nil {
|
||||
return fmt.Errorf("update trait definition %s err %v", td.Name, err)
|
||||
}
|
||||
capabilities = append(capabilities, name)
|
||||
}
|
||||
|
||||
fmt.Printf("Successful applied %d kinds of Workloads and Traits: %s.", len(capabilities), strings.Join(capabilities, ","))
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewWorkloadDefinition(manifest string) (oamv1.WorkloadDefinition, error) {
|
||||
func NewWorkloadDefinition(manifest string) oamv1.WorkloadDefinition {
|
||||
var workloadDefinition oamv1.WorkloadDefinition
|
||||
err := yaml.Unmarshal([]byte(manifest), &workloadDefinition)
|
||||
return workloadDefinition, err
|
||||
// We have tests to make sure built-in resource can always unmarshal succeed
|
||||
_ = yaml.Unmarshal([]byte(manifest), &workloadDefinition)
|
||||
return workloadDefinition
|
||||
}
|
||||
|
||||
func NewTraitDefinition(manifest string) (oamv1.TraitDefinition, error) {
|
||||
func NewTraitDefinition(manifest string) oamv1.TraitDefinition {
|
||||
var traitDefinition oamv1.TraitDefinition
|
||||
err := yaml.Unmarshal([]byte(manifest), &traitDefinition)
|
||||
return traitDefinition, err
|
||||
// We have tests to make sure built-in resource can always unmarshal succeed
|
||||
_ = yaml.Unmarshal([]byte(manifest), &traitDefinition)
|
||||
return traitDefinition
|
||||
}
|
||||
|
||||
+32
-10
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/cloud-native-application/rudrx/pkg/plugins"
|
||||
|
||||
@@ -65,23 +66,44 @@ func BaseComplete(envName string, workloadName string, appGroup string, flagSet
|
||||
}
|
||||
|
||||
for _, v := range template.Parameters {
|
||||
flagValue, _ := flagSet.GetString(v.Name)
|
||||
// Cli can check required flag before make a request to backend, but API itself could not, so validate flags here
|
||||
if v.Required && v.Name != "name" && flagValue == "" {
|
||||
return app, fmt.Errorf("required flag(s) \"%s\" not set", v.Name)
|
||||
flag := flagSet.Lookup(v.Name)
|
||||
if v.Name == "name" {
|
||||
continue
|
||||
}
|
||||
if flag == nil || flag.Value.String() == "" {
|
||||
if v.Required {
|
||||
return nil, fmt.Errorf("required flag(s) \"%s\" not set", v.Name)
|
||||
}
|
||||
continue
|
||||
}
|
||||
switch v.Type {
|
||||
case cue.IntKind:
|
||||
d, _ := strconv.ParseInt(flagValue, 10, 64)
|
||||
workloadData[v.Name] = d
|
||||
workloadData[v.Name], err = flagSet.GetInt64(v.Name)
|
||||
case cue.StringKind:
|
||||
workloadData[v.Name] = flagValue
|
||||
workloadData[v.Name], err = flagSet.GetString(v.Name)
|
||||
case cue.BoolKind:
|
||||
d, _ := strconv.ParseBool(flagValue)
|
||||
workloadData[v.Name] = d
|
||||
workloadData[v.Name], err = flagSet.GetBool(v.Name)
|
||||
case cue.NumberKind, cue.FloatKind:
|
||||
d, _ := strconv.ParseFloat(flagValue, 64)
|
||||
workloadData[v.Name] = d
|
||||
workloadData[v.Name], err = flagSet.GetFloat64(v.Name)
|
||||
}
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "of flag of type string") {
|
||||
data, _ := flagSet.GetString(v.Name)
|
||||
switch v.Type {
|
||||
case cue.IntKind:
|
||||
workloadData[v.Name], err = strconv.ParseInt(data, 10, 64)
|
||||
case cue.BoolKind:
|
||||
workloadData[v.Name], err = strconv.ParseBool(data)
|
||||
case cue.NumberKind, cue.FloatKind:
|
||||
workloadData[v.Name], err = strconv.ParseFloat(data, 64)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get flag(s) \"%s\" err %v", v.Name, err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
return nil, fmt.Errorf("get flag(s) \"%s\" err %v", v.Name, err)
|
||||
}
|
||||
}
|
||||
if err = app.SetWorkload(workloadName, tp, workloadData); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user