mirror of
https://github.com/kubevela/kubevela.git
synced 2026-02-14 18:10:21 +00:00
fix run bug
This commit is contained in:
@@ -52,17 +52,18 @@ func main() {
|
||||
logs.InitLogs()
|
||||
defer logs.FlushLogs()
|
||||
|
||||
cmdutil.CheckErr(command.Execute())
|
||||
command.Execute()
|
||||
}
|
||||
|
||||
func newCommand(args []string) *cobra.Command {
|
||||
ioStream := cmdutil.IOStreams{In: os.Stdin, Out: os.Stdout, ErrOut: os.Stderr}
|
||||
|
||||
cmds := &cobra.Command{
|
||||
Use: "rudrx",
|
||||
Short: "rudrx is a command-line tool to use OAM based micro-app engine.",
|
||||
Long: "rudrx is a command-line tool to use OAM based micro-app engine.",
|
||||
Run: runHelp,
|
||||
Use: "rudrx",
|
||||
Short: "rudrx is a command-line tool to use OAM based micro-app engine.",
|
||||
Long: "rudrx is a command-line tool to use OAM based micro-app engine.",
|
||||
Run: runHelp,
|
||||
SilenceUsage: true,
|
||||
}
|
||||
|
||||
flags := cmds.PersistentFlags()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
apiVersion: admin.oam.dev/v1alpha2
|
||||
kind: Template
|
||||
metadata:
|
||||
annotation:
|
||||
annotations:
|
||||
version: 0.0.1
|
||||
name: containerizedworkload-template
|
||||
spec:
|
||||
|
||||
@@ -3,7 +3,7 @@ kind: WorkloadDefinition
|
||||
metadata:
|
||||
name: containerizedworkloads.core.oam.dev
|
||||
annotations:
|
||||
defatultTemplateRef: containerizedworkload-template
|
||||
rudrx.oam.dev/template: containerizedworkload-template
|
||||
short: containerized
|
||||
spec:
|
||||
definitionRef:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
apiVersion: admin.oam.dev/v1alpha2
|
||||
kind: Template
|
||||
metadata:
|
||||
annotation:
|
||||
annotations:
|
||||
version: 0.0.1
|
||||
name: manualscalertrait.core.oam.dev-template
|
||||
spec:
|
||||
|
||||
@@ -3,7 +3,7 @@ kind: TraitDefinition
|
||||
metadata:
|
||||
name: manualscalertrait.core.oam.dev
|
||||
annotations:
|
||||
defatultTemplateRef: manualscalertrait.core.oam.dev-template
|
||||
rudrx.oam.dev/template: manualscalertrait.core.oam.dev-template
|
||||
short: ManualScaler
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
|
||||
@@ -3,7 +3,7 @@ kind: TraitDefinition
|
||||
metadata:
|
||||
name: simplerollouttraits.extend.oam.dev
|
||||
annotations:
|
||||
defatultTemplateRef: simplerollouttraits.extend.oam.dev-template
|
||||
rudrx.oam.dev/template: simplerollouttraits.extend.oam.dev-template
|
||||
short: SimpleRollout
|
||||
spec:
|
||||
revisionEnabled: true
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
apiVersion: admin.oam.dev/v1alpha2
|
||||
kind: Template
|
||||
metadata:
|
||||
annotation:
|
||||
annotations:
|
||||
version: 0.0.1
|
||||
name: simplerollouttraits.extend.oam.dev-template
|
||||
spec:
|
||||
|
||||
@@ -22,15 +22,12 @@ import (
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
"k8s.io/client-go/rest"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/envtest"
|
||||
"sigs.k8s.io/controller-runtime/pkg/envtest/printer"
|
||||
logf "sigs.k8s.io/controller-runtime/pkg/log"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log/zap"
|
||||
|
||||
coreoamdevv1alpha2 "github.com/cloud-native-application/rudrx/api/v1alpha2"
|
||||
// +kubebuilder:scaffold:imports
|
||||
)
|
||||
|
||||
@@ -57,19 +54,20 @@ var _ = BeforeSuite(func(done Done) {
|
||||
CRDDirectoryPaths: []string{filepath.Join("..", "config", "crd", "bases")},
|
||||
}
|
||||
|
||||
var err error
|
||||
cfg, err = testEnv.Start()
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(cfg).ToNot(BeNil())
|
||||
// TODO add later
|
||||
// var err error
|
||||
// cfg, err = testEnv.Start()
|
||||
// Expect(err).ToNot(HaveOccurred())
|
||||
// Expect(cfg).ToNot(BeNil())
|
||||
|
||||
err = coreoamdevv1alpha2.AddToScheme(scheme.Scheme)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
// err = coreoamdevv1alpha2.AddToScheme(scheme.Scheme)
|
||||
// Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// +kubebuilder:scaffold:scheme
|
||||
// // +kubebuilder:scaffold:scheme
|
||||
|
||||
k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(k8sClient).ToNot(BeNil())
|
||||
// k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme})
|
||||
// Expect(err).ToNot(HaveOccurred())
|
||||
// Expect(k8sClient).ToNot(BeNil())
|
||||
|
||||
close(done)
|
||||
}, 60)
|
||||
|
||||
@@ -16,6 +16,9 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
// TemplateLabel is the Annotation refer to template
|
||||
const TemplateLabel = "rudrx.oam.dev/template"
|
||||
|
||||
type commandOptions struct {
|
||||
Namespace string
|
||||
Template v1alpha2.Template
|
||||
@@ -33,36 +36,52 @@ func NewCommandOptions(ioStreams cmdutil.IOStreams) *commandOptions {
|
||||
// NewBindCommand return bind command
|
||||
func NewBindCommand(f cmdutil.Factory, c client.Client, ioStreams cmdutil.IOStreams, args []string) *cobra.Command {
|
||||
cmd := newBindCommand()
|
||||
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
||||
return runSubBindCommand(f, c, ioStreams, args)
|
||||
}
|
||||
cmd.SetOutput(ioStreams.Out)
|
||||
cmd.SetArgs(args)
|
||||
cmd.SetOut(ioStreams.Out)
|
||||
cmd.DisableFlagParsing = true
|
||||
|
||||
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
||||
return runSubBindCommand(cmd, f, c, ioStreams, args)
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runSubBindCommand(f cmdutil.Factory, c client.Client, ioStreams cmdutil.IOStreams, args []string) error {
|
||||
var traitDefinitions corev1alpha2.TraitDefinitionList
|
||||
func runSubBindCommand(parentCmd *cobra.Command, f cmdutil.Factory, c client.Client, ioStreams cmdutil.IOStreams, args []string) error {
|
||||
ctx := context.Background()
|
||||
o := NewCommandOptions(ioStreams)
|
||||
o.Client = c
|
||||
|
||||
bindCmd := newBindCommand()
|
||||
bindCmd.SetOutput(ioStreams.Out)
|
||||
// init fake command and pass args to fake command
|
||||
// flags and subcommand append to fake comand and parent command
|
||||
// run fake command only, show tips in parent command only
|
||||
fakeCommand := newBindCommand()
|
||||
fakeCommand.SilenceUsage = true
|
||||
fakeCommand.SilenceErrors = true
|
||||
fakeCommand.DisableAutoGenTag = true
|
||||
fakeCommand.DisableFlagsInUseLine = true
|
||||
fakeCommand.DisableSuggestions = true
|
||||
fakeCommand.SetOut(o.Out)
|
||||
if len(args) > 0 {
|
||||
bindCmd.SetArgs(args[1:])
|
||||
fakeCommand.SetArgs(args)
|
||||
} else {
|
||||
fakeCommand.SetArgs([]string{})
|
||||
}
|
||||
|
||||
var traitDefinitions corev1alpha2.TraitDefinitionList
|
||||
err := c.List(ctx, &traitDefinitions)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Listing trait definitions hit an issue: %v", err)
|
||||
}
|
||||
|
||||
for _, t := range traitDefinitions.Items {
|
||||
template := t.ObjectMeta.Annotations["defatultTemplateRef"]
|
||||
for _, template := range traitDefinitions.Items {
|
||||
templateName := template.Annotations[TemplateLabel]
|
||||
// skip tarit that without template
|
||||
if templateName == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
var traitTemplate v1alpha2.Template
|
||||
err := c.Get(ctx, client.ObjectKey{Namespace: "default", Name: template}, &traitTemplate)
|
||||
err := c.Get(ctx, client.ObjectKey{Namespace: "default", Name: templateName}, &traitTemplate)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Listing trait template hit an issue: %v", err)
|
||||
}
|
||||
@@ -73,23 +92,25 @@ func runSubBindCommand(f cmdutil.Factory, c client.Client, ioStreams cmdutil.IOS
|
||||
if err != nil {
|
||||
return fmt.Errorf("Parameters type is wrong: %v .Please report this to OAM maintainer, thanks.", err)
|
||||
}
|
||||
bindCmd.PersistentFlags().Int(p.Name, v, p.Usage)
|
||||
fakeCommand.PersistentFlags().Int(p.Name, v, p.Usage)
|
||||
parentCmd.PersistentFlags().Int(p.Name, v, p.Usage)
|
||||
} else {
|
||||
bindCmd.PersistentFlags().String(p.Name, p.Default, p.Usage)
|
||||
fakeCommand.PersistentFlags().String(p.Name, p.Default, p.Usage)
|
||||
parentCmd.PersistentFlags().String(p.Name, p.Default, p.Usage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bindCmd.RunE = func(cmd *cobra.Command, args []string) error {
|
||||
if err := o.Complete(f, bindCmd, args, ctx); err != nil {
|
||||
fakeCommand.RunE = func(cmd *cobra.Command, args []string) error {
|
||||
if err := o.Complete(fakeCommand, f, args, ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return o.Run(f, bindCmd, ctx)
|
||||
return o.Run(f, fakeCommand, ctx)
|
||||
}
|
||||
return bindCmd.Execute()
|
||||
return fakeCommand.Execute()
|
||||
}
|
||||
|
||||
func (o *commandOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string, ctx context.Context) error {
|
||||
func (o *commandOptions) Complete(cmd *cobra.Command, f cmdutil.Factory, args []string, ctx context.Context) error {
|
||||
argsLength := len(args)
|
||||
var componentName string
|
||||
c := o.Client
|
||||
@@ -121,10 +142,10 @@ func (o *commandOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []
|
||||
case 1:
|
||||
// Validate component and suggest trait
|
||||
errTip := "Error: No trait specified.\nPlease choose a trait: "
|
||||
for _, t := range traitList {
|
||||
n := t.Short
|
||||
for _, trait := range traitList {
|
||||
n := trait.Short
|
||||
if n == "" {
|
||||
n = t.Name
|
||||
n = trait.Name
|
||||
}
|
||||
errTip += n + " "
|
||||
}
|
||||
@@ -135,11 +156,11 @@ func (o *commandOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []
|
||||
var traitLongName string
|
||||
|
||||
validTrait := false
|
||||
for _, t := range traitList {
|
||||
for _, trait := range traitList {
|
||||
// Support trait name or trait short name case-sensitively
|
||||
if strings.EqualFold(t.Name, traitName) || strings.EqualFold(t.Short, traitName) {
|
||||
if strings.EqualFold(trait.Name, traitName) || strings.EqualFold(trait.Short, traitName) {
|
||||
validTrait = true
|
||||
traitLongName = t.Name
|
||||
traitLongName = trait.Name
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -152,7 +173,7 @@ func (o *commandOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []
|
||||
c.Get(ctx, client.ObjectKey{Namespace: ns, Name: traitLongName}, &traitDefinition)
|
||||
|
||||
var traitTemplate v1alpha2.Template
|
||||
c.Get(ctx, client.ObjectKey{Namespace: "default", Name: traitDefinition.ObjectMeta.Annotations["defatultTemplateRef"]}, &traitTemplate)
|
||||
c.Get(ctx, client.ObjectKey{Namespace: "default", Name: traitDefinition.ObjectMeta.Annotations[TemplateLabel]}, &traitTemplate)
|
||||
|
||||
pvd := fieldpath.Pave(traitTemplate.Spec.Object.Object)
|
||||
for _, v := range traitTemplate.Spec.Parameters {
|
||||
@@ -188,7 +209,7 @@ func (o *commandOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []
|
||||
|
||||
// Run command
|
||||
func (o *commandOptions) Run(f cmdutil.Factory, cmd *cobra.Command, ctx context.Context) error {
|
||||
o.Info("Applying trait for component", o.Component.Name)
|
||||
o.Infof("Applying trait for component %s\n", o.Component.Name)
|
||||
c := o.Client
|
||||
err := c.Update(ctx, &o.AppConfig)
|
||||
if err != nil {
|
||||
|
||||
63
pkg/cmd/bind_test.go
Normal file
63
pkg/cmd/bind_test.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
"github.com/cloud-native-application/rudrx/pkg/test"
|
||||
)
|
||||
|
||||
func TestNewBindCommand(t *testing.T) {
|
||||
TraitsNotApply := traitDefinitionExample.DeepCopy()
|
||||
TraitsNotApply.Spec.AppliesToWorkloads = []string{"core.oam.dev/v1alpha2.ContainerizedWorkload"}
|
||||
|
||||
cases := map[string]*test.CliTestCase{
|
||||
"WithNoArgs": {
|
||||
Resources: test.InitResources{
|
||||
Create: []runtime.Object{
|
||||
traitDefinitionExample.DeepCopy(),
|
||||
traitTemplateExample.DeepCopy(),
|
||||
},
|
||||
},
|
||||
ExpectedOutput: "Please append the name of an application. Use `rudr bind -h` for more detailed information.",
|
||||
Args: []string{},
|
||||
WantException: true,
|
||||
},
|
||||
"WithWrongAppconfig": {
|
||||
Resources: test.InitResources{
|
||||
Create: []runtime.Object{
|
||||
traitDefinitionExample.DeepCopy(),
|
||||
traitTemplateExample.DeepCopy(),
|
||||
},
|
||||
},
|
||||
ExpectedOutput: "applicationconfigurations.core.oam.dev \"frontend\" not found",
|
||||
Args: []string{"frontend"},
|
||||
WantException: true,
|
||||
},
|
||||
"TemplateParametersWork": {
|
||||
Resources: test.InitResources{
|
||||
Create: []runtime.Object{
|
||||
traitDefinitionExample.DeepCopy(),
|
||||
traitTemplateExample.DeepCopy(),
|
||||
},
|
||||
},
|
||||
ExpectedString: "--replicaCount int",
|
||||
Args: []string{"-h"},
|
||||
},
|
||||
"WorkSuccess": {
|
||||
Resources: test.InitResources{
|
||||
Create: []runtime.Object{
|
||||
appconfigExample.DeepCopy(),
|
||||
componentExample.DeepCopy(),
|
||||
traitDefinitionExample.DeepCopy(),
|
||||
traitTemplateExample.DeepCopy(),
|
||||
},
|
||||
},
|
||||
ExpectedOutput: "Applying trait for component app2060\nSucceeded!",
|
||||
Args: []string{"app2060", "ManualScaler", "--replicaCount", "5"},
|
||||
},
|
||||
}
|
||||
|
||||
test.NewCliTest(t, scheme, NewBindCommand, cases).Run()
|
||||
}
|
||||
192
pkg/cmd/fixtures_test.go
Normal file
192
pkg/cmd/fixtures_test.go
Normal file
@@ -0,0 +1,192 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
|
||||
|
||||
"github.com/cloud-native-application/rudrx/api/v1alpha2"
|
||||
"github.com/crossplane/oam-kubernetes-runtime/apis/core"
|
||||
corev1alpha2 "github.com/crossplane/oam-kubernetes-runtime/apis/core/v1alpha2"
|
||||
)
|
||||
|
||||
var (
|
||||
scheme = runtime.NewScheme()
|
||||
)
|
||||
|
||||
func init() {
|
||||
_ = clientgoscheme.AddToScheme(scheme)
|
||||
_ = v1alpha2.AddToScheme(scheme)
|
||||
_ = core.AddToScheme(scheme)
|
||||
// +kubebuilder:scaffold:scheme
|
||||
}
|
||||
|
||||
// used in testing
|
||||
var (
|
||||
workloadTemplateExample = &v1alpha2.Template{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: "admin.oam.dev/v1alpha2",
|
||||
Kind: "Template",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "containerizedworkload-template",
|
||||
Annotations: map[string]string{
|
||||
"version": "0.0.1",
|
||||
},
|
||||
Namespace: "default",
|
||||
},
|
||||
Spec: v1alpha2.TemplateSpec{
|
||||
Object: unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"apiVersion": "core.oam.dev/v1alpha2",
|
||||
"kind": "ContainerizedWorkload",
|
||||
"metadata": map[string]interface{}{
|
||||
"name": "pod",
|
||||
},
|
||||
"spec": map[string]interface{}{
|
||||
"containers": "",
|
||||
},
|
||||
},
|
||||
},
|
||||
LastCommandParam: "image",
|
||||
Parameters: []v1alpha2.Parameter{
|
||||
v1alpha2.Parameter{
|
||||
Name: "image",
|
||||
Short: "i",
|
||||
Required: true,
|
||||
Type: "string",
|
||||
FieldPaths: []string{"spec.containers[0].image"},
|
||||
},
|
||||
v1alpha2.Parameter{
|
||||
Name: "port",
|
||||
Short: "p",
|
||||
Required: false,
|
||||
Type: "int",
|
||||
FieldPaths: []string{"spec.containers[0].ports[0].containerPort"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
traitTemplateExample = &v1alpha2.Template{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: "admin.oam.dev/v1alpha2",
|
||||
Kind: "Template",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "manualscalertrait.core.oam.dev-template",
|
||||
Annotations: map[string]string{
|
||||
"version": "0.0.1",
|
||||
},
|
||||
Namespace: "default",
|
||||
},
|
||||
Spec: v1alpha2.TemplateSpec{
|
||||
Object: unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"apiVersion": "core.oam.dev/v1alpha2",
|
||||
"kind": "ManualScalerTrait",
|
||||
"metadata": map[string]interface{}{
|
||||
"name": "pod",
|
||||
},
|
||||
"spec": map[string]interface{}{
|
||||
"replicaCount": "2",
|
||||
},
|
||||
},
|
||||
},
|
||||
Parameters: []v1alpha2.Parameter{
|
||||
v1alpha2.Parameter{
|
||||
Name: "replicaCount",
|
||||
Short: "i",
|
||||
Required: true,
|
||||
Type: "int",
|
||||
FieldPaths: []string{"spec.replicaCount"},
|
||||
Default: "5",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
workloaddefExample = &corev1alpha2.WorkloadDefinition{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: "core.oam.dev/v1alpha2",
|
||||
Kind: "WorkloadDefinition",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "containerizedworkloads.core.oam.dev",
|
||||
Annotations: map[string]string{
|
||||
"rudrx.oam.dev/template": "containerizedworkload-template",
|
||||
},
|
||||
Namespace: "default",
|
||||
},
|
||||
Spec: corev1alpha2.WorkloadDefinitionSpec{
|
||||
Reference: corev1alpha2.DefinitionReference{
|
||||
Name: "containerizedworkloads.core.oam.dev",
|
||||
},
|
||||
ChildResourceKinds: []corev1alpha2.ChildResourceKind{
|
||||
corev1alpha2.ChildResourceKind{
|
||||
APIVersion: "apps/v1",
|
||||
Kind: "Deployment",
|
||||
},
|
||||
corev1alpha2.ChildResourceKind{
|
||||
APIVersion: "v1",
|
||||
Kind: "Service",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
appconfigExample = &corev1alpha2.ApplicationConfiguration{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: "core.oam.dev/v1alpha2",
|
||||
Kind: "ApplicationConfiguration",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "app2060",
|
||||
Annotations: map[string]string{
|
||||
"rudrx.oam.dev/template": "containerizedworkload-template",
|
||||
},
|
||||
Namespace: "default",
|
||||
},
|
||||
Spec: corev1alpha2.ApplicationConfigurationSpec{
|
||||
Components: []corev1alpha2.ApplicationConfigurationComponent{
|
||||
corev1alpha2.ApplicationConfigurationComponent{
|
||||
ComponentName: "app2060",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
componentExample = &corev1alpha2.Component{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: "core.oam.dev/v1alpha2",
|
||||
Kind: "Component",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "app2060",
|
||||
Namespace: "default",
|
||||
},
|
||||
Spec: corev1alpha2.ComponentSpec{},
|
||||
}
|
||||
|
||||
traitDefinitionExample = &corev1alpha2.TraitDefinition{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: "core.oam.dev/v1alpha2",
|
||||
Kind: "TraitDefinition",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "manualscalertrait.core.oam.dev",
|
||||
Namespace: "default",
|
||||
Annotations: map[string]string{
|
||||
"rudrx.oam.dev/template": "manualscalertrait.core.oam.dev-template",
|
||||
"short": "ManualScaler",
|
||||
},
|
||||
},
|
||||
Spec: corev1alpha2.TraitDefinitionSpec{
|
||||
Reference: corev1alpha2.DefinitionReference{
|
||||
Name: "manualscalertrait.core.oam.dev",
|
||||
},
|
||||
AppliesToWorkloads: []string{"core.oam.dev/v1alpha2.ContainerizedWorkload"},
|
||||
},
|
||||
}
|
||||
)
|
||||
@@ -30,28 +30,50 @@ func newRunOptions(ioStreams cmdutil.IOStreams) *runOptions {
|
||||
return &runOptions{IOStreams: ioStreams}
|
||||
}
|
||||
|
||||
// NewRunCommand init new command
|
||||
func NewRunCommand(f cmdutil.Factory, c client.Client, ioStreams cmdutil.IOStreams, args []string) *cobra.Command {
|
||||
cmd := newRunCommand()
|
||||
// flags pass to new command directly
|
||||
cmd.DisableFlagParsing = true
|
||||
cmd.SetArgs(args)
|
||||
cmd.SetOut(ioStreams.Out)
|
||||
|
||||
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
||||
return runSubRunCommand(f, c, ioStreams, args)
|
||||
return runSubRunCommand(cmd, f, c, ioStreams, args)
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runSubRunCommand(f cmdutil.Factory, c client.Client, ioStreams cmdutil.IOStreams, args []string) error {
|
||||
// runSubRunCommand is init a new command and run independent
|
||||
func runSubRunCommand(parentCmd *cobra.Command, f cmdutil.Factory, c client.Client, ioStreams cmdutil.IOStreams, args []string) error {
|
||||
ctx := context.Background()
|
||||
workloadNames := []string{}
|
||||
o := newRunOptions(ioStreams)
|
||||
o.client = c
|
||||
|
||||
// init new cmd, append sub cmd
|
||||
runCmd := newRunCommand()
|
||||
runCmd.SetOutput(o.Out)
|
||||
runCmd.PersistentFlags().StringP("namespace", "n", "default", "namespace for apps")
|
||||
// init fake command and pass args to fake command
|
||||
// flags and subcommand append to fake comand and parent command
|
||||
// run fake command only, show tips in parent command only
|
||||
fakeCommand := newRunCommand()
|
||||
fakeCommand.SilenceUsage = true
|
||||
fakeCommand.SilenceErrors = true
|
||||
fakeCommand.DisableAutoGenTag = true
|
||||
fakeCommand.DisableFlagsInUseLine = true
|
||||
fakeCommand.DisableSuggestions = true
|
||||
|
||||
// set args from parent
|
||||
if len(args) > 0 {
|
||||
runCmd.SetArgs(args[1:])
|
||||
fakeCommand.SetArgs(args)
|
||||
} else {
|
||||
fakeCommand.SetArgs([]string{})
|
||||
}
|
||||
fakeCommand.SetOutput(o.Out)
|
||||
fakeCommand.RunE = func(cmd *cobra.Command, args []string) error {
|
||||
return errors.New("You must specify a workload, like " + strings.Join(workloadNames, ", ") +
|
||||
"\nSee 'rudr run -h' for help and examples")
|
||||
}
|
||||
fakeCommand.PersistentFlags().StringP("namespace", "n", "default", "namespace for apps")
|
||||
parentCmd.PersistentFlags().StringP("namespace", "n", "default", "namespace for apps")
|
||||
|
||||
var workloadDefs corev1alpha2.WorkloadDefinitionList
|
||||
err := c.List(ctx, &workloadDefs)
|
||||
@@ -70,15 +92,15 @@ func runSubRunCommand(f cmdutil.Factory, c client.Client, ioStreams cmdutil.IOSt
|
||||
name = wd.Name
|
||||
}
|
||||
workloadNames = append(workloadNames, name)
|
||||
templateRef, ok := wd.ObjectMeta.Annotations["defatultTemplateRef"]
|
||||
templateRef, ok := wd.ObjectMeta.Annotations[TemplateLabel]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
var tmp v1alpha2.Template
|
||||
err = c.Get(ctx, client.ObjectKey{Namespace: "", Name: templateRef}, &tmp)
|
||||
err = c.Get(ctx, client.ObjectKey{Namespace: "default", Name: templateRef}, &tmp)
|
||||
if err != nil {
|
||||
return fmt.Errorf("list workload Definition err: %v", err)
|
||||
return fmt.Errorf("get workload Definition err: %v", err)
|
||||
}
|
||||
|
||||
subcmd := &cobra.Command{
|
||||
@@ -96,18 +118,16 @@ func runSubRunCommand(f cmdutil.Factory, c client.Client, ioStreams cmdutil.IOSt
|
||||
subcmd.SetOutput(o.Out)
|
||||
for _, v := range tmp.Spec.Parameters {
|
||||
if tmp.Spec.LastCommandParam != v.Name {
|
||||
runCmd.PersistentFlags().StringP(v.Name, v.Short, v.Default, v.Usage)
|
||||
subcmd.PersistentFlags().StringP(v.Name, v.Short, v.Default, v.Usage)
|
||||
}
|
||||
}
|
||||
|
||||
runCmd.AddCommand(subcmd)
|
||||
tmp.DeepCopyInto(&o.Template)
|
||||
fakeCommand.AddCommand(subcmd)
|
||||
parentCmd.AddCommand(subcmd)
|
||||
}
|
||||
|
||||
runCmd.RunE = func(cmd *cobra.Command, args []string) error {
|
||||
return errors.New("You must specify a workload, like " + strings.Join(workloadNames, ", ") +
|
||||
"\nSee 'rudr run -h' for help and examples")
|
||||
}
|
||||
return runCmd.Execute()
|
||||
return fakeCommand.Execute()
|
||||
}
|
||||
|
||||
func (o *runOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
|
||||
@@ -156,7 +176,6 @@ func (o *runOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []stri
|
||||
}
|
||||
|
||||
pvd.SetString("metadata.name", args[0])
|
||||
|
||||
namespaceCover := cmd.Flag("namespace").Value.String()
|
||||
if namespaceCover != "" {
|
||||
namespace = namespaceCover
|
||||
@@ -171,7 +190,7 @@ func (o *runOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []stri
|
||||
}
|
||||
|
||||
func (o *runOptions) Run(f cmdutil.Factory, cmd *cobra.Command) error {
|
||||
o.Infof("Creating AppConfig %s", o.AppConfig.Name)
|
||||
o.Infof("Creating AppConfig %s\n", o.AppConfig.Name)
|
||||
err := o.client.Create(context.Background(), &o.Component)
|
||||
if err != nil {
|
||||
return fmt.Errorf("create component err: %s", err)
|
||||
|
||||
@@ -1,201 +1,81 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"gotest.tools/assert"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
k8sRuntime "k8s.io/apimachinery/pkg/runtime"
|
||||
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
|
||||
cmdtesting "k8s.io/kubectl/pkg/cmd/testing"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client/fake"
|
||||
|
||||
coreoamdevv1alpha2 "github.com/cloud-native-application/rudrx/api/v1alpha2"
|
||||
cmdutil "github.com/cloud-native-application/rudrx/pkg/cmd/util"
|
||||
"github.com/crossplane/oam-kubernetes-runtime/apis/core"
|
||||
corev1alpha2 "github.com/crossplane/oam-kubernetes-runtime/apis/core/v1alpha2"
|
||||
"github.com/cloud-native-application/rudrx/pkg/test"
|
||||
)
|
||||
|
||||
var (
|
||||
scheme = k8sRuntime.NewScheme()
|
||||
)
|
||||
|
||||
type testResources struct {
|
||||
create []runtime.Object
|
||||
update []runtime.Object
|
||||
}
|
||||
|
||||
func init() {
|
||||
_ = clientgoscheme.AddToScheme(scheme)
|
||||
_ = coreoamdevv1alpha2.AddToScheme(scheme)
|
||||
_ = core.AddToScheme(scheme)
|
||||
// +kubebuilder:scaffold:scheme
|
||||
}
|
||||
|
||||
func TestNewRunCommand(t *testing.T) {
|
||||
templateExample, workloaddefExample := getTestExample()
|
||||
|
||||
templateExample2 := templateExample.DeepCopy()
|
||||
workloadTemplateExample2 := workloadTemplateExample.DeepCopy()
|
||||
workloaddefExample2 := workloaddefExample.DeepCopy()
|
||||
workloaddefExample2.Annotations["short"] = "containerized"
|
||||
|
||||
cases := map[string]struct {
|
||||
resources *testResources
|
||||
// want to exist with error
|
||||
wantException bool
|
||||
// output equal to
|
||||
expectedOutput string
|
||||
// output contains
|
||||
expectedString string
|
||||
args []string
|
||||
}{
|
||||
cases := map[string]*test.CliTestCase{
|
||||
"WorkloadNotDefinited": {
|
||||
resources: &testResources{
|
||||
create: []runtime.Object{
|
||||
workloaddefExample,
|
||||
templateExample,
|
||||
Resources: test.InitResources{
|
||||
Create: []runtime.Object{
|
||||
workloaddefExample.DeepCopy(),
|
||||
workloadTemplateExample.DeepCopy(),
|
||||
},
|
||||
},
|
||||
wantException: true,
|
||||
expectedString: "You must specify a workload, like containerizedworkloads.core.oam.dev",
|
||||
args: []string{},
|
||||
WantException: true,
|
||||
ExpectedString: "You must specify a workload, like containerizedworkloads.core.oam.dev",
|
||||
Args: []string{},
|
||||
},
|
||||
"WorkloadShortWork": {
|
||||
resources: &testResources{
|
||||
create: []runtime.Object{
|
||||
workloaddefExample2,
|
||||
templateExample2,
|
||||
Resources: test.InitResources{
|
||||
Create: []runtime.Object{
|
||||
workloaddefExample2.DeepCopy(),
|
||||
workloadTemplateExample2.DeepCopy(),
|
||||
},
|
||||
},
|
||||
wantException: true,
|
||||
expectedString: "You must specify a workload, like containerized",
|
||||
args: []string{},
|
||||
WantException: true,
|
||||
ExpectedString: "You must specify a workload, like containerized",
|
||||
Args: []string{},
|
||||
},
|
||||
"PortFlagNotSet": {
|
||||
Resources: test.InitResources{
|
||||
Create: []runtime.Object{
|
||||
workloaddefExample2.DeepCopy(),
|
||||
workloadTemplateExample2.DeepCopy(),
|
||||
},
|
||||
},
|
||||
ExpectedResources: []runtime.Object{
|
||||
appconfigExample,
|
||||
componentExample,
|
||||
},
|
||||
WantException: true,
|
||||
ExpectedString: "Flag `port` is NOT set, please check and try again.",
|
||||
Args: []string{"containerized", "app2060", "nginx:1.9.4"},
|
||||
},
|
||||
"TemplateParametersWork": {
|
||||
Resources: test.InitResources{
|
||||
Create: []runtime.Object{
|
||||
workloaddefExample2.DeepCopy(),
|
||||
workloadTemplateExample2.DeepCopy(),
|
||||
},
|
||||
},
|
||||
ExpectedString: "-p, --port",
|
||||
Args: []string{"containerized", "-h"},
|
||||
},
|
||||
"AppConfigCreated": {
|
||||
Resources: test.InitResources{
|
||||
Create: []runtime.Object{
|
||||
workloaddefExample2.DeepCopy(),
|
||||
workloadTemplateExample2.DeepCopy(),
|
||||
},
|
||||
},
|
||||
ExpectedExistResources: []runtime.Object{
|
||||
appconfigExample,
|
||||
componentExample,
|
||||
},
|
||||
ExpectedOutput: "Creating AppConfig app2060\nSUCCEED",
|
||||
Args: []string{"containerized", "app2060", "nginx:1.9.4", "-p", "80"},
|
||||
},
|
||||
}
|
||||
for name, tc := range cases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
factory := cmdtesting.NewTestFactory().WithNamespace("test")
|
||||
client := fake.NewFakeClientWithScheme(scheme)
|
||||
iostream, _, outPut, _ := cmdutil.NewTestIOStreams()
|
||||
|
||||
if len(tc.resources.create) != 0 {
|
||||
for _, resource := range tc.resources.create {
|
||||
err := client.Create(context.TODO(), resource)
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(tc.resources.update) != 0 {
|
||||
for _, resource := range tc.resources.update {
|
||||
err := client.Update(context.TODO(), resource)
|
||||
println(111, err.Error())
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
}
|
||||
runCmd := NewRunCommand(factory, client, iostream, []string{})
|
||||
runCmd.SetOutput(outPut)
|
||||
|
||||
err := runCmd.Execute()
|
||||
errTip := tc.expectedString
|
||||
if tc.expectedOutput != "" {
|
||||
errTip = tc.expectedOutput
|
||||
}
|
||||
if tc.wantException {
|
||||
assert.ErrorContains(t, err, errTip)
|
||||
return
|
||||
}
|
||||
|
||||
if tc.expectedOutput != "" {
|
||||
assert.Equal(t, tc.expectedOutput, outPut.String())
|
||||
return
|
||||
}
|
||||
|
||||
assert.Equal(t, true, strings.Contains(outPut.String(), tc.expectedString))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func getTestExample() (*coreoamdevv1alpha2.Template, *corev1alpha2.WorkloadDefinition) {
|
||||
templateExample := &coreoamdevv1alpha2.Template{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: "admin.oam.dev/v1alpha2",
|
||||
Kind: "Template",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "containerizedworkload-template",
|
||||
Annotations: map[string]string{
|
||||
"version": "0.0.1",
|
||||
},
|
||||
},
|
||||
Spec: coreoamdevv1alpha2.TemplateSpec{
|
||||
Object: unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"apiVersion": "core.oam.dev/v1alpha2",
|
||||
"kind": "ContainerizedWorkload",
|
||||
"metadata": map[string]interface{}{
|
||||
"name": "pod",
|
||||
},
|
||||
"spec": map[string]interface{}{
|
||||
"containers": `
|
||||
- image: myrepo/myapp:v1
|
||||
name: master
|
||||
ports:
|
||||
- containerPort: 6379
|
||||
protocol: TCP
|
||||
name: tbd`,
|
||||
},
|
||||
},
|
||||
},
|
||||
LastCommandParam: "image",
|
||||
Parameters: []coreoamdevv1alpha2.Parameter{
|
||||
coreoamdevv1alpha2.Parameter{
|
||||
Name: "image",
|
||||
Short: "i",
|
||||
Required: true,
|
||||
Type: "string",
|
||||
FieldPaths: []string{"spec.containers[0].image"},
|
||||
},
|
||||
coreoamdevv1alpha2.Parameter{
|
||||
Name: "port",
|
||||
Short: "p",
|
||||
Required: false,
|
||||
Type: "int",
|
||||
FieldPaths: []string{"spec.containers[0].ports[0].containerPort"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
workloaddefExample := &corev1alpha2.WorkloadDefinition{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: "core.oam.dev/v1alpha2",
|
||||
Kind: "WorkloadDefinition",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "containerizedworkloads.core.oam.dev",
|
||||
Annotations: map[string]string{
|
||||
"defatultTemplateRef": "containerizedworkload-template",
|
||||
},
|
||||
},
|
||||
Spec: corev1alpha2.WorkloadDefinitionSpec{
|
||||
Reference: corev1alpha2.DefinitionReference{
|
||||
Name: "containerizedworkloads.core.oam.dev",
|
||||
},
|
||||
ChildResourceKinds: []corev1alpha2.ChildResourceKind{
|
||||
corev1alpha2.ChildResourceKind{
|
||||
APIVersion: "apps/v1",
|
||||
Kind: "Deployment",
|
||||
},
|
||||
corev1alpha2.ChildResourceKind{
|
||||
APIVersion: "v1",
|
||||
Kind: "Service",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return templateExample, workloaddefExample
|
||||
test.NewCliTest(t, scheme, NewRunCommand, cases).Run()
|
||||
}
|
||||
|
||||
37
pkg/cmd/trait_test.go
Normal file
37
pkg/cmd/trait_test.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
"github.com/cloud-native-application/rudrx/pkg/test"
|
||||
)
|
||||
|
||||
func TestNewTraitCommand(t *testing.T) {
|
||||
TraitsNotApply := traitDefinitionExample.DeepCopy()
|
||||
TraitsNotApply.Spec.AppliesToWorkloads = []string{}
|
||||
|
||||
cases := map[string]*test.CliTestCase{
|
||||
"PrintTraits": {
|
||||
Resources: test.InitResources{
|
||||
Create: []runtime.Object{
|
||||
traitDefinitionExample.DeepCopy(),
|
||||
},
|
||||
},
|
||||
ExpectedString: "manualscalertrait.core.oam.dev",
|
||||
Args: []string{},
|
||||
},
|
||||
"TraitsNotApply": {
|
||||
Resources: test.InitResources{
|
||||
Create: []runtime.Object{
|
||||
TraitsNotApply,
|
||||
},
|
||||
},
|
||||
ExpectedOutput: "NAME SHORT DEFINITION APPLIES TO STATUS",
|
||||
Args: []string{},
|
||||
},
|
||||
}
|
||||
|
||||
test.NewCliTest(t, scheme, NewTraitsCommand, cases).Run()
|
||||
}
|
||||
@@ -22,16 +22,19 @@ func NewTraitsCommand(f cmdutil.Factory, c client.Client, ioStreams cmdutil.IOSt
|
||||
Example: `rudr traits`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
workloadName := cmd.Flag("workload").Value.String()
|
||||
return printTraitList(ctx, c, workloadName)
|
||||
return printTraitList(ctx, c, workloadName, ioStreams)
|
||||
},
|
||||
}
|
||||
|
||||
cmd.SetOutput(ioStreams.Out)
|
||||
// flags pass to new command directly
|
||||
cmd.DisableFlagParsing = true
|
||||
cmd.SetArgs(args)
|
||||
cmd.SetOut(ioStreams.Out)
|
||||
cmd.PersistentFlags().StringP("workload", "w", "", "Workload name")
|
||||
return cmd
|
||||
}
|
||||
|
||||
func printTraitList(ctx context.Context, c client.Client, workloadName string) error {
|
||||
func printTraitList(ctx context.Context, c client.Client, workloadName string, ioStreams cmdutil.IOStreams) error {
|
||||
traitList, err := RetrieveTraitsByWorkload(ctx, c, workloadName)
|
||||
|
||||
table := uitable.New()
|
||||
@@ -45,8 +48,7 @@ func printTraitList(ctx context.Context, c client.Client, workloadName string) e
|
||||
for _, r := range traitList {
|
||||
table.AddRow(r.Name, r.Short, r.Definition, r.AppliesTo, r.Status)
|
||||
}
|
||||
|
||||
fmt.Println(table)
|
||||
ioStreams.Info(table.String())
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -64,7 +66,6 @@ func RetrieveTraitsByWorkload(ctx context.Context, c client.Client, workloadName
|
||||
Get trait list by optional filter `workloadName`
|
||||
*/
|
||||
var traitList []TraitMeta
|
||||
|
||||
var traitDefinitionList corev1alpha2.TraitDefinitionList
|
||||
err := c.List(ctx, &traitDefinitionList)
|
||||
|
||||
|
||||
125
pkg/test/cli.go
Normal file
125
pkg/test/cli.go
Normal file
@@ -0,0 +1,125 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"gotest.tools/assert"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
cmdtesting "k8s.io/kubectl/pkg/cmd/testing"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client/fake"
|
||||
|
||||
cmdutil "github.com/cloud-native-application/rudrx/pkg/cmd/util"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// CliTest test engine
|
||||
type CliTest interface {
|
||||
Run()
|
||||
}
|
||||
|
||||
// InitResources resource to init before run testing
|
||||
type InitResources struct {
|
||||
Create []runtime.Object
|
||||
Update []runtime.Object
|
||||
}
|
||||
|
||||
// CliTestCase is testing case for cli
|
||||
type CliTestCase struct {
|
||||
// Resources to init
|
||||
Resources InitResources
|
||||
// ExpectedExistResources expected exist resources
|
||||
ExpectedExistResources []runtime.Object
|
||||
// ExpectedResources expected resources exist and equal
|
||||
ExpectedResources []runtime.Object
|
||||
// WantException expected exit with error
|
||||
WantException bool
|
||||
// ExpectedOutput output equal to
|
||||
ExpectedOutput string
|
||||
// ExpectedString output contains strings
|
||||
ExpectedString string
|
||||
Args []string
|
||||
// Namespaces to run
|
||||
Namespaces string
|
||||
}
|
||||
|
||||
type clitestImpl struct {
|
||||
cases map[string]*CliTestCase
|
||||
t *testing.T
|
||||
scheme *runtime.Scheme
|
||||
command func(f cmdutil.Factory, c client.Client, ioStreams cmdutil.IOStreams, args []string) *cobra.Command
|
||||
}
|
||||
|
||||
// NewCliTest return cli testimpl
|
||||
func NewCliTest(t *testing.T, scheme *runtime.Scheme,
|
||||
command func(f cmdutil.Factory, c client.Client, ioStreams cmdutil.IOStreams,
|
||||
args []string) *cobra.Command, cases map[string]*CliTestCase) CliTest {
|
||||
return &clitestImpl{
|
||||
cases: cases,
|
||||
t: t,
|
||||
scheme: scheme,
|
||||
command: command,
|
||||
}
|
||||
}
|
||||
|
||||
// Run testing
|
||||
func (c *clitestImpl) Run() {
|
||||
for name, tc := range c.cases {
|
||||
c.t.Run(name, func(t *testing.T) {
|
||||
factory := cmdtesting.NewTestFactory().WithNamespace("default")
|
||||
fakeClient := fake.NewFakeClientWithScheme(c.scheme)
|
||||
iostream, _, outPut, _ := cmdutil.NewTestIOStreams()
|
||||
|
||||
// init resources
|
||||
if len(tc.Resources.Create) != 0 {
|
||||
for _, resource := range tc.Resources.Create {
|
||||
err := fakeClient.Create(context.TODO(), resource)
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
}
|
||||
if len(tc.Resources.Update) != 0 {
|
||||
for _, resource := range tc.Resources.Update {
|
||||
err := fakeClient.Update(context.TODO(), resource)
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
// init command
|
||||
runCmd := c.command(factory, fakeClient, iostream, tc.Args)
|
||||
runCmd.SetOutput(outPut)
|
||||
err := runCmd.Execute()
|
||||
|
||||
// check expected resources
|
||||
if len(tc.ExpectedExistResources) != 0 {
|
||||
for _, expectedResource := range tc.ExpectedExistResources {
|
||||
object, _ := expectedResource.(metav1.Object)
|
||||
|
||||
resource := expectedResource.DeepCopyObject()
|
||||
err := fakeClient.Get(context.TODO(), client.ObjectKey{Namespace: object.GetNamespace(), Name: object.GetName()}, resource)
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
// check exit output
|
||||
errTip := tc.ExpectedString
|
||||
if tc.ExpectedOutput != "" {
|
||||
errTip = tc.ExpectedOutput
|
||||
}
|
||||
if tc.WantException {
|
||||
assert.ErrorContains(t, err, errTip)
|
||||
return
|
||||
}
|
||||
|
||||
// check output messages
|
||||
if tc.ExpectedOutput != "" {
|
||||
assert.Equal(t, tc.ExpectedOutput, outPut.String())
|
||||
return
|
||||
}
|
||||
|
||||
assert.Equal(t, true, strings.Contains(outPut.String(), tc.ExpectedString))
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user