refactor application object to have more strict schema

This commit is contained in:
天元
2020-12-29 15:48:32 +08:00
parent c0ebe8dc62
commit 3a47d5de73
21 changed files with 372 additions and 252 deletions
+1 -1
View File
@@ -105,7 +105,7 @@ vet:
lint: golangci
$(GOLANGCILINT) run ./...
reviewable: fmt vet lint manifests
reviewable: manifests fmt vet lint
go mod tidy
# Execute auto-gen code commands and ensure branch is clean.
@@ -46,6 +46,31 @@ type AppStatus struct {
Phase ApplicationPhase `json:"status,omitempty"`
}
// ApplicationTrait defines the trait of application
type ApplicationTrait struct {
Name string `json:"name"`
// +kubebuilder:pruning:PreserveUnknownFields
Properties runtime.RawExtension `json:"properties"`
}
// ApplicationComponent describe the component of application
type ApplicationComponent struct {
Name string `json:"name"`
WorkloadType string `json:"type"`
// +kubebuilder:pruning:PreserveUnknownFields
Settings runtime.RawExtension `json:"settings"`
// Traits define the trait of one component, the type must be array to keep the order.
Traits []ApplicationTrait `json:"traits,omitempty"`
}
// ApplicationSpec is the spec of Application
type ApplicationSpec struct {
Components []ApplicationComponent `json:"components"`
// TODO(wonderflow): there should have scopes defined here
}
// +kubebuilder:object:root=true
// Application is the Schema for the applications API
@@ -54,9 +79,8 @@ type Application struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
// +kubebuilder:pruning:PreserveUnknownFields
Spec runtime.RawExtension `json:"spec,omitempty"`
Status AppStatus `json:"status,omitempty"`
Spec ApplicationSpec `json:"spec,omitempty"`
Status AppStatus `json:"status,omitempty"`
}
// +kubebuilder:object:root=true
@@ -68,6 +68,29 @@ func (in *Application) DeepCopyObject() runtime.Object {
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ApplicationComponent) DeepCopyInto(out *ApplicationComponent) {
*out = *in
in.Settings.DeepCopyInto(&out.Settings)
if in.Traits != nil {
in, out := &in.Traits, &out.Traits
*out = make([]ApplicationTrait, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationComponent.
func (in *ApplicationComponent) DeepCopy() *ApplicationComponent {
if in == nil {
return nil
}
out := new(ApplicationComponent)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ApplicationConfiguration) DeepCopyInto(out *ApplicationConfiguration) {
*out = *in
@@ -346,6 +369,44 @@ func (in *ApplicationList) DeepCopyObject() runtime.Object {
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ApplicationSpec) DeepCopyInto(out *ApplicationSpec) {
*out = *in
if in.Components != nil {
in, out := &in.Components, &out.Components
*out = make([]ApplicationComponent, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationSpec.
func (in *ApplicationSpec) DeepCopy() *ApplicationSpec {
if in == nil {
return nil
}
out := new(ApplicationSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ApplicationTrait) DeepCopyInto(out *ApplicationTrait) {
*out = *in
in.Properties.DeepCopyInto(&out.Properties)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationTrait.
func (in *ApplicationTrait) DeepCopy() *ApplicationTrait {
if in == nil {
return nil
}
out := new(ApplicationTrait)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CPUResources) DeepCopyInto(out *CPUResources) {
*out = *in
@@ -30,8 +30,43 @@ spec:
metadata:
type: object
spec:
description: ApplicationSpec is the spec of Application
properties:
components:
items:
description: ApplicationComponent describe the component of application
properties:
name:
type: string
settings:
type: object
x-kubernetes-preserve-unknown-fields: true
traits:
description: Traits define the trait of one component, the type must be array to keep the order.
items:
description: ApplicationTrait defines the trait of application
properties:
name:
type: string
properties:
type: object
x-kubernetes-preserve-unknown-fields: true
required:
- name
- properties
type: object
type: array
type:
type: string
required:
- name
- settings
- type
type: object
type: array
required:
- components
type: object
x-kubernetes-preserve-unknown-fields: true
status:
description: AppStatus defines the observed state of Application
properties:
@@ -27,24 +27,26 @@ metadata:
name: application-sample
namespace: oam-test
spec:
services:
myweb:
cmd:
- sleep
- "1000"
image: busybox
scaler:
replicas: 10
service:
http:
server: 80
sidecar:
command:
components:
- name: myweb
type: worker
settings:
image: "busybox"
cmd:
- sleep
- "1000"
image: busybox
name: test-sidecar
type: worker
traits:
- name: scaler
properties:
replicas: 10
- name: sidercar
properties:
name: "sidecar-test"
image: "nginx"
- name: kservice
properties:
http:
server: 80
status:
conditions:
- lastTransitionTime: "2020-12-02T12:12:52Z"
@@ -112,13 +112,14 @@ kind: Application
metadata:
name: application-sample
spec:
services:
myweb:
components:
- name: myweb
type: worker
image: "busybox"
cmd:
- sleep
- "1000"
settings:
image: "busybox"
cmd:
- sleep
- "1000"
```
we will get a deployment
```
@@ -149,7 +150,7 @@ kind: TraitDefinition
metadata:
annotations:
definition.oam.dev/description: "service the app"
name: service
name: kservice
spec:
appliesToWorkloads:
- webservice
@@ -185,16 +186,19 @@ kind: Application
metadata:
name: application-sample
spec:
services:
myweb:
components:
- name: myweb
type: worker
image: "busybox"
cmd:
- sleep
- "1000"
service:
http:
server: 80
settings:
image: "busybox"
cmd:
- sleep
- "1000"
traits:
- name: kservice
properties:
http:
server: 80
```
we will get a new deployment and service
@@ -258,23 +262,22 @@ spec:
```
If add scaler capability to the application, as follows
```
apiVersion: core.oam.dev/v1alpha2
kind: Application
metadata:
name: application-sample
spec:
services:
myweb:
components:
- name: myweb
type: worker
image: "busybox"
cmd:
- sleep
- "1000"
service:
http:
server: 80
scaler:
replicas: 10
settings:
image: "busybox"
cmd:
- sleep
- "1000"
traits:
- name: kservice
properties:
http:
server: 80
- name: scaler
properties:
replicas: 10
```
The deployment replicas will be scale to 10
@@ -336,21 +339,26 @@ kind: Application
metadata:
name: application-sample
spec:
services:
myweb:
components:
- name: myweb
type: worker
image: "busybox"
cmd:
- sleep
- "1000"
service:
http:
server: 80
scaler:
replicas: 10
sidercar:
name: "sidecar-test"
image: "nginx"
settings:
image: "busybox"
cmd:
- sleep
- "1000"
traits:
- name: scaler
properties:
replicas: 10
- name: sidercar
properties:
name: "sidecar-test"
image: "nginx"
- name: kservice
properties:
http:
server: 80
```
The deployment updated as follows
```
@@ -0,0 +1,25 @@
apiVersion: core.oam.dev/v1alpha2
kind: Application
metadata:
name: application-sample
spec:
components:
- name: myweb
type: worker
settings:
image: "busybox"
cmd:
- sleep
- "1000"
traits:
- name: scaler
properties:
replicas: 10
- name: sidercar
properties:
name: "sidecar-test"
image: "nginx"
- name: kservice
properties:
http:
server: 80
@@ -95,7 +95,7 @@ kind: TraitDefinition
metadata:
annotations:
definition.oam.dev/description: "service the app"
name: service
name: kservice
spec:
appliesToWorkloads:
- webservice
@@ -1,20 +0,0 @@
apiVersion: core.oam.dev/v1alpha2
kind: Application
metadata:
name: application-sample
spec:
services:
myweb:
type: worker
image: "busybox"
cmd:
- sleep
- "1000"
scaler:
replicas: 10
sidercar:
name: "sidecar-test"
image: "nginx"
service:
http:
server: 80
-1
View File
@@ -57,7 +57,6 @@ require (
golang.org/x/text v0.3.4 // indirect
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0
gopkg.in/yaml.v3 v3.0.0-20200603094226-e3079894b1e8
gotest.tools v2.2.0+incompatible
helm.sh/helm/v3 v3.2.4
k8s.io/api v0.18.8
@@ -30,8 +30,43 @@ spec:
metadata:
type: object
spec:
description: ApplicationSpec is the spec of Application
properties:
components:
items:
description: ApplicationComponent describe the component of application
properties:
name:
type: string
settings:
type: object
traits:
description: Traits define the trait of one component, the type must be array to keep the order.
items:
description: ApplicationTrait defines the trait of application
properties:
name:
type: string
properties:
type: object
required:
- name
- properties
type: object
type: array
type:
type: string
required:
- name
- settings
- type
type: object
type: array
required:
- components
type: object
status:
description: AppStatus defines the observed state of Application
properties:
@@ -76,12 +76,7 @@ func (r *Reconciler) Reconcile(req ctrl.Request) (result ctrl.Result, gerr error
// parse template
appParser := parser.NewParser(template.GetHanler(fclient.NewDefinitionClient(r.Client)))
expr, err := parser.DecodeJSONMarshaler(app.Spec)
if err != nil {
app.Status.SetConditions(errorCondition("Parsed", err))
return handler.Err(err)
}
appfile, err := appParser.Parse(app.Name, expr)
appfile, err := appParser.Parse(app.Name, app)
if err != nil {
app.Status.SetConditions(errorCondition("Parsed", err))
@@ -66,7 +66,7 @@ func (ret *reter) apply(ac *v1alpha2.ApplicationConfiguration, comps ...*v1alpha
objs = append(objs, ac)
listOption := listObjs(client.MatchingLabels{
builder.OamApplicationLabel: ret.app.Name,
builder.OAMApplicationLabel: ret.app.Name,
}, client.InNamespace(ret.app.Namespace))
isController := true
@@ -21,8 +21,8 @@ type builder struct {
}
const (
// OamApplicationLabel is application's metadata label
OamApplicationLabel = "application.oam.dev"
// OAMApplicationLabel is application's metadata label
OAMApplicationLabel = "application.oam.dev"
)
// Build template to applicationConfig & Component
@@ -42,9 +42,9 @@ func (b *builder) Complete(ns string) (*v1alpha2.ApplicationConfiguration, []*v1
if appconfig.Labels == nil {
appconfig.Labels = map[string]string{}
}
appconfig.Labels[OamApplicationLabel] = b.app.Name()
appconfig.Labels[OAMApplicationLabel] = b.app.Name()
componets := []*v1alpha2.Component{}
var componets []*v1alpha2.Component
for _, wl := range b.app.Services() {
compCtx := map[string]string{"name": wl.Name()}
@@ -58,7 +58,7 @@ func (b *builder) Complete(ns string) (*v1alpha2.ApplicationConfiguration, []*v1
if component.Labels == nil {
component.Labels = map[string]string{}
}
component.Labels[OamApplicationLabel] = b.app.Name()
component.Labels[OAMApplicationLabel] = b.app.Name()
component.SetGroupVersionKind(v1alpha2.ComponentGroupVersionKind)
componets = append(componets, component)
@@ -89,9 +89,9 @@ func (b *builder) CompleteWithContext(ns string) (*v1alpha2.ApplicationConfigura
if appconfig.Labels == nil {
appconfig.Labels = map[string]string{}
}
appconfig.Labels[OamApplicationLabel] = b.app.Name()
appconfig.Labels[OAMApplicationLabel] = b.app.Name()
componets := []*v1alpha2.Component{}
var components []*v1alpha2.Component
for _, wl := range b.app.Services() {
pCtx := process.NewContext(wl.Name())
if err := wl.EvalContext(pCtx); err != nil {
@@ -113,24 +113,24 @@ func (b *builder) CompleteWithContext(ns string) (*v1alpha2.ApplicationConfigura
if comp.Labels == nil {
comp.Labels = map[string]string{}
}
comp.Labels[OamApplicationLabel] = b.app.Name()
comp.Labels[OAMApplicationLabel] = b.app.Name()
comp.SetGroupVersionKind(v1alpha2.ComponentGroupVersionKind)
componets = append(componets, comp)
components = append(components, comp)
appconfig.Spec.Components = append(appconfig.Spec.Components, *acComp)
}
return appconfig, componets, nil
return appconfig, components, nil
}
func generateOAM(pCtx process.Context) (*v1alpha2.Component, *v1alpha2.ApplicationConfigurationComponent, error) {
base, assists := pCtx.Output()
componetWorkload, err := base.Object(nil)
componentWorkload, err := base.Object(nil)
if err != nil {
return nil, nil, err
}
component := &v1alpha2.Component{}
component.Spec.Workload.Object = componetWorkload
component.Spec.Workload.Object = componentWorkload
acComponent := &v1alpha2.ApplicationConfigurationComponent{}
acComponent.Traits = []v1alpha2.ComponentTrait{}
@@ -1,8 +1,6 @@
package parser
import (
"fmt"
"cuelang.org/go/cue"
cueJson "cuelang.org/go/pkg/encoding/json"
"github.com/pkg/errors"
@@ -94,8 +92,7 @@ func (trait *Trait) Eval(render Render) ([]v1alpha2.ComponentTrait, error) {
outputs := inst.Lookup("outputs")
iter, err := outputs.List()
if err != nil {
return nil, errors.Errorf("output|outputs not found in traitDef %s ", trait.name)
// return nil,errors.WithMessagef(err,"traitDef %s outputs must be list",trait.name)
return nil, errors.Errorf("'output' or 'outputs' not found in trait definition %s ", trait.name)
}
for iter.Next() {
cueValues = append(cueValues, iter.Value())
@@ -164,95 +161,71 @@ func NewParser(handler template.Handler) *Parser {
}
// Parse convert map to Appfile
func (pser *Parser) Parse(name string, expr map[string]interface{}) (*Appfile, error) {
var svcs interface{}
for _, name := range []string{"Service", "Services", "service", "services"} {
if v, ok := expr[name]; ok {
svcs = v
}
}
if svcs == nil {
return nil, errors.Errorf("services require")
}
func (pser *Parser) Parse(name string, app *v1alpha2.Application) (*Appfile, error) {
appfile := new(Appfile)
appfile.name = name
switch v := svcs.(type) {
case map[string]interface{}:
wds := []*Workload{}
for name, wi := range v {
wd, err := pser.parseWorkload(name, wi)
if err != nil {
return nil, err
}
wds = append(wds, wd)
var wds []*Workload
for _, comp := range app.Spec.Components {
wd, err := pser.parseWorkload(comp)
if err != nil {
return nil, err
}
appfile.services = wds
default:
return nil, errors.Errorf("services format invalid(must be map)")
wds = append(wds, wd)
}
appfile.services = wds
return appfile, nil
}
func (pser *Parser) parseWorkload(name string, expr interface{}) (*Workload, error) {
func (pser *Parser) parseWorkload(comp v1alpha2.ApplicationComponent) (*Workload, error) {
workload := new(Workload)
workload.traits = []*Trait{}
workload.name = name
switch v := expr.(type) {
case map[string]interface{}:
_type, ok := v["type"]
if !ok {
return nil, errors.Errorf("type not specify")
workload.name = comp.Name
workload.typ = comp.WorkloadType
templ, kind, err := pser.templ(workload.typ)
if err != nil && !kerrors.IsNotFound(err) {
return nil, errors.WithMessagef(err, "fetch type of %s", comp.Name)
}
if kind != template.WorkloadKind {
return nil, errors.Errorf("%s type (%s) invalid", comp.Name, workload.typ)
}
workload.template = templ
settings, err := DecodeJSONMarshaler(comp.Settings)
if err != nil {
return nil, errors.Errorf("fail to parse settings for %s", comp.Name)
}
workload.params = settings
for _, traitValue := range comp.Traits {
properties, err := DecodeJSONMarshaler(traitValue.Properties)
if err != nil {
return nil, errors.Errorf("fail to parse properties of %s for %s", traitValue.Name, comp.Name)
}
workload.typ = fmt.Sprint(_type)
templ, kind, err := pser.templ(workload.typ)
if err != nil && !kerrors.IsNotFound(err) {
return nil, errors.WithMessagef(err, "fetch %s' type", name)
trait, err := pser.parseTrait(traitValue.Name, properties)
if err != nil {
return nil, errors.WithMessagef(err, "component(%s) parse trait(%s)", comp.Name, traitValue.Name)
}
if kind == template.Unkownkind || kind == template.TraitKind {
return nil, errors.Errorf("%s type (%s) invalid", name, workload.typ)
}
workload.template = templ
params := map[string]interface{}{}
for lable, value := range v {
if lable == "type" {
continue
}
trait, err := pser.parseTrait(lable, value)
if err != nil {
return nil, errors.WithMessagef(err, "service(%s) parse trait(%s)", name, lable)
}
if trait == nil {
params[lable] = value
} else {
workload.traits = append(workload.traits, trait)
}
}
workload.params = params
default:
return nil, errors.Errorf("service(%s) format invalid", name)
workload.traits = append(workload.traits, trait)
}
return workload, nil
}
func (pser *Parser) parseTrait(label string, expr interface{}) (*Trait, error) {
func (pser *Parser) parseTrait(name string, properties map[string]interface{}) (*Trait, error) {
templ, kind, err := pser.templ(label)
templ, kind, err := pser.templ(name)
if err != nil && !kerrors.IsNotFound(err) {
return nil, err
}
if kind != template.TraitKind {
return nil, nil
return nil, errors.Errorf("kind of %s is not trait", name)
}
trait := new(Trait)
trait.template = templ
trait.name = label
switch v := expr.(type) {
case map[string]interface{}:
trait.params = v
default:
return nil, errors.Errorf("trait %s params must be map", label)
}
trait.name = name
trait.params = properties
return trait, nil
}
@@ -310,7 +283,7 @@ var TestExceptApp = &Appfile{
{
name: "scaler",
params: map[string]interface{}{
"replicas": 10,
"replicas": float64(10),
},
template: `
output: {
@@ -6,8 +6,9 @@ import (
"testing"
"cuelang.org/go/cue"
"gopkg.in/yaml.v3"
"github.com/ghodss/yaml"
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2"
"github.com/oam-dev/kubevela/pkg/controller/core.oam.dev/v1alpha2/application/defclient"
"github.com/oam-dev/kubevela/pkg/controller/core.oam.dev/v1alpha2/application/template"
)
@@ -93,26 +94,33 @@ spec:
}`)
const appfileYaml = `
services:
myweb:
type: worker
image: "busybox"
cmd:
- sleep
- "1000"
scaler:
replicas: 10
apiVersion: core.oam.dev/v1alpha2
kind: Application
metadata:
name: application-sample
spec:
components:
- name: myweb
type: worker
settings:
image: "busybox"
cmd:
- sleep
- "1000"
traits:
- name: scaler
properties:
replicas: 10
`
o := map[string]interface{}{}
o := v1alpha2.Application{}
yaml.Unmarshal([]byte(appfileYaml), &o)
appfile, err := NewParser(template.GetHanler(mock)).Parse("test", o)
appfile, err := NewParser(template.GetHanler(mock)).Parse("test", &o)
if err != nil {
t.Error(err)
return
}
if !equal(TestExceptApp, appfile) {
t.Error("parser appfile wrong")
}
@@ -112,8 +112,15 @@ var _ = Describe("Test Application Controller", func() {
Name: "application-sample",
Namespace: ns.Name,
},
Spec: runtime.RawExtension{
Raw: []byte("{\"services\":{\"myweb\":{\"cmd\":[\"sleep\",\"1000\"],\"image\":\"busybox\",\"scaler\":{\"replicas\":10},\"type\":\"worker\"}}}")},
Spec: v1alpha2.ApplicationSpec{
Components: []v1alpha2.ApplicationComponent{
{
Name: "myweb",
WorkloadType: "worker",
Settings: runtime.RawExtension{Raw: []byte("{\"cmd\":[\"sleep\",\"1000\"],\"image\":\"busybox\"}")},
},
},
},
}
wd := &v1alpha2.WorkloadDefinition{}
@@ -2,7 +2,6 @@ package application
import (
"context"
"encoding/json"
"net/http"
admissionv1beta1 "k8s.io/api/admission/v1beta1"
@@ -61,11 +60,7 @@ func (h *ValidatingHandler) Handle(ctx context.Context, req admission.Request) a
// try render to validate
appParser := parser.NewParser(template.GetHanler(fclient.NewDefinitionClient(h.Client)))
expr := map[string]interface{}{}
if err := json.Unmarshal(app.Spec.Raw, &expr); err != nil {
return admission.Denied(err.Error())
}
if _, err := appParser.Parse(app.Name, expr); err != nil {
if _, err := appParser.Parse(app.Name, app); err != nil {
return admission.Denied(err.Error())
}
return admission.ValidationResponse(true, "")
@@ -38,28 +38,13 @@ var _ = Describe("Test Application Validater", func() {
Operation: admissionv1beta1.Create,
Resource: metav1.GroupVersionResource{Group: "core.oam.dev", Version: "v1alpha2", Resource: "applications"},
Object: runtime.RawExtension{
Raw: []byte(`{
"apiVersion": "core.oam.dev/v1alpha2",
"kind": "Application",
"metadata": {
"name": "application-sample"
},
"spec": {
"services": {
"myweb": {
"type": "worker",
"image": "busybox",
"cmd": [
"sleep",
"1000"
],
"scaler": {
"replicas": 10
}
}
}
}
}`),
Raw: []byte(`
{"apiVersion":"core.oam.dev/v1alpha2",
"kind":"Application",
"metadata":{"name":"application-sample"},
"spec":{"components":[{"name":"myweb","settings":{"cmd":["sleep","1000"],"image":"busybox"},
"traits":[{"name":"scaler","properties":{"replicas":10}}],"type":"worker"}]}}
`),
},
},
}
@@ -72,28 +57,11 @@ var _ = Describe("Test Application Validater", func() {
Operation: admissionv1beta1.Create,
Resource: metav1.GroupVersionResource{Group: "core.oam.dev", Version: "v1alpha2", Resource: "applications"},
Object: runtime.RawExtension{
Raw: []byte(`{
"apiVersion": "core.oam.dev/v1alpha2",
"kind": "Application",
"metadata": {
"name": "application-sample"
},
"spec": {
"services": {
"myweb": {
"type": "worker1",
"image": "busybox",
"cmd": [
"sleep",
"1000"
],
"scaler": {
"replicas": 10
}
}
}
}
}`),
Raw: []byte(`{"apiVersion":"core.oam.dev/v1alpha2",
"kind":"Application",
"metadata":{"name":"application-sample"},
"spec":{"components":[{"name":"myweb","settings":{"cmd":["sleep","1000"],"image":"busybox"},
"traits":[{"name":"scaler","properties":{"replicas":10}}],"type":"worker1"}]}}`),
},
},
}
+5 -8
View File
@@ -7,24 +7,21 @@ import (
"io/ioutil"
"time"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"github.com/ghodss/yaml"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/oam-dev/kubevela/pkg/oam/util"
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2"
"github.com/ghodss/yaml"
appsv1 "k8s.io/api/apps/v1"
v1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2"
"github.com/oam-dev/kubevela/pkg/oam/util"
)
var _ = Describe("Versioning mechanism of components", func() {
+8
View File
@@ -181,6 +181,14 @@ var _ = Describe("HealthScope", func() {
}
logf.Log.Info("Creating component", "Name", comp.Name, "Namespace", comp.Namespace)
Expect(k8sClient.Create(ctx, &comp)).Should(BeNil())
By("check component successfully created")
Eventually(
func() error {
return k8sClient.Get(ctx, client.ObjectKey{Name: componentName, Namespace: comp.Namespace}, &comp)
},
time.Second*5, time.Millisecond*100).Should(BeNil())
// Create application configuration
workloadInstanceName1 := "example-appconfig-healthscope-a"
workloadInstanceName2 := "example-appconfig-healthscope-b"