Compare commits

...

19 Commits

Author SHA1 Message Date
github-actions[bot]
f95ff4f06e [Backport release-1.1] Fix: make nginx class to be default value and allow pvc trait to attach more than once (#2471)
* Fix: make nginx class to be default value

(cherry picked from commit 9c41df7b0f)

* Fix: allow pvc trait to attach more than once

(cherry picked from commit 33cf15e439)

Co-authored-by: 天元 <jianbo.sjb@alibaba-inc.com>
2021-10-13 17:21:43 +08:00
github-actions[bot]
e30876e4d2 Fix: compatibility bug (#2470)
make reivwable

(cherry picked from commit df5a802bd4)

Co-authored-by: wangyike <wangyike_wyk@163.com>
2021-10-13 16:59:30 +08:00
github-actions[bot]
141c6bb2ef [Backport release-1.1] Fix: change raw extension to pointer (#2469)
* Fix: change raw extension to pointer

(cherry picked from commit 113f785c97)

* Test: fix ut

(cherry picked from commit 7b9dac98c2)

Co-authored-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2021-10-13 16:58:20 +08:00
github-actions[bot]
bdfd8e1f8d Fix: wrong log print format (#2453)
(cherry picked from commit 16ecbb8b91)

Co-authored-by: Xiaoxi He <xxhe@alauda.io>
2021-10-12 19:27:53 +08:00
github-actions[bot]
cfbaf38715 [Backport release-1.1] Fix: Closure Bug In newValue (#2452)
* Fix: new value bug

(cherry picked from commit dc184327a0)

* Fix: strategyUnify Bug

(cherry picked from commit 1b2c049ea8)

* Fix: e2e error

(cherry picked from commit f9bfbc0d53)

Co-authored-by: Jian.Li <lj176172@alibaba-inc.com>
2021-10-12 19:10:39 +08:00
github-actions[bot]
d3006f2d9e [Backport release-1.1] Fix: fix unhandled err (#2450)
* Fix: fix unhandled err

refer to https://lift.sonatype.com/result/bhamail/kubevela/01FFT7CSVNCPF6808ZM856V3HN?tab=results

(cherry picked from commit d0ced6cfc9)

* Test: fix panic err

(cherry picked from commit e5e5f9ac42)

Co-authored-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2021-10-12 14:36:52 +08:00
github-actions[bot]
8f7aa9b746 Fix: update ingress class (#2447)
(cherry picked from commit 77e1b8296c)

Co-authored-by: Yin Da <yd219913@alibaba-inc.com>
2021-10-11 20:50:00 +08:00
github-actions[bot]
8431cdb10d [Backport release-1.1] Fix: add Chart icon and url (#2446)
* Fix: add Chart icon and url

Added an icon and url for KubeVela chart

(cherry picked from commit 4dcca2a47f)

* Fix: remove local logo file and use a web image

(cherry picked from commit a86bdb9639)

Co-authored-by: zzxwill <zzxwill@gmail.com>
2021-10-11 20:46:44 +08:00
wyike
66013a9607 Fix: confilict (#2443)
Fix: nil pointer panic
2021-10-11 17:56:18 +08:00
github-actions[bot]
1d133df1dd [Backport release-1.1] Feat: add support for envbinding with namespace selector (#2440)
* Feat: add support for envbinding with namespace selector

(cherry picked from commit 409fe1bf38)

* Fix: service account kubeconfig e2e-test

(cherry picked from commit db7539641c)

* Docs: add comments to explain functions

(cherry picked from commit c9bf6b8914)

* Docs: add envbinding example

(cherry picked from commit 0011c4563f)

Co-authored-by: Yin Da <yd219913@alibaba-inc.com>
2021-10-11 15:36:20 +08:00
github-actions[bot]
c66f5f103f Fix: fix depends on app built-in step (#2435)
(cherry picked from commit b126cf1a34)

Co-authored-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2021-10-09 18:52:57 +08:00
github-actions[bot]
e6779f6906 [Backport release-1.1] Fix: fix apiserver 1.1.3 not available bug (#2431)
* Fix: fix apiserver 1.1.3 not available bug

(cherry picked from commit a0b0c032d4)

* Feat: change apiserver image repository

(cherry picked from commit d417e9014a)

* Fix(helm chart): fix startup args for apiserver

(cherry picked from commit fa759459af)

Co-authored-by: barnettZQG <yiyun.pro>
2021-10-09 16:52:05 +08:00
github-actions[bot]
a48b74d4be Feat: add secure tls for cluster-gateway (#2428)
(cherry picked from commit cf4d508189)

Co-authored-by: Yin Da <yd219913@alibaba-inc.com>
2021-10-09 15:24:41 +08:00
github-actions[bot]
2da80af3c4 [Backport release-1.1] Feat: add apply raw built in workflow steps (#2424)
* Feat: add apply raw built in workflow steps

(cherry picked from commit be68f388a2)

* Feat: add apply raw example

(cherry picked from commit 8243b6d916)

* Fix: change the name to apply object

(cherry picked from commit b996a04862)

* Fix: example server name

(cherry picked from commit 2341bf0f5a)

Co-authored-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2021-10-09 12:21:28 +08:00
github-actions[bot]
7bf5e17262 Chore(deps): bump github.com/containerd/containerd from 1.4.8 to 1.4.11 (#2422)
(cherry picked from commit 8450b4153e)

Co-authored-by: 天元 <jianbo.sjb@alibaba-inc.com>
2021-10-09 11:12:08 +08:00
Zheng Xi Zhou
53a6d54b73 Fix: support terraform/provider-azure addon (#2402) (#2418)
Also added some componentdefinitions for Azure cloud resource
2021-10-08 19:14:59 +08:00
github-actions[bot]
bcd072507b [Backport release-1.1] Feat: multicluster support ServiceAccountToken (#2415)
* Feat: support serviceaccount in multicluster

(cherry picked from commit 6168af830e)

* Fix: add compatibility & support sa

(cherry picked from commit 0193d74dfa)

* Fix: add multicluster sa test

(cherry picked from commit d445d29649)

* Fix: add test for upgrade func

(cherry picked from commit f4ba55b540)

* Style: format

(cherry picked from commit 0a8645c30c)

Co-authored-by: Yin Da <yd219913@alibaba-inc.com>
2021-10-08 15:55:12 +08:00
qiaozp
ae075e6cb6 Refactor(cli): Refactor vela env, deprecate vela config (#2037) (#2413)
* Refactor(cli): cut env to namespace, use application to save

Signed-off-by: qiaozp <chivalry.pp@gmail.com>

* Fix: test

* Fix: typo

(cherry picked from commit a574fc0fbf)
2021-10-08 14:44:30 +08:00
Somefive
b2127ee4fa Feat: use #ApplyComponent for EnvBinding (#2382) (#2414)
* Feat: use #ApplyComponent in EnvBinding

* Fix: application test compRev control by resourcetracker

* Fix: add more detail in error info
2021-10-08 14:43:44 +08:00
172 changed files with 3246 additions and 3238 deletions

View File

@@ -17,9 +17,13 @@ limitations under the License.
package common
import (
"encoding/json"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
types "github.com/oam-dev/terraform-controller/api/types/crossplane-runtime"
"github.com/oam-dev/kubevela/apis/core.oam.dev/condition"
"github.com/oam-dev/kubevela/apis/standard.oam.dev/v1alpha1"
@@ -109,6 +113,9 @@ type Terraform struct {
// +kubebuilder:default:=hcl
// +kubebuilder:validation:Enum:=hcl;json;remote
Type string `json:"type,omitempty"`
// ProviderReference specifies the reference to Provider
ProviderReference *types.Reference `json:"providerRef,omitempty"`
}
// A WorkloadTypeDescriptor refer to a Workload Type
@@ -369,7 +376,7 @@ type AppRolloutStatus struct {
type ApplicationTrait struct {
Type string `json:"type"`
// +kubebuilder:pruning:PreserveUnknownFields
Properties runtime.RawExtension `json:"properties,omitempty"`
Properties *runtime.RawExtension `json:"properties,omitempty"`
}
// ApplicationComponent describe the component of application
@@ -379,7 +386,7 @@ type ApplicationComponent struct {
// ExternalRevision specified the component revisionName
ExternalRevision string `json:"externalRevision,omitempty"`
// +kubebuilder:pruning:PreserveUnknownFields
Properties runtime.RawExtension `json:"properties,omitempty"`
Properties *runtime.RawExtension `json:"properties,omitempty"`
DependsOn []string `json:"dependsOn,omitempty"`
Inputs StepInputs `json:"inputs,omitempty"`
@@ -452,3 +459,29 @@ type ClusterObjectReference struct {
Creator ResourceCreatorRole `json:"creator,omitempty"`
corev1.ObjectReference `json:",inline"`
}
// RawExtensionPointer is the pointer of raw extension
type RawExtensionPointer struct {
RawExtension *runtime.RawExtension
}
// MarshalJSON may get called on pointers or values, so implement MarshalJSON on value.
// http://stackoverflow.com/questions/21390979/custom-marshaljson-never-gets-called-in-go
func (re RawExtensionPointer) MarshalJSON() ([]byte, error) {
if re.RawExtension == nil {
return nil, nil
}
if re.RawExtension.Raw == nil {
// TODO: this is to support legacy behavior of JSONPrinter and YAMLPrinter, which
// expect to call json.Marshal on arbitrary versioned objects (even those not in
// the scheme). pkg/kubectl/resource#AsVersionedObjects and its interaction with
// kubectl get on objects not in the scheme needs to be updated to ensure that the
// objects that are not part of the scheme are correctly put into the right form.
if re.RawExtension.Object != nil {
return json.Marshal(re.RawExtension.Object)
}
return []byte("null"), nil
}
// TODO: Check whether ContentType is actually JSON before returning it.
return re.RawExtension.Raw, nil
}

View File

@@ -21,7 +21,9 @@ limitations under the License.
package common
import (
crossplane_runtime "github.com/oam-dev/terraform-controller/api/types/crossplane-runtime"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
@@ -92,7 +94,11 @@ func (in *AppStatus) DeepCopy() *AppStatus {
// 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.Properties.DeepCopyInto(&out.Properties)
if in.Properties != nil {
in, out := &in.Properties, &out.Properties
*out = new(runtime.RawExtension)
(*in).DeepCopyInto(*out)
}
if in.DependsOn != nil {
in, out := &in.DependsOn, &out.DependsOn
*out = make([]string, len(*in))
@@ -163,7 +169,11 @@ func (in *ApplicationComponentStatus) DeepCopy() *ApplicationComponentStatus {
// 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)
if in.Properties != nil {
in, out := &in.Properties, &out.Properties
*out = new(runtime.RawExtension)
(*in).DeepCopyInto(*out)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationTrait.
@@ -403,6 +413,26 @@ func (in *RawComponent) DeepCopy() *RawComponent {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *RawExtensionPointer) DeepCopyInto(out *RawExtensionPointer) {
*out = *in
if in.RawExtension != nil {
in, out := &in.RawExtension, &out.RawExtension
*out = new(runtime.RawExtension)
(*in).DeepCopyInto(*out)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RawExtensionPointer.
func (in *RawExtensionPointer) DeepCopy() *RawExtensionPointer {
if in == nil {
return nil
}
out := new(RawExtensionPointer)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Revision) DeepCopyInto(out *Revision) {
*out = *in
@@ -439,7 +469,7 @@ func (in *Schematic) DeepCopyInto(out *Schematic) {
if in.Terraform != nil {
in, out := &in.Terraform, &out.Terraform
*out = new(Terraform)
**out = **in
(*in).DeepCopyInto(*out)
}
}
@@ -529,6 +559,11 @@ func (in *SubStepsStatus) DeepCopy() *SubStepsStatus {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Terraform) DeepCopyInto(out *Terraform) {
*out = *in
if in.ProviderReference != nil {
in, out := &in.ProviderReference, &out.ProviderReference
*out = new(crossplane_runtime.Reference)
**out = **in
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Terraform.

View File

@@ -1,116 +0,0 @@
/*
Copyright 2021. The KubeVela Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1alpha1
import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
"github.com/oam-dev/kubevela/apis/core.oam.dev/condition"
)
// WorkflowStepPhase describes the phase of a workflow step.
type WorkflowStepPhase string
const (
// WorkflowStepPhaseSucceeded will make the controller run the next step.
WorkflowStepPhaseSucceeded WorkflowStepPhase = "succeeded"
// WorkflowStepPhaseFailed will make the controller stop the workflow and report error in `message`.
WorkflowStepPhaseFailed WorkflowStepPhase = "failed"
// WorkflowStepPhaseTerminated will make the controller terminate the workflow.
WorkflowStepPhaseTerminated WorkflowStepPhase = "terminated"
// WorkflowStepPhaseSuspending will make the controller suspend the workflow.
WorkflowStepPhaseSuspending WorkflowStepPhase = "suspending"
// WorkflowStepPhaseRunning will make the controller continue the workflow.
WorkflowStepPhaseRunning WorkflowStepPhase = "running"
)
// WorkflowStep defines how to execute a workflow step.
type WorkflowStep struct {
// Name is the unique name of the workflow step.
Name string `json:"name"`
Type string `json:"type"`
// +kubebuilder:pruning:PreserveUnknownFields
Properties runtime.RawExtension `json:"properties,omitempty"`
Inputs common.StepInputs `json:"inputs,omitempty"`
Outputs common.StepOutputs `json:"outputs,omitempty"`
}
// A WorkflowSpec defines the desired state of a Workflow.
type WorkflowSpec struct {
Steps []WorkflowStep `json:"steps,omitempty"`
}
// A WorkflowStatus is the status of Workflow
type WorkflowStatus struct {
// ConditionedStatus reflects the observed status of a resource
condition.ConditionedStatus `json:",inline"`
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
StepIndex int `json:"stepIndex,omitempty"`
Suspend bool `json:"suspend"`
Terminated bool `json:"terminated"`
ContextBackend *corev1.ObjectReference `json:"contextBackend"`
Steps []WorkflowStepStatus `json:"steps,omitempty"`
}
// WorkflowStepStatus record the status of a workflow step
type WorkflowStepStatus struct {
Name string `json:"name,omitempty"`
Type string `json:"type,omitempty"`
Phase WorkflowStepPhase `json:"phase,omitempty"`
// A human readable message indicating details about why the workflowStep is in this state.
Message string `json:"message,omitempty"`
// A brief CamelCase message indicating details about why the workflowStep is in this state.
Reason string `json:"reason,omitempty"`
ResourceRef corev1.ObjectReference `json:"resourceRef,omitempty"`
}
// Workflow is the Schema for the Workflow API
// +kubebuilder:object:root=true
// +kubebuilder:storageversion
// +kubebuilder:subresource:status
// +kubebuilder:resource:scope=Namespaced,categories={oam},shortName=workflow
// +kubebuilder:printcolumn:name="PHASE",type=string,JSONPath=`.status.phase`
// +kubebuilder:printcolumn:name="AGE",type=date,JSONPath=".metadata.creationTimestamp"
type Workflow struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec WorkflowSpec `json:"spec,omitempty"`
Status WorkflowStatus `json:"status,omitempty"`
}
// +kubebuilder:object:root=true
// WorkflowList contains a list of Workflow.
type WorkflowList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []Workflow `json:"items"`
}
// SetConditions set condition for Workflow
func (w *Workflow) SetConditions(c ...condition.Condition) {
w.Status.SetConditions(c...)
}
// GetCondition gets condition from Workflow
func (w *Workflow) GetCondition(conditionType condition.ConditionType) condition.Condition {
return w.Status.GetCondition(conditionType)
}

View File

@@ -296,152 +296,3 @@ func (in *NamespaceSelector) DeepCopy() *NamespaceSelector {
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Workflow) DeepCopyInto(out *Workflow) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
in.Status.DeepCopyInto(&out.Status)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Workflow.
func (in *Workflow) DeepCopy() *Workflow {
if in == nil {
return nil
}
out := new(Workflow)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *Workflow) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *WorkflowList) DeepCopyInto(out *WorkflowList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]Workflow, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkflowList.
func (in *WorkflowList) DeepCopy() *WorkflowList {
if in == nil {
return nil
}
out := new(WorkflowList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *WorkflowList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *WorkflowSpec) DeepCopyInto(out *WorkflowSpec) {
*out = *in
if in.Steps != nil {
in, out := &in.Steps, &out.Steps
*out = make([]WorkflowStep, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkflowSpec.
func (in *WorkflowSpec) DeepCopy() *WorkflowSpec {
if in == nil {
return nil
}
out := new(WorkflowSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *WorkflowStatus) DeepCopyInto(out *WorkflowStatus) {
*out = *in
in.ConditionedStatus.DeepCopyInto(&out.ConditionedStatus)
if in.ContextBackend != nil {
in, out := &in.ContextBackend, &out.ContextBackend
*out = new(v1.ObjectReference)
**out = **in
}
if in.Steps != nil {
in, out := &in.Steps, &out.Steps
*out = make([]WorkflowStepStatus, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkflowStatus.
func (in *WorkflowStatus) DeepCopy() *WorkflowStatus {
if in == nil {
return nil
}
out := new(WorkflowStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *WorkflowStep) DeepCopyInto(out *WorkflowStep) {
*out = *in
in.Properties.DeepCopyInto(&out.Properties)
if in.Inputs != nil {
in, out := &in.Inputs, &out.Inputs
*out = make(common.StepInputs, len(*in))
copy(*out, *in)
}
if in.Outputs != nil {
in, out := &in.Outputs, &out.Outputs
*out = make(common.StepOutputs, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkflowStep.
func (in *WorkflowStep) DeepCopy() *WorkflowStep {
if in == nil {
return nil
}
out := new(WorkflowStep)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *WorkflowStepStatus) DeepCopyInto(out *WorkflowStepStatus) {
*out = *in
out.ResourceRef = in.ResourceRef
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkflowStepStatus.
func (in *WorkflowStepStatus) DeepCopy() *WorkflowStepStatus {
if in == nil {
return nil
}
out := new(WorkflowStepStatus)
in.DeepCopyInto(out)
return out
}

View File

@@ -54,7 +54,7 @@ type AppStatus struct {
type ApplicationTrait struct {
Name string `json:"name"`
// +kubebuilder:pruning:PreserveUnknownFields
Properties runtime.RawExtension `json:"properties,omitempty"`
Properties *runtime.RawExtension `json:"properties,omitempty"`
}
// ApplicationComponent describe the component of application

View File

@@ -44,7 +44,7 @@ func ApplicationV1alpha2ToV1beta1(v1a2 *Application, v1b1 *v1beta1.Application)
for j, trait := range comp.Traits {
traits[j] = common.ApplicationTrait{
Type: trait.Name,
Properties: *trait.Properties.DeepCopy(),
Properties: trait.Properties.DeepCopy(),
}
}
@@ -58,7 +58,7 @@ func ApplicationV1alpha2ToV1beta1(v1a2 *Application, v1b1 *v1beta1.Application)
v1b1.Spec.Components = append(v1b1.Spec.Components, common.ApplicationComponent{
Name: comp.Name,
Type: comp.WorkloadType,
Properties: *comp.Settings.DeepCopy(),
Properties: comp.Settings.DeepCopy(),
Traits: traits,
Scopes: scopes,
})
@@ -104,7 +104,7 @@ func (app *Application) ConvertFrom(src conversion.Hub) error {
for j, trait := range comp.Traits {
traits[j] = ApplicationTrait{
Name: trait.Type,
Properties: *trait.Properties.DeepCopy(),
Properties: trait.Properties.DeepCopy(),
}
}

View File

@@ -600,7 +600,11 @@ func (in *ApplicationSpec) DeepCopy() *ApplicationSpec {
// 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)
if in.Properties != nil {
in, out := &in.Properties, &out.Properties
*out = new(runtime.RawExtension)
(*in).DeepCopyInto(*out)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationTrait.

View File

@@ -44,7 +44,7 @@ type AppPolicy struct {
Type string `json:"type"`
// +kubebuilder:pruning:PreserveUnknownFields
Properties runtime.RawExtension `json:"properties,omitempty"`
Properties *runtime.RawExtension `json:"properties,omitempty"`
}
// WorkflowStep defines how to execute a workflow step.
@@ -55,7 +55,7 @@ type WorkflowStep struct {
Type string `json:"type"`
// +kubebuilder:pruning:PreserveUnknownFields
Properties runtime.RawExtension `json:"properties,omitempty"`
Properties *runtime.RawExtension `json:"properties,omitempty"`
DependsOn []string `json:"dependsOn,omitempty"`

View File

@@ -141,7 +141,11 @@ func (in *AppDeploymentStatus) DeepCopy() *AppDeploymentStatus {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AppPolicy) DeepCopyInto(out *AppPolicy) {
*out = *in
in.Properties.DeepCopyInto(&out.Properties)
if in.Properties != nil {
in, out := &in.Properties, &out.Properties
*out = new(runtime.RawExtension)
(*in).DeepCopyInto(*out)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AppPolicy.
@@ -1450,7 +1454,11 @@ func (in *Workflow) DeepCopy() *Workflow {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *WorkflowStep) DeepCopyInto(out *WorkflowStep) {
*out = *in
in.Properties.DeepCopyInto(&out.Properties)
if in.Properties != nil {
in, out := &in.Properties, &out.Properties
*out = new(runtime.RawExtension)
(*in).DeepCopyInto(*out)
}
if in.DependsOn != nil {
in, out := &in.DependsOn, &out.DependsOn
*out = make([]string, len(*in))

View File

@@ -47,12 +47,13 @@ const (
StatusStaging = "Staging"
)
// EnvMeta stores the info for app environment
// Config contains key/value pairs
type Config map[string]string
// EnvMeta stores the namespace for app environment
type EnvMeta struct {
Name string `json:"name"`
Namespace string `json:"namespace"`
Email string `json:"email,omitempty"`
Domain string `json:"domain,omitempty"`
Current string `json:"current,omitempty"`
}

View File

@@ -188,6 +188,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference to
Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -454,6 +468,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference to
Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration

View File

@@ -193,6 +193,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference to
Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -440,6 +454,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference to
Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration

View File

@@ -19,3 +19,6 @@ version: 0.1.0
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application.
appVersion: 0.1.0
home: https://kubevela.io
icon: https://kubevela.io/img/logo.jpg

View File

@@ -1232,6 +1232,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference
to Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -1621,6 +1635,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference
to Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -1908,6 +1936,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference
to Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -3318,6 +3360,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference
to Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -3600,6 +3656,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference
to Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -3971,6 +4041,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference
to Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -4221,6 +4305,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference
to Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -4487,6 +4585,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference
to Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration

View File

@@ -179,6 +179,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference to
Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -449,6 +463,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference to
Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration

View File

@@ -222,6 +222,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference
to Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -492,6 +506,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference
to Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -755,6 +783,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference
to Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -999,6 +1041,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference
to Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration

View File

@@ -151,6 +151,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference to
Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration

View File

@@ -188,6 +188,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference to
Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -454,6 +468,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference to
Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration

View File

@@ -1,352 +0,0 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.6.2
name: workflows.core.oam.dev
spec:
group: core.oam.dev
names:
categories:
- oam
kind: Workflow
listKind: WorkflowList
plural: workflows
shortNames:
- workflow
singular: workflow
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .status.phase
name: PHASE
type: string
- jsonPath: .metadata.creationTimestamp
name: AGE
type: date
name: v1alpha1
schema:
openAPIV3Schema:
description: Workflow is the Schema for the Workflow API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: A WorkflowSpec defines the desired state of a Workflow.
properties:
steps:
items:
description: WorkflowStep defines how to execute a workflow step.
properties:
inputs:
description: StepInputs defines variable input of WorkflowStep
items:
properties:
from:
type: string
parameterKey:
type: string
required:
- from
- parameterKey
type: object
type: array
name:
description: Name is the unique name of the workflow step.
type: string
outputs:
description: StepOutputs defines output variable of WorkflowStep
items:
properties:
name:
type: string
valueFrom:
type: string
required:
- name
- valueFrom
type: object
type: array
properties:
type: object
x-kubernetes-preserve-unknown-fields: true
type:
type: string
required:
- name
- type
type: object
type: array
type: object
status:
description: A WorkflowStatus is the status of Workflow
properties:
conditions:
description: Conditions of the resource.
items:
description: A Condition that may apply to a resource.
properties:
lastTransitionTime:
description: LastTransitionTime is the last time this condition
transitioned from one status to another.
format: date-time
type: string
message:
description: A Message containing details about this condition's
last transition from one status to another, if any.
type: string
reason:
description: A Reason for this condition's last transition from
one status to another.
type: string
status:
description: Status of this condition; is it currently True,
False, or Unknown?
type: string
type:
description: Type of this condition. At most one of each condition
type may apply to a resource at any point in time.
type: string
required:
- lastTransitionTime
- reason
- status
- type
type: object
type: array
contextBackend:
description: 'ObjectReference contains enough information to let you
inspect or modify the referred object. --- New uses of this type
are discouraged because of difficulty describing its usage when
embedded in APIs. 1. Ignored fields. It includes many fields which
are not generally honored. For instance, ResourceVersion and FieldPath
are both very rarely valid in actual usage. 2. Invalid usage help. It
is impossible to add specific help for individual usage. In most
embedded usages, there are particular restrictions like, "must
refer only to types A and B" or "UID not honored" or "name must
be restricted". Those cannot be well described when embedded. 3.
Inconsistent validation. Because the usages are different, the
validation rules are different by usage, which makes it hard for
users to predict what will happen. 4. The fields are both imprecise
and overly precise. Kind is not a precise mapping to a URL. This
can produce ambiguity during interpretation and require a REST
mapping. In most cases, the dependency is on the group,resource
tuple and the version of the actual struct is irrelevant. 5.
We cannot easily change it. Because this type is embedded in many
locations, updates to this type will affect numerous schemas. Don''t
make new APIs embed an underspecified API type they do not control.
Instead of using this type, create a locally provided and used type
that is well-focused on your reference. For example, ServiceReferences
for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533
.'
properties:
apiVersion:
description: API version of the referent.
type: string
fieldPath:
description: 'If referring to a piece of an object instead of
an entire object, this string should contain a valid JSON/Go
field access statement, such as desiredState.manifest.containers[2].
For example, if the object reference is to a container within
a pod, this would take on a value like: "spec.containers{name}"
(where "name" refers to the name of the container that triggered
the event) or if no container name is specified "spec.containers[2]"
(container with index 2 in this pod). This syntax is chosen
only to have some well-defined way of referencing a part of
an object. TODO: this design is not final and this field is
subject to change in the future.'
type: string
kind:
description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
type: string
namespace:
description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
type: string
resourceVersion:
description: 'Specific resourceVersion to which this reference
is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
type: string
uid:
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
observedGeneration:
format: int64
type: integer
stepIndex:
type: integer
steps:
items:
description: WorkflowStepStatus record the status of a workflow
step
properties:
message:
description: A human readable message indicating details about
why the workflowStep is in this state.
type: string
name:
type: string
phase:
description: WorkflowStepPhase describes the phase of a workflow
step.
type: string
reason:
description: A brief CamelCase message indicating details about
why the workflowStep is in this state.
type: string
resourceRef:
description: 'ObjectReference contains enough information to
let you inspect or modify the referred object. --- New uses
of this type are discouraged because of difficulty describing
its usage when embedded in APIs. 1. Ignored fields. It includes
many fields which are not generally honored. For instance,
ResourceVersion and FieldPath are both very rarely valid in
actual usage. 2. Invalid usage help. It is impossible to
add specific help for individual usage. In most embedded
usages, there are particular restrictions like, "must
refer only to types A and B" or "UID not honored" or "name
must be restricted". Those cannot be well described when
embedded. 3. Inconsistent validation. Because the usages
are different, the validation rules are different by usage,
which makes it hard for users to predict what will happen. 4.
The fields are both imprecise and overly precise. Kind is
not a precise mapping to a URL. This can produce ambiguity during
interpretation and require a REST mapping. In most cases,
the dependency is on the group,resource tuple and the
version of the actual struct is irrelevant. 5. We cannot
easily change it. Because this type is embedded in many locations,
updates to this type will affect numerous schemas. Don''t
make new APIs embed an underspecified API type they do not
control. Instead of using this type, create a locally provided
and used type that is well-focused on your reference. For
example, ServiceReferences for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533
.'
properties:
apiVersion:
description: API version of the referent.
type: string
fieldPath:
description: 'If referring to a piece of an object instead
of an entire object, this string should contain a valid
JSON/Go field access statement, such as desiredState.manifest.containers[2].
For example, if the object reference is to a container
within a pod, this would take on a value like: "spec.containers{name}"
(where "name" refers to the name of the container that
triggered the event) or if no container name is specified
"spec.containers[2]" (container with index 2 in this pod).
This syntax is chosen only to have some well-defined way
of referencing a part of an object. TODO: this design
is not final and this field is subject to change in the
future.'
type: string
kind:
description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
type: string
namespace:
description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
type: string
resourceVersion:
description: 'Specific resourceVersion to which this reference
is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
type: string
uid:
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
type:
type: string
type: object
type: array
suspend:
type: boolean
terminated:
type: boolean
required:
- contextBackend
- suspend
- terminated
type: object
type: object
served: true
storage: true
subresources:
status: {}
- name: v1beta1
schema:
openAPIV3Schema:
description: Workflow defines workflow steps and other attributes
properties:
steps:
items:
description: WorkflowStep defines how to execute a workflow step.
properties:
dependsOn:
items:
type: string
type: array
inputs:
description: StepInputs defines variable input of WorkflowStep
items:
properties:
from:
type: string
parameterKey:
type: string
required:
- from
- parameterKey
type: object
type: array
name:
description: Name is the unique name of the workflow step.
type: string
outputs:
description: StepOutputs defines output variable of WorkflowStep
items:
properties:
name:
type: string
valueFrom:
type: string
required:
- name
- valueFrom
type: object
type: array
properties:
type: object
x-kubernetes-preserve-unknown-fields: true
type:
type: string
required:
- name
- type
type: object
type: array
type: object
served: true
storage: false
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []

View File

@@ -148,6 +148,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference to
Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration

View File

@@ -193,6 +193,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference to
Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -440,6 +454,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference to
Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration

View File

@@ -0,0 +1,65 @@
apiVersion: v1
data:
initializer: |
apiVersion: core.oam.dev/v1beta1
kind: Initializer
metadata:
annotations:
addons.oam.dev/description: Kubernetes Terraform Controller for Azure
addons.oam.dev/name: terraform/provider-azure
name: terraform-provider-azure
namespace: default
spec:
appTemplate:
spec:
components:
- name: azure-account-creds
properties:
apiVersion: v1
kind: Secret
metadata:
name: azure-account-creds
namespace: vela-system
stringData:
credentials: |
armClientID: [[ index .Args "ARM_CLIENT_ID" ]]
armClientSecret: [[ index .Args "ARM_CLIENT_SECRET" ]]
armSubscriptionID: [[ index .Args "ARM_SUBSCRIPTION_ID" ]]
armTenantID: [[ index .Args "ARM_TENANT_ID" ]]
type: Opaque
type: raw
- name: azure
properties:
apiVersion: terraform.core.oam.dev/v1beta1
kind: Provider
metadata:
name: azure
namespace: default
spec:
credentials:
secretRef:
key: credentials
name: azure-account-creds
namespace: vela-system
source: Secret
provider: azure
type: raw
status:
rollout:
batchRollingState: ""
currentBatch: 0
lastTargetAppRevision: ""
rollingState: ""
upgradedReadyReplicas: 0
upgradedReplicas: 0
status:
observedGeneration: 0
kind: ConfigMap
metadata:
annotations:
addons.oam.dev/description: Kubernetes Terraform Controller for Azure
addons.oam.dev/name: terraform/provider-azure
labels:
addons.oam.dev/type: terraform-provider-azure
name: terraform-provider-azure
namespace: {{.Values.systemDefinitionNamespace}}

View File

@@ -354,6 +354,83 @@ data:
apiVersion: terraform.core.oam.dev/v1beta1
kind: Configuration
type: raw
- name: azure-database-mariadb
properties:
apiVersion: core.oam.dev/v1alpha2
kind: ComponentDefinition
metadata:
annotations:
definition.oam.dev/description: Terraform configuration for Azure Database
Mariadb
provider: azure
labels:
type: terraform
name: azure-database-mariadb
namespace: vela-system
spec:
schematic:
terraform:
configuration: |
# Configure the Microsoft Azure Provider
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "example" {
name = "tfex-mariadb-database-RG"
location = "West Europe"
}
resource "azurerm_mariadb_server" "example" {
name = "mariadb-svr-sample"
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
sku_name = "B_Gen5_2"
storage_mb = 51200
backup_retention_days = 7
geo_redundant_backup_enabled = false
administrator_login = var.username
administrator_login_password = var.password
version = "10.2"
ssl_enforcement_enabled = true
}
resource "azurerm_mariadb_database" "example" {
name = var.name
resource_group_name = azurerm_resource_group.example.name
server_name = azurerm_mariadb_server.example.name
charset = "utf8"
collation = "utf8_general_ci"
}
variable "name" {
default = "mariadb_database"
type = string
description = "Database instance name"
}
variable "username" {
default = "acctestun"
type = string
description = "Database instance username"
}
variable "password" {
default = "H@Sh1CoR3!faked"
type = string
description = "Database instance password"
}
providerRef:
name: azure
namespace: default
workload:
definition:
apiVersion: terraform.core.oam.dev/v1beta1
kind: Configuration
type: raw
status:
rollout:
batchRollingState: ""

View File

@@ -32,12 +32,28 @@ spec:
- "--secure-port={{ .Values.multicluster.clusterGateway.port }}"
- "--secret-namespace={{ .Release.Namespace }}"
- "--feature-gates=APIPriorityAndFairness=false"
{{ if .Values.multicluster.clusterGateway.secureTLS.enabled }}
- "--cert-dir={{ .Values.multicluster.clusterGateway.secureTLS.certPath }}"
{{ end }}
image: {{ .Values.multicluster.clusterGateway.image.repository }}:{{ .Values.multicluster.clusterGateway.image.tag }}
imagePullPolicy: {{ .Values.multicluster.clusterGateway.image.pullPolicy }}
resources:
{{- toYaml .Values.multicluster.clusterGateway.resources | nindent 12 }}
ports:
- containerPort: {{ .Values.multicluster.clusterGateway.port }}
{{ if .Values.multicluster.clusterGateway.secureTLS.enabled }}
volumeMounts:
- mountPath: {{ .Values.multicluster.clusterGateway.secureTLS.certPath }}
name: tls-cert-vol
readOnly: true
{{- end }}
{{ if .Values.multicluster.clusterGateway.secureTLS.enabled }}
volumes:
- name: tls-cert-vol
secret:
defaultMode: 420
secretName: {{ template "kubevela.fullname" . }}-cluster-gateway-tls
{{ end }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
@@ -84,5 +100,92 @@ spec:
namespace: {{ .Release.Namespace }}
port: {{ .Values.multicluster.clusterGateway.port }}
versionPriority: 10
insecureSkipTLSVerify: true
insecureSkipTLSVerify: {{ not .Values.multicluster.clusterGateway.secureTLS.enabled }}
{{ if .Values.multicluster.clusterGateway.secureTLS.enabled }}
caBundle: Cg==
{{ end }}
{{ end }}
---
{{ if and .Values.multicluster.enabled .Values.multicluster.clusterGateway.secureTLS.enabled }}
apiVersion: batch/v1
kind: Job
metadata:
name: {{ template "kubevela.fullname" . }}-cluster-gateway-tls-secret-create
namespace: {{ .Release.Namespace }}
annotations:
"helm.sh/hook": pre-install,pre-upgrade
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
labels:
app: {{ template "kubevela.fullname" . }}-cluster-gateway-tls-secret-create
{{- include "kubevela.labels" . | nindent 4 }}
spec:
{{- if .Capabilities.APIVersions.Has "batch/v1alpha1" }}
# Alpha feature since k8s 1.12
ttlSecondsAfterFinished: 0
{{- end }}
template:
metadata:
name: {{ template "kubevela.fullname" . }}-cluster-gateway-tls-secret-create
labels:
app: {{ template "kubevela.fullname" . }}-cluster-gateway-tls-secret-create
{{- include "kubevela.labels" . | nindent 8 }}
spec:
containers:
- name: create
image: {{ .Values.admissionWebhooks.patch.image.repository }}:{{ .Values.admissionWebhooks.patch.image.tag }}
imagePullPolicy: {{ .Values.admissionWebhooks.patch.image.pullPolicy }}
args:
- create
- --host={{ .Release.Name }}-cluster-gateway-service,{{ .Release.Name }}-cluster-gateway-service.{{ .Release.Namespace }}.svc
- --namespace={{ .Release.Namespace }}
- --secret-name={{ template "kubevela.fullname" . }}-cluster-gateway-tls
- --key-name=apiserver.key
- --cert-name=apiserver.crt
restartPolicy: OnFailure
serviceAccountName: {{ template "kubevela.fullname" . }}-admission
securityContext:
runAsGroup: 2000
runAsNonRoot: true
runAsUser: 2000
{{ end }}
---
{{ if and .Values.multicluster.enabled .Values.multicluster.clusterGateway.secureTLS.enabled }}
apiVersion: batch/v1
kind: Job
metadata:
name: {{ template "kubevela.fullname" . }}-cluster-gateway-tls-secret-patch
namespace: {{ .Release.Namespace }}
annotations:
"helm.sh/hook": post-install,post-upgrade
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
labels:
app: {{ template "kubevela.fullname" . }}-cluster-gateway-tls-secret-patch
{{- include "kubevela.labels" . | nindent 4 }}
spec:
{{- if .Capabilities.APIVersions.Has "batch/v1alpha1" }}
# Alpha feature since k8s 1.12
ttlSecondsAfterFinished: 0
{{- end }}
template:
metadata:
name: {{ template "kubevela.fullname" . }}-cluster-gateway-tls-secret-patch
labels:
app: {{ template "kubevela.fullname" . }}-cluster-gateway-tls-secret-patch
{{- include "kubevela.labels" . | nindent 8 }}
spec:
containers:
- name: patch
image: {{ .Values.multicluster.clusterGateway.image.repository }}:{{ .Values.multicluster.clusterGateway.image.tag }}
imagePullPolicy: {{ .Values.multicluster.clusterGateway.image.pullPolicy }}
command:
- /patch
args:
- --secret-namespace={{ .Release.Namespace }}
- --secret-name={{ template "kubevela.fullname" . }}-cluster-gateway-tls
restartPolicy: OnFailure
serviceAccountName: {{ include "kubevela.serviceAccountName" . }}
securityContext:
runAsGroup: 2000
runAsNonRoot: true
runAsUser: 2000
{{ end }}

View File

@@ -0,0 +1,22 @@
# Code generated by KubeVela templates. DO NOT EDIT. Please edit the original cue file.
# Definition source cue file: vela-templates/definitions/internal/apply-object.cue
apiVersion: core.oam.dev/v1beta1
kind: WorkflowStepDefinition
metadata:
annotations:
definition.oam.dev/description: Apply raw kubernetes objects for your workflow steps
name: apply-object
namespace: {{.Values.systemDefinitionNamespace}}
spec:
schematic:
cue:
template: |
import (
"vela/op"
)
apply: op.#Apply & {
value: parameter
}
parameter: {}

View File

@@ -27,7 +27,7 @@ spec:
}
}
load: op.#Steps & {
if dependsOn.err != _|_ {
if dependsOn.err != _|_ && dependsOn.value == _|_ {
configMap: op.#Read & {
value: {
apiVersion: "v1"
@@ -43,18 +43,16 @@ spec:
yaml.Unmarshal(configMap.value.data[parameter.name])
}
}
}
if dependsOn.err == _|_ {
apply: op.#Apply & {
value: {
dependsOn.value
}
wait: op.#ConditionalWait & {
continue: load.apply.value.status.status == "running"
}
}
if dependsOn.value != _|_ {
wait: op.#ConditionalWait & {
continue: dependsOn.value.status.status == "running"
}
}
}
phase: load.apply.value.status.status
wait: op.#ConditionalWait & {
continue: phase == "running"
}
parameter: {
// +usage=Specify the name of the dependent Application

View File

@@ -17,7 +17,7 @@ spec:
// +patchKey=name
containers: [{
name: context.name
// +patchKey=name
// +patchStrategy=retainKeys
env: [
for k, v in parameter.env {
name: k

View File

@@ -30,7 +30,10 @@ spec:
outputs: ingress: {
apiVersion: "networking.k8s.io/v1"
kind: "Ingress"
metadata: name: context.name
metadata: {
name: context.name
annotations: "kubernetes.io/ingress.class": parameter.class
}
spec: rules: [{
host: parameter.domain
http: paths: [
@@ -51,6 +54,9 @@ spec:
// +usage=Specify the mapping relationship between the http path and the workload port
http: [string]: int
// +usage=Specify the class of ingress to use
class: *"nginx" | string
}
status:
customStatus: |-

View File

@@ -50,7 +50,7 @@ spec:
},
]
}
outputs: pvc: {
outputs: "\(parameter.claimName)": {
apiVersion: "v1"
kind: "PersistentVolumeClaim"
metadata: name: parameter.claimName

View File

@@ -29,9 +29,9 @@ spec:
{{- toYaml .Values.securityContext | nindent 12 }}
args:
- "apiserver"
- "--bind-addr=0.0.0.0:{{ .Values.apiServer.port }}"
image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
imagePullPolicy: {{ quote .Values.image.pullPolicy }}
- "--port={{ .Values.apiServer.port }}"
image: {{ .Values.apiserverImage.repository }}:{{ .Values.apiserverImage.tag }}
imagePullPolicy: {{ quote .Values.apiserverImage.pullPolicy }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
ports:

View File

@@ -11,6 +11,10 @@ image:
repository: oamdev/vela-core
tag: latest
pullPolicy: Always
apiserverImage:
repository: oamdev/vela-apiserver
tag: v1.1.2
pullPolicy: Always
imagePullSecrets: []
nameOverride: ""
@@ -118,9 +122,12 @@ multicluster:
port: 9443
image:
repository: oamdev/cluster-gateway
tag: v1.1.1
tag: v1.1.3
pullPolicy: Always
resources:
limits:
cpu: 100m
memory: 200Mi
memory: 200Mi
secureTLS:
enabled: true
certPath: /etc/k8s-cluster-gateway-certs

View File

@@ -19,3 +19,6 @@ version: 0.1.0
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application.
appVersion: 0.1.0
home: https://kubevela.io
icon: https://kubevela.io/img/logo.jpg

View File

@@ -1232,6 +1232,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference
to Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -1621,6 +1635,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference
to Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -1908,6 +1936,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference
to Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -3318,6 +3360,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference
to Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -3600,6 +3656,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference
to Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -3971,6 +4041,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference
to Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -4221,6 +4305,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference
to Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -4487,6 +4585,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference
to Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration

View File

@@ -222,6 +222,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference
to Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -492,6 +506,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference
to Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -755,6 +783,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference
to Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -999,6 +1041,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference
to Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration

View File

@@ -151,6 +151,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference to
Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration

View File

@@ -188,6 +188,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference to
Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -454,6 +468,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference to
Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration

View File

@@ -148,6 +148,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference to
Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration

View File

@@ -193,6 +193,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference to
Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -440,6 +454,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference to
Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration

View File

@@ -32,12 +32,28 @@ spec:
- "--secure-port={{ .Values.multicluster.clusterGateway.port }}"
- "--secret-namespace={{ .Release.Namespace }}"
- "--feature-gates=APIPriorityAndFairness=false"
{{ if .Values.multicluster.clusterGateway.secureTLS.enabled }}
- "--cert-dir={{ .Values.multicluster.clusterGateway.secureTLS.certPath }}"
{{ end }}
image: {{ .Values.multicluster.clusterGateway.image.repository }}:{{ .Values.multicluster.clusterGateway.image.tag }}
imagePullPolicy: {{ .Values.multicluster.clusterGateway.image.pullPolicy }}
resources:
{{- toYaml .Values.multicluster.clusterGateway.resources | nindent 12 }}
ports:
- containerPort: {{ .Values.multicluster.clusterGateway.port }}
{{ if .Values.multicluster.clusterGateway.secureTLS.enabled }}
volumeMounts:
- mountPath: {{ .Values.multicluster.clusterGateway.secureTLS.certPath }}
name: tls-cert-vol
readOnly: true
{{- end }}
{{ if .Values.multicluster.clusterGateway.secureTLS.enabled }}
volumes:
- name: tls-cert-vol
secret:
defaultMode: 420
secretName: {{ template "kubevela.fullname" . }}-cluster-gateway-tls
{{ end }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
@@ -50,9 +66,9 @@ spec:
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
{{ end }}
{{ end }}
---
{{ if .Values.multicluster.enabled }}
{{ if .Values.multicluster.enabled }}
apiVersion: v1
kind: Service
metadata:
@@ -65,9 +81,9 @@ spec:
- protocol: TCP
port: {{ .Values.multicluster.clusterGateway.port }}
targetPort: {{ .Values.multicluster.clusterGateway.port }}
{{ end }}
{{ end }}
---
{{ if .Values.multicluster.enabled }}
{{ if .Values.multicluster.enabled }}
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
@@ -84,5 +100,92 @@ spec:
namespace: {{ .Release.Namespace }}
port: {{ .Values.multicluster.clusterGateway.port }}
versionPriority: 10
insecureSkipTLSVerify: true
{{ end }}
insecureSkipTLSVerify: {{ not .Values.multicluster.clusterGateway.secureTLS.enabled }}
{{ if .Values.multicluster.clusterGateway.secureTLS.enabled }}
caBundle: Cg==
{{ end }}
{{ end }}
---
{{ if and .Values.multicluster.enabled .Values.multicluster.clusterGateway.secureTLS.enabled }}
apiVersion: batch/v1
kind: Job
metadata:
name: {{ template "kubevela.fullname" . }}-cluster-gateway-tls-secret-create
namespace: {{ .Release.Namespace }}
annotations:
"helm.sh/hook": pre-install,pre-upgrade
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
labels:
app: {{ template "kubevela.fullname" . }}-cluster-gateway-tls-secret-create
{{- include "kubevela.labels" . | nindent 4 }}
spec:
{{- if .Capabilities.APIVersions.Has "batch/v1alpha1" }}
# Alpha feature since k8s 1.12
ttlSecondsAfterFinished: 0
{{- end }}
template:
metadata:
name: {{ template "kubevela.fullname" . }}-cluster-gateway-tls-secret-create
labels:
app: {{ template "kubevela.fullname" . }}-cluster-gateway-tls-secret-create
{{- include "kubevela.labels" . | nindent 8 }}
spec:
containers:
- name: create
image: {{ .Values.admissionWebhooks.patch.image.repository }}:{{ .Values.admissionWebhooks.patch.image.tag }}
imagePullPolicy: {{ .Values.admissionWebhooks.patch.image.pullPolicy }}
args:
- create
- --host={{ .Release.Name }}-cluster-gateway-service,{{ .Release.Name }}-cluster-gateway-service.{{ .Release.Namespace }}.svc
- --namespace={{ .Release.Namespace }}
- --secret-name={{ template "kubevela.fullname" . }}-cluster-gateway-tls
- --key-name=apiserver.key
- --cert-name=apiserver.crt
restartPolicy: OnFailure
serviceAccountName: {{ template "kubevela.fullname" . }}-admission
securityContext:
runAsGroup: 2000
runAsNonRoot: true
runAsUser: 2000
{{ end }}
---
{{ if and .Values.multicluster.enabled .Values.multicluster.clusterGateway.secureTLS.enabled }}
apiVersion: batch/v1
kind: Job
metadata:
name: {{ template "kubevela.fullname" . }}-cluster-gateway-tls-secret-patch
namespace: {{ .Release.Namespace }}
annotations:
"helm.sh/hook": post-install,post-upgrade
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
labels:
app: {{ template "kubevela.fullname" . }}-cluster-gateway-tls-secret-patch
{{- include "kubevela.labels" . | nindent 4 }}
spec:
{{- if .Capabilities.APIVersions.Has "batch/v1alpha1" }}
# Alpha feature since k8s 1.12
ttlSecondsAfterFinished: 0
{{- end }}
template:
metadata:
name: {{ template "kubevela.fullname" . }}-cluster-gateway-tls-secret-patch
labels:
app: {{ template "kubevela.fullname" . }}-cluster-gateway-tls-secret-patch
{{- include "kubevela.labels" . | nindent 8 }}
spec:
containers:
- name: patch
image: {{ .Values.multicluster.clusterGateway.image.repository }}:{{ .Values.multicluster.clusterGateway.image.tag }}
imagePullPolicy: {{ .Values.multicluster.clusterGateway.image.pullPolicy }}
command:
- /patch
args:
- --secret-namespace={{ .Release.Namespace }}
- --secret-name={{ template "kubevela.fullname" . }}-cluster-gateway-tls
restartPolicy: OnFailure
serviceAccountName: {{ include "kubevela.serviceAccountName" . }}
securityContext:
runAsGroup: 2000
runAsNonRoot: true
runAsUser: 2000
{{ end }}

View File

@@ -0,0 +1,22 @@
# Code generated by KubeVela templates. DO NOT EDIT. Please edit the original cue file.
# Definition source cue file: vela-templates/definitions/internal/apply-object.cue
apiVersion: core.oam.dev/v1beta1
kind: WorkflowStepDefinition
metadata:
annotations:
definition.oam.dev/description: Apply raw kubernetes objects for your workflow steps
name: apply-object
namespace: {{.Values.systemDefinitionNamespace}}
spec:
schematic:
cue:
template: |
import (
"vela/op"
)
apply: op.#Apply & {
value: parameter
}
parameter: {}

View File

@@ -27,7 +27,7 @@ spec:
}
}
load: op.#Steps & {
if dependsOn.err != _|_ {
if dependsOn.err != _|_ && dependsOn.value == _|_ {
configMap: op.#Read & {
value: {
apiVersion: "v1"
@@ -43,18 +43,16 @@ spec:
yaml.Unmarshal(configMap.value.data[parameter.name])
}
}
}
if dependsOn.err == _|_ {
apply: op.#Apply & {
value: {
dependsOn.value
}
wait: op.#ConditionalWait & {
continue: load.apply.value.status.status == "running"
}
}
if dependsOn.value != _|_ {
wait: op.#ConditionalWait & {
continue: dependsOn.value.status.status == "running"
}
}
}
phase: load.apply.value.status.status
wait: op.#ConditionalWait & {
continue: phase == "running"
}
parameter: {
// +usage=Specify the name of the dependent Application

View File

@@ -17,7 +17,7 @@ spec:
// +patchKey=name
containers: [{
name: context.name
// +patchKey=name
// +patchStrategy=retainKeys
env: [
for k, v in parameter.env {
name: k

View File

@@ -30,7 +30,10 @@ spec:
outputs: ingress: {
apiVersion: "networking.k8s.io/v1"
kind: "Ingress"
metadata: name: context.name
metadata: {
name: context.name
annotations: "kubernetes.io/ingress.class": parameter.class
}
spec: rules: [{
host: parameter.domain
http: paths: [
@@ -51,6 +54,9 @@ spec:
// +usage=Specify the mapping relationship between the http path and the workload port
http: [string]: int
// +usage=Specify the class of ingress to use
class: *"nginx" | string
}
status:
customStatus: |-

View File

@@ -50,7 +50,7 @@ spec:
},
]
}
outputs: pvc: {
outputs: "\(parameter.claimName)": {
apiVersion: "v1"
kind: "PersistentVolumeClaim"
metadata: name: parameter.claimName

View File

@@ -117,9 +117,12 @@ multicluster:
port: 9443
image:
repository: oamdev/cluster-gateway
tag: v1.1.1
tag: v1.1.3
pullPolicy: Always
resources:
limits:
cpu: 100m
memory: 200Mi
memory: 200Mi
secureTLS:
enabled: true
certPath: /etc/k8s-cluster-gateway-certs

View File

@@ -30,6 +30,7 @@ import (
"strings"
"time"
appsv1 "k8s.io/api/apps/v1"
"k8s.io/klog/v2"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -206,7 +207,7 @@ func main() {
LeaseDuration: &leaseDuration,
RenewDeadline: &renewDeadline,
RetryPeriod: &retryPeriod,
ClientDisableCacheFor: []client.Object{&v1beta1.ResourceTracker{}},
ClientDisableCacheFor: []client.Object{&v1beta1.ResourceTracker{}, &appsv1.ControllerRevision{}},
})
if err != nil {
klog.ErrorS(err, "Unable to create a controller manager")
@@ -325,8 +326,11 @@ func waitWebhookSecretVolume(certDir string, timeout, interval time.Duration) er
if err != nil {
return false
}
// nolint
defer f.Close()
defer func() {
if err := f.Close(); err != nil {
klog.Error(err, "Failed to close file")
}
}()
// check if dir is empty
if _, err := f.Readdir(1); errors.Is(err, io.EOF) {
return false

View File

@@ -0,0 +1,54 @@
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: mysql-pvc
spec:
components:
- name: mysql
type: webservice
properties:
env:
- name: MYSQL_ROOT_PASSWORD
value: root
image: mysql:5.7
port: 3306
cpu: 1000m
memory: 500M
traits:
- type: ingress
properties:
http:
/: 13666
domain: com.zdww1
- type: scaler
properties:
replicas: 1
- type: cpuscaler
properties:
cpuUtil: 70
min: 1
max: 3
- type: pvc
properties:
claimName: aaa
accessModes:
- ReadWriteOnce
storageClassName: nfs-dynamic-sc
resources:
requests:
storage: 1Gi
volumesToMount:
- mountPath: /aaa
name: aaa
- type: pvc
properties:
claimName: bbb
accessModes:
- ReadWriteOnce
storageClassName: nfs-dynamic-sc
resources:
requests:
storage: 1Gi
volumesToMount:
- mountPath: /bbb
name: bbb

View File

@@ -0,0 +1,78 @@
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: example-app
namespace: default
spec:
components:
- name: hello-world-server
type: webservice
properties:
image: crccheck/hello-world
port: 8000
traits:
- type: scaler
properties:
replicas: 1
- name: data-worker
type: worker
properties:
image: busybox
cmd:
- sleep
- '1000000'
policies:
- name: example-multi-env-policy
type: env-binding
properties:
envs:
- name: test
placement: # selecting the namespace (in local cluster) to deploy to
namespaceSelector:
name: test
selector:
components:
- data-worker
- name: staging
placement: # selecting the cluster to deploy to
clusterSelector:
name: cluster-worker
- name: prod
placement: # selecting both namespace and cluster to deploy to
clusterSelector:
name: cluster-worker
namespaceSelector:
name: prod
patch: # overlay patch on above components
components:
- name: hello-world-server
type: webservice
traits:
- type: scaler
properties:
replicas: 3
workflow:
steps:
# deploy to test env
- name: deploy-test
type: deploy2env
properties:
policy: example-multi-env-policy
env: test
# deploy to staging env
- name: deploy-staging
type: deploy2env
properties:
policy: example-multi-env-policy
env: staging
# deploy to prod env
- name: deploy-prod
type: deploy2env
properties:
policy: example-multi-env-policy
env: prod

View File

@@ -0,0 +1,39 @@
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: server-with-pvc
namespace: default
spec:
components:
- name: express-server
type: webservice
properties:
image: crccheck/hello-world
port: 8000
volumes:
- name: "my-pvc"
type: "pvc"
mountPath: "/test"
claimName: "myclaim"
workflow:
steps:
- name: apply-pvc
type: apply-object
properties:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: myclaim
namespace: default
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 8Gi
storageClassName: standard
- name: apply-server
type: apply-component
properties:
component: express-server

View File

@@ -1,56 +0,0 @@
apiVersion: core.oam.dev/v1beta1
kind: WorkflowStepDefinition
metadata:
name: apply-component
spec:
schematic:
cue:
template: |
import ("vela/op")
parameter: {
component: string
prefixIP?: string
}
load: op.#Load
// apply workload to kubernetes cluster
apply: op.#ApplyComponent & {
value: load.value[parameter.component]
}
// wait until workload.status equal "Running"
wait: op.#ConditionalWait & {
continue: apply.output.status.phase =="Running"
}
// export podIP
myIP: apply.output.status.podIP
---
apiVersion: core.oam.dev/v1beta1
kind: WorkflowStepDefinition
metadata:
name: apply-remaining
spec:
schematic:
cue:
template: |
import ("vela/op")
parameter: {
exceptions?: [componentName=string]: {
// skipApplyWorkload indicates whether to skip apply the workload resource
skipApplyWorkload: *true | bool
// skipAllTraits indicates to skip apply all resources of the traits.
// If this is true, skipApplyTraits will be ignored
skipAllTraits: *true| bool
// skipApplyTraits specifies the names of the traits to skip apply
skipApplyTraits: [...string]
}
}
apply: op.#ApplyRemaining & {
parameter
}

View File

@@ -0,0 +1,26 @@
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: kruise
namespace: vela-system
spec:
components:
- name: kruise
type: helm
properties:
branch: master
chart: ./charts/kruise/v0.9.0
version: "*"
repoType: git
url: https://github.com/openkruise/kruise
workflow:
steps:
- name: check-flux
type: depends-on-app
properties:
name: fluxcd
namespace: vela-system
- name: apply-kruise
type: apply-component
properties:
component: kruise

View File

@@ -111,7 +111,7 @@ var ApplicationExecContext = func(context string, appName string) bool {
var ApplicationPortForwardContext = func(context string, appName string) bool {
return ginkgo.Context(context, func() {
ginkgo.It("should get output of portward successfully", func() {
ginkgo.It("should get output of port-forward successfully", func() {
cli := fmt.Sprintf("vela port-forward %s 80:80 ", appName)
output, err := e2e.ExecAndTerminate(cli)
gomega.Expect(err).NotTo(gomega.HaveOccurred())
@@ -128,14 +128,6 @@ var ApplicationInitIntercativeCliContext = func(context string, appName string,
data := []struct {
q, a string
}{
{
q: "What is the domain of your application service (optional): ",
a: "testdomain",
},
{
q: "What is your email (optional, used to generate certification): ",
a: "test@mail",
},
{
q: "What would you like to name your application (required): ",
a: appName,

View File

@@ -100,8 +100,14 @@ func InteractiveExec(cli string, consoleFn func(*expect.Console)) (string, error
command.Stdin = console.Tty()
session, err := gexec.Start(command, console.Tty(), console.Tty())
if err != nil {
return string(output), err
}
s := session.Wait(300 * time.Second)
console.Tty().Close()
err = console.Tty().Close()
if err != nil {
return string(output), err
}
<-doneC
if err != nil {
return string(output), err

View File

@@ -33,7 +33,7 @@ var (
cli := fmt.Sprintf("vela env init %s", envName)
output, err := Exec(cli)
gomega.Expect(err).NotTo(gomega.HaveOccurred())
expectedOutput := fmt.Sprintf("environment %s created,", envName)
expectedOutput := fmt.Sprintf("environment %s created", envName)
gomega.Expect(output).To(gomega.ContainSubstring(expectedOutput))
})
})
@@ -45,7 +45,7 @@ var (
cli := fmt.Sprintf("vela env init %s --namespace %s", envName, namespace)
output, err := Exec(cli)
gomega.Expect(err).NotTo(gomega.HaveOccurred())
expectedOutput := fmt.Sprintf("environment %s created,", envName)
expectedOutput := fmt.Sprintf("environment %s created", envName)
gomega.Expect(output).To(gomega.ContainSubstring(expectedOutput))
})
})

2
e2e/env/env_test.go vendored
View File

@@ -32,7 +32,7 @@ var _ = ginkgo.Describe("Env", func() {
e2e.EnvInitContext("env init", envName)
e2e.EnvInitContext("env init another one", envName2)
e2e.EnvShowContext("env show", envName)
e2e.EnvSetContext("env sw", envName)
e2e.EnvSetContext("env set", envName)
ginkgo.Context("env list", func() {
ginkgo.It("should list all envs", func() {

6
go.mod
View File

@@ -10,7 +10,7 @@ require (
github.com/aryann/difflib v0.0.0-20210328193216-ff5ff6dc229b
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869
github.com/briandowns/spinner v1.11.1
github.com/containerd/containerd v1.4.8
github.com/containerd/containerd v1.4.11
github.com/coreos/prometheus-operator v0.41.1
github.com/crossplane/crossplane-runtime v0.14.1-0.20210722005935-0b469fcc77cd
github.com/davecgh/go-spew v1.1.1
@@ -32,9 +32,9 @@ require (
github.com/imdario/mergo v0.3.12
github.com/kyokomi/emoji v2.2.4+incompatible
github.com/mitchellh/hashstructure/v2 v2.0.1
github.com/oam-dev/cluster-gateway v0.0.0-20210907072424-2f8720b116f8
github.com/oam-dev/cluster-gateway v1.1.2
github.com/oam-dev/terraform-config-inspect v0.0.0-20210418082552-fc72d929aa28
github.com/oam-dev/terraform-controller v0.2.0
github.com/oam-dev/terraform-controller v0.2.1
github.com/olekukonko/tablewriter v0.0.5
github.com/onsi/ginkgo v1.16.4
github.com/onsi/gomega v1.16.0

17
go.sum
View File

@@ -307,8 +307,8 @@ github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on
github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ=
github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/containerd/containerd v1.4.4/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/containerd/containerd v1.4.8 h1:H0wkS4AbVKTg9vyvBdCBrxoax8AMObKbNz9Fl2N0i4Y=
github.com/containerd/containerd v1.4.8/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/containerd/containerd v1.4.11 h1:QCGOUN+i70jEEL/A6JVIbhy4f4fanzAzSR4kNG7SlcE=
github.com/containerd/containerd v1.4.11/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7 h1:6ejg6Lkk8dskcM7wQ28gONkukbQkM4qpj4RnYbpFzrI=
github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y=
@@ -580,7 +580,6 @@ github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh
github.com/go-openapi/swag v0.19.6/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY=
github.com/go-openapi/swag v0.19.7/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY=
github.com/go-openapi/swag v0.19.9/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY=
github.com/go-openapi/swag v0.19.11/go.mod h1:Uc0gKkdR+ojzsEpjh39QChyu92vPgIr72POcgHMAgSY=
github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng=
github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
github.com/go-openapi/validate v0.17.2/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4=
@@ -1201,14 +1200,14 @@ github.com/nishanths/predeclared v0.2.1/go.mod h1:HvkGJcA3naj4lOwnFXFDkFxVtSqQMB
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/oam-dev/cluster-gateway v0.0.0-20210907072424-2f8720b116f8 h1:aTfUhMr6DC+jTiBvCzv+fcgqBvIoGLvrnmXjIUgib7I=
github.com/oam-dev/cluster-gateway v0.0.0-20210907072424-2f8720b116f8/go.mod h1:ZB7/tubU3MtdQ9bzQjksjO8UK+9e0Wrw3HAqKdY/lZY=
github.com/oam-dev/cluster-gateway v1.1.2 h1:sxC8Uyx/d3Yu8nIFSz31i+4JKhJfDAS9XVIPEWa1y+Q=
github.com/oam-dev/cluster-gateway v1.1.2/go.mod h1:EjPUZwTYBe+gFtPV/yGohLE19fDr3CUg4tfSRY72fkM=
github.com/oam-dev/stern v1.13.0-alpha h1:EVjM8Qvh6LssB6t4RZrjf9DtCq1cz+/cy6OF7fpy9wk=
github.com/oam-dev/stern v1.13.0-alpha/go.mod h1:AOkvfFUv0Arz7GBi0jz7S0Jsu4K/kdvSjNsnRt1+BIg=
github.com/oam-dev/terraform-config-inspect v0.0.0-20210418082552-fc72d929aa28 h1:tD8HiFKnt0jnwdTWjeqUnfnUYLD/+Nsmj8ZGIxqDWiU=
github.com/oam-dev/terraform-config-inspect v0.0.0-20210418082552-fc72d929aa28/go.mod h1:Mu8i0/DdplvnjwRbAYPsc8+LRR27n/mp8VWdkN10GzE=
github.com/oam-dev/terraform-controller v0.2.0 h1:GBQ+CvXtY9bcRkwGaPYHbYFkbVWzDExc05hz0NL0rqs=
github.com/oam-dev/terraform-controller v0.2.0/go.mod h1:wd4rnqnJzz274Sg1/qoeIhBx1rvTZ/ECzXoMff0ucR0=
github.com/oam-dev/terraform-controller v0.2.1 h1:gGXcUDBMWKfWet84STm99RX6gXo89pyTRsgQSLq2mog=
github.com/oam-dev/terraform-controller v0.2.1/go.mod h1:5Vy6jLx9fjotEd6E005Ve1f0x3fEpVlG/DVjmqLjAq0=
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
@@ -2523,8 +2522,8 @@ sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyz
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.19/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.22 h1:fmRfl9WJ4ApJn7LxNuED4m0t18qivVQOxP6aAYG9J6c=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.22/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
sigs.k8s.io/apiserver-runtime v1.0.3-0.20210906132642-810075b08b5f h1:RM+QxWPIZi3mo3i4fiUSvyFELyKr7jjMSJ5EEmt+i6M=
sigs.k8s.io/apiserver-runtime v1.0.3-0.20210906132642-810075b08b5f/go.mod h1:ynhMgoDTl6cihO5OpeV95iG+3bzKfHwWQU2VSbmoNmk=
sigs.k8s.io/apiserver-runtime v1.0.3-0.20210913073608-0663f60bfee2 h1:c6RYHA1wUg9IEsfjnxg0WsPwvDC2Qw2eryXKXgSEF1c=
sigs.k8s.io/apiserver-runtime v1.0.3-0.20210913073608-0663f60bfee2/go.mod h1:gvPfh5FX3Wi3kIRpkh7qvY0i/DQl3SDpRtvqMGZE3Vo=
sigs.k8s.io/controller-runtime v0.6.0/go.mod h1:CpYf5pdNY/B352A1TFLAS2JVSlnGQ5O2cftPHndTroo=
sigs.k8s.io/controller-runtime v0.6.2/go.mod h1:vhcq/rlnENJ09SIRp3EveTaZ0yqH526hjf9iJdbUJ/E=
sigs.k8s.io/controller-runtime v0.9.2/go.mod h1:TxzMCHyEUpaeuOiZx/bIdc2T81vfs/aKdvJt9wuu0zk=

View File

@@ -1232,6 +1232,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference
to Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -1621,6 +1635,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference
to Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -1908,6 +1936,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference
to Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -3318,6 +3360,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference
to Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -3600,6 +3656,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference
to Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -3971,6 +4041,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference
to Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -4221,6 +4305,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference
to Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -4487,6 +4585,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference
to Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration

View File

@@ -179,6 +179,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference to
Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -449,6 +463,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference to
Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration

View File

@@ -222,6 +222,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference
to Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -492,6 +506,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference
to Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -755,6 +783,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference
to Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -999,6 +1041,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference
to Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration

View File

@@ -151,6 +151,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference to
Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration

View File

@@ -188,6 +188,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference to
Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -454,6 +468,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference to
Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration

View File

@@ -1,352 +0,0 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.6.2
name: workflows.core.oam.dev
spec:
group: core.oam.dev
names:
categories:
- oam
kind: Workflow
listKind: WorkflowList
plural: workflows
shortNames:
- workflow
singular: workflow
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .status.phase
name: PHASE
type: string
- jsonPath: .metadata.creationTimestamp
name: AGE
type: date
name: v1alpha1
schema:
openAPIV3Schema:
description: Workflow is the Schema for the Workflow API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: A WorkflowSpec defines the desired state of a Workflow.
properties:
steps:
items:
description: WorkflowStep defines how to execute a workflow step.
properties:
inputs:
description: StepInputs defines variable input of WorkflowStep
items:
properties:
from:
type: string
parameterKey:
type: string
required:
- from
- parameterKey
type: object
type: array
name:
description: Name is the unique name of the workflow step.
type: string
outputs:
description: StepOutputs defines output variable of WorkflowStep
items:
properties:
name:
type: string
valueFrom:
type: string
required:
- name
- valueFrom
type: object
type: array
properties:
type: object
type:
type: string
required:
- name
- type
type: object
type: array
type: object
status:
description: A WorkflowStatus is the status of Workflow
properties:
conditions:
description: Conditions of the resource.
items:
description: A Condition that may apply to a resource.
properties:
lastTransitionTime:
description: LastTransitionTime is the last time this condition
transitioned from one status to another.
format: date-time
type: string
message:
description: A Message containing details about this condition's
last transition from one status to another, if any.
type: string
reason:
description: A Reason for this condition's last transition from
one status to another.
type: string
status:
description: Status of this condition; is it currently True,
False, or Unknown?
type: string
type:
description: Type of this condition. At most one of each condition
type may apply to a resource at any point in time.
type: string
required:
- lastTransitionTime
- reason
- status
- type
type: object
type: array
contextBackend:
description: 'ObjectReference contains enough information to let you
inspect or modify the referred object. --- New uses of this type
are discouraged because of difficulty describing its usage when
embedded in APIs. 1. Ignored fields. It includes many fields which
are not generally honored. For instance, ResourceVersion and FieldPath
are both very rarely valid in actual usage. 2. Invalid usage help. It
is impossible to add specific help for individual usage. In most
embedded usages, there are particular restrictions like, "must
refer only to types A and B" or "UID not honored" or "name must
be restricted". Those cannot be well described when embedded. 3.
Inconsistent validation. Because the usages are different, the
validation rules are different by usage, which makes it hard for
users to predict what will happen. 4. The fields are both imprecise
and overly precise. Kind is not a precise mapping to a URL. This
can produce ambiguity during interpretation and require a REST
mapping. In most cases, the dependency is on the group,resource
tuple and the version of the actual struct is irrelevant. 5.
We cannot easily change it. Because this type is embedded in many
locations, updates to this type will affect numerous schemas. Don''t
make new APIs embed an underspecified API type they do not control.
Instead of using this type, create a locally provided and used type
that is well-focused on your reference. For example, ServiceReferences
for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533
.'
properties:
apiVersion:
description: API version of the referent.
type: string
fieldPath:
description: 'If referring to a piece of an object instead of
an entire object, this string should contain a valid JSON/Go
field access statement, such as desiredState.manifest.containers[2].
For example, if the object reference is to a container within
a pod, this would take on a value like: "spec.containers{name}"
(where "name" refers to the name of the container that triggered
the event) or if no container name is specified "spec.containers[2]"
(container with index 2 in this pod). This syntax is chosen
only to have some well-defined way of referencing a part of
an object. TODO: this design is not final and this field is
subject to change in the future.'
type: string
kind:
description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
type: string
namespace:
description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
type: string
resourceVersion:
description: 'Specific resourceVersion to which this reference
is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
type: string
uid:
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
observedGeneration:
format: int64
type: integer
stepIndex:
type: integer
steps:
items:
description: WorkflowStepStatus record the status of a workflow
step
properties:
message:
description: A human readable message indicating details about
why the workflowStep is in this state.
type: string
name:
type: string
phase:
description: WorkflowStepPhase describes the phase of a workflow
step.
type: string
reason:
description: A brief CamelCase message indicating details about
why the workflowStep is in this state.
type: string
resourceRef:
description: 'ObjectReference contains enough information to
let you inspect or modify the referred object. --- New uses
of this type are discouraged because of difficulty describing
its usage when embedded in APIs. 1. Ignored fields. It includes
many fields which are not generally honored. For instance,
ResourceVersion and FieldPath are both very rarely valid in
actual usage. 2. Invalid usage help. It is impossible to
add specific help for individual usage. In most embedded
usages, there are particular restrictions like, "must
refer only to types A and B" or "UID not honored" or "name
must be restricted". Those cannot be well described when
embedded. 3. Inconsistent validation. Because the usages
are different, the validation rules are different by usage,
which makes it hard for users to predict what will happen. 4.
The fields are both imprecise and overly precise. Kind is
not a precise mapping to a URL. This can produce ambiguity during
interpretation and require a REST mapping. In most cases,
the dependency is on the group,resource tuple and the
version of the actual struct is irrelevant. 5. We cannot
easily change it. Because this type is embedded in many locations,
updates to this type will affect numerous schemas. Don''t
make new APIs embed an underspecified API type they do not
control. Instead of using this type, create a locally provided
and used type that is well-focused on your reference. For
example, ServiceReferences for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533
.'
properties:
apiVersion:
description: API version of the referent.
type: string
fieldPath:
description: 'If referring to a piece of an object instead
of an entire object, this string should contain a valid
JSON/Go field access statement, such as desiredState.manifest.containers[2].
For example, if the object reference is to a container
within a pod, this would take on a value like: "spec.containers{name}"
(where "name" refers to the name of the container that
triggered the event) or if no container name is specified
"spec.containers[2]" (container with index 2 in this pod).
This syntax is chosen only to have some well-defined way
of referencing a part of an object. TODO: this design
is not final and this field is subject to change in the
future.'
type: string
kind:
description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
type: string
namespace:
description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
type: string
resourceVersion:
description: 'Specific resourceVersion to which this reference
is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
type: string
uid:
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
type:
type: string
type: object
type: array
suspend:
type: boolean
terminated:
type: boolean
required:
- contextBackend
- suspend
- terminated
type: object
type: object
served: true
storage: true
subresources:
status: {}
- name: v1beta1
schema:
openAPIV3Schema:
description: Workflow defines workflow steps and other attributes
properties:
steps:
items:
description: WorkflowStep defines how to execute a workflow step.
properties:
dependsOn:
items:
type: string
type: array
inputs:
description: StepInputs defines variable input of WorkflowStep
items:
properties:
from:
type: string
parameterKey:
type: string
required:
- from
- parameterKey
type: object
type: array
name:
description: Name is the unique name of the workflow step.
type: string
outputs:
description: StepOutputs defines output variable of WorkflowStep
items:
properties:
name:
type: string
valueFrom:
type: string
required:
- name
- valueFrom
type: object
type: array
properties:
type: object
type:
type: string
required:
- name
- type
type: object
type: array
type: object
served: true
storage: false
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []

View File

@@ -148,6 +148,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference to
Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration

View File

@@ -193,6 +193,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference to
Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
@@ -440,6 +454,20 @@ spec:
configuration:
description: Configuration is Terraform Configuration
type: string
providerRef:
description: ProviderReference specifies the reference to
Provider
properties:
name:
description: Name of the referenced object.
type: string
namespace:
default: default
description: Namespace of the secret.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration

View File

@@ -649,7 +649,7 @@ func generateComponentFromKubeModule(wl *Workload, appName, revision, ns string)
}
func generateTerraformConfigurationWorkload(wl *Workload, ns string) (*unstructured.Unstructured, error) {
if wl.FullTemplate.Terraform.Configuration == "" {
if wl.FullTemplate == nil || wl.FullTemplate.Terraform == nil || wl.FullTemplate.Terraform.Configuration == "" {
return nil, errors.New(errTerraformConfigurationIsNotSet)
}
params, err := json.Marshal(wl.Params)
@@ -671,6 +671,10 @@ func generateTerraformConfigurationWorkload(wl *Workload, ns string) (*unstructu
configuration.Spec.Remote = wl.FullTemplate.Terraform.Configuration
}
if wl.FullTemplate.Terraform.ProviderReference != nil {
configuration.Spec.ProviderReference = wl.FullTemplate.Terraform.ProviderReference
}
// 1. parse writeConnectionSecretToRef
if err := json.Unmarshal(params, &configuration.Spec); err != nil {
return nil, errors.Wrap(err, errFailToConvertTerraformComponentProperties)
@@ -704,7 +708,7 @@ func generateTerraformConfigurationWorkload(wl *Workload, ns string) (*unstructu
}
configuration.Spec.Variable = &runtime.RawExtension{Raw: data}
raw := util.Object2RawExtension(&configuration)
return util.RawExtension2Unstructured(&raw)
return util.RawExtension2Unstructured(raw)
}
// a helper map whose key is parameter name

View File

@@ -103,7 +103,7 @@ var _ = Describe("Test Helm schematic appfile", func() {
},
},
Helm: &common.Helm{
Release: util.Object2RawExtension(map[string]interface{}{
Release: *util.Object2RawExtension(map[string]interface{}{
"chart": map[string]interface{}{
"spec": map[string]interface{}{
"chart": "podinfo",
@@ -111,7 +111,7 @@ var _ = Describe("Test Helm schematic appfile", func() {
},
},
}),
Repository: util.Object2RawExtension(map[string]interface{}{
Repository: *util.Object2RawExtension(map[string]interface{}{
"url": "http://oam.dev/catalog/",
}),
},
@@ -909,6 +909,7 @@ func TestGenerateTerraformConfigurationWorkload(t *testing.T) {
hcl string
remote string
params map[string]interface{}
providerRef *terraformtypes.Reference
}
type want struct {
@@ -967,7 +968,18 @@ func TestGenerateTerraformConfigurationWorkload(t *testing.T) {
params: badParam,
hcl: "abc",
},
want: want{err: errors.Wrap(badParamMarshalError, errFailToConvertTerraformComponentProperties)}},
want: want{err: errors.Wrap(badParamMarshalError, errFailToConvertTerraformComponentProperties)},
},
"terraform workload has a provider reference": {
args: args{
params: badParam,
hcl: "abc",
providerRef: &terraformtypes.Reference{Name: "azure", Namespace: "default"},
},
want: want{err: errors.Wrap(badParamMarshalError, errFailToConvertTerraformComponentProperties)},
},
}
for tcName, tc := range testcases {
@@ -1027,6 +1039,9 @@ func TestGenerateTerraformConfigurationWorkload(t *testing.T) {
WriteConnectionSecretToReference: tc.args.writeConnectionSecretToRef,
}
}
if tc.args.providerRef != nil {
template.Terraform.ProviderReference = tc.args.providerRef
}
wl := &Workload{
FullTemplate: template,
@@ -1046,7 +1061,7 @@ func TestGenerateTerraformConfigurationWorkload(t *testing.T) {
Spec: configSpec,
}
rawConf := util.Object2RawExtension(tfConfiguration)
wantWL, _ := util.RawExtension2Unstructured(&rawConf)
wantWL, _ := util.RawExtension2Unstructured(rawConf)
if diff := cmp.Diff(wantWL, got); diff != "" {
t.Errorf("\n%s\ngenerateTerraformConfigurationWorkload(...): -want, +got:\n%s\n", tcName, diff)

View File

@@ -1,96 +0,0 @@
/*
Copyright 2021 The KubeVela Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package config
import (
"context"
"strings"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
)
const (
// Splitter is a splitter for configmap name generation
Splitter = "-"
// TypeConfigMap defines the type of Configmap
TypeConfigMap = "configmap"
)
// ToConfigMap will get the data of the store and upload to configmap.
// Serverside Application controller can only use the config in appfile context by configmap.
func ToConfigMap(s Store, name, envName string, configData map[string]string) (*v1.ConfigMap, error) {
namespace, err := s.Namespace(envName)
if err != nil {
return nil, err
}
var cm = v1.ConfigMap{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "ConfigMap",
},
}
cm.SetName(name)
cm.SetNamespace(namespace)
cm.Data = configData
return &cm, nil
}
// GenConfigMapName is a fixed way to name the configmap name for appfile config
func GenConfigMapName(appName, serviceName, configName string) string {
return strings.Join([]string{"kubevela", appName, serviceName, configName}, Splitter)
}
var _ Store = &Configmap{}
// Configmap is the configmap implementation of config store
type Configmap struct {
Client client.Client
}
// GetConfigData will get config data from configmap
func (f *Configmap) GetConfigData(name, envName string) ([]map[string]string, error) {
namespace, err := f.Namespace(envName)
if err != nil {
return nil, err
}
var cm v1.ConfigMap
err = f.Client.Get(context.Background(), client.ObjectKey{Name: name, Namespace: namespace}, &cm)
if err != nil {
return nil, err
}
var data []map[string]string
for k, v := range cm.Data {
data = append(data, EncodeConfigFormat(k, v))
}
return data, nil
}
// Namespace returns the namespace of the config store from env
func (f *Configmap) Namespace(envName string) (string, error) {
// TODO(wonderflow): now we regard env as namespace, it should be fixed when env is store serverside as configmap
return envName, nil
}
// Type returns the type of the config store
func (Configmap) Type() string {
return TypeConfigMap
}

View File

@@ -1,65 +0,0 @@
/*
Copyright 2021 The KubeVela Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package config
import (
"bufio"
"bytes"
"github.com/oam-dev/kubevela/pkg/utils/config"
env2 "github.com/oam-dev/kubevela/pkg/utils/env"
)
// TypeLocal defines the local config store type
const TypeLocal = "local"
// Local is the local implementation of config store
type Local struct{}
var _ Store = &Local{}
// GetConfigData will return config data from local
func (l *Local) GetConfigData(configName, envName string) ([]map[string]string, error) {
cfgData, err := config.ReadConfig(envName, configName)
if err != nil {
return nil, err
}
scanner := bufio.NewScanner(bytes.NewReader(cfgData))
var data []map[string]string
for scanner.Scan() {
k, v, err := config.ReadConfigLine(scanner.Text())
if err != nil {
return nil, err
}
data = append(data, EncodeConfigFormat(k, v))
}
return data, nil
}
// Namespace return namespace from env
func (l *Local) Namespace(envName string) (string, error) {
env, err := env2.GetEnvByName(envName)
if err != nil {
return "", err
}
return env.Namespace, nil
}
// Type returns the type of this config store implementation
func (l *Local) Type() string {
return TypeLocal
}

View File

@@ -1,76 +0,0 @@
/*
Copyright 2021 The KubeVela Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package config
import "errors"
// Store will get config data
type Store interface {
GetConfigData(configName, envName string) ([]map[string]string, error)
Type() string
Namespace(envName string) (string, error)
}
// TypeFake is a fake type
const TypeFake = "fake"
var _ Store = &Fake{}
// Fake is a fake implementation of config store, help for test
type Fake struct {
Data []map[string]string
}
// GetConfigData get data
func (f *Fake) GetConfigData(_ string, _ string) ([]map[string]string, error) {
return f.Data, nil
}
// Type return the type
func (Fake) Type() string {
return TypeFake
}
// Namespace return the Namespace
func (Fake) Namespace(_ string) (string, error) {
return "", nil
}
// EncodeConfigFormat will encode key-value to config{name: key, value: value} format
func EncodeConfigFormat(key, value string) map[string]string {
return map[string]string{
"name": key,
"value": value,
}
}
// DecodeConfigFormat will decode config{name: key, value: value} format to key-value mode.
func DecodeConfigFormat(data []map[string]string) (map[string]string, error) {
var res = make(map[string]string)
for _, d := range data {
key, ok := d["name"]
if !ok {
return nil, errors.New("invalid data format, no 'name' found")
}
value, ok := d["value"]
if !ok {
return nil, errors.New("invalid data format, no 'value' found")
}
res[key] = value
}
return res, nil
}

View File

@@ -251,7 +251,7 @@ func (p *Parser) parsePoliciesFromRevision(policies []v1beta1.AppPolicy, appRev
return ws, nil
}
func (p *Parser) makeWorkload(ctx context.Context, name, typ string, capType types.CapType, props runtime.RawExtension) (*Workload, error) {
func (p *Parser) makeWorkload(ctx context.Context, name, typ string, capType types.CapType, props *runtime.RawExtension) (*Workload, error) {
templ, err := p.tmplLoader.LoadTemplate(ctx, p.dm, p.client, typ, capType)
if err != nil {
return nil, errors.WithMessagef(err, "fetch component/policy type of %s", name)
@@ -259,7 +259,7 @@ func (p *Parser) makeWorkload(ctx context.Context, name, typ string, capType typ
return p.convertTemplate2Workload(name, typ, props, templ)
}
func (p *Parser) makeWorkloadFromRevision(name, typ string, capType types.CapType, props runtime.RawExtension, appRev *v1beta1.ApplicationRevision) (*Workload, error) {
func (p *Parser) makeWorkloadFromRevision(name, typ string, capType types.CapType, props *runtime.RawExtension, appRev *v1beta1.ApplicationRevision) (*Workload, error) {
templ, err := LoadTemplateFromRevision(typ, capType, appRev, p.dm)
if err != nil {
return nil, errors.WithMessagef(err, "fetch component/policy type of %s from revision", name)
@@ -268,8 +268,8 @@ func (p *Parser) makeWorkloadFromRevision(name, typ string, capType types.CapTyp
return p.convertTemplate2Workload(name, typ, props, templ)
}
func (p *Parser) convertTemplate2Workload(name, typ string, props runtime.RawExtension, templ *Template) (*Workload, error) {
settings, err := util.RawExtension2Map(&props)
func (p *Parser) convertTemplate2Workload(name, typ string, props *runtime.RawExtension, templ *Template) (*Workload, error) {
settings, err := util.RawExtension2Map(props)
if err != nil {
return nil, errors.WithMessagef(err, "fail to parse settings for %s", name)
}
@@ -299,7 +299,7 @@ func (p *Parser) parseWorkload(ctx context.Context, comp common.ApplicationCompo
workload.ExternalRevision = comp.ExternalRevision
for _, traitValue := range comp.Traits {
properties, err := util.RawExtension2Map(&traitValue.Properties)
properties, err := util.RawExtension2Map(traitValue.Properties)
if err != nil {
return nil, errors.Errorf("fail to parse properties of %s for %s", traitValue.Type, comp.Name)
}
@@ -335,7 +335,7 @@ func (p *Parser) ParseWorkloadFromRevision(comp common.ApplicationComponent, app
workload.ExternalRevision = comp.ExternalRevision
for _, traitValue := range comp.Traits {
properties, err := util.RawExtension2Map(&traitValue.Properties)
properties, err := util.RawExtension2Map(traitValue.Properties)
if err != nil {
return nil, errors.Errorf("fail to parse properties of %s for %s", traitValue.Type, comp.Name)
}

View File

@@ -23,6 +23,7 @@ import (
"os"
"path/filepath"
"k8s.io/klog/v2"
"sigs.k8s.io/kind/pkg/cluster"
"sigs.k8s.io/kind/pkg/cluster/nodes"
"sigs.k8s.io/kind/pkg/cluster/nodeutils"
@@ -137,7 +138,11 @@ func loadImage(imageTarName string, node nodes.Node) error {
if err != nil {
return errors.Wrap(err, "failed to open image")
}
defer f.Close()
defer func() {
if err := f.Close(); err != nil {
klog.Error(err, "Failed to close file")
}
}()
return nodeutils.LoadImageArchive(node, f)
}

View File

@@ -30,6 +30,7 @@ import (
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
"github.com/oam-dev/kubevela/apis/standard.oam.dev/v1alpha1"
"github.com/oam-dev/kubevela/pkg/controller/utils"
"github.com/oam-dev/kubevela/pkg/oam"
)
@@ -84,7 +85,14 @@ func (c *CloneSetRolloutController) VerifySpec(ctx context.Context) (bool, error
}
// make sure that the updateRevision is different from what we have already done
targetHash := c.cloneSet.Status.UpdateRevision
targetHash, verifyErr := utils.ComputeSpecHash(c.cloneSet.Spec)
if verifyErr != nil {
// do not fail the rollout because we can't compute the hash value for some reason
c.rolloutStatus.RolloutRetry(verifyErr.Error())
// nolint:nilerr
return false, nil
}
if targetHash == c.rolloutStatus.LastAppliedPodTemplateIdentifier {
return false, fmt.Errorf("there is no difference between the source and target, hash = %s", targetHash)
}

View File

@@ -137,14 +137,14 @@ var _ = Describe("cloneset controller", func() {
Expect(consistent).Should(BeFalse())
})
It("there is no difference between the source and target", func() {
It("verify rollout spec hash", func() {
By("Create a CloneSet")
cloneSet.Spec.UpdateStrategy.Paused = true
Expect(k8sClient.Create(ctx, &cloneSet)).Should(Succeed())
By("Verify should fail because the cloneset hash is not computed without kruise controller")
consistent, err := c.VerifySpec(ctx)
Expect(err).Should(Equal(fmt.Errorf("there is no difference between the source and target, hash = ")))
Expect(consistent).Should(BeFalse())
Expect(err).Should(BeNil())
Expect(consistent).Should(BeTrue())
})
It("the cloneset is in the middle of updating", func() {

View File

@@ -20,6 +20,8 @@ import (
"context"
"fmt"
"github.com/oam-dev/kubevela/pkg/controller/utils"
"github.com/crossplane/crossplane-runtime/pkg/event"
"github.com/pkg/errors"
appsv1 "k8s.io/api/apps/v1"
@@ -80,7 +82,14 @@ func (s *StatefulSetRolloutController) VerifySpec(ctx context.Context) (bool, er
s.rolloutStatus.RolloutOriginalSize = currentReplicas
// make sure that the updateRevision is different from what we have already done
targetHash := s.statefulSet.Status.UpdateRevision
targetHash, verifyErr := utils.ComputeSpecHash(s.statefulSet.Spec)
if verifyErr != nil {
// do not fail the rollout because we can't compute the hash value for some reason
s.rolloutStatus.RolloutRetry(verifyErr.Error())
// nolint:nilerr
return false, nil
}
if targetHash == s.rolloutStatus.LastAppliedPodTemplateIdentifier {
return false, fmt.Errorf("there is no difference between the source and target, hash = %s", targetHash)
}

View File

@@ -145,7 +145,7 @@ var _ = Describe("StatefulSet controller", func() {
targetHash := statefulSet.Status.UpdateRevision
c.rolloutStatus.LastAppliedPodTemplateIdentifier = targetHash
consistent, err := c.VerifySpec(ctx)
Expect(err).Should(Equal(fmt.Errorf("there is no difference between the source and target, hash = ")))
Expect(err).ShouldNot(Equal(fmt.Errorf("there is no difference between the source and target, hash = ")))
Expect(consistent).Should(BeFalse())
})
@@ -203,7 +203,8 @@ var _ = Describe("StatefulSet controller", func() {
Expect(err).Should(BeNil())
Expect(consistent).Should(BeTrue())
Expect(c.rolloutStatus.RolloutTargetSize).Should(BeEquivalentTo(*statefulSet.Spec.Replicas))
Expect(c.rolloutStatus.NewPodTemplateIdentifier).Should(BeEmpty())
// NewPodTemplateIdenifier should be fill with computed hash
Expect(c.rolloutStatus.NewPodTemplateIdentifier).ShouldNot(BeEmpty())
})
})

View File

@@ -260,12 +260,12 @@ func PatchComponent(baseComponent *common.ApplicationComponent, patchComponent *
}
// PatchProperties merge patch parameter for dst parameter
func PatchProperties(dst runtime.RawExtension, patch runtime.RawExtension) (map[string]interface{}, error) {
patchParameter, err := util.RawExtension2Map(&patch)
func PatchProperties(dst *runtime.RawExtension, patch *runtime.RawExtension) (map[string]interface{}, error) {
patchParameter, err := util.RawExtension2Map(patch)
if err != nil {
return nil, err
}
baseParameter, err := util.RawExtension2Map(&dst)
baseParameter, err := util.RawExtension2Map(dst)
if err != nil {
return nil, err
}

View File

@@ -22,6 +22,7 @@ import (
"github.com/pkg/errors"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -31,6 +32,11 @@ import (
"github.com/oam-dev/kubevela/pkg/multicluster"
)
const (
// OverrideNamespaceLabelKey identifies the override namespace for patched Application
OverrideNamespaceLabelKey = "envbinding.oam.dev/override-namespace"
)
// ClusterGatewayEngine construct the multicluster engine of using cluster-gateway
type ClusterGatewayEngine struct {
client.Client
@@ -46,63 +52,64 @@ func NewClusterGatewayEngine(cli client.Client, envBindingName string) ClusterMa
}
}
// TODO only support cluster name now, should support selector and namespace later
// TODO only support single cluster name and namespace name now, should support label selector
func (engine *ClusterGatewayEngine) prepare(ctx context.Context, configs []v1alpha1.EnvConfig) error {
engine.clusterDecisions = make(map[string]v1alpha1.ClusterDecision)
clusterNameToConfig := make(map[string]string)
locationToConfig := make(map[string]string)
for _, config := range configs {
var namespace, clusterName string
// check if namespace selector is valid
if config.Placement.NamespaceSelector != nil {
return errors.Errorf("invalid env %s: namespace selector in cluster-gateway is not supported now", config.Name)
if len(config.Placement.NamespaceSelector.Labels) != 0 {
return errors.Errorf("invalid env %s: namespace selector in cluster-gateway does not support label selector for now", config.Name)
}
namespace = config.Placement.NamespaceSelector.Name
}
if config.Placement.ClusterSelector == nil {
return errors.Errorf("invalid env %s: cluster selector must be set for now", config.Name)
// check if cluster selector is valid
if config.Placement.ClusterSelector != nil {
if len(config.Placement.ClusterSelector.Labels) != 0 {
return errors.Errorf("invalid env %s: cluster selector does not support label selector for now", config.Name)
}
clusterName = config.Placement.ClusterSelector.Name
}
if len(config.Placement.ClusterSelector.Labels) != 0 {
return errors.Errorf("invalid env %s: cluster selector does not support label selector for now", config.Name)
// set fallback cluster
if clusterName == "" {
clusterName = multicluster.ClusterLocalName
}
if len(config.Placement.ClusterSelector.Name) == 0 {
return errors.Errorf("invalid env %s: cluster selector must set cluster name for now", config.Name)
// check if current environment uses the same cluster and namespace as resource destination with other environment, if yes, a conflict occurs
location := clusterName + "/" + namespace
if dupConfigName, ok := locationToConfig[location]; ok {
return errors.Errorf("invalid env %s: location %s conflict with env %s", config.Name, location, dupConfigName)
}
clusterName := config.Placement.ClusterSelector.Name
if dupConfigName, ok := clusterNameToConfig[clusterName]; ok {
return errors.Errorf("invalid env %s: cluster name %s is conflict with env %s", config.Name, clusterName, dupConfigName)
}
clusterNameToConfig[clusterName] = config.Name
locationToConfig[clusterName] = config.Name
// check if target cluster exists
if clusterName != multicluster.ClusterLocalName {
if err := engine.Get(ctx, types.NamespacedName{Namespace: multicluster.ClusterGatewaySecretNamespace, Name: clusterName}, &v1.Secret{}); err != nil {
return errors.Wrapf(err, "failed to get cluster %s for env %s", clusterName, config.Name)
}
}
engine.clusterDecisions[config.Name] = v1alpha1.ClusterDecision{Env: config.Name, Cluster: clusterName}
engine.clusterDecisions[config.Name] = v1alpha1.ClusterDecision{Env: config.Name, Cluster: clusterName, Namespace: namespace}
}
return nil
}
func (engine *ClusterGatewayEngine) initEnvBindApps(ctx context.Context, envBinding *v1alpha1.EnvBinding, baseApp *v1beta1.Application, appParser *appfile.Parser) ([]*EnvBindApp, error) {
envBindApps, err := CreateEnvBindApps(envBinding, baseApp)
if err != nil {
return nil, err
}
if err = RenderEnvBindApps(ctx, envBindApps, appParser); err != nil {
return nil, err
}
if err = AssembleEnvBindApps(envBindApps); err != nil {
return nil, err
}
return envBindApps, nil
return CreateEnvBindApps(envBinding, baseApp)
}
func (engine *ClusterGatewayEngine) schedule(ctx context.Context, apps []*EnvBindApp) ([]v1alpha1.ClusterDecision, error) {
for _, app := range apps {
app.ScheduledManifests = make(map[string]*unstructured.Unstructured)
clusterName := engine.clusterDecisions[app.envConfig.Name].Cluster
for _, component := range app.PatchedApp.Spec.Components {
for _, manifest := range app.assembledManifests[component.Name] {
manifestName := component.Name + "/" + manifest.GetName()
multicluster.SetClusterName(manifest, clusterName)
app.ScheduledManifests[manifestName] = manifest
}
namespace := engine.clusterDecisions[app.envConfig.Name].Namespace
raw, err := runtime.DefaultUnstructuredConverter.ToUnstructured(app.PatchedApp)
if err != nil {
return nil, errors.Wrapf(err, "failed to convert app [Env: %s](%s/%s) into unstructured", app.envConfig.Name, app.PatchedApp.Namespace, app.PatchedApp.Name)
}
patchedApp := &unstructured.Unstructured{Object: raw}
multicluster.SetClusterName(patchedApp, clusterName)
SetOverrideNamespace(patchedApp, namespace)
app.ScheduledManifests[patchedApp.GetName()] = patchedApp
}
var decisions []v1alpha1.ClusterDecision
for _, decision := range engine.clusterDecisions {
@@ -110,3 +117,15 @@ func (engine *ClusterGatewayEngine) schedule(ctx context.Context, apps []*EnvBin
}
return decisions, nil
}
// SetOverrideNamespace set the override namespace for object in its label
func SetOverrideNamespace(obj *unstructured.Unstructured, overrideNamespace string) {
if overrideNamespace != "" {
labels := obj.GetLabels()
if labels == nil {
labels = map[string]string{}
}
labels[OverrideNamespaceLabelKey] = overrideNamespace
obj.SetLabels(labels)
}
}

View File

@@ -123,7 +123,7 @@ func (o *OCMEngine) schedule(ctx context.Context, apps []*EnvBindApp) ([]v1alpha
manifest := app.assembledManifests[component.Name]
for j := range manifest {
workloads = append(workloads, ocmworkv1.Manifest{
RawExtension: util.Object2RawExtension(manifest[j]),
RawExtension: *util.Object2RawExtension(manifest[j]),
})
}
}

View File

@@ -284,7 +284,7 @@ func (r *Reconciler) handleFinalizers(ctx context.Context, envBinding *v1alpha1.
func (r *Reconciler) endWithNegativeCondition(ctx context.Context, envBinding *v1alpha1.EnvBinding, cond condition.Condition) (ctrl.Result, error) {
envBinding.SetConditions(cond)
if err := r.Client.Status().Patch(ctx, envBinding, client.Merge); err != nil {
return ctrl.Result{}, errors.WithMessage(err, "cannot update initializer status")
return ctrl.Result{}, errors.WithMessage(err, "cannot update envbinding status")
}
// if any condition is changed, patching status can trigger requeue the resource and we should return nil to
// avoid requeue it again

View File

@@ -182,7 +182,7 @@ var _ = Describe("EnvBinding Normal tests", func() {
envBinding.SetNamespace(namespace)
envBinding.SetName("envbinding-select-cluster-by-name")
envBinding.Spec.AppTemplate = v1alpha1.AppTemplate{
RawExtension: util.Object2RawExtension(appTemplate),
RawExtension: *util.Object2RawExtension(appTemplate),
}
envBinding.Spec.Envs[0].Placement.ClusterSelector.Name = spokeClusterName
envBinding.Spec.OutputResourcesTo = &v1alpha1.ConfigMapReference{
@@ -229,7 +229,7 @@ var _ = Describe("EnvBinding Normal tests", func() {
envBinding.SetNamespace(namespace)
envBinding.SetName("envbinding-select-cluster-by-label")
envBinding.Spec.AppTemplate = v1alpha1.AppTemplate{
RawExtension: util.Object2RawExtension(appTemplate),
RawExtension: *util.Object2RawExtension(appTemplate),
}
envBinding.Spec.Envs[0].Placement.ClusterSelector.Labels = map[string]string{
"purpose": "test",
@@ -277,7 +277,7 @@ var _ = Describe("EnvBinding Normal tests", func() {
envBinding.SetNamespace(namespace)
envBinding.SetName("envbinding-with-two-env-config")
envBinding.Spec.AppTemplate = v1alpha1.AppTemplate{
RawExtension: util.Object2RawExtension(appTemplate),
RawExtension: *util.Object2RawExtension(appTemplate),
}
envBinding.Spec.Envs[0].Placement.ClusterSelector.Name = spokeClusterName
@@ -361,7 +361,7 @@ var _ = Describe("EnvBinding Normal tests", func() {
envBinding.SetNamespace(namespace)
envBinding.SetName("envbinding-with-app-has-helm")
envBinding.Spec.AppTemplate = v1alpha1.AppTemplate{
RawExtension: util.Object2RawExtension(appTemplate),
RawExtension: *util.Object2RawExtension(appTemplate),
}
envBinding.Spec.Envs = []v1alpha1.EnvConfig{{
@@ -416,7 +416,7 @@ var _ = Describe("EnvBinding Normal tests", func() {
envBinding.SetNamespace(namespace)
envBinding.SetName("envbinding-apply-resources-with-ocm")
envBinding.Spec.AppTemplate = v1alpha1.AppTemplate{
RawExtension: util.Object2RawExtension(appTemplate),
RawExtension: *util.Object2RawExtension(appTemplate),
}
envBinding.Spec.Envs[0].Placement.ClusterSelector.Name = spokeClusterName
envBinding.Spec.Engine = v1alpha1.OCMEngine
@@ -458,7 +458,7 @@ var _ = Describe("EnvBinding Normal tests", func() {
envBinding.SetNamespace(namespace)
envBinding.SetName("envbinding-apply-resources")
envBinding.Spec.AppTemplate = v1alpha1.AppTemplate{
RawExtension: util.Object2RawExtension(appTemplate),
RawExtension: *util.Object2RawExtension(appTemplate),
}
envBinding.Spec.Engine = v1alpha1.SingleClusterEngine
@@ -494,7 +494,7 @@ var _ = Describe("EnvBinding Normal tests", func() {
envBinding.SetNamespace(namespace)
envBinding.SetName("envbinding-store2configmap")
envBinding.Spec.AppTemplate = v1alpha1.AppTemplate{
RawExtension: util.Object2RawExtension(appTemplate),
RawExtension: *util.Object2RawExtension(appTemplate),
}
envBinding.Spec.Engine = v1alpha1.SingleClusterEngine
envBinding.Spec.OutputResourcesTo = &v1alpha1.ConfigMapReference{
@@ -538,7 +538,7 @@ var _ = Describe("EnvBinding Normal tests", func() {
envBinding.SetNamespace(namespace)
envBinding.SetName("envbinding-specify-ns")
envBinding.Spec.AppTemplate = v1alpha1.AppTemplate{
RawExtension: util.Object2RawExtension(appTemplate),
RawExtension: *util.Object2RawExtension(appTemplate),
}
envBinding.Spec.Engine = v1alpha1.SingleClusterEngine
envBinding.Spec.Envs[0].Placement = v1alpha1.EnvPlacement{
@@ -579,7 +579,7 @@ var _ = Describe("EnvBinding Normal tests", func() {
envBinding.SetNamespace(namespace)
envBinding.SetName("envbinding-select-ns-label")
envBinding.Spec.AppTemplate = v1alpha1.AppTemplate{
RawExtension: util.Object2RawExtension(appTemplate),
RawExtension: *util.Object2RawExtension(appTemplate),
}
envBinding.Spec.Engine = v1alpha1.SingleClusterEngine
envBinding.Spec.Envs[0].Placement = v1alpha1.EnvPlacement{
@@ -624,7 +624,7 @@ var _ = Describe("EnvBinding Normal tests", func() {
envBinding.SetName("test-envbinding-gc-single-cluster")
envBinding.SetNamespace(namespace)
envBinding.Spec.AppTemplate = v1alpha1.AppTemplate{
RawExtension: util.Object2RawExtension(appTemplate),
RawExtension: *util.Object2RawExtension(appTemplate),
}
envBinding.Spec.Engine = v1alpha1.SingleClusterEngine
envBinding.Spec.Envs[0].Placement = v1alpha1.EnvPlacement{
@@ -663,7 +663,6 @@ var _ = Describe("EnvBinding Normal tests", func() {
By("Create envBinding")
Expect(k8sClient.Create(ctx, envBinding)).Should(BeNil())
testutil.ReconcileOnce(&r, req)
testutil.ReconcileRetry(&r, req)
By("Check the Application created by EnvBinding Controller")
@@ -743,7 +742,7 @@ var _ = Describe("EnvBinding Normal tests", func() {
envBinding.SetName("test-envbinding-gc-multi-cluster")
envBinding.SetNamespace(namespace)
envBinding.Spec.AppTemplate = v1alpha1.AppTemplate{
RawExtension: util.Object2RawExtension(appTemplate),
RawExtension: *util.Object2RawExtension(appTemplate),
}
envBinding.Spec.Envs[0].Placement.ClusterSelector.Name = spokeClusterName
@@ -1008,7 +1007,7 @@ var podInfo = &v1beta1.ComponentDefinition{
},
Schematic: &commontype.Schematic{
HELM: &commontype.Helm{
Release: util.Object2RawExtension(map[string]interface{}{
Release: *util.Object2RawExtension(map[string]interface{}{
"chart": map[string]interface{}{
"spec": map[string]interface{}{
"chart": "podinfo",
@@ -1016,7 +1015,7 @@ var podInfo = &v1beta1.ComponentDefinition{
},
},
}),
Repository: util.Object2RawExtension(map[string]interface{}{
Repository: *util.Object2RawExtension(map[string]interface{}{
"url": "http://oam.dev/catalog/",
}),
},

View File

@@ -137,7 +137,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
r.Recorder.Event(app, event.Warning(velatypes.ReasonFailedRevision, err))
return r.endWithNegativeCondition(ctx, app, condition.ErrorCondition("Revision", err), common.ApplicationRendering)
}
klog.Info("Successfully prepare current app revision", "revisionName", handler.currentAppRev.Name,
klog.InfoS("Successfully prepare current app revision", "revisionName", handler.currentAppRev.Name,
"revisionHash", handler.currentRevHash, "isNewRevision", handler.isNewRevision)
app.Status.SetConditions(condition.ReadyCondition("Revision"))
r.Recorder.Event(app, event.Normal(velatypes.ReasonRevisoned, velatypes.MessageRevisioned))
@@ -146,7 +146,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
klog.ErrorS(err, "Failed to update application status", "application", klog.KObj(app))
return r.endWithNegativeCondition(ctx, app, condition.ReconcileError(err), common.ApplicationRendering)
}
klog.Info("Successfully apply application revision", "application", klog.KObj(app))
klog.InfoS("Successfully apply application revision", "application", klog.KObj(app))
policies, err := appFile.PrepareWorkflowAndPolicy()
if err != nil {

View File

@@ -73,7 +73,7 @@ var _ = Describe("Test Application Controller", func() {
{
Name: "myweb1",
Type: "worker",
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox","config":"myconfig"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox","config":"myconfig"}`)},
},
},
},
@@ -91,7 +91,7 @@ var _ = Describe("Test Application Controller", func() {
{
Name: "myweb2",
Type: "worker",
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
},
},
},
@@ -103,7 +103,7 @@ var _ = Describe("Test Application Controller", func() {
appFailRender := appwithNoTrait.DeepCopy()
appFailRender.SetName("app-fail-to-render")
appFailRender.Spec.Components[0].Properties = runtime.RawExtension{
appFailRender.Spec.Components[0].Properties = &runtime.RawExtension{
Raw: []byte(`{"cmd1":["sleep","1000"],"image1":"busybox"}`),
}
@@ -120,11 +120,11 @@ var _ = Describe("Test Application Controller", func() {
{
Name: "myweb",
Type: "worker-import",
Properties: runtime.RawExtension{Raw: []byte("{\"cmd\":[\"sleep\",\"1000\"],\"image\":\"busybox\"}")},
Properties: &runtime.RawExtension{Raw: []byte("{\"cmd\":[\"sleep\",\"1000\"],\"image\":\"busybox\"}")},
Traits: []common.ApplicationTrait{
{
Type: "ingress-import",
Properties: runtime.RawExtension{Raw: []byte("{\"http\":{\"/\":80},\"domain\":\"abc.com\"}")},
Properties: &runtime.RawExtension{Raw: []byte("{\"http\":{\"/\":80},\"domain\":\"abc.com\"}")},
},
},
},
@@ -176,7 +176,7 @@ var _ = Describe("Test Application Controller", func() {
appWithTrait.Spec.Components[0].Traits = []common.ApplicationTrait{
{
Type: "scaler",
Properties: runtime.RawExtension{Raw: []byte(`{"replicas":2}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"replicas":2}`)},
},
}
appWithTrait.Spec.Components[0].Name = "myweb3"
@@ -220,7 +220,7 @@ var _ = Describe("Test Application Controller", func() {
appWithTwoComp.Spec.Components = append(appWithTwoComp.Spec.Components, common.ApplicationComponent{
Name: "myweb6",
Type: "worker",
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox2","config":"myconfig"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox2","config":"myconfig"}`)},
Scopes: map[string]string{"healthscopes.core.oam.dev": "app-with-two-comp-default-health"},
})
@@ -457,7 +457,7 @@ var _ = Describe("Test Application Controller", func() {
appWithComposedWorkload.Spec.Components[0].Traits = []common.ApplicationTrait{
{
Type: "scaler",
Properties: runtime.RawExtension{Raw: []byte(`{"replicas":2}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"replicas":2}`)},
},
}
appWithComposedWorkload.Spec.Components[0].Name = compName
@@ -702,13 +702,13 @@ var _ = Describe("Test Application Controller", func() {
curApp.Spec.Components[0] = common.ApplicationComponent{
Name: "myweb5",
Type: "worker",
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox3"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox3"}`)},
Scopes: map[string]string{"healthscopes.core.oam.dev": "app-with-two-comp-default-health"},
}
curApp.Spec.Components[1] = common.ApplicationComponent{
Name: "myweb7",
Type: "worker",
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
Scopes: map[string]string{"healthscopes.core.oam.dev": "app-with-two-comp-default-health"},
}
Expect(k8sClient.Update(ctx, curApp)).Should(BeNil())
@@ -1029,9 +1029,9 @@ var _ = Describe("Test Application Controller", func() {
app := appWithTraitHealthStatus.DeepCopy()
app.Spec.Components[0].Name = compName
app.Spec.Components[0].Type = "nworker"
app.Spec.Components[0].Properties = runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox3","lives":"3","enemies":"alien"}`)}
app.Spec.Components[0].Properties = &runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox3","lives":"3","enemies":"alien"}`)}
app.Spec.Components[0].Traits[0].Type = "ingress"
app.Spec.Components[0].Traits[0].Properties = runtime.RawExtension{Raw: []byte(`{"domain":"example.com","http":{"/":80}}`)}
app.Spec.Components[0].Traits[0].Properties = &runtime.RawExtension{Raw: []byte(`{"domain":"example.com","http":{"/":80}}`)}
expDeployment.Name = app.Name
expDeployment.Namespace = ns.Name
@@ -1167,7 +1167,7 @@ var _ = Describe("Test Application Controller", func() {
appRefertoWd.Spec.Components[0] = common.ApplicationComponent{
Name: "mytask",
Type: "task",
Properties: runtime.RawExtension{Raw: []byte(`{"image":"busybox", "cmd":["sleep","1000"]}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"image":"busybox", "cmd":["sleep","1000"]}`)},
}
ns := &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
@@ -1217,7 +1217,7 @@ var _ = Describe("Test Application Controller", func() {
appMix.Spec.Components[1] = common.ApplicationComponent{
Name: "mytask",
Type: "task",
Properties: runtime.RawExtension{Raw: []byte(`{"image":"busybox", "cmd":["sleep","1000"]}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"image":"busybox", "cmd":["sleep","1000"]}`)},
}
ns := &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
@@ -1438,11 +1438,10 @@ var _ = Describe("Test Application Controller", func() {
{
Name: "myweb1",
Type: "worker",
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
Traits: []common.ApplicationTrait{
{
Type: "rollout",
Properties: runtime.RawExtension{Raw: []byte(`{}`)},
Type: "rollout",
},
},
},
@@ -1463,7 +1462,7 @@ var _ = Describe("Test Application Controller", func() {
Expect(k8sClient.Get(ctx, types.NamespacedName{Name: "myweb1", Namespace: ns.Name}, deploy)).Should(util.NotFoundMatcher{})
By("update component targetComponentRev will change")
checkApp.Spec.Components[0].Properties = runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","2000"],"image":"nginx"}`)}
checkApp.Spec.Components[0].Properties = &runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","2000"],"image":"nginx"}`)}
Expect(k8sClient.Update(ctx, checkApp)).Should(BeNil())
testutil.ReconcileOnce(reconciler, reconcile.Request{NamespacedName: appKey})
checkApp = &v1beta1.Application{}
@@ -1478,7 +1477,7 @@ var _ = Describe("Test Application Controller", func() {
By("check update rollout trait won't generate new appRevision")
appRevName := checkApp.Status.LatestRevision.Name
checkApp.Spec.Components[0].Traits[0].Properties.Raw = []byte(`{"targetRevision":"myweb1-v3"}`)
checkApp.Spec.Components[0].Traits[0].Properties = &runtime.RawExtension{Raw: []byte(`{"targetRevision":"myweb1-v3"}`)}
Expect(k8sClient.Update(ctx, checkApp)).Should(BeNil())
testutil.ReconcileOnce(reconciler, reconcile.Request{NamespacedName: appKey})
checkApp = &v1beta1.Application{}
@@ -1518,11 +1517,10 @@ var _ = Describe("Test Application Controller", func() {
Name: "myweb1",
Type: "worker",
ExternalRevision: externalRevision,
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
Traits: []common.ApplicationTrait{
{
Type: "rollout",
Properties: runtime.RawExtension{Raw: []byte(`{}`)},
Type: "rollout",
},
},
},
@@ -1570,7 +1568,7 @@ var _ = Describe("Test Application Controller", func() {
{
Name: "myweb1",
Type: "worker-revision",
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
},
},
},
@@ -1619,7 +1617,7 @@ var _ = Describe("Test Application Controller", func() {
Name: "myweb1",
Type: "worker-revision",
ExternalRevision: externalRevision,
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
},
},
},
@@ -1676,11 +1674,10 @@ var _ = Describe("Test Application Controller", func() {
{
Name: "myweb1",
Type: "worker",
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
Traits: []common.ApplicationTrait{
{
Type: "rollout",
Properties: runtime.RawExtension{Raw: []byte(`{}`)},
Type: "rollout",
},
},
},
@@ -1690,7 +1687,7 @@ var _ = Describe("Test Application Controller", func() {
{
Name: "apply",
Type: "apply-component",
Properties: runtime.RawExtension{Raw: []byte(`{"component" : "myweb1"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"component" : "myweb1"}`)},
},
},
},
@@ -1742,7 +1739,7 @@ var _ = Describe("Test Application Controller", func() {
{
Name: "myweb1",
Type: "worker-with-health",
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep"],"image":"busybox"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"cmd":["sleep"],"image":"busybox"}`)},
Inputs: common.StepInputs{
{
From: "message",
@@ -1761,7 +1758,7 @@ var _ = Describe("Test Application Controller", func() {
{
Name: "myweb2",
Type: "worker-with-health",
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox","lives": "i am lives","enemies": "empty"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox","lives": "i am lives","enemies": "empty"}`)},
Outputs: common.StepOutputs{
{Name: "message", ValueFrom: "output.status.conditions[0].message+\",\"+outputs.gameconfig.data.lives"},
{Name: "sleepTime", ValueFrom: "\"100\""},
@@ -1842,13 +1839,13 @@ var _ = Describe("Test Application Controller", func() {
{
Name: "myweb1",
Type: "worker",
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
DependsOn: []string{"myweb2"},
},
{
Name: "myweb2",
Type: "worker-with-health",
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox","lives": "i am lives","enemies": "empty"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox","lives": "i am lives","enemies": "empty"}`)},
},
},
},
@@ -1917,7 +1914,7 @@ var _ = Describe("Test Application Controller", func() {
{
Name: "myweb1",
Type: "worker-with-health",
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
DependsOn: []string{"myweb2"},
Inputs: common.StepInputs{
{
@@ -1933,7 +1930,7 @@ var _ = Describe("Test Application Controller", func() {
{
Name: "myweb2",
Type: "worker-with-health",
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox","lives": "i am lives","enemies": "empty"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox","lives": "i am lives","enemies": "empty"}`)},
Outputs: common.StepOutputs{
{Name: "message", ValueFrom: "output.status.conditions[0].message+\",\"+outputs.gameconfig.data.lives"},
},
@@ -2016,12 +2013,12 @@ var _ = Describe("Test Application Controller", func() {
{
Name: "myweb1",
Type: "worker-with-health",
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox","lives": "i am lives","enemies": "empty"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox","lives": "i am lives","enemies": "empty"}`)},
},
{
Name: "myweb2",
Type: "worker-with-health",
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox","lives": "i am lives","enemies": "empty"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox","lives": "i am lives","enemies": "empty"}`)},
},
},
},

View File

@@ -107,7 +107,7 @@ var _ = Describe("Test application controller finalizer logic", func() {
updateApp.Spec.Components[0].Traits = []common.ApplicationTrait{
{
Type: "cross-scaler",
Properties: runtime.RawExtension{Raw: []byte(`{"replicas": 1}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"replicas": 1}`)},
},
}
Expect(k8sClient.Update(ctx, updateApp)).Should(BeNil())
@@ -236,7 +236,7 @@ var _ = Describe("Test application controller finalizer logic", func() {
app.Spec.Components[0].Traits = []common.ApplicationTrait{
{
Type: "cross-scaler",
Properties: runtime.RawExtension{Raw: []byte(`{"replicas": 1}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"replicas": 1}`)},
},
}
Expect(k8sClient.Create(ctx, app)).Should(BeNil())
@@ -284,7 +284,7 @@ func getApp(appName, namespace, comptype string) *v1beta1.Application {
{
Name: "comp1",
Type: comptype,
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
},
},
},

View File

@@ -113,7 +113,7 @@ var _ = Describe("Test Application apply", func() {
Components: []common.ApplicationComponent{{
Type: "test-worker",
Name: "test-app",
Properties: runtime.RawExtension{
Properties: &runtime.RawExtension{
Raw: []byte(`{"image": "oamdev/testapp:v1", "cmd": ["node", "server.js"]}`),
},
}},

View File

@@ -199,10 +199,29 @@ func (a *AppManifestsDispatcher) retrieveLegacyResourceTrackers(ctx context.Cont
}
for _, rt := range rtList.Items {
if rt.Name != a.currentRTName &&
(a.previousRT != nil && rt.Name != a.previousRT.Name) {
(a.previousRT != nil && rt.Name != a.previousRT.Name) && !IsLifeLongResourceTracker(rt) {
a.legacyRTs = append(a.legacyRTs, rt.DeepCopy())
}
}
// compatibility code for label typo. more info: https://github.com/oam-dev/kubevela/issues/2464
// TODO(wangyikewxgm) delete after appRollout deprecated.
oldRtList := &v1beta1.ResourceTrackerList{}
if err := a.c.List(ctx, oldRtList, client.MatchingLabels{
oam.LabelAppName: ExtractAppName(a.currentRTName, a.namespace),
"app.oam.dev/namesapce": a.namespace,
}); err != nil {
return errors.Wrap(err, "cannot retrieve legacy resource trackers with miss-spell label")
}
if len(oldRtList.Items) != 0 {
for _, rt := range oldRtList.Items {
if rt.Name != a.currentRTName &&
(a.previousRT != nil && rt.Name != a.previousRT.Name) && !IsLifeLongResourceTracker(rt) {
a.legacyRTs = append(a.legacyRTs, rt.DeepCopy())
}
}
}
return nil
}
@@ -357,3 +376,9 @@ func setOrOverrideOAMControllerOwner(obj ObjectOwner, controllerOwner metav1.Own
}
obj.SetOwnerReferences(newOwnerRefs)
}
// IsLifeLongResourceTracker check if resourcetracker shares the same whole life with the entire application
func IsLifeLongResourceTracker(rt v1beta1.ResourceTracker) bool {
_, ok := rt.GetAnnotations()[oam.AnnotationResourceTrackerLifeLong]
return ok
}

View File

@@ -465,6 +465,59 @@ var _ = Describe("Test handleSkipGC func", func() {
})
})
var _ = Describe("Test compatibility code", func() {
var namespaceName string
var appName string
ctx := context.Background()
BeforeEach(func() {
namespaceName = fmt.Sprintf("%s-%s", "compatibility-code-test", strconv.FormatInt(rand.Int63(), 16))
appName = "test-app"
Expect(k8sClient.Create(ctx, &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: namespaceName}}))
})
It("Test GC skip func ", func() {
a := AppManifestsDispatcher{c: k8sClient, currentRTName: appName + "-v4-" + namespaceName, namespace: namespaceName}
resourceTracker_old := v1beta1.ResourceTracker{
ObjectMeta: metav1.ObjectMeta{
Name: appName + "-v1-" + namespaceName,
Labels: map[string]string{
oam.LabelAppNamespace: namespaceName,
oam.LabelAppName: appName,
},
},
}
resourceTracker_new := v1beta1.ResourceTracker{
ObjectMeta: metav1.ObjectMeta{
Name: appName + "-v2-" + namespaceName,
Labels: map[string]string{
"app.oam.dev/namesapce": namespaceName,
oam.LabelAppName: appName,
},
},
}
resourceTracker_previous := v1beta1.ResourceTracker{
ObjectMeta: metav1.ObjectMeta{
Name: appName + "-v3-" + namespaceName,
Labels: map[string]string{
oam.LabelAppNamespace: namespaceName,
oam.LabelAppName: appName,
},
},
}
a.previousRT = &resourceTracker_previous
Expect(a.c.Create(ctx, &resourceTracker_old)).Should(BeNil())
Expect(a.c.Create(ctx, &resourceTracker_new)).Should(BeNil())
Expect(a.retrieveLegacyResourceTrackers(ctx)).Should(BeNil())
Expect(len(a.legacyRTs)).Should(BeEquivalentTo(2))
res := map[types.UID]bool{}
for _, rt := range a.legacyRTs {
res[rt.UID] = true
}
Expect(res[resourceTracker_old.UID]).Should(BeTrue())
Expect(res[resourceTracker_new.UID]).Should(BeTrue())
})
})
// in envtest, no gc controller can delete PersistentVolume because of its finalizer
// so we just use deletion timestamp to verify its deletion
func persistentVolumeIsDeleted(pv *corev1.PersistentVolume) bool {

View File

@@ -31,6 +31,7 @@ import (
"github.com/oam-dev/kubevela/pkg/controller/core.oam.dev/v1alpha2/application/assemble"
"github.com/oam-dev/kubevela/pkg/cue/model/value"
"github.com/oam-dev/kubevela/pkg/cue/packages"
"github.com/oam-dev/kubevela/pkg/multicluster"
"github.com/oam-dev/kubevela/pkg/oam/discoverymapper"
"github.com/oam-dev/kubevela/pkg/oam/util"
"github.com/oam-dev/kubevela/pkg/utils"
@@ -91,7 +92,7 @@ func convertStepProperties(step *v1beta1.WorkflowStep, app *v1beta1.Application)
o := struct {
Component string `json:"component"`
}{}
js, err := step.Properties.MarshalJSON()
js, err := common.RawExtensionPointer{RawExtension: step.Properties}.MarshalJSON()
if err != nil {
return err
}
@@ -123,7 +124,8 @@ func convertStepProperties(step *v1beta1.WorkflowStep, app *v1beta1.Application)
}
func (h *AppHandler) applyComponentFunc(appParser *appfile.Parser, appRev *v1beta1.ApplicationRevision, af *appfile.Appfile, cli client.Client) oamProvider.ComponentApply {
return func(comp common.ApplicationComponent, patcher *value.Value) (*unstructured.Unstructured, []*unstructured.Unstructured, bool, error) {
return func(comp common.ApplicationComponent, patcher *value.Value, clusterName string, overrideNamespace string) (*unstructured.Unstructured, []*unstructured.Unstructured, bool, error) {
ctx := multicluster.ContextWithClusterName(context.Background(), clusterName)
wl, err := appParser.ParseWorkloadFromRevision(comp, appRev)
if err != nil {
@@ -137,11 +139,11 @@ func (h *AppHandler) applyComponentFunc(appParser *appfile.Parser, appRev *v1bet
if err := af.SetOAMContract(manifest); err != nil {
return nil, nil, false, errors.WithMessage(err, "SetOAMContract")
}
if err := h.HandleComponentsRevision(context.TODO(), []*types.ComponentManifest{manifest}); err != nil {
if err := h.HandleComponentsRevision(ctx, []*types.ComponentManifest{manifest}); err != nil {
return nil, nil, false, errors.WithMessage(err, "HandleComponentsRevision")
}
if len(manifest.PackagedWorkloadResources) != 0 {
if err := h.Dispatch(context.TODO(), "", common.WorkflowResourceCreator, manifest.PackagedWorkloadResources...); err != nil {
if err := h.Dispatch(ctx, clusterName, common.WorkflowResourceCreator, manifest.PackagedWorkloadResources...); err != nil {
return nil, nil, false, errors.WithMessage(err, "cannot dispatch packaged workload resources")
}
}
@@ -149,15 +151,20 @@ func (h *AppHandler) applyComponentFunc(appParser *appfile.Parser, appRev *v1bet
if err != nil {
return nil, nil, false, errors.WithMessage(err, "assemble resources before apply fail")
}
if overrideNamespace != "" {
readyWorkload.SetNamespace(overrideNamespace)
for _, readyTrait := range readyTraits {
readyTrait.SetNamespace(overrideNamespace)
}
}
skipStandardWorkload := skipApplyWorkload(wl)
if !skipStandardWorkload {
if err := h.Dispatch(context.TODO(), "", common.WorkflowResourceCreator, readyWorkload); err != nil {
if err := h.Dispatch(ctx, clusterName, common.WorkflowResourceCreator, readyWorkload); err != nil {
return nil, nil, false, errors.WithMessage(err, "DispatchStandardWorkload")
}
}
if err := h.Dispatch(context.TODO(), "", common.WorkflowResourceCreator, readyTraits...); err != nil {
if err := h.Dispatch(ctx, clusterName, common.WorkflowResourceCreator, readyTraits...); err != nil {
return nil, nil, false, errors.WithMessage(err, "DispatchTraits")
}
@@ -169,7 +176,7 @@ func (h *AppHandler) applyComponentFunc(appParser *appfile.Parser, appRev *v1bet
if !isHealth {
return nil, nil, false, nil
}
workload, traits, err := getComponentResources(manifest, skipStandardWorkload, cli)
workload, traits, err := getComponentResources(ctx, manifest, skipStandardWorkload, cli)
return workload, traits, true, err
}
}
@@ -183,14 +190,14 @@ func skipApplyWorkload(wl *appfile.Workload) bool {
return false
}
func getComponentResources(manifest *types.ComponentManifest, skipStandardWorkload bool, cli client.Client) (*unstructured.Unstructured, []*unstructured.Unstructured, error) {
func getComponentResources(ctx context.Context, manifest *types.ComponentManifest, skipStandardWorkload bool, cli client.Client) (*unstructured.Unstructured, []*unstructured.Unstructured, error) {
var (
workload *unstructured.Unstructured
traits []*unstructured.Unstructured
)
if !skipStandardWorkload {
v := manifest.StandardWorkload.DeepCopy()
if err := cli.Get(context.Background(), client.ObjectKeyFromObject(manifest.StandardWorkload), v); err != nil {
if err := cli.Get(ctx, client.ObjectKeyFromObject(manifest.StandardWorkload), v); err != nil {
return nil, nil, err
}
workload = v
@@ -198,7 +205,7 @@ func getComponentResources(manifest *types.ComponentManifest, skipStandardWorklo
for _, trait := range manifest.Traits {
v := trait.DeepCopy()
if err := cli.Get(context.Background(), client.ObjectKeyFromObject(trait), v); err != nil {
if err := cli.Get(ctx, client.ObjectKeyFromObject(trait), v); err != nil {
return workload, nil, err
}
traits = append(traits, v)

View File

@@ -81,7 +81,7 @@ var _ = Describe("Test Application workflow generator", func() {
{
Name: "myweb1",
Type: "worker-with-health",
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
Inputs: common.StepInputs{
{
From: "message",
@@ -96,7 +96,7 @@ var _ = Describe("Test Application workflow generator", func() {
{
Name: "myweb2",
Type: "worker-with-health",
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox","lives": "i am lives","enemies": "empty"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox","lives": "i am lives","enemies": "empty"}`)},
Outputs: common.StepOutputs{
{
Name: "message",
@@ -145,12 +145,12 @@ var _ = Describe("Test Application workflow generator", func() {
{
Name: "myweb1",
Type: "worker-with-health",
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
},
{
Name: "myweb2",
Type: "worker-with-health",
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox","lives": "i am lives","enemies": "empty"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox","lives": "i am lives","enemies": "empty"}`)},
},
},
},

View File

@@ -582,6 +582,27 @@ func ComputeComponentRevisionHash(comp *types.ComponentManifest) (string, error)
return utils.ComputeSpecHash(&compRevisionHash)
}
// createOrGetResourceTracker create or get a resource tracker to manage all componentRevisions
func (h *AppHandler) createOrGetResourceTracker(ctx context.Context) (*v1beta1.ResourceTracker, error) {
rt := &v1beta1.ResourceTracker{}
rtName := h.app.Name + "-" + h.app.Namespace
if err := h.r.Get(ctx, ktypes.NamespacedName{Name: rtName}, rt); err != nil {
if !apierrors.IsNotFound(err) {
return nil, err
}
rt.SetName(rtName)
rt.SetLabels(map[string]string{
oam.LabelAppName: h.app.Name,
oam.LabelAppNamespace: h.app.Namespace,
})
rt.SetAnnotations(map[string]string{oam.AnnotationResourceTrackerLifeLong: "true"})
if err = h.r.Create(ctx, rt); err != nil {
return nil, err
}
}
return rt, nil
}
// createControllerRevision records snapshot of a component
func (h *AppHandler) createControllerRevision(ctx context.Context, cm *types.ComponentManifest) error {
comp, err := componentManifest2Component(cm)
@@ -589,6 +610,10 @@ func (h *AppHandler) createControllerRevision(ctx context.Context, cm *types.Com
return err
}
revision, _ := utils.ExtractRevision(cm.RevisionName)
rt, err := h.createOrGetResourceTracker(ctx)
if err != nil {
return err
}
cr := &appsv1.ControllerRevision{
ObjectMeta: metav1.ObjectMeta{
Name: cm.RevisionName,
@@ -596,9 +621,9 @@ func (h *AppHandler) createControllerRevision(ctx context.Context, cm *types.Com
OwnerReferences: []metav1.OwnerReference{
{
APIVersion: v1beta1.SchemeGroupVersion.String(),
Kind: v1beta1.ApplicationKind,
Name: h.app.Name,
UID: h.app.UID,
Kind: v1beta1.ResourceTrackerKind,
Name: rt.GetName(),
UID: rt.GetUID(),
Controller: pointer.BoolPtr(true),
},
},
@@ -608,7 +633,7 @@ func (h *AppHandler) createControllerRevision(ctx context.Context, cm *types.Com
},
},
Revision: int64(revision),
Data: util.Object2RawExtension(comp),
Data: *util.Object2RawExtension(comp),
}
return h.r.Create(ctx, cr)
}
@@ -626,15 +651,15 @@ func componentManifest2Component(cm *types.ComponentManifest) (*v1alpha2.Compone
wl = cm.StandardWorkload.DeepCopy()
util.RemoveLabels(wl, []string{oam.LabelAppRevision})
}
component.Spec.Workload = util.Object2RawExtension(wl)
component.Spec.Workload = *util.Object2RawExtension(wl)
if len(cm.PackagedWorkloadResources) > 0 {
helm := &common.Helm{}
for _, helmResource := range cm.PackagedWorkloadResources {
if helmResource.GetKind() == helmapi.HelmReleaseGVK.Kind {
helm.Release = util.Object2RawExtension(helmResource)
helm.Release = *util.Object2RawExtension(helmResource)
}
if helmResource.GetKind() == helmapi.HelmRepositoryGVK.Kind {
helm.Repository = util.Object2RawExtension(helmResource)
helm.Repository = *util.Object2RawExtension(helmResource)
}
}
component.Spec.Helm = helm
@@ -757,6 +782,9 @@ func gatherUsingAppRevision(ctx context.Context, h *AppHandler) (map[string]bool
return nil, err
}
for _, rt := range rtList.Items {
if dispatch.IsLifeLongResourceTracker(rt) {
continue
}
appRev := dispatch.ExtractAppRevisionName(rt.Name, ns)
usingRevision[appRev] = true
}

View File

@@ -79,7 +79,7 @@ var _ = Describe("Test application controller clean up ", func() {
for i := 0; i < appRevisionLimit+1; i++ {
Expect(k8sClient.Get(ctx, appKey, checkApp)).Should(BeNil())
property := fmt.Sprintf(`{"cmd":["sleep","1000"],"image":"busybox:%d"}`, i)
checkApp.Spec.Components[0].Properties = runtime.RawExtension{Raw: []byte(property)}
checkApp.Spec.Components[0].Properties = &runtime.RawExtension{Raw: []byte(property)}
Expect(k8sClient.Update(ctx, checkApp)).Should(BeNil())
testutil.ReconcileOnceAfterFinalizer(reconciler, ctrl.Request{NamespacedName: appKey})
}
@@ -104,7 +104,7 @@ var _ = Describe("Test application controller clean up ", func() {
By("create new appRevision will remove appRevison1")
Expect(k8sClient.Get(ctx, appKey, checkApp)).Should(BeNil())
property := fmt.Sprintf(`{"cmd":["sleep","1000"],"image":"busybox:%d"}`, 6)
checkApp.Spec.Components[0].Properties = runtime.RawExtension{Raw: []byte(property)}
checkApp.Spec.Components[0].Properties = &runtime.RawExtension{Raw: []byte(property)}
Expect(k8sClient.Update(ctx, checkApp)).Should(BeNil())
_, err := reconciler.Reconcile(context.TODO(), ctrl.Request{NamespacedName: appKey})
Expect(err).Should(BeNil())
@@ -131,7 +131,7 @@ var _ = Describe("Test application controller clean up ", func() {
By("update app again will gc appRevision2")
Expect(k8sClient.Get(ctx, appKey, checkApp)).Should(BeNil())
property = fmt.Sprintf(`{"cmd":["sleep","1000"],"image":"busybox:%d"}`, 7)
checkApp.Spec.Components[0].Properties = runtime.RawExtension{Raw: []byte(property)}
checkApp.Spec.Components[0].Properties = &runtime.RawExtension{Raw: []byte(property)}
Expect(k8sClient.Update(ctx, checkApp)).Should(BeNil())
_, err = reconciler.Reconcile(context.TODO(), ctrl.Request{NamespacedName: appKey})
Expect(err).Should(BeNil())
@@ -164,7 +164,7 @@ var _ = Describe("Test application controller clean up ", func() {
for i := 0; i < appRevisionLimit+1; i++ {
Expect(k8sClient.Get(ctx, appKey, checkApp)).Should(BeNil())
property := fmt.Sprintf(`{"cmd":["sleep","1000"],"image":"busybox:%d"}`, i)
checkApp.Spec.Components[0].Properties = runtime.RawExtension{Raw: []byte(property)}
checkApp.Spec.Components[0].Properties = &runtime.RawExtension{Raw: []byte(property)}
Expect(k8sClient.Update(ctx, checkApp)).Should(BeNil())
testutil.ReconcileOnceAfterFinalizer(reconciler, ctrl.Request{NamespacedName: appKey})
}
@@ -189,7 +189,7 @@ var _ = Describe("Test application controller clean up ", func() {
By("create new appRevision will remove revision v1")
Expect(k8sClient.Get(ctx, appKey, checkApp)).Should(BeNil())
property := fmt.Sprintf(`{"cmd":["sleep","1000"],"image":"busybox:%d"}`, 6)
checkApp.Spec.Components[0].Properties = runtime.RawExtension{Raw: []byte(property)}
checkApp.Spec.Components[0].Properties = &runtime.RawExtension{Raw: []byte(property)}
Expect(k8sClient.Update(ctx, checkApp)).Should(BeNil())
_, err := reconciler.Reconcile(context.TODO(), ctrl.Request{NamespacedName: appKey})
Expect(err).Should(BeNil())
@@ -216,7 +216,7 @@ var _ = Describe("Test application controller clean up ", func() {
By("update app again will gc revision v2")
Expect(k8sClient.Get(ctx, appKey, checkApp)).Should(BeNil())
property = fmt.Sprintf(`{"cmd":["sleep","1000"],"image":"busybox:%d"}`, 7)
checkApp.Spec.Components[0].Properties = runtime.RawExtension{Raw: []byte(property)}
checkApp.Spec.Components[0].Properties = &runtime.RawExtension{Raw: []byte(property)}
Expect(k8sClient.Update(ctx, checkApp)).Should(BeNil())
_, err = reconciler.Reconcile(context.TODO(), ctrl.Request{NamespacedName: appKey})
Expect(err).Should(BeNil())
@@ -242,7 +242,7 @@ var _ = Describe("Test application controller clean up ", func() {
By("update app with comp as latest revision will not gc revision v3")
Expect(k8sClient.Get(ctx, appKey, checkApp)).Should(BeNil())
property = fmt.Sprintf(`{"cmd":["sleep","1000"],"image":"busybox:%d"}`, 6)
checkApp.Spec.Components[0].Properties = runtime.RawExtension{Raw: []byte(property)}
checkApp.Spec.Components[0].Properties = &runtime.RawExtension{Raw: []byte(property)}
Expect(k8sClient.Update(ctx, checkApp)).Should(BeNil())
_, err = reconciler.Reconcile(context.TODO(), ctrl.Request{NamespacedName: appKey})
Expect(err).Should(BeNil())
@@ -273,7 +273,7 @@ var _ = Describe("Test application controller clean up ", func() {
for i := 0; i < appRevisionLimit+1; i++ {
Expect(k8sClient.Get(ctx, appKey, checkApp)).Should(BeNil())
property := fmt.Sprintf(`{"cmd":["sleep","1000"],"image":"busybox:%d"}`, i)
checkApp.Spec.Components[0].Properties = runtime.RawExtension{Raw: []byte(property)}
checkApp.Spec.Components[0].Properties = &runtime.RawExtension{Raw: []byte(property)}
Expect(k8sClient.Update(ctx, checkApp)).Should(BeNil())
testutil.ReconcileOnceAfterFinalizer(reconciler, ctrl.Request{NamespacedName: appKey})
}
@@ -298,7 +298,7 @@ var _ = Describe("Test application controller clean up ", func() {
By("create new appRevision will remove revision v1")
Expect(k8sClient.Get(ctx, appKey, checkApp)).Should(BeNil())
property := fmt.Sprintf(`{"cmd":["sleep","1000"],"image":"busybox:%d"}`, 6)
checkApp.Spec.Components[0].Properties = runtime.RawExtension{Raw: []byte(property)}
checkApp.Spec.Components[0].Properties = &runtime.RawExtension{Raw: []byte(property)}
Expect(k8sClient.Update(ctx, checkApp)).Should(BeNil())
_, err := reconciler.Reconcile(context.TODO(), ctrl.Request{NamespacedName: appKey})
Expect(err).Should(BeNil())
@@ -325,7 +325,7 @@ var _ = Describe("Test application controller clean up ", func() {
By("update app again will gc revision v2")
Expect(k8sClient.Get(ctx, appKey, checkApp)).Should(BeNil())
property = fmt.Sprintf(`{"cmd":["sleep","1000"],"image":"busybox:%d"}`, 7)
checkApp.Spec.Components[0].Properties = runtime.RawExtension{Raw: []byte(property)}
checkApp.Spec.Components[0].Properties = &runtime.RawExtension{Raw: []byte(property)}
Expect(k8sClient.Update(ctx, checkApp)).Should(BeNil())
_, err = reconciler.Reconcile(context.TODO(), ctrl.Request{NamespacedName: appKey})
Expect(err).Should(BeNil())
@@ -351,7 +351,7 @@ var _ = Describe("Test application controller clean up ", func() {
By("update app with comp as latest revision will not gc revision v3")
Expect(k8sClient.Get(ctx, appKey, checkApp)).Should(BeNil())
property = fmt.Sprintf(`{"cmd":["sleep","1000"],"image":"busybox:%d"}`, 6)
checkApp.Spec.Components[0].Properties = runtime.RawExtension{Raw: []byte(property)}
checkApp.Spec.Components[0].Properties = &runtime.RawExtension{Raw: []byte(property)}
Expect(k8sClient.Update(ctx, checkApp)).Should(BeNil())
_, err = reconciler.Reconcile(context.TODO(), ctrl.Request{NamespacedName: appKey})
Expect(err).Should(BeNil())
@@ -382,7 +382,7 @@ var _ = Describe("Test application controller clean up ", func() {
for i := 0; i < appRevisionLimit+1; i++ {
Expect(k8sClient.Get(ctx, appKey, checkApp)).Should(BeNil())
property := fmt.Sprintf(`{"cmd":["sleep","1000"],"image":"busybox:%d"}`, i)
checkApp.Spec.Components[0].Properties = runtime.RawExtension{Raw: []byte(property)}
checkApp.Spec.Components[0].Properties = &runtime.RawExtension{Raw: []byte(property)}
Expect(k8sClient.Update(ctx, checkApp)).Should(BeNil())
testutil.ReconcileOnceAfterFinalizer(reconciler, ctrl.Request{NamespacedName: appKey})
}
@@ -407,7 +407,7 @@ var _ = Describe("Test application controller clean up ", func() {
By("create new appRevision will remove appRevison1")
Expect(k8sClient.Get(ctx, appKey, checkApp)).Should(BeNil())
property := fmt.Sprintf(`{"cmd":["sleep","1000"],"image":"busybox:%d"}`, 6)
checkApp.Spec.Components[0].Properties = runtime.RawExtension{Raw: []byte(property)}
checkApp.Spec.Components[0].Properties = &runtime.RawExtension{Raw: []byte(property)}
Expect(k8sClient.Update(ctx, checkApp)).Should(BeNil())
_, err := reconciler.Reconcile(context.TODO(), ctrl.Request{NamespacedName: appKey})
Expect(err).Should(BeNil())
@@ -437,7 +437,7 @@ var _ = Describe("Test application controller clean up ", func() {
By("update app again will gc appRevision2")
Expect(k8sClient.Get(ctx, appKey, checkApp)).Should(BeNil())
property = fmt.Sprintf(`{"cmd":["sleep","1000"],"image":"busybox:%d"}`, 7)
checkApp.Spec.Components[0].Properties = runtime.RawExtension{Raw: []byte(property)}
checkApp.Spec.Components[0].Properties = &runtime.RawExtension{Raw: []byte(property)}
Expect(k8sClient.Update(ctx, checkApp)).Should(BeNil())
_, err = reconciler.Reconcile(context.TODO(), ctrl.Request{NamespacedName: appKey})
Expect(err).Should(BeNil())
@@ -475,7 +475,7 @@ var _ = Describe("Test application controller clean up ", func() {
for i := 0; i < appRevisionLimit+1; i++ {
Expect(k8sClient.Get(ctx, appKey, checkApp)).Should(BeNil())
property := fmt.Sprintf(`{"cmd":["sleep","1000"],"image":"busybox:%d"}`, i)
checkApp.Spec.Components[0].Properties = runtime.RawExtension{Raw: []byte(property)}
checkApp.Spec.Components[0].Properties = &runtime.RawExtension{Raw: []byte(property)}
Expect(k8sClient.Update(ctx, checkApp)).Should(BeNil())
testutil.ReconcileOnceAfterFinalizer(reconciler, ctrl.Request{NamespacedName: appKey})
}
@@ -500,7 +500,7 @@ var _ = Describe("Test application controller clean up ", func() {
By("create new appRevision will remove appRevison1")
Expect(k8sClient.Get(ctx, appKey, checkApp)).Should(BeNil())
property := fmt.Sprintf(`{"cmd":["sleep","1000"],"image":"busybox:%d"}`, 6)
checkApp.Spec.Components[0].Properties = runtime.RawExtension{Raw: []byte(property)}
checkApp.Spec.Components[0].Properties = &runtime.RawExtension{Raw: []byte(property)}
Expect(k8sClient.Update(ctx, checkApp)).Should(BeNil())
_, err := reconciler.Reconcile(context.TODO(), ctrl.Request{NamespacedName: appKey})
Expect(err).Should(BeNil())
@@ -530,7 +530,7 @@ var _ = Describe("Test application controller clean up ", func() {
By("update app again will gc appRevision2")
Expect(k8sClient.Get(ctx, appKey, checkApp)).Should(BeNil())
property = fmt.Sprintf(`{"cmd":["sleep","1000"],"image":"busybox:%d"}`, 7)
checkApp.Spec.Components[0].Properties = runtime.RawExtension{Raw: []byte(property)}
checkApp.Spec.Components[0].Properties = &runtime.RawExtension{Raw: []byte(property)}
Expect(k8sClient.Update(ctx, checkApp)).Should(BeNil())
_, err = reconciler.Reconcile(context.TODO(), ctrl.Request{NamespacedName: appKey})
Expect(err).Should(BeNil())
@@ -568,7 +568,7 @@ var _ = Describe("Test application controller clean up ", func() {
for i := 0; i < appRevisionLimit+1; i++ {
Expect(k8sClient.Get(ctx, appKey, checkApp)).Should(BeNil())
property := fmt.Sprintf(`{"cmd":["sleep","1000"],"image":"busybox:%d"}`, i)
checkApp.Spec.Components[0].Properties = runtime.RawExtension{Raw: []byte(property)}
checkApp.Spec.Components[0].Properties = &runtime.RawExtension{Raw: []byte(property)}
Expect(k8sClient.Update(ctx, checkApp)).Should(BeNil())
testutil.ReconcileOnceAfterFinalizer(reconciler, ctrl.Request{NamespacedName: appKey})
}
@@ -593,7 +593,7 @@ var _ = Describe("Test application controller clean up ", func() {
By("create new appRevision will remove appRevison1")
Expect(k8sClient.Get(ctx, appKey, checkApp)).Should(BeNil())
property := fmt.Sprintf(`{"cmd":["sleep","1000"],"image":"busybox:%d"}`, 6)
checkApp.Spec.Components[0].Properties = runtime.RawExtension{Raw: []byte(property)}
checkApp.Spec.Components[0].Properties = &runtime.RawExtension{Raw: []byte(property)}
Expect(k8sClient.Update(ctx, checkApp)).Should(BeNil())
_, err := reconciler.Reconcile(context.TODO(), ctrl.Request{NamespacedName: appKey})
Expect(err).Should(BeNil())
@@ -644,7 +644,7 @@ var _ = Describe("Test application controller clean up ", func() {
for i := 7; i < 9; i++ {
Expect(k8sClient.Get(ctx, appKey, checkApp)).Should(BeNil())
property = fmt.Sprintf(`{"cmd":["sleep","1000"],"image":"busybox:%d"}`, i)
checkApp.Spec.Components[0].Properties = runtime.RawExtension{Raw: []byte(property)}
checkApp.Spec.Components[0].Properties = &runtime.RawExtension{Raw: []byte(property)}
Expect(k8sClient.Update(ctx, checkApp)).Should(BeNil())
_, err = reconciler.Reconcile(context.TODO(), ctrl.Request{NamespacedName: appKey})
Expect(err).Should(BeNil())

View File

@@ -118,13 +118,13 @@ var _ = Describe("test generate revision ", func() {
Type: cd.Name,
Name: "express-server",
Scopes: map[string]string{"healthscopes.core.oam.dev": "myapp-default-health"},
Properties: runtime.RawExtension{
Properties: &runtime.RawExtension{
Raw: []byte(`{"image": "oamdev/testapp:v1", "cmd": ["node", "server.js"]}`),
},
Traits: []common.ApplicationTrait{
{
Type: td.Name,
Properties: runtime.RawExtension{
Properties: &runtime.RawExtension{
Raw: []byte(`{"replicas": 5}`),
},
},
@@ -232,7 +232,7 @@ var _ = Describe("test generate revision ", func() {
It("Test appliction contain a SkipAppRevision tait will have same hash", func() {
rolloutTrait := common.ApplicationTrait{
Type: "rollout",
Properties: runtime.RawExtension{
Properties: &runtime.RawExtension{
Raw: []byte(`{"targetRevision":"myrev-v1"}`),
},
}
@@ -336,7 +336,7 @@ var _ = Describe("test generate revision ", func() {
Expect(err).Should(BeNil())
expectWorkload = comps[0].StandardWorkload.DeepCopy()
util.RemoveLabels(expectWorkload, []string{oam.LabelAppRevision, oam.LabelAppRevisionHash, oam.LabelAppComponentRevision})
Expect(cmp.Diff(gotComp.Spec.Workload, util.Object2RawExtension(expectWorkload))).Should(BeEmpty())
Expect(cmp.Diff(gotComp.Spec.Workload, *util.Object2RawExtension(expectWorkload))).Should(BeEmpty())
By("Verify component revision is not changed")
expectCompRevName = "express-server-v1"
@@ -348,7 +348,7 @@ var _ = Describe("test generate revision ", func() {
By("Change the application and apply again")
// bump the image tag
app.ResourceVersion = curApp.ResourceVersion
app.Spec.Components[0].Properties = runtime.RawExtension{
app.Spec.Components[0].Properties = &runtime.RawExtension{
Raw: []byte(`{"image": "oamdev/testapp:v2", "cmd": ["node", "server.js"]}`),
}
// persist the app
@@ -400,12 +400,12 @@ var _ = Describe("test generate revision ", func() {
Expect(err).Should(BeNil())
expectWorkload = comps[0].StandardWorkload.DeepCopy()
util.RemoveLabels(expectWorkload, []string{oam.LabelAppRevision, oam.LabelAppRevisionHash, oam.LabelAppComponentRevision})
Expect(cmp.Diff(gotComp.Spec.Workload, util.Object2RawExtension(expectWorkload))).Should(BeEmpty())
Expect(cmp.Diff(gotComp.Spec.Workload, *util.Object2RawExtension(expectWorkload))).Should(BeEmpty())
By("Change the application same as v1 and apply again")
// bump the image tag
app.ResourceVersion = curApp.ResourceVersion
app.Spec.Components[0].Properties = runtime.RawExtension{
app.Spec.Components[0].Properties = &runtime.RawExtension{
Raw: []byte(`{"image": "oamdev/testapp:v1", "cmd": ["node", "server.js"]}`),
}
// persist the app
@@ -465,7 +465,7 @@ var _ = Describe("test generate revision ", func() {
expectWorkload = comps[0].StandardWorkload.DeepCopy()
util.RemoveLabels(expectWorkload, []string{oam.LabelAppRevision, oam.LabelAppRevisionHash, oam.LabelAppComponentRevision})
expectWorkload.SetAnnotations(map[string]string{"testKey1": "true"})
Expect(cmp.Diff(gotComp.Spec.Workload, util.Object2RawExtension(expectWorkload))).Should(BeEmpty())
Expect(cmp.Diff(gotComp.Spec.Workload, *util.Object2RawExtension(expectWorkload))).Should(BeEmpty())
})
It("Test App with rollout template", func() {
@@ -546,7 +546,7 @@ var _ = Describe("test generate revision ", func() {
// bump the image tag
app.SetAnnotations(map[string]string{oam.AnnotationAppRollout: strconv.FormatBool(true)})
app.ResourceVersion = curApp.ResourceVersion
app.Spec.Components[0].Properties = runtime.RawExtension{
app.Spec.Components[0].Properties = &runtime.RawExtension{
Raw: []byte(`{"image": "oamdev/testapp:v2", "cmd": ["node", "server.js"]}`),
}
// persist the app

View File

@@ -55,13 +55,13 @@ var _ = Describe("Test Workflow", func() {
Components: []common.ApplicationComponent{{
Name: "test-component",
Type: "worker",
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
}},
Workflow: &oamcore.Workflow{
Steps: []oamcore.WorkflowStep{{
Name: "test-wf1",
Type: "foowf",
Properties: runtime.RawExtension{Raw: []byte(`{"namespace":"test-ns"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"namespace":"test-ns"}`)},
}},
},
},
@@ -71,7 +71,7 @@ var _ = Describe("Test Workflow", func() {
appWithWorkflowAndPolicy.Spec.Policies = []oamcore.AppPolicy{{
Name: "test-policy",
Type: "foopolicy",
Properties: runtime.RawExtension{Raw: []byte(`{"key":"test"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"key":"test"}`)},
}}
appWithPolicy := &oamcore.Application{
@@ -83,12 +83,12 @@ var _ = Describe("Test Workflow", func() {
Components: []common.ApplicationComponent{{
Name: "test-component",
Type: "worker",
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
}},
Policies: []oamcore.AppPolicy{{
Name: "test-policy",
Type: "foopolicy",
Properties: runtime.RawExtension{Raw: []byte(`{"key":"test"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"key":"test"}`)},
}},
},
}
@@ -160,7 +160,7 @@ var _ = Describe("Test Workflow", func() {
appWithPolicyAndWorkflow.Spec.Policies = []oamcore.AppPolicy{{
Name: "test-foo-policy",
Type: "foopolicy",
Properties: runtime.RawExtension{Raw: []byte(`{"key":"test"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"key":"test"}`)},
}}
Expect(k8sClient.Create(ctx, appWithPolicyAndWorkflow)).Should(BeNil())
@@ -237,7 +237,7 @@ var _ = Describe("Test Workflow", func() {
suspendApp.Spec.Workflow.Steps = []oamcore.WorkflowStep{{
Name: "suspend",
Type: "suspend",
Properties: runtime.RawExtension{Raw: []byte(`{}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{}`)},
}}
Expect(k8sClient.Create(ctx, suspendApp)).Should(BeNil())
@@ -284,12 +284,12 @@ var _ = Describe("Test Workflow", func() {
{
Name: "suspend",
Type: "suspend",
Properties: runtime.RawExtension{Raw: []byte(`{}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{}`)},
},
{
Name: "suspend-1",
Type: "suspend",
Properties: runtime.RawExtension{Raw: []byte(`{}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{}`)},
}}
Expect(k8sClient.Create(ctx, suspendApp)).Should(BeNil())
@@ -352,7 +352,7 @@ var _ = Describe("Test Workflow", func() {
{
Name: "myweb1",
Type: "worker-with-health",
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
Inputs: common.StepInputs{
{
From: "message",
@@ -367,7 +367,7 @@ var _ = Describe("Test Workflow", func() {
{
Name: "myweb2",
Type: "worker-with-health",
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox","lives": "i am lives","enemies": "empty"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox","lives": "i am lives","enemies": "empty"}`)},
Outputs: common.StepOutputs{
{Name: "message", ValueFrom: "output.status.conditions[0].message+\",\"+outputs.gameconfig.data.lives"},
},
@@ -377,11 +377,11 @@ var _ = Describe("Test Workflow", func() {
Steps: []oamcore.WorkflowStep{{
Name: "test-web2",
Type: "apply-component",
Properties: runtime.RawExtension{Raw: []byte(`{"component":"myweb2"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"component":"myweb2"}`)},
}, {
Name: "test-web1",
Type: "apply-component",
Properties: runtime.RawExtension{Raw: []byte(`{"component":"myweb1"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"component":"myweb1"}`)},
}},
},
},
@@ -461,24 +461,24 @@ var _ = Describe("Test Workflow", func() {
{
Name: "myweb1",
Type: "worker",
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
DependsOn: []string{"myweb2"},
},
{
Name: "myweb2",
Type: "worker-with-health",
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox","lives": "i am lives","enemies": "empty"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox","lives": "i am lives","enemies": "empty"}`)},
},
},
Workflow: &oamcore.Workflow{
Steps: []oamcore.WorkflowStep{{
Name: "test-web2",
Type: "apply-component",
Properties: runtime.RawExtension{Raw: []byte(`{"component":"myweb2"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"component":"myweb2"}`)},
}, {
Name: "test-web1",
Type: "apply-component",
Properties: runtime.RawExtension{Raw: []byte(`{"component":"myweb1"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"component":"myweb1"}`)},
}},
},
},
@@ -549,7 +549,7 @@ var _ = Describe("Test Workflow", func() {
{
Name: "myweb1",
Type: "worker-with-health",
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
DependsOn: []string{"myweb2"},
Inputs: common.StepInputs{
{
@@ -565,7 +565,7 @@ var _ = Describe("Test Workflow", func() {
{
Name: "myweb2",
Type: "worker-with-health",
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox","lives": "i am lives","enemies": "empty"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox","lives": "i am lives","enemies": "empty"}`)},
Outputs: common.StepOutputs{
{Name: "message", ValueFrom: "output.status.conditions[0].message+\",\"+outputs.gameconfig.data.lives"},
},
@@ -575,11 +575,11 @@ var _ = Describe("Test Workflow", func() {
Steps: []oamcore.WorkflowStep{{
Name: "test-web2",
Type: "apply-component",
Properties: runtime.RawExtension{Raw: []byte(`{"component":"myweb2"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"component":"myweb2"}`)},
}, {
Name: "test-web1",
Type: "apply-component",
Properties: runtime.RawExtension{Raw: []byte(`{"component":"myweb1"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"component":"myweb1"}`)},
}},
},
},
@@ -649,12 +649,12 @@ var _ = Describe("Test Workflow", func() {
{
Name: "myweb1",
Type: "webserver",
Properties: runtime.RawExtension{Raw: []byte(`{"image":"busybox"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"image":"busybox"}`)},
},
{
Name: "myweb2",
Type: "webserver",
Properties: runtime.RawExtension{Raw: []byte(`{"image":"busybox"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"image":"busybox"}`)},
},
},
},
@@ -666,19 +666,19 @@ var _ = Describe("Test Workflow", func() {
updateApp := &oamcore.Application{}
Expect(k8sClient.Get(ctx, appKey, updateApp)).Should(BeNil())
Expect(updateApp.Status.Phase).Should(BeEquivalentTo(common.ApplicationRunning))
updateApp.Spec.Components[0].Properties = runtime.RawExtension{Raw: []byte(`{}`)}
updateApp.Spec.Components[0].Properties = &runtime.RawExtension{Raw: []byte(`{}`)}
updateApp.Spec.Workflow = &oamcore.Workflow{
Steps: []oamcore.WorkflowStep{{
Name: "test-web2",
Type: "apply-component",
Properties: runtime.RawExtension{Raw: []byte(`{"component":"myweb2"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"component":"myweb2"}`)},
Outputs: common.StepOutputs{
{Name: "image", ValueFrom: "output.spec.template.spec.containers[0].image"},
},
}, {
Name: "test-web1",
Type: "apply-component",
Properties: runtime.RawExtension{Raw: []byte(`{"component":"myweb1"}`)},
Properties: &runtime.RawExtension{Raw: []byte(`{"component":"myweb1"}`)},
Inputs: common.StepInputs{
{
From: "image",

View File

@@ -328,7 +328,7 @@ spec:
cd.Spec.Workload.Definition = common.WorkloadGVK{APIVersion: "apps/v1", Kind: "Deployment"}
cd.Spec.Schematic = &common.Schematic{
HELM: &common.Helm{
Release: util.Object2RawExtension(map[string]interface{}{
Release: *util.Object2RawExtension(map[string]interface{}{
"chart": map[string]interface{}{
"spec": map[string]interface{}{
"chart": "podinfo",
@@ -336,7 +336,7 @@ spec:
},
},
}),
Repository: util.Object2RawExtension(map[string]interface{}{
Repository: *util.Object2RawExtension(map[string]interface{}{
"url": "http://oam.dev/catalog/",
}),
},

View File

@@ -241,6 +241,46 @@ containers: [{
}
}, ...]
}, ...]
`},
{
base: `
containers: [{
volumeMounts: [{name: "k1", path: "p1"},{name: "k1", path: "p2"},...]
},...]
volumes: [{name: "x1",value: "v1"},{name: "x2",value: "v2"},...]
`,
patch: `
// +patchKey=name
volumes: [{name: "x1",value: "v1"},{name: "x3",value: "x2"}]
containers: [{
volumeMounts: [{name: "k1", path: "p1"},{name: "k1", path: "p2"},{ name:"k2", path: "p3"}]
},...]`,
result: `containers: [{
volumeMounts: [{
path: "p1"
name: "k1"
}, {
path: "p2"
name: "k1"
}, {
path: "p3"
name: "k2"
}]
}, ...]
// +patchKey=name
volumes: [{
name: "x1"
value: "v1"
}, {
name: "x2"
value: "v2"
}, {
name: "x3"
value: "x2"
}, ...]
`},
}

View File

@@ -58,6 +58,10 @@ func (nwk *nodewalker) walk(node ast.Node) {
if n.Value != nil {
origin := nwk.pos
oriTags := nwk.tags
nwk.tags = map[string]string{}
for k, v := range oriTags {
nwk.tags[k] = v
}
nwk.pos = append(nwk.pos, labelStr(n.Label))
tags := findCommentTag(n.Comments())
for tk, tv := range tags {

View File

@@ -93,9 +93,9 @@ func NewValue(s string, pd *packages.PackageDiscover, tagTempl string, opts ...f
}
addImports := func(inst *build.Instance) error {
if pd != nil {
pd.ImportBuiltinPackagesFor(builder)
pd.ImportBuiltinPackagesFor(inst)
}
if err := stdlib.AddImportsFor(builder, tagTempl); err != nil {
if err := stdlib.AddImportsFor(inst, tagTempl); err != nil {
return err
}
return nil

View File

@@ -25,6 +25,7 @@ import (
"github.com/oam-dev/cluster-gateway/pkg/apis/cluster/v1alpha1"
errors2 "github.com/pkg/errors"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/types"
@@ -34,6 +35,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/oam-dev/kubevela/pkg/utils/common"
errors3 "github.com/oam-dev/kubevela/pkg/utils/errors"
)
type contextKey string
@@ -52,11 +54,6 @@ var (
ClusterGatewaySecretNamespace string
)
// Context create context with multi-cluster
func Context(ctx context.Context, obj *unstructured.Unstructured) context.Context {
return ContextWithClusterName(ctx, obj.GetLabels()[ClusterLabelKey])
}
// ContextWithClusterName create context with multi-cluster by cluster name
func ContextWithClusterName(ctx context.Context, clusterName string) context.Context {
return context.WithValue(ctx, ClusterContextKey, clusterName)
@@ -129,5 +126,34 @@ func Initialize(restConfig *rest.Config) error {
ClusterGatewaySecretNamespace = svc.Namespace
klog.Infof("find cluster gateway service %s/%s:%d", svc.Namespace, svc.Name, *svc.Port)
restConfig.Wrap(NewSecretModeMultiClusterRoundTripper)
if err = UpgradeExistingClusterSecret(context.Background(), c); err != nil {
// this error do not affect the running of current version
klog.ErrorS(err, "error encountered while grading existing cluster secret to the latest version")
}
return nil
}
// UpgradeExistingClusterSecret upgrade outdated cluster secrets in v1.1.1 to latest
func UpgradeExistingClusterSecret(ctx context.Context, c client.Client) error {
const outdatedClusterCredentialLabelKey = "cluster.core.oam.dev/cluster-credential"
secrets := &v1.SecretList{}
if err := c.List(ctx, secrets, client.InNamespace(ClusterGatewaySecretNamespace), client.HasLabels{outdatedClusterCredentialLabelKey}); err != nil {
if err != nil {
return errors2.Wrapf(err, "failed to find outdated cluster secrets to do upgrade")
}
}
errs := errors3.ErrorList{}
for _, item := range secrets.Items {
credType := item.Labels[v1alpha1.LabelKeyClusterCredentialType]
if credType == "" && item.Type == v1.SecretTypeTLS {
item.Labels[v1alpha1.LabelKeyClusterCredentialType] = string(v1alpha1.CredentialTypeX509Certificate)
if err := c.Update(ctx, item.DeepCopy()); err != nil {
errs.Append(errors2.Wrapf(err, "failed to update outdated secret %s", item.Name))
}
}
}
if errs.HasError() {
return errs
}
return nil
}

View File

@@ -0,0 +1,63 @@
/*
Copyright 2021 The KubeVela Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package multicluster
import (
"context"
"testing"
"github.com/oam-dev/cluster-gateway/pkg/apis/cluster/v1alpha1"
v1 "k8s.io/api/core/v1"
v12 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
"github.com/oam-dev/kubevela/pkg/utils/common"
)
func TestUpgradeExistingClusterSecret(t *testing.T) {
oldClusterGatewaySecretNamespace := ClusterGatewaySecretNamespace
ClusterGatewaySecretNamespace = "default"
defer func() {
ClusterGatewaySecretNamespace = oldClusterGatewaySecretNamespace
}()
ctx := context.Background()
c := fake.NewClientBuilder().WithScheme(common.Scheme).Build()
secret := &v1.Secret{
ObjectMeta: v12.ObjectMeta{
Name: "example-outdated-cluster-secret",
Namespace: "default",
Labels: map[string]string{
"cluster.core.oam.dev/cluster-credential": "tls",
},
},
Type: v1.SecretTypeTLS,
}
if err := c.Create(ctx, secret); err != nil {
t.Fatalf("failed to create fake outdated cluster secret, err: %v", err)
}
if err := UpgradeExistingClusterSecret(ctx, c); err != nil {
t.Fatalf("expect no error while upgrading outdated cluster secret but encounter error: %v", err)
}
newSecret := &v1.Secret{}
if err := c.Get(ctx, client.ObjectKeyFromObject(secret), newSecret); err != nil {
t.Fatalf("found error while getting updated cluster secret: %v", err)
}
if newSecret.Labels[v1alpha1.LabelKeyClusterCredentialType] != string(v1alpha1.CredentialTypeX509Certificate) {
t.Fatalf("updated secret label should has credential type x509")
}
}

View File

@@ -117,6 +117,9 @@ const (
// AnnotationDefinitionRevisionName is used to specify the name of DefinitionRevision in component/trait definition
AnnotationDefinitionRevisionName = "definitionrevision.oam.dev/name"
// AnnotationResourceTrackerLifeLong is used to identify life-long resourcetracker which should only be recycled when application is deleted
AnnotationResourceTrackerLifeLong = "resourcetracker.oam.dev/life-long"
// AnnotationAddonsName records the name of initializer stored in configMap
AnnotationAddonsName = "addons.oam.dev/name"
)

Some files were not shown because too many files have changed in this diff Show More