Chore: remove outdated apis(v1alppha2 ApplicationConfiguration Component, and HealthScope, Rollout) (#6041)

* remove outdated api

Signed-off-by: Somefive <yd219913@alibaba-inc.com>

* fix rt test: no component rt

Signed-off-by: Somefive <yd219913@alibaba-inc.com>

* recover context.revision to component hash

Signed-off-by: Somefive <yd219913@alibaba-inc.com>

---------

Signed-off-by: Somefive <yd219913@alibaba-inc.com>
This commit is contained in:
Somefive
2023-06-01 09:32:49 +08:00
committed by GitHub
parent d6788f12dd
commit dd899c2b39
284 changed files with 517 additions and 66926 deletions

View File

@@ -1,124 +0,0 @@
name: E2E Rollout Test
on:
# push:
# branches:
# - master
# - release-*
# tags:
# - v*
workflow_dispatch: {}
# pull_request:
# branches:
# - master
# - release-*
permissions:
contents: read
env:
# Common versions
GO_VERSION: '1.19'
jobs:
detect-noop:
permissions:
actions: write
runs-on: ubuntu-22.04
outputs:
noop: ${{ steps.noop.outputs.should_skip }}
steps:
- name: Detect No-op Changes
id: noop
uses: fkirc/skip-duplicate-actions@12aca0a884f6137d619d6a8a09fcc3406ced5281
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
paths_ignore: '["**.md", "**.mdx", "**.png", "**.jpg"]'
do_not_skip: '["workflow_dispatch", "schedule", "push"]'
continue-on-error: true
e2e-rollout-tests:
runs-on: self-hosted
needs: [ detect-noop ]
if: needs.detect-noop.outputs.noop != 'true'
strategy:
matrix:
k8s-version: ["v1.26"]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ matrix.k8s-version }}
cancel-in-progress: true
steps:
- name: Check out code into the Go module directory
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab
- name: Setup Go
uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753
with:
go-version: ${{ env.GO_VERSION }}
- name: Get dependencies
run: |
go get -v -t -d ./...
- name: Get Ginkgo
run: |
go install github.com/onsi/ginkgo/v2/ginkgo
go get github.com/onsi/gomega/...
- name: Tear down K3d if exist
run: |
k3d cluster delete || true
k3d cluster delete worker || true
- name: Calculate K3d args
run: |
EGRESS_ARG=""
if [[ "${{ matrix.k8s-version }}" == v1.26 ]]; then
EGRESS_ARG="--k3s-arg --egress-selector-mode=disabled@server:0"
fi
echo "EGRESS_ARG=${EGRESS_ARG}" >> $GITHUB_ENV
- name: Setup K3d
uses: nolar/setup-k3d-k3s@293b8e5822a20bc0d5bcdd4826f1a665e72aba96
with:
version: ${{ matrix.k8s-version }}
github-token: ${{ secrets.GITHUB_TOKEN }}
k3d-args: ${{ env.EGRESS_ARG }}
- name: Load image to k3d cluster
run: make image-load image-load-runtime-cluster
- name: Prepare for e2e tests
run: |
make vela-cli
make e2e-cleanup
make e2e-setup-core
make setup-runtime-e2e-cluster
helm test -n vela-system kubevela --timeout 5m
- name: Run e2e tests
run: make e2e-rollout-test
- name: Stop kubevela, get profile
run: make end-e2e
- name: Upload coverage report
uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: /tmp/e2e-profile.out
flags: e2e-rollout-tests
name: codecov-umbrella
- name: Clean e2e profile
run: rm /tmp/e2e-profile.out
- name: Cleanup image
if: ${{ always() }}
run: |
make image-cleanup
docker image prune -a -f --filter "until=24h"

View File

@@ -21,13 +21,12 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha1"
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2"
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
)
func init() {
// Register the types with the Scheme so the resources can map objects to GroupVersionKinds and back
AddToSchemes = append(AddToSchemes, v1alpha1.SchemeBuilder.AddToScheme, v1alpha2.SchemeBuilder.AddToScheme, v1beta1.SchemeBuilder.AddToScheme)
AddToSchemes = append(AddToSchemes, v1alpha1.SchemeBuilder.AddToScheme, v1beta1.SchemeBuilder.AddToScheme)
}
// AddToSchemes may be used to add all resources defined in the project to a Scheme

View File

@@ -1,123 +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 v1alpha2
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/standard.oam.dev/v1alpha1"
)
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
// AppStatus defines the observed state of Application
type AppStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// Important: Run "make" to regenerate code after modifying this file
v1alpha1.RolloutStatus `json:",inline"`
Phase common.ApplicationPhase `json:"status,omitempty"`
// Components record the related Components created by Application Controller
Components []corev1.ObjectReference `json:"components,omitempty"`
// Services record the status of the application services
Services []common.ApplicationComponentStatus `json:"services,omitempty"`
// ResourceTracker record the status of the ResourceTracker
ResourceTracker *corev1.ObjectReference `json:"resourceTracker,omitempty"`
// LatestRevision of the application configuration it generates
// +optional
LatestRevision *common.Revision `json:"latestRevision,omitempty"`
}
// ApplicationTrait defines the trait of application
type ApplicationTrait struct {
Name string `json:"name"`
// +kubebuilder:pruning:PreserveUnknownFields
Properties *runtime.RawExtension `json:"properties,omitempty"`
}
// ApplicationComponent describe the component of application
type ApplicationComponent struct {
Name string `json:"name"`
WorkloadType string `json:"type"`
// +kubebuilder:pruning:PreserveUnknownFields
Settings runtime.RawExtension `json:"settings,omitempty"`
// Traits define the trait of one component, the type must be array to keep the order.
Traits []ApplicationTrait `json:"traits,omitempty"`
// +kubebuilder:pruning:PreserveUnknownFields
// scopes in ApplicationComponent defines the component-level scopes
// the format is <scope-type:scope-instance-name> pairs, the key represents type of `ScopeDefinition` while the value represent the name of scope instance.
Scopes map[string]string `json:"scopes,omitempty"`
}
// ApplicationSpec is the spec of Application
type ApplicationSpec struct {
Components []ApplicationComponent `json:"components"`
// TODO(wonderflow): we should have application level scopes supported here
// RolloutPlan is the details on how to rollout the resources
// The controller simply replace the old resources with the new one if there is no rollout plan involved
// +optional
RolloutPlan *v1alpha1.RolloutPlan `json:"rolloutPlan,omitempty"`
}
// Application is the Schema for the applications API
// +kubebuilder:object:root=true
// +kubebuilder:resource:categories={oam},shortName={app,velaapp}
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="COMPONENT",type=string,JSONPath=`.spec.components[*].name`
// +kubebuilder:printcolumn:name="TYPE",type=string,JSONPath=`.spec.components[*].type`
// +kubebuilder:printcolumn:name="PHASE",type=string,JSONPath=`.status.status`
// +kubebuilder:printcolumn:name="HEALTHY",type=boolean,JSONPath=`.status.services[*].healthy`
// +kubebuilder:printcolumn:name="STATUS",type=string,JSONPath=`.status.services[*].message`
// +kubebuilder:printcolumn:name="AGE",type=date,JSONPath=".metadata.creationTimestamp"
type Application struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec ApplicationSpec `json:"spec,omitempty"`
Status common.AppStatus `json:"status,omitempty"`
}
// +kubebuilder:object:root=true
// ApplicationList contains a list of Application
type ApplicationList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []Application `json:"items"`
}
// GetComponent get the component from the application based on its workload type
func (app *Application) GetComponent(workloadType string) *ApplicationComponent {
for _, c := range app.Spec.Components {
if c.WorkloadType == workloadType {
return &c
}
}
return nil
}

View File

@@ -1,68 +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 v1alpha2
import (
"reflect"
"testing"
)
func TestApplicationGetComponent(t *testing.T) {
ac1 := ApplicationComponent{
Name: "ac1",
WorkloadType: "type1",
}
ac2 := ApplicationComponent{
Name: "ac2",
WorkloadType: "type2",
}
tests := map[string]struct {
app *Application
componentName string
want *ApplicationComponent
}{
"test get one": {
app: &Application{
Spec: ApplicationSpec{
Components: []ApplicationComponent{
ac1, ac2,
},
},
},
componentName: ac1.WorkloadType,
want: &ac1,
},
"test get none": {
app: &Application{
Spec: ApplicationSpec{
Components: []ApplicationComponent{
ac2,
},
},
},
componentName: ac1.WorkloadType,
want: nil,
},
}
for name, tt := range tests {
t.Run(name, func(t *testing.T) {
if got := tt.app.GetComponent(tt.componentName); !reflect.DeepEqual(got, tt.want) {
t.Errorf("GetComponent() = %v, want %v", got, tt.want)
}
})
}
}

View File

@@ -1,73 +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 v1alpha2
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
)
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
// ApplicationRevisionSpec is the spec of ApplicationRevision
type ApplicationRevisionSpec struct {
// Application records the snapshot of the created/modified Application
Application Application `json:"application"`
// ComponentDefinitions records the snapshot of the componentDefinitions related with the created/modified Application
ComponentDefinitions map[string]ComponentDefinition `json:"componentDefinitions,omitempty"`
// WorkloadDefinitions records the snapshot of the workloadDefinitions related with the created/modified Application
WorkloadDefinitions map[string]WorkloadDefinition `json:"workloadDefinitions,omitempty"`
// TraitDefinitions records the snapshot of the traitDefinitions related with the created/modified Application
TraitDefinitions map[string]TraitDefinition `json:"traitDefinitions,omitempty"`
// ScopeDefinitions records the snapshot of the scopeDefinitions related with the created/modified Application
ScopeDefinitions map[string]ScopeDefinition `json:"scopeDefinitions,omitempty"`
// Components records the rendered components from Application, it will contains the whole K8s CR of workload in it.
Components []common.RawComponent `json:"components,omitempty"`
// ApplicationConfiguration records the rendered applicationConfiguration from Application,
// it will contains the whole K8s CR of trait and the reference component in it.
// +kubebuilder:validation:EmbeddedResource
// +kubebuilder:pruning:PreserveUnknownFields
ApplicationConfiguration runtime.RawExtension `json:"applicationConfiguration"`
}
// ApplicationRevision is the Schema for the ApplicationRevision API
// +kubebuilder:object:root=true
// +kubebuilder:resource:categories={oam},shortName=apprev
// +kubebuilder:printcolumn:name="AGE",type=date,JSONPath=".metadata.creationTimestamp"
type ApplicationRevision struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec ApplicationRevisionSpec `json:"spec,omitempty"`
}
// ApplicationRevisionList contains a list of ApplicationRevision
// +kubebuilder:object:root=true
type ApplicationRevisionList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []ApplicationRevision `json:"items"`
}

View File

@@ -1,103 +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 v1alpha2
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"github.com/oam-dev/kubevela/apis/core.oam.dev/condition"
"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
)
// ComponentDefinitionSpec defines the desired state of ComponentDefinition
type ComponentDefinitionSpec struct {
// Workload is a workload type descriptor
Workload common.WorkloadTypeDescriptor `json:"workload"`
// ChildResourceKinds are the list of GVK of the child resources this workload generates
ChildResourceKinds []common.ChildResourceKind `json:"childResourceKinds,omitempty"`
// RevisionLabel indicates which label for underlying resources(e.g. pods) of this workload
// can be used by trait to create resource selectors(e.g. label selector for pods).
// +optional
RevisionLabel string `json:"revisionLabel,omitempty"`
// PodSpecPath indicates where/if this workload has K8s podSpec field
// if one workload has podSpec, trait can do lot's of assumption such as port, env, volume fields.
// +optional
PodSpecPath string `json:"podSpecPath,omitempty"`
// Status defines the custom health policy and status message for workload
// +optional
Status *common.Status `json:"status,omitempty"`
// Schematic defines the data format and template of the encapsulation of the workload
// +optional
Schematic *common.Schematic `json:"schematic,omitempty"`
// Extension is used for extension needs by OAM platform builders
// +optional
// +kubebuilder:pruning:PreserveUnknownFields
Extension *runtime.RawExtension `json:"extension,omitempty"`
}
// ComponentDefinitionStatus is the status of ComponentDefinition
type ComponentDefinitionStatus struct {
// ConditionedStatus reflects the observed status of a resource
condition.ConditionedStatus `json:",inline"`
// ConfigMapRef refer to a ConfigMap which contains OpenAPI V3 JSON schema of Component parameters.
ConfigMapRef string `json:"configMapRef,omitempty"`
// LatestRevision of the component definition
// +optional
LatestRevision *common.Revision `json:"latestRevision,omitempty"`
}
// +kubebuilder:object:root=true
// ComponentDefinition is the Schema for the componentdefinitions API
// +kubebuilder:resource:scope=Namespaced,categories={oam},shortName=comp
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="WORKLOAD-KIND",type=string,JSONPath=".spec.workload.definition.kind"
// +kubebuilder:printcolumn:name="DESCRIPTION",type=string,JSONPath=".metadata.annotations.definition\\.oam\\.dev/description"
type ComponentDefinition struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec ComponentDefinitionSpec `json:"spec,omitempty"`
Status ComponentDefinitionStatus `json:"status,omitempty"`
}
// SetConditions set condition for WorkloadDefinition
func (cd *ComponentDefinition) SetConditions(c ...condition.Condition) {
cd.Status.SetConditions(c...)
}
// GetCondition gets condition from WorkloadDefinition
func (cd *ComponentDefinition) GetCondition(conditionType condition.ConditionType) condition.Condition {
return cd.Status.GetCondition(conditionType)
}
// +kubebuilder:object:root=true
// ComponentDefinitionList contains a list of ComponentDefinition
type ComponentDefinitionList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []ComponentDefinition `json:"items"`
}

View File

@@ -1,139 +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 v1alpha2
import (
"fmt"
"reflect"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/klog/v2"
"sigs.k8s.io/controller-runtime/pkg/conversion"
"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
)
// ApplicationV1alpha2ToV1beta1 will convert v1alpha2 to v1beta1
func ApplicationV1alpha2ToV1beta1(v1a2 *Application, v1b1 *v1beta1.Application) {
// 1) convert metav1.TypeMeta
// apiVersion and Kind automatically converted
// 2) convert metav1.ObjectMeta
v1b1.ObjectMeta = *v1a2.ObjectMeta.DeepCopy()
// 3) convert Spec ApplicationSpec
// 3.1) convert Spec.Components
for _, comp := range v1a2.Spec.Components {
// convert trait, especially for `.name` -> `.type`
var traits = make([]common.ApplicationTrait, len(comp.Traits))
for j, trait := range comp.Traits {
traits[j] = common.ApplicationTrait{
Type: trait.Name,
Properties: trait.Properties.DeepCopy(),
}
}
// deep copy scopes
scopes := make(map[string]string)
for k, v := range comp.Scopes {
scopes[k] = v
}
// convert component
// `.settings` -> `.properties`
v1b1.Spec.Components = append(v1b1.Spec.Components, common.ApplicationComponent{
Name: comp.Name,
Type: comp.WorkloadType,
Properties: comp.Settings.DeepCopy(),
Traits: traits,
Scopes: scopes,
})
}
// 4) convert Status common.AppStatus
v1b1.Status = *v1a2.Status.DeepCopy()
}
// ConvertTo converts this Application to the Hub version (v1beta1 only for now).
func (app *Application) ConvertTo(dst conversion.Hub) error {
switch convertedApp := dst.(type) {
case *v1beta1.Application:
klog.Infof("convert *v1alpha2.Application [%s] to *v1beta1.Application", app.Name)
ApplicationV1alpha2ToV1beta1(app, convertedApp)
return nil
default:
}
return fmt.Errorf("unsupported convertTo object %v", reflect.TypeOf(dst))
}
// ConvertFrom converts from the Hub version (v1beta1) to this version (v1alpha2).
func (app *Application) ConvertFrom(src conversion.Hub) error {
switch sourceApp := src.(type) {
case *v1beta1.Application:
klog.Infof("convert *v1alpha2.Application from *v1beta1.Application [%s]", sourceApp.Name)
// 1) convert metav1.TypeMeta
// apiVersion and Kind automatically converted
// 2) convert metav1.ObjectMeta
app.ObjectMeta = *sourceApp.ObjectMeta.DeepCopy()
// 3) convert Spec ApplicationSpec
// 3.1) convert Spec.Components
for _, comp := range sourceApp.Spec.Components {
// convert trait, especially for `.type` -> `.name`
var traits = make([]ApplicationTrait, len(comp.Traits))
for j, trait := range comp.Traits {
traits[j] = ApplicationTrait{
Name: trait.Type,
Properties: trait.Properties.DeepCopy(),
}
}
// deep copy scopes
scopes := make(map[string]string)
for k, v := range comp.Scopes {
scopes[k] = v
}
// convert component
// `.properties` -> `.settings`
var compProperties runtime.RawExtension
if comp.Properties != nil {
compProperties = *comp.Properties.DeepCopy()
}
app.Spec.Components = append(app.Spec.Components, ApplicationComponent{
Name: comp.Name,
WorkloadType: comp.Type,
Settings: compProperties,
Traits: traits,
Scopes: scopes,
})
}
// 4) convert Status common.AppStatus
app.Status = *sourceApp.Status.DeepCopy()
return nil
default:
}
return fmt.Errorf("unsupported ConvertFrom object %v", reflect.TypeOf(src))
}

View File

@@ -1,117 +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 v1alpha2
import (
"fmt"
"testing"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"github.com/stretchr/testify/require"
"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
)
var app = Application{
Spec: ApplicationSpec{
Components: []ApplicationComponent{{
Name: "test-component",
WorkloadType: "worker",
Traits: []ApplicationTrait{},
Scopes: map[string]string{},
}},
},
}
type errType struct {
}
func (*errType) Hub() {}
func (*errType) DeepCopyObject() runtime.Object {
return nil
}
func (*errType) GetObjectKind() schema.ObjectKind {
return nil
}
func TestApplicationV1alpha2ToV1beta1(t *testing.T) {
r := require.New(t)
expected := &v1beta1.Application{}
ApplicationV1alpha2ToV1beta1(&app, expected)
r.Equal(expected, &v1beta1.Application{
Spec: v1beta1.ApplicationSpec{
Components: []common.ApplicationComponent{{
Name: "test-component",
Type: "worker",
Properties: &runtime.RawExtension{},
Traits: []common.ApplicationTrait{},
Scopes: map[string]string{},
}},
},
})
}
func TestConvertTo(t *testing.T) {
r := require.New(t)
expected := &v1beta1.Application{}
err := app.ConvertTo(expected)
r.NoError(err)
r.Equal(expected, &v1beta1.Application{
Spec: v1beta1.ApplicationSpec{
Components: []common.ApplicationComponent{{
Name: "test-component",
Type: "worker",
Properties: &runtime.RawExtension{},
Traits: []common.ApplicationTrait{},
Scopes: map[string]string{},
}},
},
})
errCase := &errType{}
err = app.ConvertTo(errCase)
r.Equal(err, fmt.Errorf("unsupported convertTo object *v1alpha2.errType"))
}
func TestConvertFrom(t *testing.T) {
r := require.New(t)
to := &Application{}
from := &v1beta1.Application{
Spec: v1beta1.ApplicationSpec{
Components: []common.ApplicationComponent{{
Name: "test-component",
Type: "worker",
Properties: &runtime.RawExtension{},
Traits: []common.ApplicationTrait{},
Scopes: map[string]string{},
}},
},
}
err := to.ConvertFrom(from)
r.NoError(err)
r.Equal(to.Spec, app.Spec)
errCase := &errType{}
err = app.ConvertFrom(errCase)
r.Equal(err, fmt.Errorf("unsupported ConvertFrom object *v1alpha2.errType"))
}

View File

@@ -1,146 +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 v1alpha2
import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/oam-dev/kubevela/apis/core.oam.dev/condition"
"github.com/oam-dev/kubevela/pkg/oam"
)
// HealthStatus represents health status strings.
type HealthStatus string
const (
// StatusHealthy represents healthy status.
StatusHealthy HealthStatus = "HEALTHY"
// StatusUnhealthy represents unhealthy status.
StatusUnhealthy = "UNHEALTHY"
// StatusUnknown represents unknown status.
StatusUnknown = "UNKNOWN"
)
var _ oam.Scope = &HealthScope{}
// A HealthScopeSpec defines the desired state of a HealthScope.
type HealthScopeSpec struct {
// ProbeTimeout is the amount of time in seconds to wait when receiving a response before marked failure.
ProbeTimeout *int32 `json:"probe-timeout,omitempty"`
// ProbeInterval is the amount of time in seconds between probing tries.
ProbeInterval *int32 `json:"probe-interval,omitempty"`
// AppRefs records references of applications' components
AppRefs []AppReference `json:"appReferences,omitempty"`
// WorkloadReferences to the workloads that are in this scope.
// +deprecated
WorkloadReferences []corev1.ObjectReference `json:"workloadRefs"`
}
// AppReference records references of an application's components
type AppReference struct {
AppName string `json:"appName,omitempty"`
CompReferences []CompReference `json:"compReferences,omitempty"`
}
// CompReference records references of a component's resources
type CompReference struct {
CompName string `json:"compName,omitempty"`
Workload corev1.ObjectReference `json:"workload,omitempty"`
Traits []corev1.ObjectReference `json:"traits,omitempty"`
}
// A HealthScopeStatus represents the observed state of a HealthScope.
type HealthScopeStatus struct {
condition.ConditionedStatus `json:",inline"`
// ScopeHealthCondition represents health condition summary of the scope
ScopeHealthCondition ScopeHealthCondition `json:"scopeHealthCondition"`
// AppHealthConditions represents health condition of applications in the scope
AppHealthConditions []*AppHealthCondition `json:"appHealthConditions,omitempty"`
// WorkloadHealthConditions represents health condition of workloads in the scope
// Use AppHealthConditions to provide app level status
// +deprecated
WorkloadHealthConditions []*WorkloadHealthCondition `json:"healthConditions,omitempty"`
}
// AppHealthCondition represents health condition of an application
type AppHealthCondition struct {
AppName string `json:"appName"`
EnvName string `json:"envName,omitempty"`
Components []*WorkloadHealthCondition `json:"components,omitempty"`
}
// ScopeHealthCondition represents health condition summary of a scope.
type ScopeHealthCondition struct {
HealthStatus HealthStatus `json:"healthStatus"`
Total int64 `json:"total,omitempty"`
HealthyWorkloads int64 `json:"healthyWorkloads,omitempty"`
UnhealthyWorkloads int64 `json:"unhealthyWorkloads,omitempty"`
UnknownWorkloads int64 `json:"unknownWorkloads,omitempty"`
}
// WorkloadHealthCondition represents informative health condition of a workload.
type WorkloadHealthCondition struct {
// ComponentName represents the component name if target is a workload
ComponentName string `json:"componentName,omitempty"`
TargetWorkload corev1.ObjectReference `json:"targetWorkload,omitempty"`
HealthStatus HealthStatus `json:"healthStatus"`
Diagnosis string `json:"diagnosis,omitempty"`
// WorkloadStatus represents status of workloads whose HealthStatus is UNKNOWN.
WorkloadStatus string `json:"workloadStatus,omitempty"`
CustomStatusMsg string `json:"customStatusMsg,omitempty"`
Traits []*TraitHealthCondition `json:"traits,omitempty"`
}
// TraitHealthCondition represents informative health condition of a trait.
type TraitHealthCondition struct {
Type string `json:"type"`
Resource string `json:"resource"`
HealthStatus HealthStatus `json:"healthStatus"`
Diagnosis string `json:"diagnosis,omitempty"`
CustomStatusMsg string `json:"customStatusMsg,omitempty"`
}
// +kubebuilder:object:root=true
// A HealthScope determines an aggregate health status based of the health of components.
// +kubebuilder:resource:categories={oam}
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:JSONPath=".status.health",name=HEALTH,type=string
type HealthScope struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec HealthScopeSpec `json:"spec,omitempty"`
Status HealthScopeStatus `json:"status,omitempty"`
}
// +kubebuilder:object:root=true
// HealthScopeList contains a list of HealthScope.
type HealthScopeList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []HealthScope `json:"items"`
}

View File

@@ -1,673 +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 v1alpha2
import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/intstr"
"github.com/oam-dev/kubevela/apis/core.oam.dev/condition"
"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
"github.com/oam-dev/kubevela/apis/types"
)
// A WorkloadDefinitionSpec defines the desired state of a WorkloadDefinition.
type WorkloadDefinitionSpec struct {
// Reference to the CustomResourceDefinition that defines this workload kind.
Reference common.DefinitionReference `json:"definitionRef"`
// ChildResourceKinds are the list of GVK of the child resources this workload generates
ChildResourceKinds []common.ChildResourceKind `json:"childResourceKinds,omitempty"`
// RevisionLabel indicates which label for underlying resources(e.g. pods) of this workload
// can be used by trait to create resource selectors(e.g. label selector for pods).
// +optional
RevisionLabel string `json:"revisionLabel,omitempty"`
// PodSpecPath indicates where/if this workload has K8s podSpec field
// if one workload has podSpec, trait can do lot's of assumption such as port, env, volume fields.
// +optional
PodSpecPath string `json:"podSpecPath,omitempty"`
// Status defines the custom health policy and status message for workload
// +optional
Status *common.Status `json:"status,omitempty"`
// Schematic defines the data format and template of the encapsulation of the workload
// +optional
Schematic *common.Schematic `json:"schematic,omitempty"`
// Extension is used for extension needs by OAM platform builders
// +optional
// +kubebuilder:pruning:PreserveUnknownFields
Extension *runtime.RawExtension `json:"extension,omitempty"`
}
// WorkloadDefinitionStatus is the status of WorkloadDefinition
type WorkloadDefinitionStatus struct {
condition.ConditionedStatus `json:",inline"`
}
// +kubebuilder:object:root=true
// A WorkloadDefinition registers a kind of Kubernetes custom resource as a
// valid OAM workload kind by referencing its CustomResourceDefinition. The CRD
// is used to validate the schema of the workload when it is embedded in an OAM
// Component.
// +kubebuilder:resource:scope=Namespaced,categories={oam},shortName=workload
// +kubebuilder:printcolumn:name="DEFINITION-NAME",type=string,JSONPath=".spec.definitionRef.name"
type WorkloadDefinition struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec WorkloadDefinitionSpec `json:"spec,omitempty"`
Status WorkloadDefinitionStatus `json:"status,omitempty"`
}
// SetConditions set condition for WorkloadDefinition
func (wd *WorkloadDefinition) SetConditions(c ...condition.Condition) {
wd.Status.SetConditions(c...)
}
// GetCondition gets condition from WorkloadDefinition
func (wd *WorkloadDefinition) GetCondition(conditionType condition.ConditionType) condition.Condition {
return wd.Status.GetCondition(conditionType)
}
// +kubebuilder:object:root=true
// WorkloadDefinitionList contains a list of WorkloadDefinition.
type WorkloadDefinitionList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []WorkloadDefinition `json:"items"`
}
// A TraitDefinitionSpec defines the desired state of a TraitDefinition.
type TraitDefinitionSpec struct {
// Reference to the CustomResourceDefinition that defines this trait kind.
Reference common.DefinitionReference `json:"definitionRef,omitempty"`
// Revision indicates whether a trait is aware of component revision
// +optional
RevisionEnabled bool `json:"revisionEnabled,omitempty"`
// WorkloadRefPath indicates where/if a trait accepts a workloadRef object
// +optional
WorkloadRefPath string `json:"workloadRefPath,omitempty"`
// PodDisruptive specifies whether using the trait will cause the pod to restart or not.
// +optional
PodDisruptive bool `json:"podDisruptive,omitempty"`
// AppliesToWorkloads specifies the list of workload kinds this trait
// applies to. Workload kinds are specified in kind.group/version format,
// e.g. server.core.oam.dev/v1alpha2. Traits that omit this field apply to
// all workload kinds.
// +optional
AppliesToWorkloads []string `json:"appliesToWorkloads,omitempty"`
// ConflictsWith specifies the list of traits(CRD name, Definition name, CRD group)
// which could not apply to the same workloads with this trait.
// Traits that omit this field can work with any other traits.
// Example rules:
// "service" # Trait definition name
// "services.k8s.io" # API resource/crd name
// "*.networking.k8s.io" # API group
// "labelSelector:foo=bar" # label selector
// labelSelector format: https://pkg.go.dev/k8s.io/apimachinery/pkg/labels#Parse
// +optional
ConflictsWith []string `json:"conflictsWith,omitempty"`
// Schematic defines the data format and template of the encapsulation of the trait
// +optional
Schematic *common.Schematic `json:"schematic,omitempty"`
// Status defines the custom health policy and status message for trait
// +optional
Status *common.Status `json:"status,omitempty"`
// Extension is used for extension needs by OAM platform builders
// +optional
// +kubebuilder:pruning:PreserveUnknownFields
Extension *runtime.RawExtension `json:"extension,omitempty"`
}
// TraitDefinitionStatus is the status of TraitDefinition
type TraitDefinitionStatus struct {
// ConditionedStatus reflects the observed status of a resource
condition.ConditionedStatus `json:",inline"`
// ConfigMapRef refer to a ConfigMap which contains OpenAPI V3 JSON schema of Component parameters.
ConfigMapRef string `json:"configMapRef,omitempty"`
// LatestRevision of the trait definition
// +optional
LatestRevision *common.Revision `json:"latestRevision,omitempty"`
}
// +kubebuilder:object:root=true
// A TraitDefinition registers a kind of Kubernetes custom resource as a valid
// OAM trait kind by referencing its CustomResourceDefinition. The CRD is used
// to validate the schema of the trait when it is embedded in an OAM
// ApplicationConfiguration.
// +kubebuilder:resource:scope=Namespaced,categories={oam},shortName=trait
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="APPLIES-TO",type=string,JSONPath=".spec.appliesToWorkloads"
// +kubebuilder:printcolumn:name="DESCRIPTION",type=string,JSONPath=".metadata.annotations.definition\\.oam\\.dev/description"
type TraitDefinition struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec TraitDefinitionSpec `json:"spec,omitempty"`
Status TraitDefinitionStatus `json:"status,omitempty"`
}
// SetConditions set condition for TraitDefinition
func (td *TraitDefinition) SetConditions(c ...condition.Condition) {
td.Status.SetConditions(c...)
}
// GetCondition gets condition from TraitDefinition
func (td *TraitDefinition) GetCondition(conditionType condition.ConditionType) condition.Condition {
return td.Status.GetCondition(conditionType)
}
// +kubebuilder:object:root=true
// TraitDefinitionList contains a list of TraitDefinition.
type TraitDefinitionList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []TraitDefinition `json:"items"`
}
// A ScopeDefinitionSpec defines the desired state of a ScopeDefinition.
type ScopeDefinitionSpec struct {
// Reference to the CustomResourceDefinition that defines this scope kind.
Reference common.DefinitionReference `json:"definitionRef"`
// WorkloadRefsPath indicates if/where a scope accepts workloadRef objects
WorkloadRefsPath string `json:"workloadRefsPath,omitempty"`
// AllowComponentOverlap specifies whether an OAM component may exist in
// multiple instances of this kind of scope.
AllowComponentOverlap bool `json:"allowComponentOverlap"`
// Extension is used for extension needs by OAM platform builders
// +optional
// +kubebuilder:pruning:PreserveUnknownFields
Extension *runtime.RawExtension `json:"extension,omitempty"`
}
// +kubebuilder:object:root=true
// A ScopeDefinition registers a kind of Kubernetes custom resource as a valid
// OAM scope kind by referencing its CustomResourceDefinition. The CRD is used
// to validate the schema of the scope when it is embedded in an OAM
// ApplicationConfiguration.
// +kubebuilder:printcolumn:JSONPath=".spec.definitionRef.name",name=DEFINITION-NAME,type=string
// +kubebuilder:resource:scope=Namespaced,categories={oam},shortName=scope
type ScopeDefinition struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec ScopeDefinitionSpec `json:"spec,omitempty"`
}
// +kubebuilder:object:root=true
// ScopeDefinitionList contains a list of ScopeDefinition.
type ScopeDefinitionList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []ScopeDefinition `json:"items"`
}
// A ComponentParameter defines a configurable parameter of a component.
type ComponentParameter struct {
// Name of this parameter. OAM ApplicationConfigurations will specify
// parameter values using this name.
Name string `json:"name"`
// FieldPaths specifies an array of fields within this Component's workload
// that will be overwritten by the value of this parameter. The type of the
// parameter (e.g. int, string) is inferred from the type of these fields;
// All fields must be of the same type. Fields are specified as JSON field
// paths without a leading dot, for example 'spec.replicas'.
FieldPaths []string `json:"fieldPaths"`
// +kubebuilder:default:=false
// Required specifies whether or not a value for this parameter must be
// supplied when authoring an ApplicationConfiguration.
// +optional
Required *bool `json:"required,omitempty"`
// Description of this parameter.
// +optional
Description *string `json:"description,omitempty"`
}
// A ComponentSpec defines the desired state of a Component.
type ComponentSpec struct {
// A Workload that will be created for each ApplicationConfiguration that
// includes this Component. Workload is an instance of a workloadDefinition.
// We either use the GVK info or a special "type" field in the workload to associate
// the content of the workload with its workloadDefinition
// +kubebuilder:validation:EmbeddedResource
// +kubebuilder:pruning:PreserveUnknownFields
Workload runtime.RawExtension `json:"workload"`
// HelmRelease records a Helm release used by a Helm module workload.
// +optional
Helm *common.Helm `json:"helm,omitempty"`
// Parameters exposed by this component. ApplicationConfigurations that
// reference this component may specify values for these parameters, which
// will in turn be injected into the embedded workload.
// +optional
Parameters []ComponentParameter `json:"parameters,omitempty"`
}
// A ComponentStatus represents the observed state of a Component.
type ComponentStatus struct {
// The generation observed by the component controller.
// +optional
ObservedGeneration int64 `json:"observedGeneration"`
condition.ConditionedStatus `json:",inline"`
// LatestRevision of component
// +optional
LatestRevision *common.Revision `json:"latestRevision,omitempty"`
// One Component should only be used by one AppConfig
}
// +kubebuilder:object:root=true
// A Component describes how an OAM workload kind may be instantiated.
// +kubebuilder:resource:categories={oam}
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:JSONPath=".spec.workload.kind",name=WORKLOAD-KIND,type=string
// +kubebuilder:printcolumn:name="age",type="date",JSONPath=".metadata.creationTimestamp"
type Component struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec ComponentSpec `json:"spec,omitempty"`
Status ComponentStatus `json:"status,omitempty"`
}
// +kubebuilder:object:root=true
// ComponentList contains a list of Component.
type ComponentList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []Component `json:"items"`
}
// A ComponentParameterValue specifies a value for a named parameter. The
// associated component must publish a parameter with this name.
type ComponentParameterValue struct {
// Name of the component parameter to set.
Name string `json:"name"`
// Value to set.
Value intstr.IntOrString `json:"value"`
}
// A ComponentTrait specifies a trait that should be applied to a component.
type ComponentTrait struct {
// A Trait that will be created for the component
// +kubebuilder:validation:EmbeddedResource
// +kubebuilder:pruning:PreserveUnknownFields
Trait runtime.RawExtension `json:"trait"`
// DataOutputs specify the data output sources from this trait.
// +optional
DataOutputs []DataOutput `json:"dataOutputs,omitempty"`
// DataInputs specify the data input sinks into this trait.
// +optional
DataInputs []DataInput `json:"dataInputs,omitempty"`
}
// A ComponentScope specifies a scope in which a component should exist.
type ComponentScope struct {
// A ScopeReference must refer to an OAM scope resource.
ScopeReference corev1.ObjectReference `json:"scopeRef"`
}
// An ApplicationConfigurationComponent specifies a component of an
// ApplicationConfiguration. Each component is used to instantiate a workload.
type ApplicationConfigurationComponent struct {
// ComponentName specifies a component whose latest revision will be bind
// with ApplicationConfiguration. When the spec of the referenced component
// changes, ApplicationConfiguration will automatically migrate all trait
// affect from the prior revision to the new one. This is mutually exclusive
// with RevisionName.
// +optional
ComponentName string `json:"componentName,omitempty"`
// RevisionName of a specific component revision to which to bind
// ApplicationConfiguration. This is mutually exclusive with componentName.
// +optional
RevisionName string `json:"revisionName,omitempty"`
// DataOutputs specify the data output sources from this component.
DataOutputs []DataOutput `json:"dataOutputs,omitempty"`
// DataInputs specify the data input sinks into this component.
DataInputs []DataInput `json:"dataInputs,omitempty"`
// ParameterValues specify values for the the specified component's
// parameters. Any parameter required by the component must be specified.
// +optional
ParameterValues []ComponentParameterValue `json:"parameterValues,omitempty"`
// Traits of the specified component.
// +optional
Traits []ComponentTrait `json:"traits,omitempty"`
// Scopes in which the specified component should exist.
// +optional
Scopes []ComponentScope `json:"scopes,omitempty"`
}
// An ApplicationConfigurationSpec defines the desired state of a
// ApplicationConfiguration.
type ApplicationConfigurationSpec struct {
// Components of which this ApplicationConfiguration consists. Each
// component will be used to instantiate a workload.
Components []ApplicationConfigurationComponent `json:"components"`
}
// A TraitStatus represents the state of a trait.
type TraitStatus string
// A WorkloadTrait represents a trait associated with a workload and its status
type WorkloadTrait struct {
// Status is a place holder for a customized controller to fill
// if it needs a single place to summarize the status of the trait
Status TraitStatus `json:"status,omitempty"`
// Reference to a trait created by an ApplicationConfiguration.
Reference corev1.ObjectReference `json:"traitRef"`
// Message will allow controller to leave some additional information for this trait
Message string `json:"message,omitempty"`
// AppliedGeneration indicates the generation observed by the appConfig controller.
// The same field is also recorded in the annotations of traits.
// A trait is possible to be deleted from cluster after created.
// This field is useful to track the observed generation of traits after they are
// deleted.
AppliedGeneration int64 `json:"appliedGeneration,omitempty"`
// DependencyUnsatisfied notify does the trait has dependency unsatisfied
DependencyUnsatisfied bool `json:"dependencyUnsatisfied,omitempty"`
}
// A ScopeStatus represents the state of a scope.
type ScopeStatus string
// A WorkloadScope represents a scope associated with a workload and its status
type WorkloadScope struct {
// Status is a place holder for a customized controller to fill
// if it needs a single place to summarize the status of the scope
Status ScopeStatus `json:"status,omitempty"`
// Reference to a scope created by an ApplicationConfiguration.
Reference corev1.ObjectReference `json:"scopeRef"`
}
// A WorkloadStatus represents the status of a workload.
type WorkloadStatus struct {
// Status is a place holder for a customized controller to fill
// if it needs a single place to summarize the entire status of the workload
Status string `json:"status,omitempty"`
// ComponentName that produced this workload.
ComponentName string `json:"componentName,omitempty"`
// ComponentRevisionName of current component
ComponentRevisionName string `json:"componentRevisionName,omitempty"`
// DependencyUnsatisfied notify does the workload has dependency unsatisfied
DependencyUnsatisfied bool `json:"dependencyUnsatisfied,omitempty"`
// AppliedComponentRevision indicates the applied component revision name of this workload
AppliedComponentRevision string `json:"appliedComponentRevision,omitempty"`
// Reference to a workload created by an ApplicationConfiguration.
Reference corev1.ObjectReference `json:"workloadRef,omitempty"`
// Traits associated with this workload.
Traits []WorkloadTrait `json:"traits,omitempty"`
// Scopes associated with this workload.
Scopes []WorkloadScope `json:"scopes,omitempty"`
}
// HistoryWorkload contain the old component revision that are still running
type HistoryWorkload struct {
// Revision of this workload
Revision string `json:"revision,omitempty"`
// Reference to running workload.
Reference corev1.ObjectReference `json:"workloadRef,omitempty"`
}
// A ApplicationStatus represents the state of the entire application.
type ApplicationStatus string
// An ApplicationConfigurationStatus represents the observed state of a
// ApplicationConfiguration.
type ApplicationConfigurationStatus struct {
condition.ConditionedStatus `json:",inline"`
// Status is a place holder for a customized controller to fill
// if it needs a single place to summarize the status of the entire application
Status ApplicationStatus `json:"status,omitempty"`
Dependency DependencyStatus `json:"dependency,omitempty"`
// RollingStatus indicates what phase are we in the rollout phase
RollingStatus types.RollingStatus `json:"rollingStatus,omitempty"`
// Workloads created by this ApplicationConfiguration.
Workloads []WorkloadStatus `json:"workloads,omitempty"`
// The generation observed by the appConfig controller.
// +optional
ObservedGeneration int64 `json:"observedGeneration"`
// HistoryWorkloads will record history but still working revision workloads.
HistoryWorkloads []HistoryWorkload `json:"historyWorkloads,omitempty"`
}
// DependencyStatus represents the observed state of the dependency of
// an ApplicationConfiguration.
type DependencyStatus struct {
Unsatisfied []UnstaifiedDependency `json:"unsatisfied,omitempty"`
}
// UnstaifiedDependency describes unsatisfied dependency flow between
// one pair of objects.
type UnstaifiedDependency struct {
Reason string `json:"reason"`
From DependencyFromObject `json:"from"`
To DependencyToObject `json:"to"`
}
// DependencyFromObject represents the object that dependency data comes from.
type DependencyFromObject struct {
corev1.ObjectReference `json:",inline"`
FieldPath string `json:"fieldPath,omitempty"`
}
// DependencyToObject represents the object that dependency data goes to.
type DependencyToObject struct {
corev1.ObjectReference `json:",inline"`
FieldPaths []string `json:"fieldPaths,omitempty"`
}
// +kubebuilder:object:root=true
// An ApplicationConfiguration represents an OAM application.
// +kubebuilder:resource:shortName=appconfig,categories={oam}
// +kubebuilder:subresource:status
type ApplicationConfiguration struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec ApplicationConfigurationSpec `json:"spec,omitempty"`
Status ApplicationConfigurationStatus `json:"status,omitempty"`
}
// +kubebuilder:object:root=true
// ApplicationConfigurationList contains a list of ApplicationConfiguration.
type ApplicationConfigurationList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []ApplicationConfiguration `json:"items"`
}
// DataOutput specifies a data output source from an object.
type DataOutput struct {
// Name is the unique name of a DataOutput in an ApplicationConfiguration.
Name string `json:"name,omitempty"`
// FieldPath refers to the value of an object's field.
FieldPath string `json:"fieldPath,omitempty"`
// Conditions specify the conditions that should be satisfied before emitting a data output.
// Different conditions are AND-ed together.
// If no conditions is specified, it is by default to check output value not empty.
// +optional
Conditions []ConditionRequirement `json:"conditions,omitempty"`
// OutputStore specifies the object used to store intermediate data generated by Operations
OutputStore StoreReference `json:"outputStore,omitempty"`
}
// StoreReference specifies the referenced object in DataOutput or DataInput
type StoreReference struct {
corev1.ObjectReference `json:",inline"`
// Operations specify the data processing operations
Operations []DataOperation `json:"operations,omitempty"`
}
// DataOperation defines the specific operation for data
type DataOperation struct {
// Type specifies the type of DataOperation
Type string `json:"type"`
// Operator specifies the operation under this DataOperation type
Operator DataOperator `json:"op"`
// ToFieldPath refers to the value of an object's field
ToFieldPath string `json:"toFieldPath"`
// ToDataPath refers to the value of an object's specfied by ToDataPath. For example the ToDataPath "redis" specifies "redis info" in '{"redis":"redis info"}'
ToDataPath string `json:"toDataPath,omitempty"`
// +optional
// Value specifies an expected value
// This is mutually exclusive with ValueFrom
Value string `json:"value,omitempty"`
// +optional
// ValueFrom specifies expected value from object such as workload and trait
// This is mutually exclusive with Value
ValueFrom ValueFrom `json:"valueFrom,omitempty"`
Conditions []ConditionRequirement `json:"conditions,omitempty"`
}
// DataOperator defines the type of Operator in DataOperation
type DataOperator string
const (
// AddOperator specifies the add operation for data passing
AddOperator DataOperator = "add"
// DeleteOperator specifies the delete operation for data passing
DeleteOperator DataOperator = "delete"
// ReplaceOperator specifies the replace operation for data passing
ReplaceOperator DataOperator = "replace"
)
// DataInput specifies a data input sink to an object.
// If input is array, it will be appended to the target field paths.
type DataInput struct {
// ValueFrom specifies the value source.
ValueFrom DataInputValueFrom `json:"valueFrom,omitempty"`
// ToFieldPaths specifies the field paths of an object to fill passed value.
ToFieldPaths []string `json:"toFieldPaths,omitempty"`
// StrategyMergeKeys specifies the merge key if the toFieldPaths target is an array.
// The StrategyMergeKeys is optional, by default, if the toFieldPaths target is an array, we will append.
// If StrategyMergeKeys specified, we will check the key in the target array.
// If any key exist, do update; if no key exist, append.
StrategyMergeKeys []string `json:"strategyMergeKeys,omitempty"`
// When the Conditions is satified, ToFieldPaths will be filled with passed value
Conditions []ConditionRequirement `json:"conditions,omitempty"`
// InputStore specifies the object used to read intermediate data genereted by DataOutput
InputStore StoreReference `json:"inputStore,omitempty"`
}
// DataInputValueFrom specifies the value source for a data input.
type DataInputValueFrom struct {
// DataOutputName matches a name of a DataOutput in the same AppConfig.
DataOutputName string `json:"dataOutputName"`
}
// ConditionRequirement specifies the requirement to match a value.
type ConditionRequirement struct {
Operator ConditionOperator `json:"op"`
// +optional
// Value specifies an expected value
// This is mutually exclusive with ValueFrom
Value string `json:"value,omitempty"`
// +optional
// ValueFrom specifies expected value from AppConfig
// This is mutually exclusive with Value
ValueFrom ValueFrom `json:"valueFrom,omitempty"`
// +optional
// FieldPath specifies got value from workload/trait object
FieldPath string `json:"fieldPath,omitempty"`
}
// ValueFrom gets value from AppConfig object by specifying a path
type ValueFrom struct {
FieldPath string `json:"fieldPath"`
}
// ConditionOperator specifies the operator to match a value.
type ConditionOperator string
const (
// ConditionEqual indicates equal to given value
ConditionEqual ConditionOperator = "eq"
// ConditionNotEqual indicates not equal to given value
ConditionNotEqual ConditionOperator = "notEq"
// ConditionNotEmpty indicates given value not empty
ConditionNotEmpty ConditionOperator = "notEmpty"
)

View File

@@ -1,355 +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 v1alpha2
package v1alpha2
import (
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/util/intstr"
)
// An OperatingSystem required by a containerised workload.
type OperatingSystem string
// Supported operating system types.
const (
OperatingSystemLinux OperatingSystem = "linux"
OperatingSystemWindows OperatingSystem = "windows"
)
// A CPUArchitecture required by a containerised workload.
type CPUArchitecture string
// Supported architectures
const (
CPUArchitectureI386 CPUArchitecture = "i386"
CPUArchitectureAMD64 CPUArchitecture = "amd64"
CPUArchitectureARM CPUArchitecture = "arm"
CPUArchitectureARM64 CPUArchitecture = "arm64"
)
// A SecretKeySelector is a reference to a secret key in an arbitrary namespace.
type SecretKeySelector struct {
// The name of the secret.
Name string `json:"name"`
// The key to select.
Key string `json:"key"`
}
// TODO(negz): The OAM spec calls for float64 quantities in some cases, but this
// is incompatible with controller-gen and Kubernetes API conventions. We should
// reassess whether resource.Quantity is appropriate after resolving
// https://github.com/oam-dev/spec/issues/313
// CPUResources required by a container.
type CPUResources struct {
// Required CPU count. 1.0 represents one CPU core.
Required resource.Quantity `json:"required"`
}
// MemoryResources required by a container.
type MemoryResources struct {
// Required memory.
Required resource.Quantity `json:"required"`
}
// GPUResources required by a container.
type GPUResources struct {
// Required GPU count.
Required resource.Quantity `json:"required"`
}
// DiskResource required by a container.
type DiskResource struct {
// Required disk space.
Required resource.Quantity `json:"required"`
// Ephemeral specifies whether an external disk needs to be mounted.
// +optional
Ephemeral *bool `json:"ephemeral,omitempty"`
}
// A VolumeAccessMode determines how a volume may be accessed.
type VolumeAccessMode string
// Volume access modes.
const (
VolumeAccessModeRO VolumeAccessMode = "RO"
VolumeAccessModeRW VolumeAccessMode = "RW"
)
// A VolumeSharingPolicy determines how a volume may be shared.
type VolumeSharingPolicy string
// Volume sharing policies.
const (
VolumeSharingPolicyExclusive VolumeSharingPolicy = "Exclusive"
VolumeSharingPolicyShared VolumeSharingPolicy = "Shared"
)
// VolumeResource required by a container.
type VolumeResource struct {
// Name of this volume. Must be unique within its container.
Name string `json:"name"`
// MountPath at which this volume will be mounted within its container.
MountPath string `json:"mountPath"`
// TODO(negz): Use +kubebuilder:default marker to default AccessMode to RW
// and SharingPolicy to Exclusive once we're generating v1 CRDs.
// AccessMode of this volume; RO (read only) or RW (read and write).
// +optional
// +kubebuilder:validation:Enum=RO;RW
AccessMode *VolumeAccessMode `json:"accessMode,omitempty"`
// SharingPolicy of this volume; Exclusive or Shared.
// +optional
// +kubebuilder:validation:Enum=Exclusive;Shared
SharingPolicy *VolumeSharingPolicy `json:"sharingPolicy,omitempty"`
// Disk requirements of this volume.
// +optional
Disk *DiskResource `json:"disk,omitempty"`
}
// ExtendedResource required by a container.
type ExtendedResource struct {
// Name of the external resource. Resource names are specified in
// kind.group/version format, e.g. motionsensor.ext.example.com/v1.
Name string `json:"name"`
// Required extended resource(s), e.g. 8 or "very-cool-widget"
Required intstr.IntOrString `json:"required"`
}
// ContainerResources specifies a container's required compute resources.
type ContainerResources struct {
// CPU required by this container.
CPU CPUResources `json:"cpu"`
// Memory required by this container.
Memory MemoryResources `json:"memory"`
// GPU required by this container.
// +optional
GPU *GPUResources `json:"gpu,omitempty"`
// Volumes required by this container.
// +optional
Volumes []VolumeResource `json:"volumes,omitempty"`
// Extended resources required by this container.
// +optional
Extended []ExtendedResource `json:"extended,omitempty"`
}
// A ContainerEnvVar specifies an environment variable that should be set within
// a container.
type ContainerEnvVar struct {
// Name of the environment variable. Must be composed of valid Unicode
// letter and number characters, as well as _ and -.
// +kubebuilder:validation:Pattern=^[-_a-zA-Z0-9]+$
Name string `json:"name"`
// Value of the environment variable.
// +optional
Value *string `json:"value,omitempty"`
// FromSecret is a secret key reference which can be used to assign a value
// to the environment variable.
// +optional
FromSecret *SecretKeySelector `json:"fromSecret,omitempty"`
}
// A ContainerConfigFile specifies a configuration file that should be written
// within a container.
type ContainerConfigFile struct {
// Path within the container at which the configuration file should be
// written.
Path string `json:"path"`
// Value that should be written to the configuration file.
// +optional
Value *string `json:"value,omitempty"`
// FromSecret is a secret key reference which can be used to assign a value
// to be written to the configuration file at the given path in the
// container.
// +optional
FromSecret *SecretKeySelector `json:"fromSecret,omitempty"`
}
// A TransportProtocol represents a transport layer protocol.
type TransportProtocol string
// Transport protocols.
const (
TransportProtocolTCP TransportProtocol = "TCP"
TransportProtocolUDP TransportProtocol = "UDP"
)
// A ContainerPort specifies a port that is exposed by a container.
type ContainerPort struct {
// Name of this port. Must be unique within its container. Must be lowercase
// alphabetical characters.
// +kubebuilder:validation:Pattern=^[a-z]+$
Name string `json:"name"`
// Port number. Must be unique within its container.
Port int32 `json:"containerPort"`
// TODO(negz): Use +kubebuilder:default marker to default Protocol to TCP
// once we're generating v1 CRDs.
// Protocol used by the server listening on this port.
// +kubebuilder:validation:Enum=TCP;UDP
// +optional
Protocol *TransportProtocol `json:"protocol,omitempty"`
}
// An ExecProbe probes a container's health by executing a command.
type ExecProbe struct {
// Command to be run by this probe.
Command []string `json:"command"`
}
// A HTTPHeader to be passed when probing a container.
type HTTPHeader struct {
// Name of this HTTP header. Must be unique per probe.
Name string `json:"name"`
// Value of this HTTP header.
Value string `json:"value"`
}
// A HTTPGetProbe probes a container's health by sending an HTTP GET request.
type HTTPGetProbe struct {
// Path to probe, e.g. '/healthz'.
Path string `json:"path"`
// Port to probe.
Port int32 `json:"port"`
// HTTPHeaders to send with the GET request.
// +optional
HTTPHeaders []HTTPHeader `json:"httpHeaders,omitempty"`
}
// A TCPSocketProbe probes a container's health by connecting to a TCP socket.
type TCPSocketProbe struct {
// Port this probe should connect to.
Port int32 `json:"port"`
}
// A ContainerHealthProbe specifies how to probe the health of a container.
// Exactly one of Exec, HTTPGet, or TCPSocket must be specified.
type ContainerHealthProbe struct {
// Exec probes a container's health by executing a command.
// +optional
Exec *ExecProbe `json:"exec,omitempty"`
// HTTPGet probes a container's health by sending an HTTP GET request.
// +optional
HTTPGet *HTTPGetProbe `json:"httpGet,omitempty"`
// TCPSocketProbe probes a container's health by connecting to a TCP socket.
// +optional
TCPSocket *TCPSocketProbe `json:"tcpSocket,omitempty"`
// InitialDelaySeconds after a container starts before the first probe.
// +optional
InitialDelaySeconds *int32 `json:"initialDelaySeconds,omitempty"`
// TODO(negz): Use +kubebuilder:default marker to default PeriodSeconds,
// TimeoutSeconds, SuccessThreshold, and FailureThreshold to 10, 1, 1, and 3
// respectively once we're generating v1 CRDs.
// PeriodSeconds between probes.
// +optional
PeriodSeconds *int32 `json:"periodSeconds,omitempty"`
// TimeoutSeconds after which the probe times out.
// +optional
TimeoutSeconds *int32 `json:"timeoutSeconds,omitempty"`
// SuccessThreshold specifies how many consecutive probes must success in
// order for the container to be considered healthy.
// +optional
SuccessThreshold *int32 `json:"successThreshold,omitempty"`
// FailureThreshold specifies how many consecutive probes must fail in order
// for the container to be considered healthy.
// +optional
FailureThreshold *int32 `json:"failureThreshold,omitempty"`
}
// A Container represents an Open Containers Initiative (OCI) container.
type Container struct {
// Name of this container. Must be unique within its workload.
Name string `json:"name"`
// Image this container should run. Must be a path-like or URI-like
// representation of an OCI image. May be prefixed with a registry address
// and should be suffixed with a tag.
Image string `json:"image"`
// Resources required by this container
// +optional
Resources *ContainerResources `json:"resources,omitempty"`
// Command to be run by this container.
// +optional
Command []string `json:"command,omitempty"`
// Arguments to be passed to the command run by this container.
// +optional
Arguments []string `json:"args,omitempty"`
// Environment variables that should be set within this container.
// +optional
Environment []ContainerEnvVar `json:"env,omitempty"`
// ConfigFiles that should be written within this container.
// +optional
ConfigFiles []ContainerConfigFile `json:"config,omitempty"`
// Ports exposed by this container.
// +optional
Ports []ContainerPort `json:"ports,omitempty"`
// A LivenessProbe assesses whether this container is alive. Containers that
// fail liveness probes will be restarted.
// +optional
LivenessProbe *ContainerHealthProbe `json:"livenessProbe,omitempty"`
// A ReadinessProbe assesses whether this container is ready to serve
// requests. Containers that fail readiness probes will be withdrawn from
// service.
// +optional
ReadinessProbe *ContainerHealthProbe `json:"readinessProbe,omitempty"`
// TODO(negz): Ideally the key within this secret would be configurable, but
// the current OAM spec allows only a secret name.
// ImagePullSecret specifies the name of a Secret from which the
// credentials required to pull this container's image can be loaded.
// +optional
ImagePullSecret *string `json:"imagePullSecret,omitempty"`
}

View File

@@ -1,22 +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 v1alpha2 contains resources relating to the Open Application Model.
// See https://github.com/oam-dev/spec for more details.
// +kubebuilder:object:generate=true
// +groupName=core.oam.dev
// +versionName=v1alpha2
package v1alpha2

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.
*/
// This code is manually implemented, but should be generated in the future.
package v1alpha2
import (
corev1 "k8s.io/api/core/v1"
"github.com/oam-dev/kubevela/apis/core.oam.dev/condition"
)
// GetCondition of this ApplicationConfiguration.
func (ac *ApplicationConfiguration) GetCondition(ct condition.ConditionType) condition.Condition {
return ac.Status.GetCondition(ct)
}
// SetConditions of this ApplicationConfiguration.
func (ac *ApplicationConfiguration) SetConditions(c ...condition.Condition) {
ac.Status.SetConditions(c...)
}
// GetCondition of this Component.
func (cm *Component) GetCondition(ct condition.ConditionType) condition.Condition {
return cm.Status.GetCondition(ct)
}
// SetConditions of this Component.
func (cm *Component) SetConditions(c ...condition.Condition) {
cm.Status.SetConditions(c...)
}
// GetCondition of this HealthScope.
func (hs *HealthScope) GetCondition(ct condition.ConditionType) condition.Condition {
return hs.Status.GetCondition(ct)
}
// SetConditions of this HealthScope.
func (hs *HealthScope) SetConditions(c ...condition.Condition) {
hs.Status.SetConditions(c...)
}
// GetWorkloadReferences to get all workload references for scope.
func (hs *HealthScope) GetWorkloadReferences() []corev1.ObjectReference {
return hs.Spec.WorkloadReferences
}
// AddWorkloadReference to add a workload reference to this scope.
func (hs *HealthScope) AddWorkloadReference(r corev1.ObjectReference) {
hs.Spec.WorkloadReferences = append(hs.Spec.WorkloadReferences, r)
}

View File

@@ -1,124 +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 v1alpha2
import (
"reflect"
"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/controller-runtime/pkg/scheme"
"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
)
// Package type metadata.
const (
Group = common.Group
Version = "v1alpha2"
)
var (
// SchemeGroupVersion is group version used to register these objects
SchemeGroupVersion = schema.GroupVersion{Group: Group, Version: Version}
// SchemeBuilder is used to add go types to the GroupVersionKind scheme
SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion}
)
// ComponentDefinition type metadata.
var (
ComponentDefinitionKind = reflect.TypeOf(ComponentDefinition{}).Name()
ComponentDefinitionGroupKind = schema.GroupKind{Group: Group, Kind: ComponentDefinitionKind}.String()
ComponentDefinitionKindAPIVersion = ComponentDefinitionKind + "." + SchemeGroupVersion.String()
ComponentDefinitionGroupVersionKind = SchemeGroupVersion.WithKind(ComponentDefinitionKind)
)
// WorkloadDefinition type metadata.
var (
WorkloadDefinitionKind = reflect.TypeOf(WorkloadDefinition{}).Name()
WorkloadDefinitionGroupKind = schema.GroupKind{Group: Group, Kind: WorkloadDefinitionKind}.String()
WorkloadDefinitionKindAPIVersion = WorkloadDefinitionKind + "." + SchemeGroupVersion.String()
WorkloadDefinitionGroupVersionKind = SchemeGroupVersion.WithKind(WorkloadDefinitionKind)
)
// TraitDefinition type metadata.
var (
TraitDefinitionKind = reflect.TypeOf(TraitDefinition{}).Name()
TraitDefinitionGroupKind = schema.GroupKind{Group: Group, Kind: TraitDefinitionKind}.String()
TraitDefinitionKindAPIVersion = TraitDefinitionKind + "." + SchemeGroupVersion.String()
TraitDefinitionGroupVersionKind = SchemeGroupVersion.WithKind(TraitDefinitionKind)
)
// ScopeDefinition type metadata.
var (
ScopeDefinitionKind = reflect.TypeOf(ScopeDefinition{}).Name()
ScopeDefinitionGroupKind = schema.GroupKind{Group: Group, Kind: ScopeDefinitionKind}.String()
ScopeDefinitionKindAPIVersion = ScopeDefinitionKind + "." + SchemeGroupVersion.String()
ScopeDefinitionGroupVersionKind = SchemeGroupVersion.WithKind(ScopeDefinitionKind)
)
// Component type metadata.
var (
ComponentKind = reflect.TypeOf(Component{}).Name()
ComponentGroupKind = schema.GroupKind{Group: Group, Kind: ComponentKind}.String()
ComponentKindAPIVersion = ComponentKind + "." + SchemeGroupVersion.String()
ComponentGroupVersionKind = SchemeGroupVersion.WithKind(ComponentKind)
)
// ApplicationConfiguration type metadata.
var (
ApplicationConfigurationKind = reflect.TypeOf(ApplicationConfiguration{}).Name()
ApplicationConfigurationGroupKind = schema.GroupKind{Group: Group, Kind: ApplicationConfigurationKind}.String()
ApplicationConfigurationKindAPIVersion = ApplicationConfigurationKind + "." + SchemeGroupVersion.String()
ApplicationConfigurationGroupVersionKind = SchemeGroupVersion.WithKind(ApplicationConfigurationKind)
)
// HealthScope type metadata.
var (
HealthScopeKind = reflect.TypeOf(HealthScope{}).Name()
HealthScopeGroupKind = schema.GroupKind{Group: Group, Kind: HealthScopeKind}.String()
HealthScopeKindAPIVersion = HealthScopeKind + "." + SchemeGroupVersion.String()
HealthScopeGroupVersionKind = SchemeGroupVersion.WithKind(HealthScopeKind)
)
// Application type metadata.
var (
ApplicationKind = reflect.TypeOf(Application{}).Name()
ApplicationGroupKind = schema.GroupKind{Group: Group, Kind: ApplicationKind}.String()
ApplicationKindAPIVersion = ApplicationKind + "." + SchemeGroupVersion.String()
ApplicationKindVersionKind = SchemeGroupVersion.WithKind(ApplicationKind)
)
// ApplicationRevision type metadata
var (
ApplicationRevisionKind = reflect.TypeOf(ApplicationRevision{}).Name()
ApplicationRevisionGroupKind = schema.GroupKind{Group: Group, Kind: ApplicationRevisionKind}.String()
ApplicationRevisionKindAPIVersion = ApplicationRevisionKind + "." + SchemeGroupVersion.String()
ApplicationRevisionGroupVersionKind = SchemeGroupVersion.WithKind(ApplicationRevisionKind)
)
func init() {
SchemeBuilder.Register(&ComponentDefinition{}, &ComponentDefinitionList{})
SchemeBuilder.Register(&WorkloadDefinition{}, &WorkloadDefinitionList{})
SchemeBuilder.Register(&TraitDefinition{}, &TraitDefinitionList{})
SchemeBuilder.Register(&ScopeDefinition{}, &ScopeDefinitionList{})
SchemeBuilder.Register(&Component{}, &ComponentList{})
SchemeBuilder.Register(&ApplicationConfiguration{}, &ApplicationConfigurationList{})
SchemeBuilder.Register(&HealthScope{}, &HealthScopeList{})
SchemeBuilder.Register(&Application{}, &ApplicationList{})
SchemeBuilder.Register(&ApplicationRevision{}, &ApplicationRevisionList{})
}

File diff suppressed because it is too large Load Diff

View File

@@ -205,7 +205,6 @@ func TestResourceTrackerCompression(t *testing.T) {
"../../../charts/vela-core/templates/kubevela-controller.yaml",
"../../../charts/vela-core/README.md",
"../../../pkg/velaql/providers/query/testdata/machinelearning.seldon.io_seldondeployments.yaml",
"../../../legacy/charts/vela-core-legacy/crds/standard.oam.dev_podspecworkloads.yaml",
}
for _, p := range paths {
b, err := os.ReadFile(p)

View File

@@ -25,10 +25,6 @@ limitations under the License.
// Generate deepcopy methodsets and CRD manifests
//go:generate go run -tags generate sigs.k8s.io/controller-tools/cmd/controller-gen object:headerFile=../hack/boilerplate.go.txt paths=./... crd:crdVersions=v1,generateEmbeddedObjectMeta=true output:artifacts:config=../config/crd/base
// Generate legacy_support for K8s 1.12~1.15 versions CRD manifests
//go:generate go run -tags generate sigs.k8s.io/controller-tools/cmd/controller-gen object:headerFile=../hack/boilerplate.go.txt paths=./... crd:generateEmbeddedObjectMeta=true output:artifacts:config=../legacy/charts/vela-core-legacy/crds
//go:generate go run ../legacy/convert/main.go ../legacy/charts/vela-core-legacy/crds
package apis
import (

File diff suppressed because it is too large Load Diff

View File

@@ -19,868 +19,6 @@ spec:
singular: application
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .spec.components[*].name
name: COMPONENT
type: string
- jsonPath: .spec.components[*].type
name: TYPE
type: string
- jsonPath: .status.status
name: PHASE
type: string
- jsonPath: .status.services[*].healthy
name: HEALTHY
type: boolean
- jsonPath: .status.services[*].message
name: STATUS
type: string
- jsonPath: .metadata.creationTimestamp
name: AGE
type: date
name: v1alpha2
schema:
openAPIV3Schema:
description: Application is the Schema for the applications 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: ApplicationSpec is the spec of Application
properties:
components:
items:
description: ApplicationComponent describe the component of application
properties:
name:
type: string
scopes:
additionalProperties:
type: string
description: scopes in ApplicationComponent defines the component-level
scopes the format is <scope-type:scope-instance-name> pairs,
the key represents type of `ScopeDefinition` while the value
represent the name of scope instance.
type: object
x-kubernetes-preserve-unknown-fields: true
settings:
type: object
x-kubernetes-preserve-unknown-fields: true
traits:
description: Traits define the trait of one component, the type
must be array to keep the order.
items:
description: ApplicationTrait defines the trait of application
properties:
name:
type: string
properties:
type: object
x-kubernetes-preserve-unknown-fields: true
required:
- name
type: object
type: array
type:
type: string
required:
- name
- type
type: object
type: array
rolloutPlan:
description: RolloutPlan is the details on how to rollout the resources
The controller simply replace the old resources with the new one
if there is no rollout plan involved
properties:
batchPartition:
description: All pods in the batches up to the batchPartition
(included) will have the target resource specification while
the rest still have the source resource This is designed for
the operators to manually rollout Default is the the number
of batches which will rollout all the batches
format: int32
type: integer
canaryMetric:
description: CanaryMetric provides a way for the rollout process
to automatically check certain metrics before complete the process
items:
description: CanaryMetric holds the reference to metrics used
for canary analysis
properties:
interval:
description: Interval represents the windows size
type: string
metricsRange:
description: Range value accepted for this metric
properties:
max:
anyOf:
- type: integer
- type: string
description: Maximum value
x-kubernetes-int-or-string: true
min:
anyOf:
- type: integer
- type: string
description: Minimum value
x-kubernetes-int-or-string: true
type: object
name:
description: Name of the metric
type: string
templateRef:
description: TemplateRef references a metric template object
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
x-kubernetes-map-type: atomic
required:
- name
type: object
type: array
numBatches:
description: The number of batches, default = 1
format: int32
type: integer
paused:
description: Paused the rollout, default is false
type: boolean
rolloutBatches:
description: The exact distribution among batches. its size has
to be exactly the same as the NumBatches (if set) The total
number cannot exceed the targetSize or the size of the source
resource We will IGNORE the last batch's replica field if it's
a percentage since round errors can lead to inaccurate sum We
highly recommend to leave the last batch's replica field empty
items:
description: RolloutBatch is used to describe how the each batch
rollout should be
properties:
batchRolloutWebhooks:
description: RolloutWebhooks provides a way for the batch
rollout to interact with an external process
items:
description: RolloutWebhook holds the reference to external
checks used for canary analysis
properties:
expectedStatus:
description: ExpectedStatus contains all the expected
http status code that we will accept as success
items:
type: integer
type: array
metadata:
additionalProperties:
type: string
description: Metadata (key-value pairs) for this webhook
type: object
method:
description: Method the HTTP call method, default
is POST
type: string
name:
description: Name of this webhook
type: string
type:
description: Type of this webhook
type: string
url:
description: URL address of this webhook
type: string
required:
- name
- type
- url
type: object
type: array
canaryMetric:
description: CanaryMetric provides a way for the batch rollout
process to automatically check certain metrics before
moving to the next batch
items:
description: CanaryMetric holds the reference to metrics
used for canary analysis
properties:
interval:
description: Interval represents the windows size
type: string
metricsRange:
description: Range value accepted for this metric
properties:
max:
anyOf:
- type: integer
- type: string
description: Maximum value
x-kubernetes-int-or-string: true
min:
anyOf:
- type: integer
- type: string
description: Minimum value
x-kubernetes-int-or-string: true
type: object
name:
description: Name of the metric
type: string
templateRef:
description: TemplateRef references a metric template
object
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
x-kubernetes-map-type: atomic
required:
- name
type: object
type: array
instanceInterval:
description: The wait time, in seconds, between instances
upgrades, default = 0
format: int32
type: integer
maxUnavailable:
anyOf:
- type: integer
- type: string
description: MaxUnavailable is the max allowed number of
pods that is unavailable during the upgrade. We will mark
the batch as ready as long as there are less or equal
number of pods unavailable than this number. default =
0
x-kubernetes-int-or-string: true
podList:
description: The list of Pods to get upgraded it is mutually
exclusive with the Replicas field
items:
type: string
type: array
replicas:
anyOf:
- type: integer
- type: string
description: 'Replicas is the number of pods to upgrade
in this batch it can be an absolute number (ex: 5) or
a percentage of total pods we will ignore the percentage
of the last batch to just fill the gap it is mutually
exclusive with the PodList field'
x-kubernetes-int-or-string: true
type: object
type: array
rolloutStrategy:
description: RolloutStrategy defines strategies for the rollout
plan The default is IncreaseFirstRolloutStrategyType
type: string
rolloutWebhooks:
description: RolloutWebhooks provide a way for the rollout to
interact with an external process
items:
description: RolloutWebhook holds the reference to external
checks used for canary analysis
properties:
expectedStatus:
description: ExpectedStatus contains all the expected http
status code that we will accept as success
items:
type: integer
type: array
metadata:
additionalProperties:
type: string
description: Metadata (key-value pairs) for this webhook
type: object
method:
description: Method the HTTP call method, default is POST
type: string
name:
description: Name of this webhook
type: string
type:
description: Type of this webhook
type: string
url:
description: URL address of this webhook
type: string
required:
- name
- type
- url
type: object
type: array
targetSize:
description: The size of the target resource. The default is the
same as the size of the source resource.
format: int32
type: integer
type: object
required:
- components
type: object
status:
description: AppStatus defines the observed state of Application
properties:
appliedResources:
description: AppliedResources record the resources that the workflow
step apply.
items:
description: ClusterObjectReference defines the object reference
with cluster.
properties:
apiVersion:
description: API version of the referent.
type: string
cluster:
type: string
creator:
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
x-kubernetes-map-type: atomic
type: array
components:
description: Components record the related Components created by Application
Controller
items:
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. \n 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
x-kubernetes-map-type: atomic
type: array
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
latestRevision:
description: LatestRevision of the application configuration it generates
properties:
name:
type: string
revision:
format: int64
type: integer
revisionHash:
description: RevisionHash record the hash value of the spec of
ApplicationRevision object.
type: string
required:
- name
- revision
type: object
observedGeneration:
description: The generation observed by the application controller.
format: int64
type: integer
policy:
description: PolicyStatus records the status of policy Deprecated
This field is only used by EnvBinding Policy which is deprecated.
items:
description: PolicyStatus records the status of policy Deprecated
properties:
name:
type: string
status:
type: object
x-kubernetes-preserve-unknown-fields: true
type:
type: string
required:
- name
- type
type: object
type: array
services:
description: Services record the status of the application services
items:
description: ApplicationComponentStatus record the health status
of App component
properties:
cluster:
type: string
env:
type: string
healthy:
type: boolean
message:
type: string
name:
type: string
namespace:
type: string
scopes:
items:
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. \n
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
x-kubernetes-map-type: atomic
type: array
traits:
items:
description: ApplicationTraitStatus records the trait health
status
properties:
healthy:
type: boolean
message:
type: string
type:
type: string
required:
- healthy
- type
type: object
type: array
workloadDefinition:
description: WorkloadDefinition is the definition of a WorkloadDefinition,
such as deployments/apps.v1
properties:
apiVersion:
type: string
kind:
type: string
required:
- apiVersion
- kind
type: object
required:
- healthy
- name
type: object
type: array
status:
description: ApplicationPhase is a label for the condition of an application
at the current time
type: string
workflow:
description: Workflow record the status of workflow
properties:
appRevision:
type: string
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. \n 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
x-kubernetes-map-type: atomic
endTime:
format: date-time
nullable: true
type: string
finished:
type: boolean
message:
type: string
mode:
type: string
startTime:
format: date-time
type: string
status:
description: WorkflowRunPhase is a label for the condition of
a WorkflowRun at the current time
type: string
steps:
items:
description: WorkflowStepStatus record the status of a workflow
step, include step status and subStep status
properties:
firstExecuteTime:
description: FirstExecuteTime is the first time this step
execution.
format: date-time
type: string
id:
type: string
lastExecuteTime:
description: LastExecuteTime is the last time this step
execution.
format: date-time
type: string
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
subSteps:
items:
description: StepStatus record the base status of workflow
step, which could be workflow step or subStep
properties:
firstExecuteTime:
description: FirstExecuteTime is the first time this
step execution.
format: date-time
type: string
id:
type: string
lastExecuteTime:
description: LastExecuteTime is the last time this
step execution.
format: date-time
type: string
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
type:
type: string
required:
- id
type: object
type: array
type:
type: string
required:
- id
type: object
type: array
suspend:
type: boolean
suspendState:
type: string
terminated:
type: boolean
required:
- finished
- mode
- suspend
- terminated
type: object
type: object
type: object
served: true
storage: false
subresources:
status: {}
- additionalPrinterColumns:
- jsonPath: .spec.components[*].name
name: COMPONENT

View File

@@ -18,333 +18,6 @@ spec:
singular: componentdefinition
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .spec.workload.definition.kind
name: WORKLOAD-KIND
type: string
- jsonPath: .metadata.annotations.definition\.oam\.dev/description
name: DESCRIPTION
type: string
name: v1alpha2
schema:
openAPIV3Schema:
description: ComponentDefinition is the Schema for the componentdefinitions
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: ComponentDefinitionSpec defines the desired state of ComponentDefinition
properties:
childResourceKinds:
description: ChildResourceKinds are the list of GVK of the child resources
this workload generates
items:
description: A ChildResourceKind defines a child Kubernetes resource
kind with a selector
properties:
apiVersion:
description: APIVersion of the child resource
type: string
kind:
description: Kind of the child resource
type: string
selector:
additionalProperties:
type: string
description: Selector to select the child resources that the
workload wants to expose to traits
type: object
required:
- apiVersion
- kind
type: object
type: array
extension:
description: Extension is used for extension needs by OAM platform
builders
type: object
x-kubernetes-preserve-unknown-fields: true
podSpecPath:
description: PodSpecPath indicates where/if this workload has K8s
podSpec field if one workload has podSpec, trait can do lot's of
assumption such as port, env, volume fields.
type: string
revisionLabel:
description: RevisionLabel indicates which label for underlying resources(e.g.
pods) of this workload can be used by trait to create resource selectors(e.g.
label selector for pods).
type: string
schematic:
description: Schematic defines the data format and template of the
encapsulation of the workload
properties:
cue:
description: CUE defines the encapsulation in CUE format
properties:
template:
description: Template defines the abstraction template data
of the capability, it will replace the old CUE template
in extension field. Template is a required field if CUE
is defined in Capability Definition.
type: string
required:
- template
type: object
helm:
description: A Helm represents resources used by a Helm module
properties:
release:
description: Release records a Helm release used by a Helm
module workload.
type: object
x-kubernetes-preserve-unknown-fields: true
repository:
description: HelmRelease records a Helm repository used by
a Helm module workload.
type: object
x-kubernetes-preserve-unknown-fields: true
required:
- release
- repository
type: object
kube:
description: Kube defines the encapsulation in raw Kubernetes
resource format
properties:
parameters:
description: Parameters defines configurable parameters
items:
description: A KubeParameter defines a configurable parameter
of a component.
properties:
description:
description: Description of this parameter.
type: string
fieldPaths:
description: "FieldPaths specifies an array of fields
within this workload that will be overwritten by the
value of this parameter. \tAll fields must be of the
same type. Fields are specified as JSON field paths
without a leading dot, for example 'spec.replicas'."
items:
type: string
type: array
name:
description: Name of this parameter
type: string
required:
default: false
description: Required specifies whether or not a value
for this parameter must be supplied when authoring
an Application.
type: boolean
type:
description: 'ValueType indicates the type of the parameter
value, and only supports basic data types: string,
number, boolean.'
enum:
- string
- number
- boolean
type: string
required:
- fieldPaths
- name
- type
type: object
type: array
template:
description: Template defines the raw Kubernetes resource
type: object
x-kubernetes-preserve-unknown-fields: true
required:
- template
type: object
terraform:
description: Terraform is the struct to describe cloud resources
managed by Hashicorp Terraform
properties:
configuration:
description: Configuration is Terraform Configuration
type: string
customRegion:
description: Region is cloud provider's region. It will override
the region in the region field of ProviderReference
type: string
deleteResource:
default: true
description: DeleteResource will determine whether provisioned
cloud resources will be deleted when CR is deleted
type: boolean
gitCredentialsSecretReference:
description: GitCredentialsSecretReference specifies the reference
to the secret containing the git credentials
properties:
name:
description: name is unique within a namespace to reference
a secret resource.
type: string
namespace:
description: namespace defines the space within which
the secret name must be unique.
type: string
type: object
x-kubernetes-map-type: atomic
path:
description: Path is the sub-directory of remote git repository.
It's valid when remote is set
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 referenced object.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
it is, HCL or JSON syntax
enum:
- hcl
- json
- remote
type: string
writeConnectionSecretToRef:
description: WriteConnectionSecretToReference specifies the
namespace and name of a Secret to which any connection details
for this managed resource should be written. Connection
details frequently include the endpoint, username, and password
required to connect to the managed resource.
properties:
name:
description: Name of the secret.
type: string
namespace:
description: Namespace of the secret.
type: string
required:
- name
type: object
required:
- configuration
type: object
type: object
status:
description: Status defines the custom health policy and status message
for workload
properties:
customStatus:
description: CustomStatus defines the custom status message that
could display to user
type: string
healthPolicy:
description: HealthPolicy defines the health check policy for
the abstraction
type: string
type: object
workload:
description: Workload is a workload type descriptor
properties:
definition:
description: Definition mutually exclusive to workload.type, a
embedded WorkloadDefinition
properties:
apiVersion:
type: string
kind:
type: string
required:
- apiVersion
- kind
type: object
type:
description: Type ref to a WorkloadDefinition via name
type: string
type: object
required:
- workload
type: object
status:
description: ComponentDefinitionStatus is the status of ComponentDefinition
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
configMapRef:
description: ConfigMapRef refer to a ConfigMap which contains OpenAPI
V3 JSON schema of Component parameters.
type: string
latestRevision:
description: LatestRevision of the component definition
properties:
name:
type: string
revision:
format: int64
type: integer
revisionHash:
description: RevisionHash record the hash value of the spec of
ApplicationRevision object.
type: string
required:
- name
- revision
type: object
type: object
type: object
served: true
storage: false
subresources:
status: {}
- additionalPrinterColumns:
- jsonPath: .spec.workload.definition.kind
name: WORKLOAD-KIND

View File

@@ -1,586 +0,0 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.11.3
name: healthscopes.core.oam.dev
spec:
group: core.oam.dev
names:
categories:
- oam
kind: HealthScope
listKind: HealthScopeList
plural: healthscopes
singular: healthscope
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .status.health
name: HEALTH
type: string
name: v1alpha2
schema:
openAPIV3Schema:
description: A HealthScope determines an aggregate health status based of
the health of components.
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 HealthScopeSpec defines the desired state of a HealthScope.
properties:
appReferences:
description: AppRefs records references of applications' components
items:
description: AppReference records references of an application's
components
properties:
appName:
type: string
compReferences:
items:
description: CompReference records references of a component's
resources
properties:
compName:
type: string
traits:
items:
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.
\n 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
x-kubernetes-map-type: atomic
type: array
workload:
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. \n 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
x-kubernetes-map-type: atomic
type: object
type: array
type: object
type: array
probe-interval:
description: ProbeInterval is the amount of time in seconds between
probing tries.
format: int32
type: integer
probe-timeout:
description: ProbeTimeout is the amount of time in seconds to wait
when receiving a response before marked failure.
format: int32
type: integer
workloadRefs:
description: WorkloadReferences to the workloads that are in this
scope.
items:
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. \n 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
x-kubernetes-map-type: atomic
type: array
required:
- workloadRefs
type: object
status:
description: A HealthScopeStatus represents the observed state of a HealthScope.
properties:
appHealthConditions:
description: AppHealthConditions represents health condition of applications
in the scope
items:
description: AppHealthCondition represents health condition of an
application
properties:
appName:
type: string
components:
items:
description: WorkloadHealthCondition represents informative
health condition of a workload.
properties:
componentName:
description: ComponentName represents the component name
if target is a workload
type: string
customStatusMsg:
type: string
diagnosis:
type: string
healthStatus:
description: HealthStatus represents health status strings.
type: string
targetWorkload:
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. \n 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
x-kubernetes-map-type: atomic
traits:
items:
description: TraitHealthCondition represents informative
health condition of a trait.
properties:
customStatusMsg:
type: string
diagnosis:
type: string
healthStatus:
description: HealthStatus represents health status
strings.
type: string
resource:
type: string
type:
type: string
required:
- healthStatus
- resource
- type
type: object
type: array
workloadStatus:
description: WorkloadStatus represents status of workloads
whose HealthStatus is UNKNOWN.
type: string
required:
- healthStatus
type: object
type: array
envName:
type: string
required:
- appName
type: object
type: array
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
healthConditions:
description: WorkloadHealthConditions represents health condition
of workloads in the scope Use AppHealthConditions to provide app
level status
items:
description: WorkloadHealthCondition represents informative health
condition of a workload.
properties:
componentName:
description: ComponentName represents the component name if
target is a workload
type: string
customStatusMsg:
type: string
diagnosis:
type: string
healthStatus:
description: HealthStatus represents health status strings.
type: string
targetWorkload:
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. \n 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
x-kubernetes-map-type: atomic
traits:
items:
description: TraitHealthCondition represents informative health
condition of a trait.
properties:
customStatusMsg:
type: string
diagnosis:
type: string
healthStatus:
description: HealthStatus represents health status strings.
type: string
resource:
type: string
type:
type: string
required:
- healthStatus
- resource
- type
type: object
type: array
workloadStatus:
description: WorkloadStatus represents status of workloads whose
HealthStatus is UNKNOWN.
type: string
required:
- healthStatus
type: object
type: array
scopeHealthCondition:
description: ScopeHealthCondition represents health condition summary
of the scope
properties:
healthStatus:
description: HealthStatus represents health status strings.
type: string
healthyWorkloads:
format: int64
type: integer
total:
format: int64
type: integer
unhealthyWorkloads:
format: int64
type: integer
unknownWorkloads:
format: int64
type: integer
required:
- healthStatus
type: object
required:
- scopeHealthCondition
type: object
type: object
served: true
storage: true
subresources:
status: {}

View File

@@ -18,69 +18,6 @@ spec:
singular: scopedefinition
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .spec.definitionRef.name
name: DEFINITION-NAME
type: string
name: v1alpha2
schema:
openAPIV3Schema:
description: A ScopeDefinition registers a kind of Kubernetes custom resource
as a valid OAM scope kind by referencing its CustomResourceDefinition. The
CRD is used to validate the schema of the scope when it is embedded in an
OAM ApplicationConfiguration.
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 ScopeDefinitionSpec defines the desired state of a ScopeDefinition.
properties:
allowComponentOverlap:
description: AllowComponentOverlap specifies whether an OAM component
may exist in multiple instances of this kind of scope.
type: boolean
definitionRef:
description: Reference to the CustomResourceDefinition that defines
this scope kind.
properties:
name:
description: Name of the referenced CustomResourceDefinition.
type: string
version:
description: Version indicate which version should be used if
CRD has multiple versions by default it will use the first one
if not specified
type: string
required:
- name
type: object
extension:
description: Extension is used for extension needs by OAM platform
builders
type: object
workloadRefsPath:
description: WorkloadRefsPath indicates if/where a scope accepts workloadRef
objects
type: string
required:
- allowComponentOverlap
- definitionRef
type: object
type: object
served: true
storage: false
subresources: {}
- additionalPrinterColumns:
- jsonPath: .spec.definitionRef.name
name: DEFINITION-NAME
@@ -131,7 +68,7 @@ spec:
description: Extension is used for extension needs by OAM platform
builders
type: object
x-kubernetes-preserve-unknown-fields: true
workloadRefsPath:
description: WorkloadRefsPath indicates if/where a scope accepts workloadRef
objects

View File

@@ -18,325 +18,6 @@ spec:
singular: traitdefinition
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .spec.appliesToWorkloads
name: APPLIES-TO
type: string
- jsonPath: .metadata.annotations.definition\.oam\.dev/description
name: DESCRIPTION
type: string
name: v1alpha2
schema:
openAPIV3Schema:
description: A TraitDefinition registers a kind of Kubernetes custom resource
as a valid OAM trait kind by referencing its CustomResourceDefinition. The
CRD is used to validate the schema of the trait when it is embedded in an
OAM ApplicationConfiguration.
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 TraitDefinitionSpec defines the desired state of a TraitDefinition.
properties:
appliesToWorkloads:
description: AppliesToWorkloads specifies the list of workload kinds
this trait applies to. Workload kinds are specified in kind.group/version
format, e.g. server.core.oam.dev/v1alpha2. Traits that omit this
field apply to all workload kinds.
items:
type: string
type: array
conflictsWith:
description: 'ConflictsWith specifies the list of traits(CRD name,
Definition name, CRD group) which could not apply to the same workloads
with this trait. Traits that omit this field can work with any other
traits. Example rules: "service" # Trait definition name "services.k8s.io"
# API resource/crd name "*.networking.k8s.io" # API group "labelSelector:foo=bar"
# label selector labelSelector format: https://pkg.go.dev/k8s.io/apimachinery/pkg/labels#Parse'
items:
type: string
type: array
definitionRef:
description: Reference to the CustomResourceDefinition that defines
this trait kind.
properties:
name:
description: Name of the referenced CustomResourceDefinition.
type: string
version:
description: Version indicate which version should be used if
CRD has multiple versions by default it will use the first one
if not specified
type: string
required:
- name
type: object
extension:
description: Extension is used for extension needs by OAM platform
builders
type: object
x-kubernetes-preserve-unknown-fields: true
podDisruptive:
description: PodDisruptive specifies whether using the trait will
cause the pod to restart or not.
type: boolean
revisionEnabled:
description: Revision indicates whether a trait is aware of component
revision
type: boolean
schematic:
description: Schematic defines the data format and template of the
encapsulation of the trait
properties:
cue:
description: CUE defines the encapsulation in CUE format
properties:
template:
description: Template defines the abstraction template data
of the capability, it will replace the old CUE template
in extension field. Template is a required field if CUE
is defined in Capability Definition.
type: string
required:
- template
type: object
helm:
description: A Helm represents resources used by a Helm module
properties:
release:
description: Release records a Helm release used by a Helm
module workload.
type: object
x-kubernetes-preserve-unknown-fields: true
repository:
description: HelmRelease records a Helm repository used by
a Helm module workload.
type: object
x-kubernetes-preserve-unknown-fields: true
required:
- release
- repository
type: object
kube:
description: Kube defines the encapsulation in raw Kubernetes
resource format
properties:
parameters:
description: Parameters defines configurable parameters
items:
description: A KubeParameter defines a configurable parameter
of a component.
properties:
description:
description: Description of this parameter.
type: string
fieldPaths:
description: "FieldPaths specifies an array of fields
within this workload that will be overwritten by the
value of this parameter. \tAll fields must be of the
same type. Fields are specified as JSON field paths
without a leading dot, for example 'spec.replicas'."
items:
type: string
type: array
name:
description: Name of this parameter
type: string
required:
default: false
description: Required specifies whether or not a value
for this parameter must be supplied when authoring
an Application.
type: boolean
type:
description: 'ValueType indicates the type of the parameter
value, and only supports basic data types: string,
number, boolean.'
enum:
- string
- number
- boolean
type: string
required:
- fieldPaths
- name
- type
type: object
type: array
template:
description: Template defines the raw Kubernetes resource
type: object
x-kubernetes-preserve-unknown-fields: true
required:
- template
type: object
terraform:
description: Terraform is the struct to describe cloud resources
managed by Hashicorp Terraform
properties:
configuration:
description: Configuration is Terraform Configuration
type: string
customRegion:
description: Region is cloud provider's region. It will override
the region in the region field of ProviderReference
type: string
deleteResource:
default: true
description: DeleteResource will determine whether provisioned
cloud resources will be deleted when CR is deleted
type: boolean
gitCredentialsSecretReference:
description: GitCredentialsSecretReference specifies the reference
to the secret containing the git credentials
properties:
name:
description: name is unique within a namespace to reference
a secret resource.
type: string
namespace:
description: namespace defines the space within which
the secret name must be unique.
type: string
type: object
x-kubernetes-map-type: atomic
path:
description: Path is the sub-directory of remote git repository.
It's valid when remote is set
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 referenced object.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
it is, HCL or JSON syntax
enum:
- hcl
- json
- remote
type: string
writeConnectionSecretToRef:
description: WriteConnectionSecretToReference specifies the
namespace and name of a Secret to which any connection details
for this managed resource should be written. Connection
details frequently include the endpoint, username, and password
required to connect to the managed resource.
properties:
name:
description: Name of the secret.
type: string
namespace:
description: Namespace of the secret.
type: string
required:
- name
type: object
required:
- configuration
type: object
type: object
status:
description: Status defines the custom health policy and status message
for trait
properties:
customStatus:
description: CustomStatus defines the custom status message that
could display to user
type: string
healthPolicy:
description: HealthPolicy defines the health check policy for
the abstraction
type: string
type: object
workloadRefPath:
description: WorkloadRefPath indicates where/if a trait accepts a
workloadRef object
type: string
type: object
status:
description: TraitDefinitionStatus is the status of TraitDefinition
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
configMapRef:
description: ConfigMapRef refer to a ConfigMap which contains OpenAPI
V3 JSON schema of Component parameters.
type: string
latestRevision:
description: LatestRevision of the trait definition
properties:
name:
type: string
revision:
format: int64
type: integer
revisionHash:
description: RevisionHash record the hash value of the spec of
ApplicationRevision object.
type: string
required:
- name
- revision
type: object
type: object
type: object
served: true
storage: false
subresources:
status: {}
- additionalPrinterColumns:
- jsonPath: .spec.appliesToWorkloads
name: APPLIES-TO

View File

@@ -45,11 +45,9 @@ import (
"github.com/oam-dev/kubevela/cmd/core/app/options"
"github.com/oam-dev/kubevela/pkg/auth"
"github.com/oam-dev/kubevela/pkg/cache"
standardcontroller "github.com/oam-dev/kubevela/pkg/controller"
commonconfig "github.com/oam-dev/kubevela/pkg/controller/common"
oamv1alpha2 "github.com/oam-dev/kubevela/pkg/controller/core.oam.dev/v1alpha2"
"github.com/oam-dev/kubevela/pkg/controller/core.oam.dev/v1alpha2/application"
"github.com/oam-dev/kubevela/pkg/controller/utils"
oamv1alpha2 "github.com/oam-dev/kubevela/pkg/controller/core.oam.dev/v1beta1"
"github.com/oam-dev/kubevela/pkg/controller/core.oam.dev/v1beta1/application"
"github.com/oam-dev/kubevela/pkg/features"
"github.com/oam-dev/kubevela/pkg/monitor/watcher"
"github.com/oam-dev/kubevela/pkg/multicluster"
@@ -171,11 +169,6 @@ func run(ctx context.Context, s *options.CoreOptions) error {
return err
}
if err := utils.CheckDisabledCapabilities(s.DisableCaps); err != nil {
klog.ErrorS(err, "Unable to get enabled capabilities")
return err
}
pd, err := packages.NewPackageDiscover(mgr.GetConfig())
if err != nil {
klog.Error(err, "Failed to create CRD discovery for CUE package client")
@@ -247,11 +240,6 @@ func prepareRun(ctx context.Context, mgr manager.Manager, s *options.CoreOptions
return err
}
if err := standardcontroller.Setup(mgr, s.DisableCaps, *s.ControllerArgs); err != nil {
klog.ErrorS(err, "Unable to setup the vela core controller")
return err
}
if err := multicluster.InitClusterInfo(mgr.GetConfig()); err != nil {
klog.ErrorS(err, "Init control plane cluster info")
return err

View File

@@ -1,4 +1,4 @@
apiVersion: core.oam.dev/v1alpha2
apiVersion: core.oam.dev/v1beta1
kind: TraitDefinition
metadata:
annotations:

View File

@@ -1,4 +1,4 @@
apiVersion: core.oam.dev/v1alpha2
apiVersion: core.oam.dev/v1beta1
kind: ComponentDefinition
metadata:
name: alibaba-oss

View File

@@ -1,118 +0,0 @@
# WorkFlow with OCM
In this tutorial, you will create an ack cluster as a production environment and deploy the configured app
to this production environment.
## Prerequisites
- In order to follow the guide, you will need a Kubernetes cluster version 1.20+ as control-plane cluster, and
the cluster's APIServer has an external IP.
- Store the AK/AS of Alibaba Cloud to the Secret.
```shell
export ALICLOUD_ACCESS_KEY=xxx; export ALICLOUD_SECRET_KEY=yyy
```
```shell
# If you'd like to use Alicloud Security Token Service, also export `ALICLOUD_SECURITY_TOKEN`.
export ALICLOUD_SECURITY_TOKEN=zzz
```
```shell
sh hack/prepare-alibaba-credentials.sh
```
```shell
$ kubectl get secret -n vela-system
NAME TYPE DATA AGE
alibaba-account-creds Opaque 1 11s
```
- Install Definitions
```shell
kubectl apply -f definitions
```
## Create Initializer terraform-alibaba
Initializer terraform-alibaba will create an environment which allows users use terraform to create cloud resource on aliyun.
```shell
kubectl apply -f initializers/init-terraform-alibaba.yaml
```
It will take few minutes to wait the `PHASE` of Initializer `terraform-alibaba` to be `success`.
```shell
$ kubectl get initializers.core.oam.dev -n vela-system
NAMESPACE NAME PHASE AGE
vela-system terraform-alibaba success 94s
```
## Create Initializer managed-cluster
Initializer managed-cluster can create an ack cluster and use OCM to manage the cluster.
1. You should set the `hubAPIServer` to the public network address in `init-managed-cluster.yaml`
```yaml
# init-managed-cluster.yaml
- name: register-ack
type: register-cluster
inputs:
...
properties:
# user should set public network address of your control-plane cluster APIServer
hubAPIServer: {{ public network address of APIServer }}
```
2. Apply the Initializer managed-cluster
```shell
kubectl apply -f initializers/init-managed-cluster.yaml
```
It will take 15 to 20 minutes to create an ack cluster, please wait until the status of `managed-cluster` to be `success`.
```shell
$ kubectl get initializers.core.oam.dev -n vela-system
NAMESPACE NAME PHASE AGE
vela-system managed-cluster success 45m
```
3. Check the new ack cluster has been registered
```shell
$ kubectl get managedclusters.cluster.open-cluster-management.io
NAME HUB ACCEPTED MANAGED CLUSTER URLS JOINED AVAILABLE AGE
poc-01 true {{ APIServer address }} True True 30s
```
## Deploy the resource to ack cluster
install trait `expose` from default capability center.
```shell
vela cap install default-cap-center/expose
```
```shell
kubectl apply -f app.yaml
```
check the app `workflow-demo` was created successfully
```shell
$ kubectl get app workflow-demo
NAME COMPONENT TYPE PHASE HEALTHY STATUS AGE
workflow-demo podinfo-server webservice running true 7s
```
use kubectl connect to the managed-cluster `poc-01` and check the resources in the app
are successfully deployed to the cluster `poc-01`.
```shell
$ kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
podinfo-server 1/1 1 1 40s
```

View File

@@ -1,48 +0,0 @@
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: workflow-demo
namespace: default
spec:
components:
- name: podinfo-server
type: webservice
properties:
image: stefanprodan/podinfo:5.2.1
port: 9898
traits:
- type: expose
properties:
port: [9898]
policies:
- name: prod-env
type: env-binding
properties:
engine: ocm
envs:
- name: prod
patch:
components:
- name: podinfo-server
type: webservice
properties:
image: stefanprodan/podinfo:6.0.0
port: 9898
traits:
- type: expose
properties:
port: [9898]
type: LoadBalancer
placement:
clusterSelector:
labels:
purpose: test
workflow:
steps:
- name: deploy-server
type: mutil-env
properties:
env: prod
policy: prod-env

View File

@@ -1,57 +0,0 @@
apiVersion: core.oam.dev/v1beta1
kind: WorkflowStepDefinition
metadata:
name: create-ack
namespace: vela-system
spec:
schematic:
cue:
template: |
import (
"vela/op"
"encoding/base64"
)
configuration: op.#Load & {
component: parameter.component
}
apply: op.#Apply & {
value: {
configuration.value.workload
}
}
wait: op.#ConditionalWait & {
continue: apply.value.status.state == "Available"
}
secretName: apply.value.spec.writeConnectionSecretToRef.name
secretNamespace: apply.value.spec.writeConnectionSecretToRef.namespace
ackConn: op.#Read & {
value: {
apiVersion: "v1"
kind: "Secret"
metadata: {
name: secretName
namespace: secretNamespace
}
}
}
parameter: {
component: string
}
connInfo: {
clusterName: base64.Decode(null, ackConn.value.data["name"])
clusterCACert: base64.Decode(null, ackConn.value.data["cluster_ca_cert"])
clientCert: base64.Decode(null, ackConn.value.data["client_cert"])
clientKey: base64.Decode(null, ackConn.value.data["client_key"])
clusterAPIServer: base64.Decode(null, ackConn.value.data["api_server_internet"])
}

View File

@@ -1,191 +0,0 @@
apiVersion: core.oam.dev/v1beta1
kind: WorkflowStepDefinition
metadata:
name: register-cluster
namespace: vela-system
spec:
schematic:
cue:
template: |
import ("vela/op")
clusterrole: op.#Apply & {
value: {
apiVersion: "rbac.authorization.k8s.io/v1"
kind: "ClusterRole"
metadata: {
name: "cluster-register"
}
rules: [{
apiGroups: [""]
resources: ["configmaps", "namespaces", "serviceaccounts", "services", "secrets"]
verbs: ["create", "get", "list", "update", "watch", "patch", "delete"]
}, {
apiGroups: ["", "events.k8s.io"]
resources: ["events"]
verbs: ["create", "update", "patch"]
}, {
apiGroups: ["rbac.authorization.k8s.io"]
resources: ["clusterrolebindings", "rolebindings"]
verbs: ["create", "get", "list", "update", "watch", "patch", "delete"]
}, {
apiGroups: ["rbac.authorization.k8s.io"]
resources: ["clusterroles", "roles"]
verbs: ["create", "get", "list", "update", "watch", "patch", "delete", "escalate", "bind"]
}, {
apiGroups: ["rbac.authorization.k8s.io"]
resources: ["clusterroles", "roles"]
verbs: ["create", "get", "list", "update", "watch", "patch", "delete", "escalate", "bind"]
}, {
apiGroups: ["certificates.k8s.io"]
resources: ["certificatesigningrequests"]
verbs: ["create", "get", "list", "watch"]
}, {
apiGroups: ["certificates.k8s.io"]
resources: ["certificatesigningrequests/approval"]
verbs: ["update"]
}, {
apiGroups: ["certificates.k8s.io"]
resources: ["signers"]
resourceNames: ["kubernetes.io/*"]
verbs: ["approve"]
}, {
apiGroups: ["cluster.open-cluster-management.io"]
resources: ["managedclusters"]
verbs: ["create", "get", "list", "update", "watch", "delete"]
}, {
apiGroups: ["register.open-cluster-management.io"]
resources: ["managedclusters", "managedclusters/accept"]
verbs: ["create", "get", "list", "update", "watch", "delete"]
}]
}
}
serviceaccount: op.#Apply & {
value: {
apiVersion: "v1"
kind: "ServiceAccount"
metadata: {
name: "cluster-register"
namespace: "default"
}
}
}
rolebinding: op.#Apply & {
value: {
apiVersion: "rbac.authorization.k8s.io/v1"
kind: "ClusterRoleBinding"
metadata: {
name: "cluster-register"
}
roleRef: {
apiGroup: "rbac.authorization.k8s.io"
kind: "ClusterRole"
name: "cluster-register"
}
subjects: [{
kind: "ServiceAccount"
name: "cluster-register"
namespace: "default"
}]
}
}
register: op.#Apply & {
value: {
apiVersion: "batch/v1"
kind: "Job"
metadata: {
name: "cluster-register"
namespace: "default"
}
spec: {
template: {
spec: {
containers: [{
name: "cluster-register"
image: "oamdev/cluster-register:v1.0"
imagePullPolicy: "Always"
command: [
"/app", "--cluster-name=" + "\(parameter.connInfo.clusterName)",
"--hub-api-server=" + "\(parameter.hubAPIServer)",
"--cluster-ca-cert=" + "\(parameter.connInfo.clusterCACert)",
"--client-cert=" + "\(parameter.connInfo.clientCert)",
"--client-key=" + "\(parameter.connInfo.clientKey)",
"--api-server-internet=" + "\(parameter.connInfo.clusterAPIServer)",
"--kube-config=" + "\(parameter.connInfo.kubeConfig)",
]
}]
restartPolicy: "OnFailure"
serviceAccountName: "cluster-register"
}
}
}
}
}
wait: op.#ConditionalWait & {
continue: register.value.status.succeeded == 1
}
clusterSet: op.#Apply & {
value: {
apiVersion: "cluster.open-cluster-management.io/v1alpha1"
kind: "ManagedClusterSet"
metadata: name: parameter.env
}
}
clusterSetBinding: op.#Apply & {
value: {
apiVersion: "cluster.open-cluster-management.io/v1alpha1"
kind: "ManagedClusterSetBinding"
metadata: {
name: parameter.env
namespace: parameter.initNameSpace
}
spec: clusterSet: parameter.env
}
}
managedCluster: op.#Read & {
value: {
apiVersion: "cluster.open-cluster-management.io/v1"
kind: "ManagedCluster"
metadata: {
name: parameter.connInfo.clusterName
}
}
}
patchManagedCluster: op.#Apply & {
value: {
managedCluster.value
metadata: labels: {
"cluster.open-cluster-management.io/clusterset": parameter.env
}
metadata: labels: parameter.patchLabels
}
}
parameter: {
env: string
initNameSpace: *"default" | string
patchLabels: [string]: string
hubAPIServer: *"" | string
connInfo: {
clusterName: string
clusterCACert: *"" | string
clientCert: *"" | string
clientKey: *"" | string
clusterAPIServer: *"" | string
kubeConfig: *"" | string
}
}

View File

@@ -1,6 +0,0 @@
#!/bin/bash
echo "accessKeyID: ${ALICLOUD_ACCESS_KEY}\naccessKeySecret: ${ALICLOUD_SECRET_KEY}\nsecurityToken: ${ALICLOUD_SECURITY_TOKEN}" > alibaba-credentials.conf
kubectl create namespace vela-system
kubectl create secret generic alibaba-account-creds -n vela-system --from-file=credentials=alibaba-credentials.conf
rm -f alibaba-credentials.conf

View File

@@ -1,48 +0,0 @@
apiVersion: core.oam.dev/v1beta1
kind: Initializer
metadata:
name: managed-cluster
namespace: vela-system
spec:
appTemplate:
spec:
components:
- name: ack-worker
type: alibaba-ack
properties:
writeConnectionSecretToRef:
name: ack-conn
namespace: vela-system
workflow:
steps:
- name: terraform-ack
type: create-ack
properties:
component: ack-worker
outputs:
- name: connInfo
valueFrom: connInfo
- name: register-ack
type: register-cluster
inputs:
- from: connInfo
parameterKey: connInfo
properties:
# user should set public network address of APIServer
hubAPIServer: {{ public network address of APIServer }}
env: prod
initNameSpace: default
patchLabels:
purpose: test
dependsOn:
- ref:
apiVersion: core.oam.dev/v1beta1
kind: Initializer
name: terraform-alibaba
namespace: vela-system
- ref:
apiVersion: core.oam.dev/v1beta1
kind: Initializer
name: ocm-cluster-manager
namespace: vela-system

View File

@@ -1,31 +0,0 @@
apiVersion: core.oam.dev/v1beta1
kind: Initializer
metadata:
name: terraform-alibaba
namespace: vela-system
spec:
appTemplate:
spec:
components:
- name: default
type: raw
properties:
apiVersion: terraform.core.oam.dev/v1beta1
kind: Provider
metadata:
namespace: default
spec:
provider: alibaba
region: cn-hongkong
credentials:
source: Secret
secretRef:
namespace: vela-system
name: alibaba-account-creds
key: credentials
dependsOn:
- ref:
apiVersion: core.oam.dev/v1beta1
kind: Initializer
name: terraform
namespace: vela-system

View File

@@ -1,119 +0,0 @@
# Rollout with OCM
In this tutorial, you will use rollout in runtime cluster with OCM.
## Prerequisites
- Have a multi-cluster environment witch have installed OCM by following this [guide](../README.md). The name of managed cluster generally is `poc-01`.
- Install vela-rollout chart in managed-cluster with Helm.
```shell
$ helm repo add kubevela https://charts.kubevela.net/core
```
```shell
$ helm install vela-rollout --create-namespace -n vela-system kubevela/vela-rollout
```
## Install workflowStepDefinition
Apply workflowStepDefinitions in control-plane cluster.
```shell
$ kubectl apply -f dispatchRevDef.yaml
```
```shell
$ kubectl apply -f dispatchTraits.yaml
```
## Deploy and rollout
1. Apply application in control-plane cluster.
```shell
$ kubectl apply -f app-first-scale.yaml
```
Wait a few minutes, check rollout and workload status in managed cluster.
```shell
$ kubectl get rollout
NAME TARGET UPGRADED READY BATCH-STATE ROLLING-STATE AGE
nginx-server 2 2 2 batchReady rolloutSucceed 25h
```
```shell
$ kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-server-v1 2/2 2 2 25h
```
2. Update application to v2.
```shell
$ kubectl apply -f app-update-v2.yaml
```
check rollout and workload status.
```shell
$ kubectl get rollout
NAME TARGET UPGRADED READY BATCH-STATE ROLLING-STATE AGE
nginx-server 2 2 2 batchReady rolloutSucceed 25h
```
```shell
$ kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-server-v2 2/2 2 2 25h
```
3. Scale up.
```shell
$ kubectl apply -f app-v2-scale.yaml
```
check the status of rollout and workload.
```shell
$ kubectl get rollout
NAME TARGET UPGRADED READY BATCH-STATE ROLLING-STATE AGE
nginx-server 4 4 4 batchReady rolloutSucceed 25h
```
```shell
$ kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-server-v2 4/4 4 4 25h
```
4. Roll back to v1.
```shell
$ kubectl apply -f app-revert.yaml
```
check rollout and workload status.
```shell
$ kubectl get rollout
NAME TARGET UPGRADED READY BATCH-STATE ROLLING-STATE AGE
nginx-server 4 4 4 batchReady rolloutSucceed 25h
```
```shell
$ kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-server-v1 4/4 4 4 25h
```
5. Scale down.
```shell
$ kubectl apply -f app-scale-down-v1.yaml
```
check rollout and workload status.
```shell
$ kubectl get rollout
NAME TARGET UPGRADED READY BATCH-STATE ROLLING-STATE AGE
nginx-server 2 2 2 batchReady rolloutSucceed 25h
```
```shell
$ kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-server-v1 2/2 2 2 25h
```

View File

@@ -1,36 +0,0 @@
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: workflow-rollout-demo
namespace: default
spec:
components:
- name: nginx-server
externalRevision: nginx-server-v1
type: webservice
properties:
image: nginx:1.20.0
port: 80
traits:
- type: rollout
properties:
targetRevision: nginx-server-v1
targetSize: 2
# Rollout the two replicas in two batches
rolloutBatches:
- replicas: 1
- replicas: 1
workflow:
steps:
- name: dispatch-comp-rev-v1
type: dispatch-comp-rev
properties:
compRev: nginx-server-v1
cluster: poc-01
- name: dispatchRollout
type: dispatch-traits
properties:
component: nginx-server
cluster: poc-01

View File

@@ -1,41 +0,0 @@
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: workflow-rollout-demo
namespace: default
spec:
components:
- name: nginx-server
externalRevision: nginx-server-v2
type: webservice
properties:
image: nginx:1.21
port: 80
traits:
- type: rollout
properties:
targetRevision: nginx-server-v1
targetSize: 4
rolloutBatches:
- replicas: 2
- replicas: 2
workflow:
steps:
- name: dispatch-comp-rev-v1
type: dispatch-comp-rev
properties:
compRev: nginx-server-v1
cluster: poc-01
- name: dispatch-comp-rev-v2
type: dispatch-comp-rev
properties:
compRev: nginx-server-v2
cluster: poc-01
- name: dispatchRollout
type: dispatch-traits
properties:
component: nginx-server
cluster: poc-01

View File

@@ -1,41 +0,0 @@
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: workflow-rollout-demo
namespace: default
spec:
components:
- name: nginx-server
externalRevision: nginx-server-v2
type: webservice
properties:
image: nginx:1.21
port: 80
traits:
- type: rollout
properties:
targetRevision: nginx-server-v1
targetSize: 2
rolloutBatches:
- replicas: 1
- replicas: 1
workflow:
steps:
- name: dispatch-comp-rev-v1
type: dispatch-comp-rev
properties:
compRev: nginx-server-v1
cluster: cluster2
- name: dispatch-comp-rev-v2
type: dispatch-comp-rev
properties:
compRev: nginx-server-v2
cluster: cluster2
- name: dispatchRollout
type: dispatch-traits
properties:
component: nginx-server
cluster: cluster2

View File

@@ -1,43 +0,0 @@
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: workflow-rollout-demo
namespace: default
spec:
components:
- name: nginx-server
externalRevision: nginx-server-v2
type: webservice
properties:
image: nginx:1.21
port: 80
traits:
- type: rollout
properties:
targetRevision: nginx-server-v2
targetSize: 2
# Upgrade the replicas in two batches. Each batch will upgrade only one.
rolloutBatches:
- replicas: 1
- replicas: 1
workflow:
steps:
# If we delete this, the ManifestWork will also be removed in managed cluster, which would prohibits us to do rollback later.
- name: dispatch-comp-rev-v1
type: dispatch-comp-rev
properties:
compRev: nginx-server-v1
cluster: poc-01
- name: dispatch-comp-rev-v2
type: dispatch-comp-rev
properties:
compRev: nginx-server-v2
cluster: poc-01
- name: dispatchRollout
type: dispatch-traits
properties:
component: nginx-server
cluster: poc-01

View File

@@ -1,42 +0,0 @@
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: workflow-rollout-demo
namespace: default
spec:
components:
- name: nginx-server
externalRevision: nginx-server-v2
type: webservice
properties:
image: nginx:1.21
port: 80
traits:
- type: rollout
properties:
targetRevision: nginx-server-v2
targetSize: 4
# This means to rollout two more replicas in two batches.
rolloutBatches:
- replicas: 1
- replicas: 1
workflow:
steps:
- name: dispatch-comp-rev-v1
type: dispatch-comp-rev
properties:
compRev: nginx-server-v1
cluster: poc-01
- name: dispatch-comp-rev-v2
type: dispatch-comp-rev
properties:
compRev: nginx-server-v2
cluster: poc-01
- name: dispatchRollout
type: dispatch-traits
properties:
component: nginx-server
cluster: poc-01

View File

@@ -1,60 +0,0 @@
apiVersion: core.oam.dev/v1beta1
kind: WorkflowStepDefinition
metadata:
name: dispatch-comp-rev
namespace: vela-system
spec:
schematic:
cue:
template: |
import ("vela/op")
componentRev: op.#Read & {
value: {
kind: "ControllerRevision"
apiVersion: "apps/v1"
metadata: {
name: parameter.compRev
namespace: context.namespace
}
}
}
apply: op.#Apply & {
value: {
apiVersion: "work.open-cluster-management.io/v1"
kind: "ManifestWork"
metadata: {
namespace: parameter.cluster
name: "comprevision-" + parameter.compRev
}
spec: {
workload: {
manifests: [{
kind: "ControllerRevision"
apiVersion: "apps/v1"
metadata: {
name: parameter.compRev
namespace: context.namespace
}
data: {
apiVersion: "core.oam.dev/v1alpha2"
kind: "Component"
metadata:
name: context.name
namespace: context.namespace
spec:
workload: {
componentRev.value.data.spec.workload
}
}
}]
}
}
}
}
parameter: {
compRev: string
cluster: string
}

View File

@@ -1,34 +0,0 @@
apiVersion: core.oam.dev/v1beta1
kind: WorkflowStepDefinition
metadata:
name: dispatch-traits
namespace: vela-system
spec:
schematic:
cue:
template: |
import ("vela/op")
comp: op.#Load & {
component: parameter.component
}
apply: op.#Apply & {
value: {
apiVersion: "work.open-cluster-management.io/v1"
kind: "ManifestWork"
metadata: {
namespace: parameter.cluster
name: parameter.component + "-traits"
}
spec: {
workload: manifests : comp.value.auxiliaries
}
}
}
parameter: {
component: string
cluster: string
}

View File

@@ -1,4 +1,4 @@
apiVersion: core.oam.dev/v1alpha2
apiVersion: core.oam.dev/v1beta1
kind: ComponentDefinition
metadata:
name: alibaba-oss

View File

@@ -1,180 +0,0 @@
# Quick start
This example show case how one can use a flagger trait to rollout a component with
## Install OAM flagger
```shell script
make
helm install -n flagger rollout charts/flagger/
```
## Install Vela core
```shell script
make
bin/vela install
```
## Run ApplicationConfiguration V1
```shell script
kubectl apply -f e2e/raw-objects/samples/rollout-demo/definitions.yaml
traitdefinition.core.oam.dev/canaries.flagger.app created
traitdefinition.core.oam.dev/ingresses.extensions created
workloaddefinition.core.oam.dev/deployments.apps created
kubectl apply -f e2e/raw-objects/samples/rollout-demo/deploy-component-v1.yaml
component.core.oam.dev/rollout-demo-app created
kubectl apply -f e2e/raw-objects/samples/rollout-demo/appConfig-rollout-v1.yaml
applicationconfiguration.core.oam.dev/sample-application-rollout created
```
## Verify that revision workload is created
```shell script
kubectl get controllerrevision
NAME CONTROLLER REVISION AGE
rollout-demo-app-v1 component.core.oam.dev/rollout-demo-app 1 64s
kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
rollout-demo-app-v1 1/1 1 1 80s
```
## Upgrade the component to v2 and change the revision name of the component in the appConfig
```shell script
kubectl apply -f e2e/raw-objects/samples/rollout-demo/deploy-component-v2.yaml
component.core.oam.dev/rollout-demo-app configured
kubectl apply -f e2e/raw-objects/samples/rollout-demo/appConfig-rollout-v2.yaml
applicationconfiguration.core.oam.dev/sample-application-rollout created
```
## Verify that new revision workload is created and the workloads
```shell script
kubectl get controllerrevision
NAME CONTROLLER REVISION AGE
rollout-demo-app-v1 component.core.oam.dev/rollout-demo-app 1 90s
rollout-demo-app-v2 component.core.oam.dev/rollout-demo-app 2 5s
```
## Verify that we have created services that select all pods in all the revisions
```shell script
kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
rollout-demo-app ClusterIP 10.103.185.101 <none> 80/TCP 2m52s
rollout-demo-app-canary ClusterIP 10.99.87.149 <none> 80/TCP 2m22s
rollout-demo-app-primary ClusterIP 10.102.31.57 <none> 80/TCP 2m22s
kubectl describe svc rollout-demo-app
Name: rollout-demo-app
Namespace: default
Labels: app=rollout-demo-app
Annotations: <none>
Selector: app=rollout-demo-app
Type: ClusterIP
IP: 10.103.185.101
Port: http 80/TCP
TargetPort: 8080/TCP
Endpoints: 172.17.0.13:8080,172.17.0.14:8080,172.17.0.15:8080 + 4 more...
Session Affinity: None
Events: <none>
```
## Verify the version of the canary and primary deployment are what is intended
```shell script
kubectl get deploy rollout-demo-app-v1 -o=jsonpath="{.spec.template.spec.containers[0].image}"
stefanprodan/podinfo:4.0.6
kubectl get deploy rollout-demo-app-v2 -o=jsonpath="{.spec.template.spec.containers[0].image}"
stefanprodan/podinfo:5.0.2
```
## Observe the flagger canary
```shell script
kubectl get canary --watch
NAME STATUS WEIGHT LASTTRANSITIONTIME
rollout-demo-app Initializing 0 2020-10-24T10:59:56Z
rollout-demo-app Initializing 0 2020-10-24T10:59:56Z
rollout-demo-app Initialized 0 2020-10-24T11:00:54Z
rollout-demo-app Progressing 0 2020-10-24T11:01:24Z
rollout-demo-app Progressing 10 2020-10-24T11:01:54Z
rollout-demo-app Progressing 20 2020-10-24T11:02:24Z
rollout-demo-app Progressing 30 2020-10-24T11:02:54Z
rollout-demo-app Progressing 40 2020-10-24T11:03:24Z
rollout-demo-app Progressing 50 2020-10-24T11:03:54Z
rollout-demo-app Promoting 0 2020-10-24T11:04:24Z
rollout-demo-app Promoting 100 2020-10-24T11:04:54Z
rollout-demo-app Finalising 0 2020-10-24T11:05:24Z
```
## Observe that the rollout through the canary object, you shall see something like this
```shell script
kubectl describe canary
...
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning Synced 5m30s flagger waiting for rollout to finish: observed deployment generation less then desired generation
Normal Synced 5m (x2 over 5m30s) flagger all the metrics providers are available!
Normal Synced 5m flagger Initialization done! rollout-demo-app.default
Normal Synced 4m30s flagger New revision detected! Scaling up rollout-demo-app-v2.default
Normal Synced 4m flagger Starting canary analysis for rollout-demo-app-v2.default
Normal Synced 4m flagger Advance rollout-demo-app.default canary weight 10
Normal Synced 3m30s flagger Advance rollout-demo-app.default canary weight 20
Normal Synced 3m flagger Advance rollout-demo-app.default canary weight 30
Normal Synced 2m30s flagger Advance rollout-demo-app.default canary weight 40
Normal Synced 2m flagger Advance rollout-demo-app.default canary weight 50
Normal Synced 30s flagger Promote rollout-demo-app.default
Normal Synced 30s flagger Promoting the traffic to the new targe in one shot
Normal Synced 0s (x3 over 60s) flagger (combined from similar events): Promotion completed!
```
## Verify that the instances of the v2 workload is the same as the canary maxReplica
```shell script
kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
rollout-demo-app-v1 0/0 0 0 15m
rollout-demo-app-v2 7/7 7 7 15m
```
## Roll back to V1
```shell script
kubectl apply -f e2e/raw-objects/samples/rollout-demo/appConfig-rollback-v1.yaml
applicationconfiguration.core.oam.dev/sample-application-rollout configured
```
## Observe the flagger canary rollback
```shell script
kubectl get canary --watch
NAME STATUS WEIGHT LASTTRANSITIONTIME
rollback-demo-app Initialized 0 2020-10-24T11:17:04Z
rollback-demo-app Progressing 0 2020-10-24T11:17:34Z
rollback-demo-app Progressing 10 2020-10-24T11:18:04Z
rollback-demo-app Progressing 20 2020-10-24T11:18:34Z
rollback-demo-app Progressing 30 2020-10-24T11:19:04Z
rollback-demo-app Progressing 40 2020-10-24T11:19:34Z
rollback-demo-app Progressing 50 2020-10-24T11:20:04Z
rollback-demo-app Promoting 0 2020-10-24T11:20:34Z
rollback-demo-app Promoting 100 2020-10-24T11:21:04Z
rollback-demo-app Finalising 0 2020-10-24T11:21:34Z
rollback-demo-app Succeeded 0 2020-10-24T11:22:04Z
```
## Verify that the instances of the v1 workload is the same as the canary maxReplica
```shell script
kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
rollout-demo-app-v1 7/7 7 7 24m
rollout-demo-app-v2 0/0 0 0 24m
```
## Clean up
```shell script
kubectl delete -f e2e/raw-objects/samples/rollout-demo/
```
## Improvements
1. The current component garbage collector uses a very unreliable way to figour out if a workload is a revisioned one that needs to keep or GCed. (basically to see if its name starts with componentName-)
2. The workload name will not be component-v when the user actually put a name in the component. This will lead to problems in the above case
3. Modify the primary/canary service so that they point to the primary/canary resources individually

View File

@@ -1,72 +0,0 @@
# Rollout Trait Design
## Flagger rollout flow
Here is the 10,000 ft overview of the flagger rollout flow
The overall controller Run function starts the processNextItem every second in the background. The processNextItme basically calls SyncHandler on each item in the queue.
It calls the scheduleCanary() function in a for loop.
SyncHandler
1. Set the canary status as **Initializing** if canary is not deleted
2. Finalize (revert) the canary process if the canary has "revertOnDelete" flag. This means reverting the canary process when the canary object is deleted. OAM should NEVER set this to true.
3. Each canary will be mapped to a job which runs the "AdvanceCanary" logic below forever until stopped
AdvanceCanary
1. Create Canary controller/Service router/Mesh router/ through a factory
2. CanaryController initialize the primary resource by copying from the target
3. ServiceRouter initialize creates the serivce for the canary/primary resources
4. Check if the canary has changed if the primary is initialized successfully. Just return if not.
5. Check if the rollout webhook confirms to start
6. Check if the Primary is ready, return if not
7. MeshRouter starts to calculate the traffic weight between primary/canary
8. Set the canary status as **Initialized** if it's initializing and return. Otherwise, set it to **Progressing** if it determined to advance
9. Check if the canary revision (spec) changes or dependency changes during rollout, if so, reset to **Progressing**
10. Check if no need to do analysis, go straight to finish the rollout if not. The default is to route 100% to primary which is not what we want. OAM should NEVER set this to true.
11. Check with rollback webhooks, rollback if something is wrong
12. Check if the status is promoting, call controller promote which just copy canary spec to primary. This will set the status to **Finalizing** if there is no error.
13. Check if the status is finalizing. Finalize delete the canary and set the canary status as **Succeeded**
14. Roll back if the number of failed cases cross certain threshold.
15. Pick a strategy based on the spec.Analysis (A/B testing, Blue/Green or Canary). The canary status is set as **Promoting** at the end of those phase.
## Problems with the flagger design in OAM
The problem with the current flagger design is that it wants to be strictly GitOps compatible. Thus, it
cannot touch the image related fields in the "target" object. That's why it has to create a "primary" deployment
and treat the "target" as the "canary" while doing the rollout. It finally "promotes" the primary
by copying everything from the "canary" to the "primary" after it 's done.
We don't need to stick to that scheme, but we face a similar problem as our component/workload controller
will constantly reconcile the target component too.
1. One way is to pin the component to a specific revision in the application configuration. The user then can modify
the component and that can be automatically picked up by the rollout trait. The draw-back of this approach is that
the upgrade will end up with the workload with the latest version not the workload in the applcation configuration.
2. Another way is to not allow the component to specify the "replicas" by the user. In this way, a user can modify
the container related fields which leads to a new workload of size 0 created. The rollout trait
can pick up the "last" revision of the component and its corresponding workload as the source. The nice part of this
approach is the new component will be the canary, thus keeping it under the application controller's control
and ready to be upgraded again.
We decide to take the second approach as it matches with the flow better.
## Proposed OAM Design
- Add a new "meshProvider" type "OAM", the scheduler will automatically set the meshProvider as the "routeTrait" implementation
which is SMI for now.
- OAM can fill the workloadRef to the `targetRef` automatically. This will point the trait to the workload
which has its "componentRevisionName" in its label.
- Write an OAM flagger resource controller that works with the podSpecWorkload/containerizedWorkload/Deployment
- Find the last live component revision as the canary if the user didn't explicitly spell out the revisionName
- We need to use the workload itself as the canary, and the "source" as the primary
- The Initialize function will be no-op
- The controller will adjust the replica size between the canary and the primary if there is HPA associated with the workload
- The Promote function will simply reduce the primary (source) replicas zero and bump the canary (target)
- It seems that we don't need an OAM specific router (even if the service/routing name is a bit mis-matched)
- Remove all the hard coded string literal "primary" from the scheduler.go file
## What is not covered
- This design does not cover the case that HPA is involved. This requires some changes at the OAM
runtime to keep the HPA trait on the old workload.
- We need a way to translate the status of the flagger trait status back to the rollout output if we
don't plan to introduce a rollout CRD.
- The rollout experience needs to be combined with the metris/route/autoscaler traits together to have
a merely complete CD experience. The very basic case is for the canary to emit Prometheus metrics. The rollout
trait needs to setup metrics checkers and threatholds to move to the next stages.

View File

@@ -1,40 +0,0 @@
apiVersion: core.oam.dev/v1alpha2
kind: ApplicationConfiguration
metadata:
name: sample-application-rollout
spec:
components:
- revisionName: rollout-demo-app-v1
traits:
- trait:
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: rollback-demo-app
spec:
sourceRef:
apiVersion: apps/v1
kind: Deployment
name: rollout-demo-app-v2
namespace: default
provider: smi
progressDeadlineSeconds: 60
service:
name: rollout-demo-app
# ClusterIP port number
port: 80
# container port number or name
targetPort: 8080
analysis:
# schedule interval (default 60s)
interval: 15s
# max number of failed metric checks before rollback
threshold: 10
# max traffic percentage routed to canary
# percentage (0-100)
maxWeight: 50
# canary increment step
# percentage (0-100)
stepWeight: 10
# max replicas scale up to canary
maxReplicas: 7

View File

@@ -1,34 +0,0 @@
apiVersion: core.oam.dev/v1alpha2
kind: ApplicationConfiguration
metadata:
name: sample-application-rollout
spec:
components:
- revisionName: rollout-demo-app-v1
traits:
- trait:
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: rollout-demo-app
spec:
provider: smi
progressDeadlineSeconds: 60
service:
# ClusterIP port number
port: 80
# container port number or name
targetPort: 8080
analysis:
# schedule interval (default 60s)
interval: 0s
# max number of failed metric checks before rollback
threshold: 10
# max traffic percentage routed to canary
# percentage (0-100)
maxWeight: 50
# canary increment step
# percentage (0-100)
stepWeight: 10
# max replicas scale up to canary
maxReplicas: 7

View File

@@ -1,35 +0,0 @@
apiVersion: core.oam.dev/v1alpha2
kind: ApplicationConfiguration
metadata:
name: sample-application-rollout
spec:
components:
- revisionName: rollout-demo-app-v2
traits:
- trait:
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: rollout-demo-app
spec:
provider: smi
progressDeadlineSeconds: 60
service:
name: rollout-demo-app
# ClusterIP port number
port: 80
# container port number or name
targetPort: 8080
analysis:
# schedule interval (default 60s)
interval: 15s
# max number of failed metric checks before rollback
threshold: 10
# max traffic percentage routed to canary
# percentage (0-100)
maxWeight: 50
# canary increment step
# percentage (0-100)
stepWeight: 10
# max replicas scale up to canary
maxReplicas: 7

View File

@@ -1,20 +0,0 @@
apiVersion: core.oam.dev/v1alpha2
kind: TraitDefinition
metadata:
name: canaries.flagger.app
spec:
appliesToWorkloads:
- podspecworkload.standard.oam.dev
- deployments.apps
definitionRef:
name: canaries.flagger.app
workloadRefPath: spec.targetRef
revisionEnabled: true
---
apiVersion: core.oam.dev/v1alpha2
kind: WorkloadDefinition
metadata:
name: deployments.apps
spec:
definitionRef:
name: deployments.apps

View File

@@ -1,26 +0,0 @@
apiVersion: core.oam.dev/v1alpha2
kind: Component
metadata:
name: rollout-demo-app
spec:
workload:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: rollout-demo-app
spec:
selector:
matchLabels:
app: rollout-demo-app
template:
metadata:
labels:
app: rollout-demo-app
spec:
containers:
- image: stefanprodan/podinfo:4.0.6
name: metrics-provider
ports:
- name: http
containerPort: 8080

View File

@@ -1,26 +0,0 @@
apiVersion: core.oam.dev/v1alpha2
kind: Component
metadata:
name: rollout-demo-app
spec:
workload:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: rollout-demo-app
spec:
selector:
matchLabels:
app: rollout-demo-app
template:
metadata:
labels:
app: rollout-demo-app
spec:
containers:
- image: stefanprodan/podinfo:5.0.2
name: metrics-provider
ports:
- name: http
containerPort: 8080

View File

@@ -1,19 +0,0 @@
apiVersion: core.oam.dev/v1alpha2
kind: Component
metadata:
name: rollout-demo-app
spec:
workload:
apiVersion: standard.oam.dev/v1alpha1
kind: PodSpecWorkload
metadata:
labels:
app: rollout-demo-app
spec:
podSpec:
containers:
- image: stefanprodan/podinfo:4.0.6
name: metrics-provider
ports:
- name: http
containerPort: 8080

View File

@@ -1,19 +0,0 @@
apiVersion: core.oam.dev/v1alpha2
kind: Component
metadata:
name: rollout-demo-app
spec:
workload:
apiVersion: standard.oam.dev/v1alpha1
kind: PodSpecWorkload
metadata:
labels:
app: rollout-demo-app
spec:
podSpec:
containers:
- image: stefanprodan/podinfo:5.0.2
name: metrics-provider
ports:
- name: http
containerPort: 8080

17
go.mod
View File

@@ -8,9 +8,6 @@ require (
github.com/FogDong/uitable v0.0.5
github.com/Masterminds/semver/v3 v3.2.1
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8
github.com/alibabacloud-go/cs-20151215/v3 v3.0.35
github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.4
github.com/alibabacloud-go/tea v1.1.20
github.com/aryann/difflib v0.0.0-20210328193216-ff5ff6dc229b
github.com/bluele/gcache v0.0.2
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869
@@ -23,10 +20,9 @@ require (
github.com/cue-exp/kubevelafix v0.0.0-20220922150317-aead819d979d
github.com/dave/jennifer v1.6.1
github.com/davecgh/go-spew v1.1.1
github.com/deckarep/golang-set v1.8.0
github.com/emicklei/go-restful/v3 v3.10.2 // indirect
github.com/ettle/strcase v0.1.1
github.com/evanphx/json-patch v5.6.0+incompatible
github.com/evanphx/json-patch v5.6.0+incompatible // indirect
github.com/evanphx/json-patch/v5 v5.6.0 // indirect
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect
github.com/fatih/camelcase v1.0.0 // indirect
@@ -134,15 +130,7 @@ require (
github.com/acomagu/bufpipe v1.0.4 // indirect
github.com/agext/levenshtein v1.2.3 // indirect
github.com/alessio/shellescape v1.4.1 // indirect
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.4 // indirect
github.com/alibabacloud-go/debug v0.0.0-20190504072949-9472017b5c68 // indirect
github.com/alibabacloud-go/endpoint-util v1.1.1 // indirect
github.com/alibabacloud-go/openapi-util v0.1.0 // indirect
github.com/alibabacloud-go/tea-utils v1.4.5 // indirect
github.com/alibabacloud-go/tea-utils/v2 v2.0.1 // indirect
github.com/alibabacloud-go/tea-xml v1.1.2 // indirect
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1704 // indirect
github.com/aliyun/credentials-go v1.1.2 // indirect
github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 // indirect
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 // indirect
@@ -152,7 +140,6 @@ require (
github.com/cenkalti/backoff/v4 v4.2.0 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/chai2010/gettext-go v1.0.2 // indirect
github.com/clbanning/mxj/v2 v2.5.5 // indirect
github.com/cloudflare/circl v1.3.3 // indirect
github.com/cockroachdb/apd/v2 v2.0.2 // indirect
github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect
@@ -262,12 +249,10 @@ require (
github.com/sergi/go-diff v1.1.0 // indirect
github.com/shopspring/decimal v1.3.1 // indirect
github.com/skeema/knownhosts v1.1.0 // indirect
github.com/spf13/afero v1.8.2 // indirect
github.com/spf13/cast v1.5.0 // indirect
github.com/stoewer/go-strcase v1.2.0 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
github.com/tjfoc/gmsm v1.3.2 // indirect
github.com/vbatts/tar-split v0.11.3 // indirect
github.com/xanzy/ssh-agent v0.3.3 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect

75
go.sum
View File

@@ -1,18 +1,15 @@
cloud.google.com/go v0.100.2 h1:t9Iw5QH5v4XtlEQaCtUY7x6sCABps8sW0acw7e2WQ6Y=
cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigtable v1.2.0/go.mod h1:JcVAOl45lrTmQfLj7T6TxyMzIN/3FGGcFm+2xVAli2o=
cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow=
cloud.google.com/go/compute v1.19.1 h1:am86mquDUgjGNWxiGn+5PGLbmgiWXlE/yNWpIpNvuXY=
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.3.0/go.mod h1:9IAwXhoyBJ7z9LcAwkj0/7NnPzYaPeZxxVp3zm+5IqA=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE=
contrib.go.opencensus.io/exporter/ocagent v0.6.0/go.mod h1:zmKjrJcdo0aYcVS7bmEeSEBLPA9YJp5bjrofdU3pIXs=
cuelang.org/go v0.5.0 h1:D6N0UgTGJCOxFKU8RU+qYvavKNsVc/+ZobmifStVJzU=
@@ -129,41 +126,9 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/alessio/shellescape v1.4.1 h1:V7yhSDDn8LP4lc4jS8pFkt0zCnzVJlG5JXy9BVKJUX0=
github.com/alessio/shellescape v1.4.1/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30=
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.4 h1:iC9YFYKDGEy3n/FtqJnOkZsene9olVspKmkX5A2YBEo=
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.4/go.mod h1:sCavSAvdzOjul4cEqeVtvlSaSScfNsTQ+46HwlTL1hc=
github.com/alibabacloud-go/cs-20151215/v3 v3.0.35 h1:yArmXiJD8m8WPu8ZKBroLNAn+5REA6c9BngwZIh4A4Q=
github.com/alibabacloud-go/cs-20151215/v3 v3.0.35/go.mod h1:NxWlrjZkPlfsrPPfsHmHBKwF82MDEfc/0qNA4ooIMQ8=
github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.2/go.mod h1:5JHVmnHvGzR2wNdgaW1zDLQG8kOC4Uec8ubkMogW7OQ=
github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.4 h1:7Q2FEyqxeZeIkwYMwRC3uphxV4i7O2eV4ETe21d6lS4=
github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.4/go.mod h1:5JHVmnHvGzR2wNdgaW1zDLQG8kOC4Uec8ubkMogW7OQ=
github.com/alibabacloud-go/debug v0.0.0-20190504072949-9472017b5c68 h1:NqugFkGxx1TXSh/pBcU00Y6bljgDPaFdh5MUSeJ7e50=
github.com/alibabacloud-go/debug v0.0.0-20190504072949-9472017b5c68/go.mod h1:6pb/Qy8c+lqua8cFpEy7g39NRRqOWc3rOwAy8m5Y2BY=
github.com/alibabacloud-go/endpoint-util v1.1.0/go.mod h1:O5FuCALmCKs2Ff7JFJMudHs0I5EBgecXXxZRyswlEjE=
github.com/alibabacloud-go/endpoint-util v1.1.1 h1:ZkBv2/jnghxtU0p+upSU0GGzW1VL9GQdZO3mcSUTUy8=
github.com/alibabacloud-go/endpoint-util v1.1.1/go.mod h1:O5FuCALmCKs2Ff7JFJMudHs0I5EBgecXXxZRyswlEjE=
github.com/alibabacloud-go/openapi-util v0.0.11/go.mod h1:sQuElr4ywwFRlCCberQwKRFhRzIyG4QTP/P4y1CJ6Ws=
github.com/alibabacloud-go/openapi-util v0.1.0 h1:0z75cIULkDrdEhkLWgi9tnLe+KhAFE/r5Pb3312/eAY=
github.com/alibabacloud-go/openapi-util v0.1.0/go.mod h1:sQuElr4ywwFRlCCberQwKRFhRzIyG4QTP/P4y1CJ6Ws=
github.com/alibabacloud-go/tea v1.1.0/go.mod h1:IkGyUSX4Ba1V+k4pCtJUc6jDpZLFph9QMy2VUPTwukg=
github.com/alibabacloud-go/tea v1.1.7/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4=
github.com/alibabacloud-go/tea v1.1.8/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4=
github.com/alibabacloud-go/tea v1.1.17/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A=
github.com/alibabacloud-go/tea v1.1.19/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A=
github.com/alibabacloud-go/tea v1.1.20 h1:wFK4xEbvGYMtzTyHhIju9D7ecWxvSUdoLO6y4vDLFik=
github.com/alibabacloud-go/tea v1.1.20/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A=
github.com/alibabacloud-go/tea-utils v1.3.1/go.mod h1:EI/o33aBfj3hETm4RLiAxF/ThQdSngxrpF8rKUDJjPE=
github.com/alibabacloud-go/tea-utils v1.4.5 h1:h0/6Xd2f3bPE4XHTvkpjwxowIwRCJAJOqY6Eq8f3zfA=
github.com/alibabacloud-go/tea-utils v1.4.5/go.mod h1:KNcT0oXlZZxOXINnZBs6YvgOd5aYp9U67G+E3R8fcQw=
github.com/alibabacloud-go/tea-utils/v2 v2.0.0/go.mod h1:U5MTY10WwlquGPS34DOeomUGBB0gXbLueiq5Trwu0C4=
github.com/alibabacloud-go/tea-utils/v2 v2.0.1 h1:K6kwgo+UiYx+/kr6CO0PN5ACZDzE3nnn9d77215AkTs=
github.com/alibabacloud-go/tea-utils/v2 v2.0.1/go.mod h1:U5MTY10WwlquGPS34DOeomUGBB0gXbLueiq5Trwu0C4=
github.com/alibabacloud-go/tea-xml v1.1.2 h1:oLxa7JUXm2EDFzMg+7oRsYc+kutgCVwm+bZlhhmvW5M=
github.com/alibabacloud-go/tea-xml v1.1.2/go.mod h1:Rq08vgCcCAjHyRi/M7xlHKUykZCEtyBy9+DPF6GgEu8=
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1704 h1:PpfENOj/vPfhhy9N2OFRjpue0hjM5XqAp2thFmkXXIk=
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1704/go.mod h1:RcDobYh8k5VP6TNybz9m++gL3ijVI5wueVr0EM10VsU=
github.com/aliyun/aliyun-oss-go-sdk v2.0.4+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
github.com/aliyun/credentials-go v1.1.2 h1:qU1vwGIBb3UJ8BwunHDRFtAhS6jnQLnde/yk0+Ih2GY=
github.com/aliyun/credentials-go v1.1.2/go.mod h1:ozcZaMR5kLM7pwtCMEpVmQ242suV6qTJya2bDq4X1Tw=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
@@ -263,8 +228,6 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
github.com/clbanning/mxj/v2 v2.5.5 h1:oT81vUeEiQQ/DcHbzSytRngP6Ky9O+L+0Bw0zSJag9E=
github.com/clbanning/mxj/v2 v2.5.5/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I=
@@ -273,7 +236,6 @@ github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUK
github.com/cloudtty/cloudtty v0.5.2 h1:3sp9CU4aN7nhBNCKCsae277Sw06uKx+o2dnln3mVXvo=
github.com/cloudtty/cloudtty v0.5.2/go.mod h1:gyxZNmuHhu+53n0mQV6n8TfMw4uwJHIA/7hZ2kKv1/4=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
@@ -336,8 +298,6 @@ github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4=
github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo=
github.com/denisenkom/go-mssqldb v0.9.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
@@ -393,7 +353,6 @@ github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4s
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
@@ -760,7 +719,6 @@ github.com/googleapis/gnostic v0.3.1/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1a
github.com/googleapis/gnostic v0.4.0/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU=
github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU=
github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4=
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
github.com/gophercloud/gophercloud v0.3.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
@@ -769,7 +727,6 @@ github.com/gophercloud/gophercloud v0.10.0/go.mod h1:gmC5oQqMDOMO1t1gq5DquX/yAU8
github.com/gophercloud/gophercloud v0.11.0/go.mod h1:gmC5oQqMDOMO1t1gq5DquX/yAU808e/4mzjjDA76+Ss=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gopherjs/gopherjs v0.0.0-20191106031601-ce3c9ade29de/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
@@ -1264,7 +1221,6 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
github.com/pkg/term v0.0.0-20180730021639-bffc007b7fd5/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ=
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -1408,7 +1364,6 @@ github.com/skeema/knownhosts v1.1.0 h1:Wvr9V0MxhjRbl3f9nMnKnFfiWTJmtECJ9Njkea3ys
github.com/skeema/knownhosts v1.1.0/go.mod h1:sKFq3RD6/TKZkSWn8boUbDC7Qkgcv+8XXijpFO6roag=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM=
github.com/smartystreets/assertions v1.1.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
@@ -1420,8 +1375,6 @@ github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
github.com/spf13/afero v1.8.2 h1:xehSyVa0YnHWsJ49JFljMpg1HX19V6NDZ1fkm1Xznbo=
github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
@@ -1483,8 +1436,6 @@ github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhV
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
github.com/tjfoc/gmsm v1.3.2 h1:7JVkAn5bvUJ7HtU08iW6UiD+UTmJTIToHCfeFzkcCxM=
github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 h1:uruHq4dN7GR16kFc5fp3d1RIYzJW5onx8Ybykw2YQFA=
@@ -1527,7 +1478,6 @@ github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.30/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
@@ -1581,7 +1531,6 @@ go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc=
@@ -1689,19 +1638,15 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20191202143827-86a70503ff7e/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20191219195013-becbf705a915/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200422194213-44a606286825/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
@@ -1740,7 +1685,6 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
@@ -1785,7 +1729,6 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
@@ -1824,8 +1767,6 @@ golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4Iltr
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
@@ -1875,9 +1816,7 @@ golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190530182044-ad28b68e88f1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -1910,7 +1849,6 @@ golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -1919,11 +1857,9 @@ golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -1983,7 +1919,6 @@ golang.org/x/text v0.3.1-0.20180805044716-cb6730876b98/go.mod h1:NqM8EUOU14njkJ3
golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
@@ -2025,7 +1960,6 @@ golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
@@ -2055,11 +1989,9 @@ golang.org/x/tools v0.0.0-20200313205530-4303120df7d8/go.mod h1:Sl4aGygMT6LrqrWc
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200422205258-72e4a01eba43/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200509030707-2212a7e161a5/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200603131246-cc40288be839/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
@@ -2096,7 +2028,6 @@ google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsb
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.26.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8=
google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k=
google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
@@ -2105,7 +2036,6 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
@@ -2132,8 +2062,6 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY
google.golang.org/genproto v0.0.0-20200603110839-e855014d5736/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201102152239-715cce707fb0/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
@@ -2168,8 +2096,6 @@ google.golang.org/grpc v1.29.0/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
@@ -2227,7 +2153,6 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.56.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=

View File

@@ -17,15 +17,4 @@ done
rm ${TEMPLATE_DIR}/*.bak
TEMPLATE_DIR="../../legacy/charts/vela-core-legacy/crds"
for filename in `ls "$TEMPLATE_DIR"`; do
sed -i.bak '/creationTimestamp: null/d' "${TEMPLATE_DIR}/$filename"
done
rm ${TEMPLATE_DIR}/*.bak
popd

View File

@@ -26,12 +26,7 @@ import (
var (
oldCRD = map[string]bool{
"components": true,
"applicationconfigurations": true,
"scopedefinitions": true,
"rollouts": true,
"healthscopes": true,
"workloaddefinitions": true,
"workloaddefinitions": true,
}
)

View File

@@ -1,39 +0,0 @@
# Legacy Support
Now lots of apps are still running on Kubernetes clusters version v1.14 or v1.15, while KubeVela core requires the minimum
Kubernetes version to be v1.16+.
Currently, the main blocker is KubeVela uses CRD v1, while those old Kubernetes versions don't support CRD v1.
So we generate v1beta1 CRD here for convenience. But we have no guarantee that KubeVela core will support the
legacy Kubernetes versions.
Follow the instructions in [README](../README.md) to create a namespace like `vela-system` and add the OAM Kubernetes
Runtime helm repo.
```
$ kubectl create namespace vela-system
$ helm repo add kubevela https://charts.kubevela.net/core
```
Run the following command to install a KubeVela core legacy chart.
```
$ helm install -n vela-system vela-core-legacy kubevela/vela-core-legacy
```
If you'd like to install an older version of the legacy chart, use `helm search` to choose a proper chart version. Remember
to add flag `--devel` if you prefer pre-release versions.
```
$ helm search repo vela-core-legacy -l
NAME CHART VERSION APP VERSION DESCRIPTION
kubevela/vela-core-legacy 0.2 0.2 A Helm chart for legacy KubeVela core Controlle...
kubevela/vela-core-legacy 0.0.1 0.1 A Helm chart for legacy KubeVela core Controlle...
$ helm install -n vela-system kubevela-legacy kubevela/vela-core-legacy --version 0.0.1
```
Install the legacy chart as below if you want a nightly version.
```
$ helm install -n vela-system vela-core-legacy kubevela/vela-core-legacy --set image.tag=master
```

View File

@@ -1,21 +0,0 @@
apiVersion: v1
name: vela-core-legacy
description: A Helm chart for legacy KubeVela Core Controller, targeted on Kubernetes v1.14 and v1.15
# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
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

View File

@@ -1,246 +0,0 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.6.2
name: appdeployments.core.oam.dev
spec:
group: core.oam.dev
names:
categories:
- oam
kind: AppDeployment
listKind: AppDeploymentList
plural: appdeployments
shortNames:
- appdeploy
singular: appdeployment
scope: Namespaced
versions:
- name: v1beta1
schema:
openAPIV3Schema:
description: AppDeployment is the Schema for the AppDeployment 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: AppDeploymentSpec defines how to describe an upgrade between
different apps
properties:
appRevisions:
description: AppRevision specifies AppRevision resources to and the
rules to apply to them.
items:
description: AppRevision specifies an AppRevision resource to and
the rules to apply to it.
properties:
placement:
description: Placement defines the cluster placement rules for
an app revision.
items:
description: ClusterPlacement defines the cluster placement
rules for an app revision.
properties:
clusterSelector:
description: ClusterSelector selects the cluster to deploy
apps to. If not specified, it indicates the host cluster
per se.
properties:
labels:
additionalProperties:
type: string
description: Labels defines the label selector to
select the cluster.
type: object
name:
description: Name is the name of the cluster.
type: string
type: object
distribution:
description: Distribution defines the replica distribution
of an AppRevision to a cluster.
properties:
replicas:
description: Replicas is the replica number.
type: integer
type: object
type: object
type: array
revisionName:
description: RevisionName is the name of the AppRevision.
type: string
type: object
type: array
traffic:
description: Traffic defines the traffic rules to apply across revisions.
properties:
gateways:
description: Gateways specifies the names of gateways that should
apply these rules. Gateways in other namespaces may be referred
to by `<gateway namespace>/<gateway name>`; specifying a gateway
with no namespace qualifier is the same as specifying the AppDeployment's
namespace.
items:
type: string
type: array
hosts:
description: Hosts are the destination hosts to which traffic
is being sent. Could be a DNS name with wildcard prefix or an
IP address.
items:
type: string
type: array
http:
description: HTTP defines the rules to match and split http traffoc
across revisions.
items:
description: HTTPRule defines the rules to match and split http
traffic across revisions.
properties:
match:
description: Match defines the conditions to be satisfied
for the rule to be activated. All conditions inside a
single match block have AND semantics, while the list
of match blocks have OR semantics. The rule is matched
if any one of the match blocks succeed.
items:
description: HTTPMatchRequest specifies a set of criterion
to be met in order for the rule to be applied to the
HTTP request. For example, the following restricts the
rule to match only requests where the URL path starts
with /ratings/v2/ and the request contains a custom
`end-user` header with value `jason`.
properties:
uri:
description: URI defines how to match with an URI.
properties:
prefix:
type: string
type: object
type: object
type: array
weightedTargets:
description: WeightedTargets defines the revision targets
to select and route traffic to.
items:
description: WeightedTarget defines the revision target
to select and route traffic to.
properties:
componentName:
description: ComponentName is the name of the component.
Note that it is the original component name in the
Application. No need to append revision.
type: string
port:
description: Port is the port to route traffic towards.
type: integer
revisionName:
description: RevisionName is the name of the app revision.
type: string
weight:
description: Weight defines the proportion of traffic
to be forwarded to the service version. (0-100).
Sum of weights across destinations SHOULD BE ==
100. If there is only one destination in a rule,
the weight value is assumed to be 100.
type: integer
type: object
type: array
type: object
type: array
type: object
type: object
status:
description: AppDeploymentStatus defines the observed state of AppDeployment
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
phase:
description: Phase shows the phase that the AppDeployment is undergoing.
If Phase is Rolling, no update should be made to the spec.
type: string
placement:
description: Placement shows the cluster placement results of the
app revisions.
items:
description: PlacementStatus shows the cluster placement results
of an app revision.
properties:
clusters:
description: Clusters shows cluster placement results.
items:
description: ClusterPlacementStatus shows the placement results
of a cluster.
properties:
clusterName:
description: ClusterName indicates the name of the cluster
to deploy apps to. If empty, it indicates the host cluster
per se.
type: string
replicas:
description: Replicas indicates the replica number of
an app revision to deploy to a cluster.
type: integer
type: object
type: array
revisionName:
description: RevisionName is the name of the AppRevision.
type: string
type: object
type: array
type: object
type: object
served: true
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []

View File

@@ -1,954 +0,0 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.6.2
name: approllouts.core.oam.dev
spec:
group: core.oam.dev
names:
categories:
- oam
kind: AppRollout
listKind: AppRolloutList
plural: approllouts
shortNames:
- approllout
singular: approllout
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .status.rolloutStatus.rolloutTargetSize
name: TARGET
type: string
- jsonPath: .status.rolloutStatus.upgradedReplicas
name: UPGRADED
type: string
- jsonPath: .status.rolloutStatus.upgradedReadyReplicas
name: READY
type: string
- jsonPath: .status.rolloutStatus.batchRollingState
name: BATCH-STATE
type: string
- jsonPath: .status.rolloutStatus.rollingState
name: ROLLING-STATE
type: string
- jsonPath: .metadata.creationTimestamp
name: AGE
type: date
name: v1alpha2
schema:
openAPIV3Schema:
description: AppRollout is the Schema for the AppRollout 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: AppRolloutSpec defines how to describe an upgrade between
different apps
properties:
componentList:
description: 'The list of component to upgrade in the application.
We only support single component application so far TODO: (RZ) Support
multiple components in an application'
items:
type: string
type: array
revertOnDelete:
description: RevertOnDelete revert the rollout when the rollout CR
is deleted It will remove the target app from the kubernetes if
it's set to true
type: boolean
rolloutPlan:
description: RolloutPlan is the details on how to rollout the resources
properties:
batchPartition:
description: All pods in the batches up to the batchPartition
(included) will have the target resource specification while
the rest still have the source resource This is designed for
the operators to manually rollout Default is the the number
of batches which will rollout all the batches
format: int32
type: integer
canaryMetric:
description: CanaryMetric provides a way for the rollout process
to automatically check certain metrics before complete the process
items:
description: CanaryMetric holds the reference to metrics used
for canary analysis
properties:
interval:
description: Interval represents the windows size
type: string
metricsRange:
description: Range value accepted for this metric
properties:
max:
anyOf:
- type: integer
- type: string
description: Maximum value
x-kubernetes-int-or-string: true
min:
anyOf:
- type: integer
- type: string
description: Minimum value
x-kubernetes-int-or-string: true
type: object
name:
description: Name of the metric
type: string
templateRef:
description: TemplateRef references a metric template object
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
required:
- name
type: object
type: array
numBatches:
description: The number of batches, default = 1
format: int32
type: integer
paused:
description: Paused the rollout, default is false
type: boolean
rolloutBatches:
description: The exact distribution among batches. its size has
to be exactly the same as the NumBatches (if set) The total
number cannot exceed the targetSize or the size of the source
resource We will IGNORE the last batch's replica field if it's
a percentage since round errors can lead to inaccurate sum We
highly recommend to leave the last batch's replica field empty
items:
description: RolloutBatch is used to describe how the each batch
rollout should be
properties:
batchRolloutWebhooks:
description: RolloutWebhooks provides a way for the batch
rollout to interact with an external process
items:
description: RolloutWebhook holds the reference to external
checks used for canary analysis
properties:
expectedStatus:
description: ExpectedStatus contains all the expected
http status code that we will accept as success
items:
type: integer
type: array
metadata:
additionalProperties:
type: string
description: Metadata (key-value pairs) for this webhook
type: object
method:
description: Method the HTTP call method, default
is POST
type: string
name:
description: Name of this webhook
type: string
type:
description: Type of this webhook
type: string
url:
description: URL address of this webhook
type: string
required:
- name
- type
- url
type: object
type: array
canaryMetric:
description: CanaryMetric provides a way for the batch rollout
process to automatically check certain metrics before
moving to the next batch
items:
description: CanaryMetric holds the reference to metrics
used for canary analysis
properties:
interval:
description: Interval represents the windows size
type: string
metricsRange:
description: Range value accepted for this metric
properties:
max:
anyOf:
- type: integer
- type: string
description: Maximum value
x-kubernetes-int-or-string: true
min:
anyOf:
- type: integer
- type: string
description: Minimum value
x-kubernetes-int-or-string: true
type: object
name:
description: Name of the metric
type: string
templateRef:
description: TemplateRef references a metric template
object
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
required:
- name
type: object
type: array
instanceInterval:
description: The wait time, in seconds, between instances
upgrades, default = 0
format: int32
type: integer
maxUnavailable:
anyOf:
- type: integer
- type: string
description: MaxUnavailable is the max allowed number of
pods that is unavailable during the upgrade. We will mark
the batch as ready as long as there are less or equal
number of pods unavailable than this number. default =
0
x-kubernetes-int-or-string: true
podList:
description: The list of Pods to get upgraded it is mutually
exclusive with the Replicas field
items:
type: string
type: array
replicas:
anyOf:
- type: integer
- type: string
description: 'Replicas is the number of pods to upgrade
in this batch it can be an absolute number (ex: 5) or
a percentage of total pods we will ignore the percentage
of the last batch to just fill the gap it is mutually
exclusive with the PodList field'
x-kubernetes-int-or-string: true
type: object
type: array
rolloutStrategy:
description: RolloutStrategy defines strategies for the rollout
plan The default is IncreaseFirstRolloutStrategyType
type: string
rolloutWebhooks:
description: RolloutWebhooks provide a way for the rollout to
interact with an external process
items:
description: RolloutWebhook holds the reference to external
checks used for canary analysis
properties:
expectedStatus:
description: ExpectedStatus contains all the expected http
status code that we will accept as success
items:
type: integer
type: array
metadata:
additionalProperties:
type: string
description: Metadata (key-value pairs) for this webhook
type: object
method:
description: Method the HTTP call method, default is POST
type: string
name:
description: Name of this webhook
type: string
type:
description: Type of this webhook
type: string
url:
description: URL address of this webhook
type: string
required:
- name
- type
- url
type: object
type: array
targetSize:
description: The size of the target resource. The default is the
same as the size of the source resource.
format: int32
type: integer
type: object
sourceAppRevisionName:
description: SourceAppRevisionName contains the name of the applicationRevision
that we need to upgrade from. it can be empty only when the rolling
is only a scale event
type: string
targetAppRevisionName:
description: TargetAppRevisionName contains the name of the applicationRevision
that we need to upgrade to.
type: string
required:
- rolloutPlan
- targetAppRevisionName
type: object
status:
description: AppRolloutStatus defines the observed state of AppRollout
properties:
LastSourceAppRevision:
description: LastSourceAppRevision contains the name of the app that
we need to upgrade from. We will restart the rollout if this is
not the same as the spec
type: string
batchRollingState:
description: BatchRollingState only meaningful when the Status is
rolling
type: string
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
currentBatch:
description: The current batch the rollout is working on/blocked it
starts from 0
format: int32
type: integer
lastAppliedPodTemplateIdentifier:
description: lastAppliedPodTemplateIdentifier is a string that uniquely
represent the last pod template each workload type could use different
ways to identify that so we cannot compare between resources We
update this field only after a successful rollout
type: string
lastTargetAppRevision:
description: LastUpgradedTargetAppRevision contains the name of the
app that we upgraded to We will restart the rollout if this is not
the same as the spec
type: string
rollingState:
description: RollingState is the Rollout State
type: string
rolloutOriginalSize:
description: RolloutTargetSize is the size of the target resources.
This is determined once the initial spec verification and does not
change until the rollout is restarted
format: int32
type: integer
rolloutTargetSize:
description: RolloutTargetSize is the size of the target resources.
This is determined once the initial spec verification and does not
change until the rollout is restarted
format: int32
type: integer
targetGeneration:
description: NewPodTemplateIdentifier is a string that uniquely represent
the new pod template each workload type could use different ways
to identify that so we cannot compare between resources
type: string
upgradedReadyReplicas:
description: UpgradedReadyReplicas is the number of Pods upgraded
by the rollout controller that have a Ready Condition.
format: int32
type: integer
upgradedReplicas:
description: UpgradedReplicas is the number of Pods upgraded by the
rollout controller
format: int32
type: integer
required:
- currentBatch
- lastTargetAppRevision
- rollingState
- upgradedReadyReplicas
- upgradedReplicas
type: object
type: object
served: true
storage: false
subresources:
status: {}
- additionalPrinterColumns:
- jsonPath: .status.rolloutTargetSize
name: TARGET
type: string
- jsonPath: .status.upgradedReplicas
name: UPGRADED
type: string
- jsonPath: .status.upgradedReadyReplicas
name: READY
type: string
- jsonPath: .status.batchRollingState
name: BATCH-STATE
type: string
- jsonPath: .status.rollingState
name: ROLLING-STATE
type: string
- jsonPath: .metadata.creationTimestamp
name: AGE
type: date
name: v1beta1
schema:
openAPIV3Schema:
description: AppRollout is the Schema for the AppRollout 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: AppRolloutSpec defines how to describe an upgrade between
different apps
properties:
componentList:
description: 'The list of component to upgrade in the application.
We only support single component application so far TODO: (RZ) Support
multiple components in an application'
items:
type: string
type: array
revertOnDelete:
description: RevertOnDelete revert the failed rollout when the rollout
CR is deleted It will revert the change back to the source version
at once (not in batches) Default is false
type: boolean
rolloutPlan:
description: RolloutPlan is the details on how to rollout the resources
properties:
batchPartition:
description: All pods in the batches up to the batchPartition
(included) will have the target resource specification while
the rest still have the source resource This is designed for
the operators to manually rollout Default is the the number
of batches which will rollout all the batches
format: int32
type: integer
canaryMetric:
description: CanaryMetric provides a way for the rollout process
to automatically check certain metrics before complete the process
items:
description: CanaryMetric holds the reference to metrics used
for canary analysis
properties:
interval:
description: Interval represents the windows size
type: string
metricsRange:
description: Range value accepted for this metric
properties:
max:
anyOf:
- type: integer
- type: string
description: Maximum value
x-kubernetes-int-or-string: true
min:
anyOf:
- type: integer
- type: string
description: Minimum value
x-kubernetes-int-or-string: true
type: object
name:
description: Name of the metric
type: string
templateRef:
description: TemplateRef references a metric template object
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
required:
- name
type: object
type: array
numBatches:
description: The number of batches, default = 1
format: int32
type: integer
paused:
description: Paused the rollout, default is false
type: boolean
rolloutBatches:
description: The exact distribution among batches. its size has
to be exactly the same as the NumBatches (if set) The total
number cannot exceed the targetSize or the size of the source
resource We will IGNORE the last batch's replica field if it's
a percentage since round errors can lead to inaccurate sum We
highly recommend to leave the last batch's replica field empty
items:
description: RolloutBatch is used to describe how the each batch
rollout should be
properties:
batchRolloutWebhooks:
description: RolloutWebhooks provides a way for the batch
rollout to interact with an external process
items:
description: RolloutWebhook holds the reference to external
checks used for canary analysis
properties:
expectedStatus:
description: ExpectedStatus contains all the expected
http status code that we will accept as success
items:
type: integer
type: array
metadata:
additionalProperties:
type: string
description: Metadata (key-value pairs) for this webhook
type: object
method:
description: Method the HTTP call method, default
is POST
type: string
name:
description: Name of this webhook
type: string
type:
description: Type of this webhook
type: string
url:
description: URL address of this webhook
type: string
required:
- name
- type
- url
type: object
type: array
canaryMetric:
description: CanaryMetric provides a way for the batch rollout
process to automatically check certain metrics before
moving to the next batch
items:
description: CanaryMetric holds the reference to metrics
used for canary analysis
properties:
interval:
description: Interval represents the windows size
type: string
metricsRange:
description: Range value accepted for this metric
properties:
max:
anyOf:
- type: integer
- type: string
description: Maximum value
x-kubernetes-int-or-string: true
min:
anyOf:
- type: integer
- type: string
description: Minimum value
x-kubernetes-int-or-string: true
type: object
name:
description: Name of the metric
type: string
templateRef:
description: TemplateRef references a metric template
object
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
required:
- name
type: object
type: array
instanceInterval:
description: The wait time, in seconds, between instances
upgrades, default = 0
format: int32
type: integer
maxUnavailable:
anyOf:
- type: integer
- type: string
description: MaxUnavailable is the max allowed number of
pods that is unavailable during the upgrade. We will mark
the batch as ready as long as there are less or equal
number of pods unavailable than this number. default =
0
x-kubernetes-int-or-string: true
podList:
description: The list of Pods to get upgraded it is mutually
exclusive with the Replicas field
items:
type: string
type: array
replicas:
anyOf:
- type: integer
- type: string
description: 'Replicas is the number of pods to upgrade
in this batch it can be an absolute number (ex: 5) or
a percentage of total pods we will ignore the percentage
of the last batch to just fill the gap it is mutually
exclusive with the PodList field'
x-kubernetes-int-or-string: true
type: object
type: array
rolloutStrategy:
description: RolloutStrategy defines strategies for the rollout
plan The default is IncreaseFirstRolloutStrategyType
type: string
rolloutWebhooks:
description: RolloutWebhooks provide a way for the rollout to
interact with an external process
items:
description: RolloutWebhook holds the reference to external
checks used for canary analysis
properties:
expectedStatus:
description: ExpectedStatus contains all the expected http
status code that we will accept as success
items:
type: integer
type: array
metadata:
additionalProperties:
type: string
description: Metadata (key-value pairs) for this webhook
type: object
method:
description: Method the HTTP call method, default is POST
type: string
name:
description: Name of this webhook
type: string
type:
description: Type of this webhook
type: string
url:
description: URL address of this webhook
type: string
required:
- name
- type
- url
type: object
type: array
targetSize:
description: The size of the target resource. The default is the
same as the size of the source resource.
format: int32
type: integer
type: object
sourceAppRevisionName:
description: SourceAppRevisionName contains the name of the applicationConfiguration
that we need to upgrade from. it can be empty only when it's the
first time to deploy the application
type: string
targetAppRevisionName:
description: TargetAppRevisionName contains the name of the applicationConfiguration
that we need to upgrade to. Here we use an applicationConfiguration
as a revision of an application, thus the name alone is suffice
type: string
required:
- rolloutPlan
- targetAppRevisionName
type: object
status:
description: AppRolloutStatus defines the observed state of AppRollout
properties:
LastSourceAppRevision:
description: LastSourceAppRevision contains the name of the app that
we need to upgrade from. We will restart the rollout if this is
not the same as the spec
type: string
batchRollingState:
description: BatchRollingState only meaningful when the Status is
rolling
type: string
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
currentBatch:
description: The current batch the rollout is working on/blocked it
starts from 0
format: int32
type: integer
lastAppliedPodTemplateIdentifier:
description: lastAppliedPodTemplateIdentifier is a string that uniquely
represent the last pod template each workload type could use different
ways to identify that so we cannot compare between resources We
update this field only after a successful rollout
type: string
lastTargetAppRevision:
description: LastUpgradedTargetAppRevision contains the name of the
app that we upgraded to We will restart the rollout if this is not
the same as the spec
type: string
rollingState:
description: RollingState is the Rollout State
type: string
rolloutOriginalSize:
description: RolloutTargetSize is the size of the target resources.
This is determined once the initial spec verification and does not
change until the rollout is restarted
format: int32
type: integer
rolloutTargetSize:
description: RolloutTargetSize is the size of the target resources.
This is determined once the initial spec verification and does not
change until the rollout is restarted
format: int32
type: integer
targetGeneration:
description: NewPodTemplateIdentifier is a string that uniquely represent
the new pod template each workload type could use different ways
to identify that so we cannot compare between resources
type: string
upgradedReadyReplicas:
description: UpgradedReadyReplicas is the number of Pods upgraded
by the rollout controller that have a Ready Condition.
format: int32
type: integer
upgradedReplicas:
description: UpgradedReplicas is the number of Pods upgraded by the
rollout controller
format: int32
type: integer
required:
- currentBatch
- lastTargetAppRevision
- rollingState
- upgradedReadyReplicas
- upgradedReplicas
type: object
type: object
served: true
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []

View File

@@ -1,60 +0,0 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.6.2
name: clusters.core.oam.dev
spec:
group: core.oam.dev
names:
kind: Cluster
listKind: ClusterList
plural: clusters
singular: cluster
scope: Namespaced
versions:
- name: v1beta1
schema:
openAPIV3Schema:
description: Cluster is the Schema for the clusters 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: ClusterSpec defines the desired state of Cluster
properties:
kubeconfigSecretRef:
description: KubeconfigSecretRef specifies the reference to the secret
that contains the kubeconfig in field `config`.
properties:
name:
description: Name of a secret within the enclosing namespace.
type: string
required:
- name
type: object
type: object
status:
description: ClusterStatus defines the observed state of Cluster
type: object
type: object
served: true
storage: true
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []

View File

@@ -1,674 +0,0 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.11.4
name: componentdefinitions.core.oam.dev
spec:
group: core.oam.dev
names:
categories:
- oam
kind: ComponentDefinition
listKind: ComponentDefinitionList
plural: componentdefinitions
shortNames:
- comp
singular: componentdefinition
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .spec.workload.definition.kind
name: WORKLOAD-KIND
type: string
- jsonPath: .metadata.annotations.definition\.oam\.dev/description
name: DESCRIPTION
type: string
name: v1alpha2
schema:
openAPIV3Schema:
description: ComponentDefinition is the Schema for the componentdefinitions
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: ComponentDefinitionSpec defines the desired state of ComponentDefinition
properties:
childResourceKinds:
description: ChildResourceKinds are the list of GVK of the child resources
this workload generates
items:
description: A ChildResourceKind defines a child Kubernetes resource
kind with a selector
properties:
apiVersion:
description: APIVersion of the child resource
type: string
kind:
description: Kind of the child resource
type: string
selector:
additionalProperties:
type: string
description: Selector to select the child resources that the
workload wants to expose to traits
type: object
required:
- apiVersion
- kind
type: object
type: array
extension:
description: Extension is used for extension needs by OAM platform
builders
type: object
podSpecPath:
description: PodSpecPath indicates where/if this workload has K8s
podSpec field if one workload has podSpec, trait can do lot's of
assumption such as port, env, volume fields.
type: string
revisionLabel:
description: RevisionLabel indicates which label for underlying resources(e.g.
pods) of this workload can be used by trait to create resource selectors(e.g.
label selector for pods).
type: string
schematic:
description: Schematic defines the data format and template of the
encapsulation of the workload
properties:
cue:
description: CUE defines the encapsulation in CUE format
properties:
template:
description: Template defines the abstraction template data
of the capability, it will replace the old CUE template
in extension field. Template is a required field if CUE
is defined in Capability Definition.
type: string
required:
- template
type: object
helm:
description: A Helm represents resources used by a Helm module
properties:
release:
description: Release records a Helm release used by a Helm
module workload.
type: object
repository:
description: HelmRelease records a Helm repository used by
a Helm module workload.
type: object
required:
- release
- repository
type: object
kube:
description: Kube defines the encapsulation in raw Kubernetes
resource format
properties:
parameters:
description: Parameters defines configurable parameters
items:
description: A KubeParameter defines a configurable parameter
of a component.
properties:
description:
description: Description of this parameter.
type: string
fieldPaths:
description: "FieldPaths specifies an array of fields
within this workload that will be overwritten by the
value of this parameter. \tAll fields must be of the
same type. Fields are specified as JSON field paths
without a leading dot, for example 'spec.replicas'."
items:
type: string
type: array
name:
description: Name of this parameter
type: string
required:
description: Required specifies whether or not a value
for this parameter must be supplied when authoring
an Application.
type: boolean
type:
description: 'ValueType indicates the type of the parameter
value, and only supports basic data types: string,
number, boolean.'
enum:
- string
- number
- boolean
type: string
required:
- fieldPaths
- name
- type
type: object
type: array
template:
description: Template defines the raw Kubernetes resource
type: object
required:
- template
type: object
terraform:
description: Terraform is the struct to describe cloud resources
managed by Hashicorp Terraform
properties:
configuration:
description: Configuration is Terraform Configuration
type: string
customRegion:
description: Region is cloud provider's region. It will override
the region in the region field of ProviderReference
type: string
deleteResource:
default: true
description: DeleteResource will determine whether provisioned
cloud resources will be deleted when CR is deleted
type: boolean
gitCredentialsSecretReference:
description: GitCredentialsSecretReference specifies the reference
to the secret containing the git credentials
properties:
name:
description: name is unique within a namespace to reference
a secret resource.
type: string
namespace:
description: namespace defines the space within which
the secret name must be unique.
type: string
type: object
x-kubernetes-map-type: atomic
path:
description: Path is the sub-directory of remote git repository.
It's valid when remote is set
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 referenced object.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
it is, HCL or JSON syntax
enum:
- hcl
- json
- remote
type: string
writeConnectionSecretToRef:
description: WriteConnectionSecretToReference specifies the
namespace and name of a Secret to which any connection details
for this managed resource should be written. Connection
details frequently include the endpoint, username, and password
required to connect to the managed resource.
properties:
name:
description: Name of the secret.
type: string
namespace:
description: Namespace of the secret.
type: string
required:
- name
type: object
required:
- configuration
type: object
type: object
status:
description: Status defines the custom health policy and status message
for workload
properties:
customStatus:
description: CustomStatus defines the custom status message that
could display to user
type: string
healthPolicy:
description: HealthPolicy defines the health check policy for
the abstraction
type: string
type: object
workload:
description: Workload is a workload type descriptor
properties:
definition:
description: Definition mutually exclusive to workload.type, a
embedded WorkloadDefinition
properties:
apiVersion:
type: string
kind:
type: string
required:
- apiVersion
- kind
type: object
type:
description: Type ref to a WorkloadDefinition via name
type: string
type: object
required:
- workload
type: object
status:
description: ComponentDefinitionStatus is the status of ComponentDefinition
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
configMapRef:
description: ConfigMapRef refer to a ConfigMap which contains OpenAPI
V3 JSON schema of Component parameters.
type: string
latestRevision:
description: LatestRevision of the component definition
properties:
name:
type: string
revision:
format: int64
type: integer
revisionHash:
description: RevisionHash record the hash value of the spec of
ApplicationRevision object.
type: string
required:
- name
- revision
type: object
type: object
type: object
served: true
storage: false
subresources:
status: {}
- additionalPrinterColumns:
- jsonPath: .spec.workload.definition.kind
name: WORKLOAD-KIND
type: string
- jsonPath: .metadata.annotations.definition\.oam\.dev/description
name: DESCRIPTION
type: string
name: v1beta1
schema:
openAPIV3Schema:
description: ComponentDefinition is the Schema for the componentdefinitions
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: ComponentDefinitionSpec defines the desired state of ComponentDefinition
properties:
childResourceKinds:
description: ChildResourceKinds are the list of GVK of the child resources
this workload generates
items:
description: A ChildResourceKind defines a child Kubernetes resource
kind with a selector
properties:
apiVersion:
description: APIVersion of the child resource
type: string
kind:
description: Kind of the child resource
type: string
selector:
additionalProperties:
type: string
description: Selector to select the child resources that the
workload wants to expose to traits
type: object
required:
- apiVersion
- kind
type: object
type: array
extension:
description: Extension is used for extension needs by OAM platform
builders
type: object
podSpecPath:
description: PodSpecPath indicates where/if this workload has K8s
podSpec field if one workload has podSpec, trait can do lot's of
assumption such as port, env, volume fields.
type: string
revisionLabel:
description: RevisionLabel indicates which label for underlying resources(e.g.
pods) of this workload can be used by trait to create resource selectors(e.g.
label selector for pods).
type: string
schematic:
description: Schematic defines the data format and template of the
encapsulation of the workload
properties:
cue:
description: CUE defines the encapsulation in CUE format
properties:
template:
description: Template defines the abstraction template data
of the capability, it will replace the old CUE template
in extension field. Template is a required field if CUE
is defined in Capability Definition.
type: string
required:
- template
type: object
helm:
description: A Helm represents resources used by a Helm module
properties:
release:
description: Release records a Helm release used by a Helm
module workload.
type: object
repository:
description: HelmRelease records a Helm repository used by
a Helm module workload.
type: object
required:
- release
- repository
type: object
kube:
description: Kube defines the encapsulation in raw Kubernetes
resource format
properties:
parameters:
description: Parameters defines configurable parameters
items:
description: A KubeParameter defines a configurable parameter
of a component.
properties:
description:
description: Description of this parameter.
type: string
fieldPaths:
description: "FieldPaths specifies an array of fields
within this workload that will be overwritten by the
value of this parameter. \tAll fields must be of the
same type. Fields are specified as JSON field paths
without a leading dot, for example 'spec.replicas'."
items:
type: string
type: array
name:
description: Name of this parameter
type: string
required:
description: Required specifies whether or not a value
for this parameter must be supplied when authoring
an Application.
type: boolean
type:
description: 'ValueType indicates the type of the parameter
value, and only supports basic data types: string,
number, boolean.'
enum:
- string
- number
- boolean
type: string
required:
- fieldPaths
- name
- type
type: object
type: array
template:
description: Template defines the raw Kubernetes resource
type: object
required:
- template
type: object
terraform:
description: Terraform is the struct to describe cloud resources
managed by Hashicorp Terraform
properties:
configuration:
description: Configuration is Terraform Configuration
type: string
customRegion:
description: Region is cloud provider's region. It will override
the region in the region field of ProviderReference
type: string
deleteResource:
default: true
description: DeleteResource will determine whether provisioned
cloud resources will be deleted when CR is deleted
type: boolean
gitCredentialsSecretReference:
description: GitCredentialsSecretReference specifies the reference
to the secret containing the git credentials
properties:
name:
description: name is unique within a namespace to reference
a secret resource.
type: string
namespace:
description: namespace defines the space within which
the secret name must be unique.
type: string
type: object
x-kubernetes-map-type: atomic
path:
description: Path is the sub-directory of remote git repository.
It's valid when remote is set
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 referenced object.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
it is, HCL or JSON syntax
enum:
- hcl
- json
- remote
type: string
writeConnectionSecretToRef:
description: WriteConnectionSecretToReference specifies the
namespace and name of a Secret to which any connection details
for this managed resource should be written. Connection
details frequently include the endpoint, username, and password
required to connect to the managed resource.
properties:
name:
description: Name of the secret.
type: string
namespace:
description: Namespace of the secret.
type: string
required:
- name
type: object
required:
- configuration
type: object
type: object
status:
description: Status defines the custom health policy and status message
for workload
properties:
customStatus:
description: CustomStatus defines the custom status message that
could display to user
type: string
healthPolicy:
description: HealthPolicy defines the health check policy for
the abstraction
type: string
type: object
workload:
description: Workload is a workload type descriptor
properties:
definition:
description: Definition mutually exclusive to workload.type, a
embedded WorkloadDefinition
properties:
apiVersion:
type: string
kind:
type: string
required:
- apiVersion
- kind
type: object
type:
description: Type ref to a WorkloadDefinition via name
type: string
type: object
required:
- workload
type: object
status:
description: ComponentDefinitionStatus is the status of ComponentDefinition
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
configMapRef:
description: ConfigMapRef refer to a ConfigMap which contains OpenAPI
V3 JSON schema of Component parameters.
type: string
latestRevision:
description: LatestRevision of the component definition
properties:
name:
type: string
revision:
format: int64
type: integer
revisionHash:
description: RevisionHash record the hash value of the spec of
ApplicationRevision object.
type: string
required:
- name
- revision
type: object
type: object
type: object
served: true
storage: true
subresources:
status: {}

View File

@@ -1,171 +0,0 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.11.4
name: components.core.oam.dev
spec:
group: core.oam.dev
names:
categories:
- oam
kind: Component
listKind: ComponentList
plural: components
singular: component
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .spec.workload.kind
name: WORKLOAD-KIND
type: string
- jsonPath: .metadata.creationTimestamp
name: age
type: date
name: v1alpha2
schema:
openAPIV3Schema:
description: A Component describes how an OAM workload kind may be instantiated.
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 ComponentSpec defines the desired state of a Component.
properties:
helm:
description: HelmRelease records a Helm release used by a Helm module
workload.
properties:
release:
description: Release records a Helm release used by a Helm module
workload.
type: object
repository:
description: HelmRelease records a Helm repository used by a Helm
module workload.
type: object
required:
- release
- repository
type: object
parameters:
description: Parameters exposed by this component. ApplicationConfigurations
that reference this component may specify values for these parameters,
which will in turn be injected into the embedded workload.
items:
description: A ComponentParameter defines a configurable parameter
of a component.
properties:
description:
description: Description of this parameter.
type: string
fieldPaths:
description: FieldPaths specifies an array of fields within
this Component's workload that will be overwritten by the
value of this parameter. The type of the parameter (e.g. int,
string) is inferred from the type of these fields; All fields
must be of the same type. Fields are specified as JSON field
paths without a leading dot, for example 'spec.replicas'.
items:
type: string
type: array
name:
description: Name of this parameter. OAM ApplicationConfigurations
will specify parameter values using this name.
type: string
required:
description: Required specifies whether or not a value for this
parameter must be supplied when authoring an ApplicationConfiguration.
type: boolean
required:
- fieldPaths
- name
type: object
type: array
workload:
description: A Workload that will be created for each ApplicationConfiguration
that includes this Component. Workload is an instance of a workloadDefinition.
We either use the GVK info or a special "type" field in the workload
to associate the content of the workload with its workloadDefinition
type: object
required:
- workload
type: object
status:
description: A ComponentStatus represents the observed state of a Component.
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
latestRevision:
description: LatestRevision of component
properties:
name:
type: string
revision:
format: int64
type: integer
revisionHash:
description: RevisionHash record the hash value of the spec of
ApplicationRevision object.
type: string
required:
- name
- revision
type: object
observedGeneration:
description: The generation observed by the component controller.
format: int64
type: integer
type: object
type: object
served: true
storage: true
subresources:
status: {}

View File

@@ -1,319 +0,0 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.6.2
name: envbindings.core.oam.dev
spec:
group: core.oam.dev
names:
categories:
- oam
kind: EnvBinding
listKind: EnvBindingList
plural: envbindings
shortNames:
- envbind
singular: envbinding
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .spec.engine
name: ENGINE
type: string
- jsonPath: .status.phase
name: PHASE
type: string
- jsonPath: .metadata.creationTimestamp
name: AGE
type: date
name: v1alpha1
schema:
openAPIV3Schema:
description: EnvBinding is the Schema for the EnvBinding 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 EnvBindingSpec defines the desired state of a EnvBinding.
properties:
appTemplate:
description: AppTemplate indicates the application template.
type: object
engine:
description: ClusterManagementEngine represents a multi-cluster management
solution
type: string
envs:
items:
description: EnvConfig is the configuration for different environments.
properties:
name:
type: string
patch:
description: EnvPatch specify the parameter configuration for
different environments
properties:
components:
items:
description: ApplicationComponent describe the component
of application
properties:
dependsOn:
items:
type: string
type: array
externalRevision:
description: ExternalRevision specified the component
revisionName
type: string
inputs:
description: StepInputs defines variable input of
WorkflowStep
items:
properties:
from:
type: string
parameterKey:
type: string
required:
- from
- parameterKey
type: object
type: array
name:
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
scopes:
additionalProperties:
type: string
description: scopes in ApplicationComponent defines
the component-level scopes the format is <scope-type:scope-instance-name>
pairs, the key represents type of `ScopeDefinition`
while the value represent the name of scope instance.
type: object
traits:
description: Traits define the trait of one component,
the type must be array to keep the order.
items:
description: ApplicationTrait defines the trait
of application
properties:
properties:
type: object
type:
type: string
required:
- type
type: object
type: array
type:
type: string
required:
- name
- type
type: object
type: array
required:
- components
type: object
placement:
description: EnvPlacement defines the placement rules for an
app.
properties:
clusterSelector:
description: ClusterSelector defines the rules to select
a Cluster resource. Either name or labels is needed.
properties:
labels:
additionalProperties:
type: string
description: Labels defines the label selector to select
the cluster.
type: object
name:
description: Name is the name of the cluster.
type: string
type: object
namespaceSelector:
description: NamespaceSelector defines the rules to select
a Namespace resource. Either name or labels is needed.
properties:
labels:
additionalProperties:
type: string
description: Labels defines the label selector to select
the namespace.
type: object
name:
description: Name is the name of the namespace.
type: string
type: object
type: object
selector:
description: EnvSelector defines which components should this
env contains
properties:
components:
items:
type: string
type: array
type: object
required:
- name
- patch
type: object
type: array
outputResourcesTo:
description: OutputResourcesTo specifies the namespace and name of
a ConfigMap which store the resources rendered after differentiated
configuration
properties:
name:
description: Name of the secret.
type: string
namespace:
description: Namespace of the secret.
type: string
required:
- name
type: object
required:
- appTemplate
- envs
type: object
status:
description: A EnvBindingStatus is the status of EnvBinding
properties:
clusterDecisions:
items:
description: ClusterDecision recorded the mapping of environment
and cluster
properties:
cluster:
type: string
env:
type: string
namespace:
type: string
required:
- env
type: object
type: array
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
phase:
description: EnvBindingPhase is a label for the condition of a EnvBinding
at the current time
type: string
resourceTracker:
description: ResourceTracker record the status of the ResourceTracker
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: object
type: object
served: true
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []

View File

@@ -1,586 +0,0 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.11.4
name: healthscopes.core.oam.dev
spec:
group: core.oam.dev
names:
categories:
- oam
kind: HealthScope
listKind: HealthScopeList
plural: healthscopes
singular: healthscope
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .status.health
name: HEALTH
type: string
name: v1alpha2
schema:
openAPIV3Schema:
description: A HealthScope determines an aggregate health status based of
the health of components.
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 HealthScopeSpec defines the desired state of a HealthScope.
properties:
appReferences:
description: AppRefs records references of applications' components
items:
description: AppReference records references of an application's
components
properties:
appName:
type: string
compReferences:
items:
description: CompReference records references of a component's
resources
properties:
compName:
type: string
traits:
items:
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.
\n 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
x-kubernetes-map-type: atomic
type: array
workload:
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. \n 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
x-kubernetes-map-type: atomic
type: object
type: array
type: object
type: array
probe-interval:
description: ProbeInterval is the amount of time in seconds between
probing tries.
format: int32
type: integer
probe-timeout:
description: ProbeTimeout is the amount of time in seconds to wait
when receiving a response before marked failure.
format: int32
type: integer
workloadRefs:
description: WorkloadReferences to the workloads that are in this
scope.
items:
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. \n 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
x-kubernetes-map-type: atomic
type: array
required:
- workloadRefs
type: object
status:
description: A HealthScopeStatus represents the observed state of a HealthScope.
properties:
appHealthConditions:
description: AppHealthConditions represents health condition of applications
in the scope
items:
description: AppHealthCondition represents health condition of an
application
properties:
appName:
type: string
components:
items:
description: WorkloadHealthCondition represents informative
health condition of a workload.
properties:
componentName:
description: ComponentName represents the component name
if target is a workload
type: string
customStatusMsg:
type: string
diagnosis:
type: string
healthStatus:
description: HealthStatus represents health status strings.
type: string
targetWorkload:
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. \n 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
x-kubernetes-map-type: atomic
traits:
items:
description: TraitHealthCondition represents informative
health condition of a trait.
properties:
customStatusMsg:
type: string
diagnosis:
type: string
healthStatus:
description: HealthStatus represents health status
strings.
type: string
resource:
type: string
type:
type: string
required:
- healthStatus
- resource
- type
type: object
type: array
workloadStatus:
description: WorkloadStatus represents status of workloads
whose HealthStatus is UNKNOWN.
type: string
required:
- healthStatus
type: object
type: array
envName:
type: string
required:
- appName
type: object
type: array
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
healthConditions:
description: WorkloadHealthConditions represents health condition
of workloads in the scope Use AppHealthConditions to provide app
level status
items:
description: WorkloadHealthCondition represents informative health
condition of a workload.
properties:
componentName:
description: ComponentName represents the component name if
target is a workload
type: string
customStatusMsg:
type: string
diagnosis:
type: string
healthStatus:
description: HealthStatus represents health status strings.
type: string
targetWorkload:
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. \n 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
x-kubernetes-map-type: atomic
traits:
items:
description: TraitHealthCondition represents informative health
condition of a trait.
properties:
customStatusMsg:
type: string
diagnosis:
type: string
healthStatus:
description: HealthStatus represents health status strings.
type: string
resource:
type: string
type:
type: string
required:
- healthStatus
- resource
- type
type: object
type: array
workloadStatus:
description: WorkloadStatus represents status of workloads whose
HealthStatus is UNKNOWN.
type: string
required:
- healthStatus
type: object
type: array
scopeHealthCondition:
description: ScopeHealthCondition represents health condition summary
of the scope
properties:
healthStatus:
description: HealthStatus represents health status strings.
type: string
healthyWorkloads:
format: int64
type: integer
total:
format: int64
type: integer
unhealthyWorkloads:
format: int64
type: integer
unknownWorkloads:
format: int64
type: integer
required:
- healthStatus
type: object
required:
- scopeHealthCondition
type: object
type: object
served: true
storage: true
subresources:
status: {}

View File

@@ -1,50 +0,0 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.11.4
name: policies.core.oam.dev
spec:
group: core.oam.dev
names:
categories:
- oam
kind: Policy
listKind: PolicyList
plural: policies
singular: policy
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .type
name: TYPE
type: string
name: v1alpha1
schema:
openAPIV3Schema:
description: Policy is the Schema for the policy 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
properties:
type: object
type:
type: string
required:
- type
type: object
served: true
storage: true
subresources: {}

View File

@@ -1,286 +0,0 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.11.4
name: policydefinitions.core.oam.dev
spec:
group: core.oam.dev
names:
categories:
- oam
kind: PolicyDefinition
listKind: PolicyDefinitionList
plural: policydefinitions
shortNames:
- def-policy
singular: policydefinition
scope: Namespaced
versions:
- name: v1beta1
schema:
openAPIV3Schema:
description: PolicyDefinition is the Schema for the policydefinitions 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: PolicyDefinitionSpec defines the desired state of PolicyDefinition
properties:
definitionRef:
description: Reference to the CustomResourceDefinition that defines
this trait kind.
properties:
name:
description: Name of the referenced CustomResourceDefinition.
type: string
version:
description: Version indicate which version should be used if
CRD has multiple versions by default it will use the first one
if not specified
type: string
required:
- name
type: object
manageHealthCheck:
description: ManageHealthCheck means the policy will handle health
checking and skip application controller built-in health checking.
type: boolean
schematic:
description: Schematic defines the data format and template of the
encapsulation of the policy definition. Only CUE schematic is supported
for now.
properties:
cue:
description: CUE defines the encapsulation in CUE format
properties:
template:
description: Template defines the abstraction template data
of the capability, it will replace the old CUE template
in extension field. Template is a required field if CUE
is defined in Capability Definition.
type: string
required:
- template
type: object
helm:
description: A Helm represents resources used by a Helm module
properties:
release:
description: Release records a Helm release used by a Helm
module workload.
type: object
repository:
description: HelmRelease records a Helm repository used by
a Helm module workload.
type: object
required:
- release
- repository
type: object
kube:
description: Kube defines the encapsulation in raw Kubernetes
resource format
properties:
parameters:
description: Parameters defines configurable parameters
items:
description: A KubeParameter defines a configurable parameter
of a component.
properties:
description:
description: Description of this parameter.
type: string
fieldPaths:
description: "FieldPaths specifies an array of fields
within this workload that will be overwritten by the
value of this parameter. \tAll fields must be of the
same type. Fields are specified as JSON field paths
without a leading dot, for example 'spec.replicas'."
items:
type: string
type: array
name:
description: Name of this parameter
type: string
required:
description: Required specifies whether or not a value
for this parameter must be supplied when authoring
an Application.
type: boolean
type:
description: 'ValueType indicates the type of the parameter
value, and only supports basic data types: string,
number, boolean.'
enum:
- string
- number
- boolean
type: string
required:
- fieldPaths
- name
- type
type: object
type: array
template:
description: Template defines the raw Kubernetes resource
type: object
required:
- template
type: object
terraform:
description: Terraform is the struct to describe cloud resources
managed by Hashicorp Terraform
properties:
configuration:
description: Configuration is Terraform Configuration
type: string
customRegion:
description: Region is cloud provider's region. It will override
the region in the region field of ProviderReference
type: string
deleteResource:
default: true
description: DeleteResource will determine whether provisioned
cloud resources will be deleted when CR is deleted
type: boolean
gitCredentialsSecretReference:
description: GitCredentialsSecretReference specifies the reference
to the secret containing the git credentials
properties:
name:
description: name is unique within a namespace to reference
a secret resource.
type: string
namespace:
description: namespace defines the space within which
the secret name must be unique.
type: string
type: object
x-kubernetes-map-type: atomic
path:
description: Path is the sub-directory of remote git repository.
It's valid when remote is set
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 referenced object.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
it is, HCL or JSON syntax
enum:
- hcl
- json
- remote
type: string
writeConnectionSecretToRef:
description: WriteConnectionSecretToReference specifies the
namespace and name of a Secret to which any connection details
for this managed resource should be written. Connection
details frequently include the endpoint, username, and password
required to connect to the managed resource.
properties:
name:
description: Name of the secret.
type: string
namespace:
description: Namespace of the secret.
type: string
required:
- name
type: object
required:
- configuration
type: object
type: object
type: object
status:
description: PolicyDefinitionStatus is the status of PolicyDefinition
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
configMapRef:
description: ConfigMapRef refer to a ConfigMap which contains OpenAPI
V3 JSON schema of Component parameters.
type: string
latestRevision:
description: LatestRevision of the component definition
properties:
name:
type: string
revision:
format: int64
type: integer
revisionHash:
description: RevisionHash record the hash value of the spec of
ApplicationRevision object.
type: string
required:
- name
- revision
type: object
type: object
type: object
served: true
storage: true
subresources:
status: {}

View File

@@ -1,187 +0,0 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.11.4
name: resourcetrackers.core.oam.dev
spec:
group: core.oam.dev
names:
categories:
- oam
kind: ResourceTracker
listKind: ResourceTrackerList
plural: resourcetrackers
shortNames:
- rt
singular: resourcetracker
scope: Cluster
versions:
- additionalPrinterColumns:
- jsonPath: .spec.type
name: TYPE
type: string
- jsonPath: .metadata.labels['app\.oam\.dev\/name']
name: APP
type: string
- jsonPath: .metadata.labels['app\.oam\.dev\/namespace']
name: APP-NS
type: string
- jsonPath: .spec.applicationGeneration
name: APP-GEN
type: number
name: v1beta1
schema:
openAPIV3Schema:
description: An ResourceTracker represents a tracker for track cross namespace
resources
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: ResourceTrackerSpec define the spec of resourceTracker
properties:
applicationGeneration:
format: int64
type: integer
compression:
description: ResourceTrackerCompression represents the compressed
components in ResourceTracker.
properties:
data:
type: string
type:
description: Type the compression type
type: string
type: object
managedResources:
items:
description: ManagedResource define the resource to be managed by
ResourceTracker
properties:
apiVersion:
description: API version of the referent.
type: string
cluster:
type: string
component:
type: string
creator:
type: string
deleted:
description: Deleted marks the resource to be deleted
type: boolean
env:
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
raw:
type: object
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
skipGC:
description: SkipGC marks the resource to skip gc
type: boolean
trait:
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
x-kubernetes-map-type: atomic
type: array
type:
description: ResourceTrackerType defines the type of resourceTracker
type: string
required:
- applicationGeneration
type: object
status:
description: ResourceTrackerStatus define the status of resourceTracker
For backward-compatibility
properties:
trackedResources:
description: Deprecated
items:
description: ClusterObjectReference defines the object reference
with cluster.
properties:
apiVersion:
description: API version of the referent.
type: string
cluster:
type: string
creator:
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
x-kubernetes-map-type: atomic
type: array
type: object
type: object
served: true
storage: true
subresources:
status: {}

View File

@@ -1,376 +0,0 @@
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.2.4
name: rollouts.core.oam.dev
spec:
additionalPrinterColumns:
- JSONPath: .status.rolloutTargetSize
name: TARGET
type: string
- JSONPath: .status.upgradedReplicas
name: UPGRADED
type: string
- JSONPath: .status.upgradedReadyReplicas
name: READY
type: string
- JSONPath: .status.batchRollingState
name: BATCH-STATE
type: string
- JSONPath: .status.rollingState
name: ROLLING-STATE
type: string
- JSONPath: .metadata.creationTimestamp
name: AGE
type: date
group: core.oam.dev
names:
categories:
- oam
kind: Rollout
listKind: RolloutList
plural: rollouts
shortNames:
- rollout
singular: rollout
scope: Namespaced
subresources:
status: {}
validation:
openAPIV3Schema:
description: Rollout is the Schema for the Rollout 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: RolloutSpec defines how to describe an update between different compRevision
properties:
componentName:
description: ComponentName specify the component name
type: string
rolloutPlan:
description: RolloutPlan is the details on how to rollout the resources
properties:
batchPartition:
description: All pods in the batches up to the batchPartition (included) will have the target resource specification while the rest still have the source resource This is designed for the operators to manually rollout Default is the the number of batches which will rollout all the batches
format: int32
type: integer
canaryMetric:
description: CanaryMetric provides a way for the rollout process to automatically check certain metrics before complete the process
items:
description: CanaryMetric holds the reference to metrics used for canary analysis
properties:
interval:
description: Interval represents the windows size
type: string
metricsRange:
description: Range value accepted for this metric
properties:
max:
anyOf:
- type: integer
- type: string
description: Maximum value
x-kubernetes-int-or-string: true
min:
anyOf:
- type: integer
- type: string
description: Minimum value
x-kubernetes-int-or-string: true
type: object
name:
description: Name of the metric
type: string
templateRef:
description: TemplateRef references a metric template object
properties:
apiVersion:
description: APIVersion of the referenced object.
type: string
kind:
description: Kind of the referenced object.
type: string
name:
description: Name of the referenced object.
type: string
uid:
description: UID of the referenced object.
type: string
required:
- apiVersion
- kind
- name
type: object
required:
- name
type: object
type: array
numBatches:
description: The number of batches, default = 1
format: int32
type: integer
paused:
description: Paused the rollout, default is false
type: boolean
rolloutBatches:
description: The exact distribution among batches. its size has to be exactly the same as the NumBatches (if set) The total number cannot exceed the targetSize or the size of the source resource We will IGNORE the last batch's replica field if it's a percentage since round errors can lead to inaccurate sum We highly recommend to leave the last batch's replica field empty
items:
description: RolloutBatch is used to describe how the each batch rollout should be
properties:
batchRolloutWebhooks:
description: RolloutWebhooks provides a way for the batch rollout to interact with an external process
items:
description: RolloutWebhook holds the reference to external checks used for canary analysis
properties:
expectedStatus:
description: ExpectedStatus contains all the expected http status code that we will accept as success
items:
type: integer
type: array
metadata:
additionalProperties:
type: string
description: Metadata (key-value pairs) for this webhook
type: object
method:
description: Method the HTTP call method, default is POST
type: string
name:
description: Name of this webhook
type: string
type:
description: Type of this webhook
type: string
url:
description: URL address of this webhook
type: string
required:
- name
- type
- url
type: object
type: array
canaryMetric:
description: CanaryMetric provides a way for the batch rollout process to automatically check certain metrics before moving to the next batch
items:
description: CanaryMetric holds the reference to metrics used for canary analysis
properties:
interval:
description: Interval represents the windows size
type: string
metricsRange:
description: Range value accepted for this metric
properties:
max:
anyOf:
- type: integer
- type: string
description: Maximum value
x-kubernetes-int-or-string: true
min:
anyOf:
- type: integer
- type: string
description: Minimum value
x-kubernetes-int-or-string: true
type: object
name:
description: Name of the metric
type: string
templateRef:
description: TemplateRef references a metric template object
properties:
apiVersion:
description: APIVersion of the referenced object.
type: string
kind:
description: Kind of the referenced object.
type: string
name:
description: Name of the referenced object.
type: string
uid:
description: UID of the referenced object.
type: string
required:
- apiVersion
- kind
- name
type: object
required:
- name
type: object
type: array
instanceInterval:
description: The wait time, in seconds, between instances upgrades, default = 0
format: int32
type: integer
maxUnavailable:
anyOf:
- type: integer
- type: string
description: MaxUnavailable is the max allowed number of pods that is unavailable during the upgrade. We will mark the batch as ready as long as there are less or equal number of pods unavailable than this number. default = 0
x-kubernetes-int-or-string: true
podList:
description: The list of Pods to get upgraded it is mutually exclusive with the Replicas field
items:
type: string
type: array
replicas:
anyOf:
- type: integer
- type: string
description: 'Replicas is the number of pods to upgrade in this batch it can be an absolute number (ex: 5) or a percentage of total pods we will ignore the percentage of the last batch to just fill the gap it is mutually exclusive with the PodList field'
x-kubernetes-int-or-string: true
type: object
type: array
rolloutStrategy:
description: RolloutStrategy defines strategies for the rollout plan The default is IncreaseFirstRolloutStrategyType
type: string
rolloutWebhooks:
description: RolloutWebhooks provide a way for the rollout to interact with an external process
items:
description: RolloutWebhook holds the reference to external checks used for canary analysis
properties:
expectedStatus:
description: ExpectedStatus contains all the expected http status code that we will accept as success
items:
type: integer
type: array
metadata:
additionalProperties:
type: string
description: Metadata (key-value pairs) for this webhook
type: object
method:
description: Method the HTTP call method, default is POST
type: string
name:
description: Name of this webhook
type: string
type:
description: Type of this webhook
type: string
url:
description: URL address of this webhook
type: string
required:
- name
- type
- url
type: object
type: array
targetSize:
description: The size of the target resource. The default is the same as the size of the source resource.
format: int32
type: integer
type: object
sourceRevisionName:
description: SourceRevisionName contains the name of the componentRevisionName that we need to upgrade from. it can be empty only when it's the first time to deploy the application
type: string
targetRevisionName:
description: TargetRevisionName contains the name of the componentRevisionName that we need to upgrade to.
type: string
required:
- componentName
- rolloutPlan
- targetRevisionName
type: object
status:
description: RolloutStatus defines the observed state of rollout
properties:
LastSourceRevision:
description: LastSourceRevision contains the name of the componentRevisionName that we need to upgrade from. We will restart the rollout if this is not the same as the spec
type: string
batchRollingState:
description: BatchRollingState only meaningful when the Status is rolling
type: string
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
currentBatch:
description: The current batch the rollout is working on/blocked it starts from 0
format: int32
type: integer
lastAppliedPodTemplateIdentifier:
description: lastAppliedPodTemplateIdentifier is a string that uniquely represent the last pod template each workload type could use different ways to identify that so we cannot compare between resources We update this field only after a successful rollout
type: string
lastTargetRevision:
description: LastUpgradedTargetRevision contains the name of the componentRevisionName that we upgraded to We will restart the rollout if this is not the same as the spec
type: string
rollingState:
description: RollingState is the Rollout State
type: string
rolloutOriginalSize:
description: RolloutTargetSize is the size of the target resources. This is determined once the initial spec verification and does not change until the rollout is restarted
format: int32
type: integer
rolloutTargetSize:
description: RolloutTargetSize is the size of the target resources. This is determined once the initial spec verification and does not change until the rollout is restarted
format: int32
type: integer
targetGeneration:
description: NewPodTemplateIdentifier is a string that uniquely represent the new pod template each workload type could use different ways to identify that so we cannot compare between resources
type: string
upgradedReadyReplicas:
description: UpgradedReadyReplicas is the number of Pods upgraded by the rollout controller that have a Ready Condition.
format: int32
type: integer
upgradedReplicas:
description: UpgradedReplicas is the number of Pods upgraded by the rollout controller
format: int32
type: integer
required:
- currentBatch
- lastTargetRevision
- rollingState
- upgradedReadyReplicas
- upgradedReplicas
type: object
type: object
version: v1beta1
versions:
- name: v1beta1
served: true
storage: true
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []

View File

@@ -1,673 +0,0 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.11.4
name: traitdefinitions.core.oam.dev
spec:
group: core.oam.dev
names:
categories:
- oam
kind: TraitDefinition
listKind: TraitDefinitionList
plural: traitdefinitions
shortNames:
- trait
singular: traitdefinition
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .spec.appliesToWorkloads
name: APPLIES-TO
type: string
- jsonPath: .metadata.annotations.definition\.oam\.dev/description
name: DESCRIPTION
type: string
name: v1alpha2
schema:
openAPIV3Schema:
description: A TraitDefinition registers a kind of Kubernetes custom resource
as a valid OAM trait kind by referencing its CustomResourceDefinition. The
CRD is used to validate the schema of the trait when it is embedded in an
OAM ApplicationConfiguration.
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 TraitDefinitionSpec defines the desired state of a TraitDefinition.
properties:
appliesToWorkloads:
description: AppliesToWorkloads specifies the list of workload kinds
this trait applies to. Workload kinds are specified in kind.group/version
format, e.g. server.core.oam.dev/v1alpha2. Traits that omit this
field apply to all workload kinds.
items:
type: string
type: array
conflictsWith:
description: 'ConflictsWith specifies the list of traits(CRD name,
Definition name, CRD group) which could not apply to the same workloads
with this trait. Traits that omit this field can work with any other
traits. Example rules: "service" # Trait definition name "services.k8s.io"
# API resource/crd name "*.networking.k8s.io" # API group "labelSelector:foo=bar"
# label selector labelSelector format: https://pkg.go.dev/k8s.io/apimachinery/pkg/labels#Parse'
items:
type: string
type: array
definitionRef:
description: Reference to the CustomResourceDefinition that defines
this trait kind.
properties:
name:
description: Name of the referenced CustomResourceDefinition.
type: string
version:
description: Version indicate which version should be used if
CRD has multiple versions by default it will use the first one
if not specified
type: string
required:
- name
type: object
extension:
description: Extension is used for extension needs by OAM platform
builders
type: object
podDisruptive:
description: PodDisruptive specifies whether using the trait will
cause the pod to restart or not.
type: boolean
revisionEnabled:
description: Revision indicates whether a trait is aware of component
revision
type: boolean
schematic:
description: Schematic defines the data format and template of the
encapsulation of the trait
properties:
cue:
description: CUE defines the encapsulation in CUE format
properties:
template:
description: Template defines the abstraction template data
of the capability, it will replace the old CUE template
in extension field. Template is a required field if CUE
is defined in Capability Definition.
type: string
required:
- template
type: object
helm:
description: A Helm represents resources used by a Helm module
properties:
release:
description: Release records a Helm release used by a Helm
module workload.
type: object
repository:
description: HelmRelease records a Helm repository used by
a Helm module workload.
type: object
required:
- release
- repository
type: object
kube:
description: Kube defines the encapsulation in raw Kubernetes
resource format
properties:
parameters:
description: Parameters defines configurable parameters
items:
description: A KubeParameter defines a configurable parameter
of a component.
properties:
description:
description: Description of this parameter.
type: string
fieldPaths:
description: "FieldPaths specifies an array of fields
within this workload that will be overwritten by the
value of this parameter. \tAll fields must be of the
same type. Fields are specified as JSON field paths
without a leading dot, for example 'spec.replicas'."
items:
type: string
type: array
name:
description: Name of this parameter
type: string
required:
description: Required specifies whether or not a value
for this parameter must be supplied when authoring
an Application.
type: boolean
type:
description: 'ValueType indicates the type of the parameter
value, and only supports basic data types: string,
number, boolean.'
enum:
- string
- number
- boolean
type: string
required:
- fieldPaths
- name
- type
type: object
type: array
template:
description: Template defines the raw Kubernetes resource
type: object
required:
- template
type: object
terraform:
description: Terraform is the struct to describe cloud resources
managed by Hashicorp Terraform
properties:
configuration:
description: Configuration is Terraform Configuration
type: string
customRegion:
description: Region is cloud provider's region. It will override
the region in the region field of ProviderReference
type: string
deleteResource:
default: true
description: DeleteResource will determine whether provisioned
cloud resources will be deleted when CR is deleted
type: boolean
gitCredentialsSecretReference:
description: GitCredentialsSecretReference specifies the reference
to the secret containing the git credentials
properties:
name:
description: name is unique within a namespace to reference
a secret resource.
type: string
namespace:
description: namespace defines the space within which
the secret name must be unique.
type: string
type: object
x-kubernetes-map-type: atomic
path:
description: Path is the sub-directory of remote git repository.
It's valid when remote is set
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 referenced object.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
it is, HCL or JSON syntax
enum:
- hcl
- json
- remote
type: string
writeConnectionSecretToRef:
description: WriteConnectionSecretToReference specifies the
namespace and name of a Secret to which any connection details
for this managed resource should be written. Connection
details frequently include the endpoint, username, and password
required to connect to the managed resource.
properties:
name:
description: Name of the secret.
type: string
namespace:
description: Namespace of the secret.
type: string
required:
- name
type: object
required:
- configuration
type: object
type: object
status:
description: Status defines the custom health policy and status message
for trait
properties:
customStatus:
description: CustomStatus defines the custom status message that
could display to user
type: string
healthPolicy:
description: HealthPolicy defines the health check policy for
the abstraction
type: string
type: object
workloadRefPath:
description: WorkloadRefPath indicates where/if a trait accepts a
workloadRef object
type: string
type: object
status:
description: TraitDefinitionStatus is the status of TraitDefinition
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
configMapRef:
description: ConfigMapRef refer to a ConfigMap which contains OpenAPI
V3 JSON schema of Component parameters.
type: string
latestRevision:
description: LatestRevision of the trait definition
properties:
name:
type: string
revision:
format: int64
type: integer
revisionHash:
description: RevisionHash record the hash value of the spec of
ApplicationRevision object.
type: string
required:
- name
- revision
type: object
type: object
type: object
served: true
storage: false
subresources:
status: {}
- additionalPrinterColumns:
- jsonPath: .spec.appliesToWorkloads
name: APPLIES-TO
type: string
- jsonPath: .metadata.annotations.definition\.oam\.dev/description
name: DESCRIPTION
type: string
name: v1beta1
schema:
openAPIV3Schema:
description: A TraitDefinition registers a kind of Kubernetes custom resource
as a valid OAM trait kind by referencing its CustomResourceDefinition. The
CRD is used to validate the schema of the trait when it is embedded in an
OAM ApplicationConfiguration.
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 TraitDefinitionSpec defines the desired state of a TraitDefinition.
properties:
appliesToWorkloads:
description: AppliesToWorkloads specifies the list of workload kinds
this trait applies to. Workload kinds are specified in resource.group/version
format, e.g. server.core.oam.dev/v1alpha2. Traits that omit this
field apply to all workload kinds.
items:
type: string
type: array
conflictsWith:
description: 'ConflictsWith specifies the list of traits(CRD name,
Definition name, CRD group) which could not apply to the same workloads
with this trait. Traits that omit this field can work with any other
traits. Example rules: "service" # Trait definition name "services.k8s.io"
# API resource/crd name "*.networking.k8s.io" # API group "labelSelector:foo=bar"
# label selector labelSelector format: https://pkg.go.dev/k8s.io/apimachinery/pkg/labels#Parse'
items:
type: string
type: array
controlPlaneOnly:
description: ControlPlaneOnly defines which cluster is dispatched
to
type: boolean
definitionRef:
description: Reference to the CustomResourceDefinition that defines
this trait kind.
properties:
name:
description: Name of the referenced CustomResourceDefinition.
type: string
version:
description: Version indicate which version should be used if
CRD has multiple versions by default it will use the first one
if not specified
type: string
required:
- name
type: object
extension:
description: Extension is used for extension needs by OAM platform
builders
type: object
manageWorkload:
description: ManageWorkload defines the trait would be responsible
for creating the workload
type: boolean
podDisruptive:
description: PodDisruptive specifies whether using the trait will
cause the pod to restart or not.
type: boolean
revisionEnabled:
description: Revision indicates whether a trait is aware of component
revision
type: boolean
schematic:
description: Schematic defines the data format and template of the
encapsulation of the trait. Only CUE and Kube schematic are supported
for now.
properties:
cue:
description: CUE defines the encapsulation in CUE format
properties:
template:
description: Template defines the abstraction template data
of the capability, it will replace the old CUE template
in extension field. Template is a required field if CUE
is defined in Capability Definition.
type: string
required:
- template
type: object
helm:
description: A Helm represents resources used by a Helm module
properties:
release:
description: Release records a Helm release used by a Helm
module workload.
type: object
repository:
description: HelmRelease records a Helm repository used by
a Helm module workload.
type: object
required:
- release
- repository
type: object
kube:
description: Kube defines the encapsulation in raw Kubernetes
resource format
properties:
parameters:
description: Parameters defines configurable parameters
items:
description: A KubeParameter defines a configurable parameter
of a component.
properties:
description:
description: Description of this parameter.
type: string
fieldPaths:
description: "FieldPaths specifies an array of fields
within this workload that will be overwritten by the
value of this parameter. \tAll fields must be of the
same type. Fields are specified as JSON field paths
without a leading dot, for example 'spec.replicas'."
items:
type: string
type: array
name:
description: Name of this parameter
type: string
required:
description: Required specifies whether or not a value
for this parameter must be supplied when authoring
an Application.
type: boolean
type:
description: 'ValueType indicates the type of the parameter
value, and only supports basic data types: string,
number, boolean.'
enum:
- string
- number
- boolean
type: string
required:
- fieldPaths
- name
- type
type: object
type: array
template:
description: Template defines the raw Kubernetes resource
type: object
required:
- template
type: object
terraform:
description: Terraform is the struct to describe cloud resources
managed by Hashicorp Terraform
properties:
configuration:
description: Configuration is Terraform Configuration
type: string
customRegion:
description: Region is cloud provider's region. It will override
the region in the region field of ProviderReference
type: string
deleteResource:
default: true
description: DeleteResource will determine whether provisioned
cloud resources will be deleted when CR is deleted
type: boolean
gitCredentialsSecretReference:
description: GitCredentialsSecretReference specifies the reference
to the secret containing the git credentials
properties:
name:
description: name is unique within a namespace to reference
a secret resource.
type: string
namespace:
description: namespace defines the space within which
the secret name must be unique.
type: string
type: object
x-kubernetes-map-type: atomic
path:
description: Path is the sub-directory of remote git repository.
It's valid when remote is set
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 referenced object.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
it is, HCL or JSON syntax
enum:
- hcl
- json
- remote
type: string
writeConnectionSecretToRef:
description: WriteConnectionSecretToReference specifies the
namespace and name of a Secret to which any connection details
for this managed resource should be written. Connection
details frequently include the endpoint, username, and password
required to connect to the managed resource.
properties:
name:
description: Name of the secret.
type: string
namespace:
description: Namespace of the secret.
type: string
required:
- name
type: object
required:
- configuration
type: object
type: object
stage:
description: Stage defines the stage information to which this trait
resource processing belongs. Currently, PreDispatch and PostDispatch
are provided, which are used to control resource pre-process and
post-process respectively.
type: string
status:
description: Status defines the custom health policy and status message
for trait
properties:
customStatus:
description: CustomStatus defines the custom status message that
could display to user
type: string
healthPolicy:
description: HealthPolicy defines the health check policy for
the abstraction
type: string
type: object
workloadRefPath:
description: WorkloadRefPath indicates where/if a trait accepts a
workloadRef object
type: string
type: object
status:
description: TraitDefinitionStatus is the status of TraitDefinition
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
configMapRef:
description: ConfigMapRef refer to a ConfigMap which contains OpenAPI
V3 JSON schema of Component parameters.
type: string
latestRevision:
description: LatestRevision of the component definition
properties:
name:
type: string
revision:
format: int64
type: integer
revisionHash:
description: RevisionHash record the hash value of the spec of
ApplicationRevision object.
type: string
required:
- name
- revision
type: object
type: object
type: object
served: true
storage: true
subresources:
status: {}

View File

@@ -1,172 +0,0 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.9.0
name: workflows.core.oam.dev
spec:
group: core.oam.dev
names:
categories:
- oam
kind: Workflow
listKind: WorkflowList
plural: workflows
singular: workflow
scope: Namespaced
versions:
- 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
mode:
description: WorkflowExecuteMode defines the mode of workflow execution
properties:
steps:
description: Steps is the mode of workflow steps execution
type: string
subSteps:
description: SubSteps is the mode of workflow sub steps execution
type: string
type: object
steps:
items:
description: WorkflowStep defines how to execute a workflow step.
properties:
dependsOn:
description: DependsOn is the dependency of the step
items:
type: string
type: array
if:
description: If is the if condition of the step
type: string
inputs:
description: Inputs is the inputs of the step
items:
properties:
from:
type: string
parameterKey:
type: string
required:
- from
- parameterKey
type: object
type: array
meta:
description: Meta is the meta data of the workflow step.
properties:
alias:
type: string
type: object
name:
description: Name is the unique name of the workflow step.
type: string
outputs:
description: Outputs is the outputs of the step
items:
properties:
name:
type: string
valueFrom:
type: string
required:
- name
- valueFrom
type: object
type: array
properties:
description: Properties is the properties of the step
type: object
subSteps:
items:
description: WorkflowStepBase defines the workflow step base
properties:
dependsOn:
description: DependsOn is the dependency of the step
items:
type: string
type: array
if:
description: If is the if condition of the step
type: string
inputs:
description: Inputs is the inputs of the step
items:
properties:
from:
type: string
parameterKey:
type: string
required:
- from
- parameterKey
type: object
type: array
meta:
description: Meta is the meta data of the workflow step.
properties:
alias:
type: string
type: object
name:
description: Name is the unique name of the workflow step.
type: string
outputs:
description: Outputs is the outputs of the step
items:
properties:
name:
type: string
valueFrom:
type: string
required:
- name
- valueFrom
type: object
type: array
properties:
description: Properties is the properties of the step
type: object
timeout:
description: Timeout is the timeout of the step
type: string
type:
description: Type is the type of the workflow step.
type: string
required:
- name
- type
type: object
type: array
timeout:
description: Timeout is the timeout of the step
type: string
type:
description: Type is the type of the workflow step.
type: string
required:
- name
- type
type: object
type: array
type: object
served: true
storage: true

View File

@@ -1,283 +0,0 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.11.4
name: workflowstepdefinitions.core.oam.dev
spec:
group: core.oam.dev
names:
categories:
- oam
kind: WorkflowStepDefinition
listKind: WorkflowStepDefinitionList
plural: workflowstepdefinitions
shortNames:
- workflowstep
singular: workflowstepdefinition
scope: Namespaced
versions:
- name: v1beta1
schema:
openAPIV3Schema:
description: WorkflowStepDefinition is the Schema for the workflowstepdefinitions
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: WorkflowStepDefinitionSpec defines the desired state of WorkflowStepDefinition
properties:
definitionRef:
description: Reference to the CustomResourceDefinition that defines
this trait kind.
properties:
name:
description: Name of the referenced CustomResourceDefinition.
type: string
version:
description: Version indicate which version should be used if
CRD has multiple versions by default it will use the first one
if not specified
type: string
required:
- name
type: object
schematic:
description: Schematic defines the data format and template of the
encapsulation of the workflow step definition. Only CUE schematic
is supported for now.
properties:
cue:
description: CUE defines the encapsulation in CUE format
properties:
template:
description: Template defines the abstraction template data
of the capability, it will replace the old CUE template
in extension field. Template is a required field if CUE
is defined in Capability Definition.
type: string
required:
- template
type: object
helm:
description: A Helm represents resources used by a Helm module
properties:
release:
description: Release records a Helm release used by a Helm
module workload.
type: object
repository:
description: HelmRelease records a Helm repository used by
a Helm module workload.
type: object
required:
- release
- repository
type: object
kube:
description: Kube defines the encapsulation in raw Kubernetes
resource format
properties:
parameters:
description: Parameters defines configurable parameters
items:
description: A KubeParameter defines a configurable parameter
of a component.
properties:
description:
description: Description of this parameter.
type: string
fieldPaths:
description: "FieldPaths specifies an array of fields
within this workload that will be overwritten by the
value of this parameter. \tAll fields must be of the
same type. Fields are specified as JSON field paths
without a leading dot, for example 'spec.replicas'."
items:
type: string
type: array
name:
description: Name of this parameter
type: string
required:
description: Required specifies whether or not a value
for this parameter must be supplied when authoring
an Application.
type: boolean
type:
description: 'ValueType indicates the type of the parameter
value, and only supports basic data types: string,
number, boolean.'
enum:
- string
- number
- boolean
type: string
required:
- fieldPaths
- name
- type
type: object
type: array
template:
description: Template defines the raw Kubernetes resource
type: object
required:
- template
type: object
terraform:
description: Terraform is the struct to describe cloud resources
managed by Hashicorp Terraform
properties:
configuration:
description: Configuration is Terraform Configuration
type: string
customRegion:
description: Region is cloud provider's region. It will override
the region in the region field of ProviderReference
type: string
deleteResource:
default: true
description: DeleteResource will determine whether provisioned
cloud resources will be deleted when CR is deleted
type: boolean
gitCredentialsSecretReference:
description: GitCredentialsSecretReference specifies the reference
to the secret containing the git credentials
properties:
name:
description: name is unique within a namespace to reference
a secret resource.
type: string
namespace:
description: namespace defines the space within which
the secret name must be unique.
type: string
type: object
x-kubernetes-map-type: atomic
path:
description: Path is the sub-directory of remote git repository.
It's valid when remote is set
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 referenced object.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
it is, HCL or JSON syntax
enum:
- hcl
- json
- remote
type: string
writeConnectionSecretToRef:
description: WriteConnectionSecretToReference specifies the
namespace and name of a Secret to which any connection details
for this managed resource should be written. Connection
details frequently include the endpoint, username, and password
required to connect to the managed resource.
properties:
name:
description: Name of the secret.
type: string
namespace:
description: Namespace of the secret.
type: string
required:
- name
type: object
required:
- configuration
type: object
type: object
type: object
status:
description: WorkflowStepDefinitionStatus is the status of WorkflowStepDefinition
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
configMapRef:
description: ConfigMapRef refer to a ConfigMap which contains OpenAPI
V3 JSON schema of Component parameters.
type: string
latestRevision:
description: LatestRevision of the component definition
properties:
name:
type: string
revision:
format: int64
type: integer
revisionHash:
description: RevisionHash record the hash value of the spec of
ApplicationRevision object.
type: string
required:
- name
- revision
type: object
type: object
type: object
served: true
storage: true
subresources:
status: {}

View File

@@ -1,625 +0,0 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.11.4
name: workloaddefinitions.core.oam.dev
spec:
group: core.oam.dev
names:
categories:
- oam
kind: WorkloadDefinition
listKind: WorkloadDefinitionList
plural: workloaddefinitions
shortNames:
- workload
singular: workloaddefinition
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .spec.definitionRef.name
name: DEFINITION-NAME
type: string
name: v1alpha2
schema:
openAPIV3Schema:
description: A WorkloadDefinition registers a kind of Kubernetes custom resource
as a valid OAM workload kind by referencing its CustomResourceDefinition.
The CRD is used to validate the schema of the workload when it is embedded
in an OAM Component.
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 WorkloadDefinitionSpec defines the desired state of a WorkloadDefinition.
properties:
childResourceKinds:
description: ChildResourceKinds are the list of GVK of the child resources
this workload generates
items:
description: A ChildResourceKind defines a child Kubernetes resource
kind with a selector
properties:
apiVersion:
description: APIVersion of the child resource
type: string
kind:
description: Kind of the child resource
type: string
selector:
additionalProperties:
type: string
description: Selector to select the child resources that the
workload wants to expose to traits
type: object
required:
- apiVersion
- kind
type: object
type: array
definitionRef:
description: Reference to the CustomResourceDefinition that defines
this workload kind.
properties:
name:
description: Name of the referenced CustomResourceDefinition.
type: string
version:
description: Version indicate which version should be used if
CRD has multiple versions by default it will use the first one
if not specified
type: string
required:
- name
type: object
extension:
description: Extension is used for extension needs by OAM platform
builders
type: object
podSpecPath:
description: PodSpecPath indicates where/if this workload has K8s
podSpec field if one workload has podSpec, trait can do lot's of
assumption such as port, env, volume fields.
type: string
revisionLabel:
description: RevisionLabel indicates which label for underlying resources(e.g.
pods) of this workload can be used by trait to create resource selectors(e.g.
label selector for pods).
type: string
schematic:
description: Schematic defines the data format and template of the
encapsulation of the workload
properties:
cue:
description: CUE defines the encapsulation in CUE format
properties:
template:
description: Template defines the abstraction template data
of the capability, it will replace the old CUE template
in extension field. Template is a required field if CUE
is defined in Capability Definition.
type: string
required:
- template
type: object
helm:
description: A Helm represents resources used by a Helm module
properties:
release:
description: Release records a Helm release used by a Helm
module workload.
type: object
repository:
description: HelmRelease records a Helm repository used by
a Helm module workload.
type: object
required:
- release
- repository
type: object
kube:
description: Kube defines the encapsulation in raw Kubernetes
resource format
properties:
parameters:
description: Parameters defines configurable parameters
items:
description: A KubeParameter defines a configurable parameter
of a component.
properties:
description:
description: Description of this parameter.
type: string
fieldPaths:
description: "FieldPaths specifies an array of fields
within this workload that will be overwritten by the
value of this parameter. \tAll fields must be of the
same type. Fields are specified as JSON field paths
without a leading dot, for example 'spec.replicas'."
items:
type: string
type: array
name:
description: Name of this parameter
type: string
required:
description: Required specifies whether or not a value
for this parameter must be supplied when authoring
an Application.
type: boolean
type:
description: 'ValueType indicates the type of the parameter
value, and only supports basic data types: string,
number, boolean.'
enum:
- string
- number
- boolean
type: string
required:
- fieldPaths
- name
- type
type: object
type: array
template:
description: Template defines the raw Kubernetes resource
type: object
required:
- template
type: object
terraform:
description: Terraform is the struct to describe cloud resources
managed by Hashicorp Terraform
properties:
configuration:
description: Configuration is Terraform Configuration
type: string
customRegion:
description: Region is cloud provider's region. It will override
the region in the region field of ProviderReference
type: string
deleteResource:
default: true
description: DeleteResource will determine whether provisioned
cloud resources will be deleted when CR is deleted
type: boolean
gitCredentialsSecretReference:
description: GitCredentialsSecretReference specifies the reference
to the secret containing the git credentials
properties:
name:
description: name is unique within a namespace to reference
a secret resource.
type: string
namespace:
description: namespace defines the space within which
the secret name must be unique.
type: string
type: object
x-kubernetes-map-type: atomic
path:
description: Path is the sub-directory of remote git repository.
It's valid when remote is set
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 referenced object.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
it is, HCL or JSON syntax
enum:
- hcl
- json
- remote
type: string
writeConnectionSecretToRef:
description: WriteConnectionSecretToReference specifies the
namespace and name of a Secret to which any connection details
for this managed resource should be written. Connection
details frequently include the endpoint, username, and password
required to connect to the managed resource.
properties:
name:
description: Name of the secret.
type: string
namespace:
description: Namespace of the secret.
type: string
required:
- name
type: object
required:
- configuration
type: object
type: object
status:
description: Status defines the custom health policy and status message
for workload
properties:
customStatus:
description: CustomStatus defines the custom status message that
could display to user
type: string
healthPolicy:
description: HealthPolicy defines the health check policy for
the abstraction
type: string
type: object
required:
- definitionRef
type: object
status:
description: WorkloadDefinitionStatus is the status of WorkloadDefinition
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
type: object
type: object
served: true
storage: false
subresources: {}
- additionalPrinterColumns:
- jsonPath: .spec.definitionRef.name
name: DEFINITION-NAME
type: string
- jsonPath: .metadata.annotations.definition\.oam\.dev/description
name: DESCRIPTION
type: string
name: v1beta1
schema:
openAPIV3Schema:
description: A WorkloadDefinition registers a kind of Kubernetes custom resource
as a valid OAM workload kind by referencing its CustomResourceDefinition.
The CRD is used to validate the schema of the workload when it is embedded
in an OAM Component.
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 WorkloadDefinitionSpec defines the desired state of a WorkloadDefinition.
properties:
childResourceKinds:
description: ChildResourceKinds are the list of GVK of the child resources
this workload generates
items:
description: A ChildResourceKind defines a child Kubernetes resource
kind with a selector
properties:
apiVersion:
description: APIVersion of the child resource
type: string
kind:
description: Kind of the child resource
type: string
selector:
additionalProperties:
type: string
description: Selector to select the child resources that the
workload wants to expose to traits
type: object
required:
- apiVersion
- kind
type: object
type: array
definitionRef:
description: Reference to the CustomResourceDefinition that defines
this workload kind.
properties:
name:
description: Name of the referenced CustomResourceDefinition.
type: string
version:
description: Version indicate which version should be used if
CRD has multiple versions by default it will use the first one
if not specified
type: string
required:
- name
type: object
extension:
description: Extension is used for extension needs by OAM platform
builders
type: object
podSpecPath:
description: PodSpecPath indicates where/if this workload has K8s
podSpec field if one workload has podSpec, trait can do lot's of
assumption such as port, env, volume fields.
type: string
revisionLabel:
description: RevisionLabel indicates which label for underlying resources(e.g.
pods) of this workload can be used by trait to create resource selectors(e.g.
label selector for pods).
type: string
schematic:
description: Schematic defines the data format and template of the
encapsulation of the workload
properties:
cue:
description: CUE defines the encapsulation in CUE format
properties:
template:
description: Template defines the abstraction template data
of the capability, it will replace the old CUE template
in extension field. Template is a required field if CUE
is defined in Capability Definition.
type: string
required:
- template
type: object
helm:
description: A Helm represents resources used by a Helm module
properties:
release:
description: Release records a Helm release used by a Helm
module workload.
type: object
repository:
description: HelmRelease records a Helm repository used by
a Helm module workload.
type: object
required:
- release
- repository
type: object
kube:
description: Kube defines the encapsulation in raw Kubernetes
resource format
properties:
parameters:
description: Parameters defines configurable parameters
items:
description: A KubeParameter defines a configurable parameter
of a component.
properties:
description:
description: Description of this parameter.
type: string
fieldPaths:
description: "FieldPaths specifies an array of fields
within this workload that will be overwritten by the
value of this parameter. \tAll fields must be of the
same type. Fields are specified as JSON field paths
without a leading dot, for example 'spec.replicas'."
items:
type: string
type: array
name:
description: Name of this parameter
type: string
required:
description: Required specifies whether or not a value
for this parameter must be supplied when authoring
an Application.
type: boolean
type:
description: 'ValueType indicates the type of the parameter
value, and only supports basic data types: string,
number, boolean.'
enum:
- string
- number
- boolean
type: string
required:
- fieldPaths
- name
- type
type: object
type: array
template:
description: Template defines the raw Kubernetes resource
type: object
required:
- template
type: object
terraform:
description: Terraform is the struct to describe cloud resources
managed by Hashicorp Terraform
properties:
configuration:
description: Configuration is Terraform Configuration
type: string
customRegion:
description: Region is cloud provider's region. It will override
the region in the region field of ProviderReference
type: string
deleteResource:
default: true
description: DeleteResource will determine whether provisioned
cloud resources will be deleted when CR is deleted
type: boolean
gitCredentialsSecretReference:
description: GitCredentialsSecretReference specifies the reference
to the secret containing the git credentials
properties:
name:
description: name is unique within a namespace to reference
a secret resource.
type: string
namespace:
description: namespace defines the space within which
the secret name must be unique.
type: string
type: object
x-kubernetes-map-type: atomic
path:
description: Path is the sub-directory of remote git repository.
It's valid when remote is set
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 referenced object.
type: string
required:
- name
type: object
type:
default: hcl
description: Type specifies which Terraform configuration
it is, HCL or JSON syntax
enum:
- hcl
- json
- remote
type: string
writeConnectionSecretToRef:
description: WriteConnectionSecretToReference specifies the
namespace and name of a Secret to which any connection details
for this managed resource should be written. Connection
details frequently include the endpoint, username, and password
required to connect to the managed resource.
properties:
name:
description: Name of the secret.
type: string
namespace:
description: Namespace of the secret.
type: string
required:
- name
type: object
required:
- configuration
type: object
type: object
status:
description: Status defines the custom health policy and status message
for workload
properties:
customStatus:
description: CustomStatus defines the custom status message that
could display to user
type: string
healthPolicy:
description: HealthPolicy defines the health check policy for
the abstraction
type: string
type: object
required:
- definitionRef
type: object
status:
description: WorkloadDefinitionStatus is the status of WorkloadDefinition
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
type: object
type: object
served: true
storage: true
subresources: {}

View File

@@ -1,58 +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 main // #nosec
import (
"fmt"
"log"
"os"
"path/filepath"
"strings"
)
func main() {
dir, err := os.Getwd()
if err != nil {
log.Fatal(err)
}
if len(os.Args) > 1 {
dir = os.Args[1]
}
err = filepath.Walk(dir, func(path string, info os.FileInfo, _ error) error {
if info.IsDir() {
return nil
}
/* #nosec */
data, err := os.ReadFile(path)
if err != nil {
fmt.Fprintln(os.Stderr, "failed to read file", err)
return err
}
newdata := strings.ReplaceAll(string(data), "x-kubernetes-embedded-resource: true", "")
newdata = strings.ReplaceAll(newdata, "x-kubernetes-preserve-unknown-fields: true", "")
newdata = strings.ReplaceAll(newdata, "default: false", "")
/* #nosec */
if err = os.WriteFile(path, []byte(newdata), 0644); err != nil {
fmt.Fprintln(os.Stderr, "failed to write file:", err)
return err
}
return nil
})
if err != nil {
log.Fatal(err)
}
}

View File

@@ -352,7 +352,7 @@ func (af *Appfile) SetOAMContract(comp *types.ComponentManifest) error {
Name: comp.StandardWorkload.GetName(),
}
for _, trait := range comp.Traits {
af.assembleTrait(trait, compName, commonLabels)
af.assembleTrait(trait, comp.Name, commonLabels)
if err := af.setWorkloadRefToTrait(workloadRef, trait); err != nil && !IsNotFoundInAppFile(err) {
return errors.WithMessagef(err, "cannot set workload reference to trait %q", trait.GetName())
}
@@ -443,14 +443,12 @@ func (af *Appfile) setWorkloadLabels(wl *unstructured.Unstructured, commonLabels
}
func (af *Appfile) assembleTrait(trait *unstructured.Unstructured, compName string, labels map[string]string) {
traitType := trait.GetLabels()[oam.TraitTypeLabel]
// only set generated name when name is unspecified
// it's by design to set arbitrary name in render phase
if len(trait.GetName()) == 0 {
traitType := trait.GetLabels()[oam.TraitTypeLabel]
cpTrait := trait.DeepCopy()
// remove labels that should not be calculated into hash
util.RemoveLabels(cpTrait, []string{oam.LabelAppRevision})
traitName := util.GenTraitNameCompatible(compName, cpTrait, traitType)
traitName := util.GenTraitName(compName, cpTrait, traitType)
trait.SetName(traitName)
}
af.setTraitLabels(trait, labels)

View File

@@ -335,137 +335,6 @@ wait: op.#ConditionalWait & {
})
})
var _ = Describe("Test Policy", func() {
It("test generate PolicyWorkloads", func() {
testAppfile := &Appfile{
Name: "test-app",
Namespace: "default",
Workloads: []*Workload{
{
Name: "test-comp",
Type: "worker",
CapabilityCategory: oamtypes.KubeCategory,
engine: definition.NewWorkloadAbstractEngine("test-comp", pd),
FullTemplate: &Template{
Kube: &common.Kube{
Template: func() runtime.RawExtension {
yamlStr := `apiVersion: apps/v1
kind: Deployment
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
ports:
- containerPort: 80 `
b, _ := yaml.YAMLToJSON([]byte(yamlStr))
return runtime.RawExtension{Raw: b}
}(),
},
},
},
},
PolicyWorkloads: []*Workload{
{
Name: "test-policy",
Type: "test-policy",
Params: map[string]interface{}{
"boundComponents": []string{"test-comp"},
},
FullTemplate: &Template{TemplateStr: ` output: {
apiVersion: "core.oam.dev/v1alpha2"
kind: "HealthScope"
spec: {
for k, v in parameter.boundComponents {
compName: v
workload: {
apiVersion: context.artifacts[v].workload.apiVersion
kind: context.artifacts[v].workload.kind
name: v
}
},
}
}
outputs: virtualservice: {
apiVersion: "networking.istio.io/v1alpha3"
kind: "VirtualService"
spec: {
hosts: "abc"
http: ["abc"]
}
}
parameter: {
boundComponents: [...string]
}`},
engine: definition.NewWorkloadAbstractEngine("test-policy", pd),
},
},
app: &v1beta1.Application{},
}
_, err := testAppfile.GenerateComponentManifests()
Expect(err).Should(BeNil())
testAppfile.parser = &Parser{client: k8sClient}
gotPolicies, err := testAppfile.GeneratePolicyManifests(context.Background())
Expect(err).Should(BeNil())
Expect(len(gotPolicies)).ShouldNot(Equal(0))
expectPolicy0 := unstructured.Unstructured{
Object: map[string]interface{}{
"spec": map[string]interface{}{
"compName": "test-comp",
"workload": map[string]interface{}{
"name": "test-comp",
"apiVersion": "apps/v1",
"kind": "Deployment",
},
},
"metadata": map[string]interface{}{
"name": "test-policy",
"namespace": "default",
"labels": map[string]interface{}{
"app.oam.dev/name": "test-app",
"app.oam.dev/component": "test-policy",
"app.oam.dev/appRevision": "",
},
},
"apiVersion": "core.oam.dev/v1alpha2",
"kind": "HealthScope",
},
}
Expect(len(gotPolicies)).Should(Equal(2))
gotPolicy := gotPolicies[0]
Expect(cmp.Diff(gotPolicy.Object, expectPolicy0.Object)).Should(BeEmpty())
expectPolicy1 := unstructured.Unstructured{
Object: map[string]interface{}{
"spec": map[string]interface{}{
"hosts": "abc",
"http": []interface{}{"abc"},
},
"metadata": map[string]interface{}{
"name": "test-policy",
"namespace": "default",
"labels": map[string]interface{}{
"app.oam.dev/name": "test-app",
"app.oam.dev/component": "test-policy",
"app.oam.dev/appRevision": "",
},
},
"apiVersion": "networking.istio.io/v1alpha3",
"kind": "VirtualService",
},
}
gotPolicy = gotPolicies[1]
Expect(cmp.Diff(gotPolicy.Object, expectPolicy1.Object)).Should(BeEmpty())
})
})
var _ = Describe("Test Terraform schematic appfile", func() {
It("workload capability is Terraform", func() {
var (

View File

@@ -14,30 +14,30 @@ spec:
metadata: {}
spec:
components:
- name: myweb-1
properties:
cmd:
- sleep
- "1000"
enemies: alien
image: busybox
lives: "3"
traits:
- properties:
domain: www.example.com
http:
/: 80
type: myingress
type: myworker
- name: myweb-2
properties:
cmd:
- sleep
- "1000"
enemies: alien
image: busybox
lives: "3"
type: myworker
- name: myweb-1
properties:
cmd:
- sleep
- "1000"
enemies: alien
image: busybox
lives: "3"
traits:
- properties:
domain: www.example.com
http:
/: 80
type: myingress
type: myworker
- name: myweb-2
properties:
cmd:
- sleep
- "1000"
enemies: alien
image: busybox
lives: "3"
type: myworker
status: {}
applicationConfiguration:
apiVersion: core.oam.dev/v1alpha2
@@ -45,50 +45,50 @@ spec:
metadata: {}
spec:
components:
- componentName: myweb-1
revisionName: myweb-1-v1
traits:
- trait:
apiVersion: v1
kind: Service
metadata:
labels:
app.oam.dev/appRevision: livediff-demo-v1
app.oam.dev/component: myweb-1
app.oam.dev/name: livediff-demo
trait.oam.dev/resource: service
trait.oam.dev/type: myingress
name: myweb-1
namespace: default
spec:
ports:
- port: 80
targetPort: 80
selector:
app.oam.dev/component: myweb-1
- trait:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
labels:
app.oam.dev/appRevision: livediff-demo-v1
app.oam.dev/component: myweb-1
app.oam.dev/name: livediff-demo
trait.oam.dev/resource: ingress
trait.oam.dev/type: myingress
name: myweb-1
namespace: default
spec:
rules:
- host: www.example.com
http:
paths:
- backend:
serviceName: myweb-1
servicePort: 80
path: /
- componentName: myweb-2
revisionName: myweb-2-v1
- componentName: myweb-1
revisionName: myweb-1-v1
traits:
- trait:
apiVersion: v1
kind: Service
metadata:
labels:
app.oam.dev/appRevision: livediff-demo-v1
app.oam.dev/component: myweb-1
app.oam.dev/name: livediff-demo
trait.oam.dev/resource: service
trait.oam.dev/type: myingress
name: myweb-1
namespace: default
spec:
ports:
- port: 80
targetPort: 80
selector:
app.oam.dev/component: myweb-1
- trait:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
labels:
app.oam.dev/appRevision: livediff-demo-v1
app.oam.dev/component: myweb-1
app.oam.dev/name: livediff-demo
trait.oam.dev/resource: ingress
trait.oam.dev/type: myingress
name: myweb-1
namespace: default
spec:
rules:
- host: www.example.com
http:
paths:
- backend:
serviceName: myweb-1
servicePort: 80
path: /
- componentName: myweb-2
revisionName: myweb-2-v1
status:
dependency: {}
observedGeneration: 0
@@ -114,79 +114,6 @@ spec:
kind: Deployment
type: deployments.apps
status: {}
components:
- raw:
apiVersion: core.oam.dev/v1alpha2
kind: Component
metadata:
labels:
app.oam.dev/component-revision-hash: b63b8ddf2352632a
name: myweb-1
spec:
workload:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.oam.dev/appRevision: livediff-demo-v1
app.oam.dev/component: myweb-1
app.oam.dev/name: livediff-demo
workload.oam.dev/type: myworker
name: myweb-1
namespace: default
spec:
selector:
matchLabels:
app.oam.dev/component: myweb-1
template:
metadata:
labels:
app.oam.dev/component: myweb-1
spec:
containers:
- command:
- sleep
- "1000"
image: busybox
name: myweb-1
status:
observedGeneration: 0
- raw:
apiVersion: core.oam.dev/v1alpha2
kind: Component
metadata:
labels:
app.oam.dev/component-revision-hash: 85369ee876f97b85
name: myweb-2
spec:
workload:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.oam.dev/appRevision: livediff-demo-v1
app.oam.dev/component: myweb-2
app.oam.dev/name: livediff-demo
workload.oam.dev/type: myworker
name: myweb-2
namespace: default
spec:
selector:
matchLabels:
app.oam.dev/component: myweb-2
template:
metadata:
labels:
app.oam.dev/component: myweb-2
spec:
containers:
- command:
- sleep
- "1000"
image: busybox
name: myweb-2
status:
observedGeneration: 0
resourcesConfigMap:
name: livediff-demo-v1
traitDefinitions:
@@ -196,7 +123,7 @@ spec:
metadata: {}
spec:
appliesToWorkloads:
- '*'
- '*'
definitionRef:
name: ""
schematic:
@@ -212,4 +139,4 @@ spec:
parameter.domain\n\t\t\thttp: {\n\t\t\t\tpaths: [\n\t\t\t\t\tfor k, v in parameter.http
{\n\t\t\t\t\t\tpath: k\n\t\t\t\t\t\tbackend: {\n\t\t\t\t\t\t\tserviceName:
context.name\n\t\t\t\t\t\t\tservicePort: v\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t]\n\t\t\t}\n\t\t}]\n\t}\n}\n"
status: {}
status: {}

View File

@@ -1,51 +0,0 @@
apiVersion: core.oam.dev/v1alpha2
kind: ApplicationConfiguration
metadata:
creationTimestamp: null
labels:
app.oam.dev/name: app-dryrun
name: app-dryrun
spec:
components:
- componentName: myweb
traits:
- trait:
apiVersion: v1
kind: Service
metadata:
labels:
app.oam.dev/appRevision: ""
app.oam.dev/component: myweb
app.oam.dev/name: app-dryrun
trait.oam.dev/resource: service
trait.oam.dev/type: myingress
name: myweb
spec:
ports:
- port: 80
targetPort: 80
selector:
app.oam.dev/component: myweb
- trait:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
labels:
app.oam.dev/appRevision: ""
app.oam.dev/component: myweb
app.oam.dev/name: app-dryrun
trait.oam.dev/resource: ingress
trait.oam.dev/type: myingress
name: myweb
spec:
rules:
- host: www.example.com
http:
paths:
- backend:
serviceName: myweb
servicePort: 80
path: /
status:
dependency: {}
observedGeneration: 0

View File

@@ -29,11 +29,9 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2"
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
"github.com/oam-dev/kubevela/apis/types"
"github.com/oam-dev/kubevela/pkg/oam"
"github.com/oam-dev/kubevela/pkg/oam/mock"
oamutil "github.com/oam-dev/kubevela/pkg/oam/util"
)
@@ -83,7 +81,7 @@ func TestLoadComponentTemplate(t *testing.T) {
`
var componentDefintion = `
apiVersion: core.oam.dev/v1alpha2
apiVersion: core.oam.dev/v1beta1
kind: ComponentDefinition
metadata:
name: worker
@@ -129,100 +127,6 @@ spec:
}
}
func TestLoadWorkloadTemplate(t *testing.T) {
cueTemplate := `
context: {
name: "test"
}
output: {
apiVersion: "apps/v1"
kind: "Deployment"
spec: {
selector: matchLabels: {
"app.oam.dev/component": context.name
}
template: {
metadata: labels: {
"app.oam.dev/component": context.name
}
spec: {
containers: [{
name: context.name
image: parameter.image
if parameter["cmd"] != _|_ {
command: parameter.cmd
}
}]
}
}
selector:
matchLabels:
"app.oam.dev/component": context.name
}
}
parameter: {
// +usage=Which image would you like to use for your service
// +short=i
image: string
cmd?: [...string]
}
`
var workloadDefintion = `
apiVersion: core.oam.dev/v1alpha2
kind: WorkloadDefinition
metadata:
name: worker
namespace: default
annotations:
definition.oam.dev/description: "Long-running scalable backend worker without network endpoint"
spec:
workload:
definition:
apiVersion: apps/v1
kind: Deployment
extension:
template: |
` + cueTemplate
// Create mock client
tclient := test.MockClient{
MockGet: func(ctx context.Context, key ktypes.NamespacedName, obj client.Object) error {
switch o := obj.(type) {
case *v1alpha2.WorkloadDefinition:
cd, err := oamutil.UnMarshalStringToWorkloadDefinition(workloadDefintion)
if err != nil {
return err
}
*o = *cd
case *v1alpha2.ComponentDefinition:
err := mock.NewMockNotFoundErr()
return err
}
return nil
},
}
temp, err := LoadTemplate(context.TODO(), &tclient, "worker", types.TypeComponentDefinition)
if err != nil {
t.Error(err)
return
}
inst := cuecontext.New().CompileString(temp.TemplateStr)
instDest := cuecontext.New().CompileString(cueTemplate)
s1, _ := inst.Value().String()
s2, _ := instDest.Value().String()
if s1 != s2 {
t.Errorf("parsered template is not correct")
}
}
func TestLoadTraitTemplate(t *testing.T) {
cueTemplate := `
parameter: {
@@ -275,7 +179,7 @@ func TestLoadTraitTemplate(t *testing.T) {
`
var traitDefintion = `
apiVersion: core.oam.dev/v1alpha2
apiVersion: core.oam.dev/v1beta1
kind: TraitDefinition
metadata:
annotations:
@@ -414,7 +318,7 @@ func TestLoadSchematicToTemplate(t *testing.T) {
func TestDryRunTemplateLoader(t *testing.T) {
compDefStr := `
apiVersion: core.oam.dev/v1alpha2
apiVersion: core.oam.dev/v1beta1
kind: ComponentDefinition
metadata:
name: myworker
@@ -431,7 +335,7 @@ spec:
template: testCUE `
traitDefStr := `
apiVersion: core.oam.dev/v1alpha2
apiVersion: core.oam.dev/v1beta1
kind: TraitDefinition
metadata:
name: myingress

View File

@@ -1,227 +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 cloudprovider
import (
"context"
"encoding/json"
"fmt"
"strings"
cs20151215 "github.com/alibabacloud-go/cs-20151215/v3/client"
openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
"github.com/alibabacloud-go/tea/tea"
types "github.com/oam-dev/terraform-controller/api/types/crossplane-runtime"
v1beta12 "github.com/oam-dev/terraform-controller/api/v1beta2"
"github.com/pkg/errors"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/klog/v2"
"k8s.io/utils/pointer"
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/oam-dev/kubevela/pkg/utils/util"
)
const (
aliyunAPIEndpoint = "cs.cn-hangzhou.aliyuncs.com"
)
// AliyunCloudProvider describes the cloud provider in aliyun
type AliyunCloudProvider struct {
*cs20151215.Client
k8sClient client.Client
accessKeyID string
accessKeySecret string
}
// NewAliyunCloudProvider create aliyun cloud provider
func NewAliyunCloudProvider(accessKeyID string, accessKeySecret string, k8sClient client.Client) (*AliyunCloudProvider, error) {
config := &openapi.Config{
AccessKeyId: pointer.String(accessKeyID),
AccessKeySecret: pointer.String(accessKeySecret),
}
config.Endpoint = tea.String(aliyunAPIEndpoint)
c, err := cs20151215.NewClient(config)
if err != nil {
return nil, err
}
return &AliyunCloudProvider{Client: c, k8sClient: k8sClient, accessKeyID: accessKeyID, accessKeySecret: accessKeySecret}, nil
}
// IsInvalidKey check if error is InvalidAccessKey or InvalidSecretKey
func (provider *AliyunCloudProvider) IsInvalidKey(err error) bool {
return strings.Contains(err.Error(), "InvalidAccessKeyId") || strings.Contains(err.Error(), "Code: SignatureDoesNotMatch")
}
func (provider *AliyunCloudProvider) decodeClusterLabels(tags []*cs20151215.Tag) map[string]string {
labels := map[string]string{}
for _, tag := range tags {
if tag != nil {
labels[getString(tag.Key)] = getString(tag.Value)
}
}
return labels
}
func (provider *AliyunCloudProvider) decodeClusterURL(masterURL string) (url struct {
APIServerEndpoint string `json:"api_server_endpoint"`
IntranetAPIServerEndpoint string `json:"intranet_api_server_endpoint"`
}) {
if err := json.Unmarshal([]byte(masterURL), &url); err != nil {
klog.Info("failed to unmarshal masterUrl %s", masterURL)
}
return
}
func (provider *AliyunCloudProvider) getDashboardURL(clusterID string) string {
return fmt.Sprintf("https://cs.console.aliyun.com/#/k8s/cluster/%s/v2/info/overview", clusterID)
}
func getString(s *string) string {
if s == nil {
return ""
}
return *s
}
// ListCloudClusters list clusters with page info, return clusters, total count and error
func (provider *AliyunCloudProvider) ListCloudClusters(pageNumber int, pageSize int) ([]*CloudCluster, int, error) {
describeClustersV1Request := &cs20151215.DescribeClustersV1Request{
PageSize: pointer.Int64(int64(pageSize)),
PageNumber: pointer.Int64(int64(pageNumber)),
}
resp, err := provider.DescribeClustersV1(describeClustersV1Request)
if err != nil {
return nil, 0, err
}
var clusters []*CloudCluster
for _, cluster := range resp.Body.Clusters {
if cluster == nil {
continue
}
labels := provider.decodeClusterLabels(cluster.Tags)
url := provider.decodeClusterURL(getString(cluster.MasterUrl))
clusters = append(clusters, &CloudCluster{
ID: getString(cluster.ClusterId),
Name: getString(cluster.Name),
Type: getString(cluster.ClusterType),
Zone: getString(cluster.ZoneId),
ZoneID: getString(cluster.ZoneId),
RegionID: getString(cluster.RegionId),
VpcID: getString(cluster.VpcId),
Labels: labels,
Status: getString(cluster.State),
APIServerURL: url.APIServerEndpoint,
DashBoardURL: provider.getDashboardURL(getString(cluster.ClusterId)),
})
}
return clusters, int(*resp.Body.PageInfo.TotalCount), nil
}
// GetClusterKubeConfig get cluster kubeconfig by clusterID
func (provider *AliyunCloudProvider) GetClusterKubeConfig(clusterID string) (string, error) {
req := &cs20151215.DescribeClusterUserKubeconfigRequest{}
resp, err := provider.DescribeClusterUserKubeconfig(pointer.String(clusterID), req)
if err != nil {
return "", err
}
return *resp.Body.Config, nil
}
// GetClusterInfo retrieves cluster info by clusterID
func (provider *AliyunCloudProvider) GetClusterInfo(clusterID string) (*CloudCluster, error) {
resp, err := provider.DescribeClusterDetail(pointer.String(clusterID))
if err != nil {
return nil, err
}
cluster := resp.Body
labels := provider.decodeClusterLabels(cluster.Tags)
url := provider.decodeClusterURL(*cluster.MasterUrl)
return &CloudCluster{
Provider: ProviderAliyun,
ID: *cluster.ClusterId,
Name: *cluster.Name,
Type: *cluster.ClusterType,
Zone: *cluster.ZoneId,
ZoneID: *cluster.ZoneId,
RegionID: *cluster.RegionId,
VpcID: *cluster.VpcId,
Labels: labels,
Status: *cluster.State,
APIServerURL: url.APIServerEndpoint,
DashBoardURL: provider.getDashboardURL(*cluster.ClusterId),
}, nil
}
// CreateCloudCluster create cloud cluster
func (provider *AliyunCloudProvider) CreateCloudCluster(ctx context.Context, clusterName string, zone string, worker int, cpu int64, mem int64) (string, error) {
name := GetCloudClusterFullName(ProviderAliyun, clusterName)
ns := util.GetRuntimeNamespace()
terraformProviderName, err := bootstrapTerraformProvider(ctx, provider.k8sClient, ns, ProviderAliyun, "alibaba", provider.accessKeyID, provider.accessKeySecret, "cn-hongkong")
if err != nil {
return "", errors.Wrapf(err, "failed to bootstrap terraform provider")
}
properties := map[string]interface{}{
"k8s_name_prefix": clusterName,
}
if zone != "" {
properties["zone_id"] = zone
}
if cpu != 0 {
properties["cpu_core_count"] = cpu
}
if mem != 0 {
properties["memory_size"] = mem
}
if worker != 0 {
properties["k8s_worker_number"] = worker
}
bs, err := json.Marshal(properties)
if err != nil {
return name, errors.Wrapf(err, "failed to marshal cloud cluster app properties")
}
cfg := v1beta12.Configuration{
ObjectMeta: v1.ObjectMeta{
Name: name,
Namespace: ns,
Labels: map[string]string{
CloudClusterCreatorLabelKey: ProviderAliyun,
},
},
Spec: v1beta12.ConfigurationSpec{
ProviderReference: &types.Reference{
Name: terraformProviderName,
Namespace: ns,
},
Remote: "https://github.com/kubevela-contrib/terraform-modules.git",
Variable: &runtime.RawExtension{Raw: bs},
},
}
cfg.Spec.Path = "alibaba/cs/dedicated-kubernetes"
cfg.Spec.WriteConnectionSecretToReference = &types.SecretReference{
Name: name,
Namespace: ns,
}
if err = provider.k8sClient.Create(ctx, &cfg); err != nil {
return name, errors.Wrapf(err, "failed to create cloud cluster terraform configuration")
}
return name, nil
}

View File

@@ -1,48 +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 cloudprovider
import (
"context"
"github.com/pkg/errors"
"sigs.k8s.io/controller-runtime/pkg/client"
)
const (
// CloudClusterCreatorLabelKey labels the creator of cloud cluster
CloudClusterCreatorLabelKey = "api.core.oam.dev/cloud-cluster-creator"
)
// CloudClusterProvider abstracts the cloud provider to provide cluster access
type CloudClusterProvider interface {
IsInvalidKey(err error) bool
ListCloudClusters(pageNumber int, pageSize int) ([]*CloudCluster, int, error)
GetClusterKubeConfig(clusterID string) (string, error)
GetClusterInfo(clusterID string) (*CloudCluster, error)
CreateCloudCluster(ctx context.Context, clusterName string, zone string, worker int, cpu int64, mem int64) (string, error)
}
// GetClusterProvider creates interface for getting cloud cluster provider
func GetClusterProvider(provider string, accessKeyID string, accessKeySecret string, k8sClient client.Client) (CloudClusterProvider, error) {
switch provider {
case ProviderAliyun:
return NewAliyunCloudProvider(accessKeyID, accessKeySecret, k8sClient)
default:
return nil, errors.Errorf("cluster provider %s is not implemented", provider)
}
}

View File

@@ -1,94 +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 cloudprovider
import (
"context"
"crypto/sha256"
"fmt"
"strings"
types "github.com/oam-dev/terraform-controller/api/types/crossplane-runtime"
v1beta12 "github.com/oam-dev/terraform-controller/api/v1beta1"
"github.com/pkg/errors"
v12 "k8s.io/api/core/v1"
kerrors "k8s.io/apimachinery/pkg/api/errors"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
)
func computeProviderHashKey(provider string, accessKeyID string, accessKeySecret string) string {
return fmt.Sprintf("%x", sha256.Sum256([]byte(strings.Join([]string{provider, accessKeyID, accessKeySecret}, "::"))))[:8] // #nosec
}
// GetCloudClusterFullName construct the full name of cloud cluster which will be used as the name of terraform configuration
func GetCloudClusterFullName(provider string, clusterName string) string {
return fmt.Sprintf("cloud-cluster-%s-%s", provider, clusterName)
}
func bootstrapTerraformProvider(ctx context.Context, k8sClient client.Client, ns string, provider string, tfProvider string, accessKeyID string, accessKeySecret string, region string) (string, error) {
hashKey := computeProviderHashKey(provider, accessKeyID, accessKeySecret)
secretName := fmt.Sprintf("tf-provider-cred-%s-%s", provider, hashKey)
terraformProviderName := fmt.Sprintf("tf-provider-%s-%s", provider, hashKey)
secret := v12.Secret{
ObjectMeta: v1.ObjectMeta{
Name: secretName,
Namespace: ns,
},
StringData: map[string]string{"credentials": fmt.Sprintf("accessKeyID: %s\naccessKeySecret: %s\nsecurityToken:\n", accessKeyID, accessKeySecret)},
Type: v12.SecretTypeOpaque,
}
var err error
if err = k8sClient.Get(ctx, client.ObjectKeyFromObject(&secret), &v12.Secret{}); err != nil {
if kerrors.IsNotFound(err) {
err = k8sClient.Create(ctx, &secret)
}
if err != nil {
return "", errors.Wrapf(err, "failed to upsert terraform provider secret")
}
}
terraformProvider := v1beta12.Provider{
ObjectMeta: v1.ObjectMeta{
Name: terraformProviderName,
Namespace: ns,
},
Spec: v1beta12.ProviderSpec{
Credentials: v1beta12.ProviderCredentials{
SecretRef: &types.SecretKeySelector{
Key: "credentials",
SecretReference: types.SecretReference{
Name: secretName,
Namespace: ns,
},
},
Source: types.CredentialsSourceSecret,
},
Provider: tfProvider,
Region: region,
},
}
if err = k8sClient.Get(ctx, client.ObjectKeyFromObject(&terraformProvider), &v1beta12.Provider{}); err != nil {
if kerrors.IsNotFound(err) {
err = k8sClient.Create(ctx, &terraformProvider)
}
if err != nil {
return "", errors.Wrapf(err, "failed to upsert terraform provider")
}
}
return terraformProviderName, nil
}

View File

@@ -1,38 +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 cloudprovider
const (
// ProviderAliyun cloud provider aliyun
ProviderAliyun = "aliyun"
)
// CloudCluster describes the interface that cloud provider should return
type CloudCluster struct {
Provider string `json:"provider"`
ID string `json:"id"`
Name string `json:"name"`
Type string `json:"type"`
Zone string `json:"zone"`
ZoneID string `json:"zoneID"`
RegionID string `json:"regionID"`
VpcID string `json:"vpcID"`
Labels map[string]string `json:"labels"`
Status string `json:"status"`
APIServerURL string `json:"apiServerURL"`
DashBoardURL string `json:"dashboardURL"`
}

View File

@@ -1,26 +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 common
// error msg for common usage
const (
ErrLocatingWorkload = "failed to locate the workload"
ErrLocatingService = "failed to locate any the services"
ErrCreatingService = "failed to create the services"
ErrUpdateStatus = "failed to update status"
)

View File

@@ -1,386 +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 rollout
import (
"context"
"fmt"
"reflect"
"time"
"github.com/crossplane/crossplane-runtime/pkg/event"
kruisev1 "github.com/openkruise/kruise-api/apps/v1alpha1"
apps "k8s.io/api/apps/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/types"
"k8s.io/klog/v2"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
"github.com/oam-dev/kubevela/apis/standard.oam.dev/v1alpha1"
"github.com/oam-dev/kubevela/pkg/controller/common"
"github.com/oam-dev/kubevela/pkg/controller/common/rollout/workloads"
"github.com/oam-dev/kubevela/pkg/oam"
)
// the default time to check back if we still have work to do
const rolloutReconcileRequeueTime = 5 * time.Second
// Controller is the controller that controls the rollout plan resource
type Controller struct {
client client.Client
recorder event.Recorder
parentController oam.Object
rolloutSpec *v1alpha1.RolloutPlan
rolloutStatus *v1alpha1.RolloutStatus
targetWorkload *unstructured.Unstructured
sourceWorkload *unstructured.Unstructured
}
// NewRolloutPlanController creates a RolloutPlanController
func NewRolloutPlanController(client client.Client, parentController oam.Object, recorder event.Recorder,
rolloutSpec *v1alpha1.RolloutPlan, rolloutStatus *v1alpha1.RolloutStatus,
targetWorkload, sourceWorkload *unstructured.Unstructured) *Controller {
initializedRolloutStatus := rolloutStatus.DeepCopy()
if len(initializedRolloutStatus.BatchRollingState) == 0 {
initializedRolloutStatus.BatchRollingState = v1alpha1.BatchInitializingState
}
return &Controller{
client: client,
parentController: parentController,
recorder: recorder,
rolloutSpec: rolloutSpec.DeepCopy(),
rolloutStatus: initializedRolloutStatus,
targetWorkload: targetWorkload,
sourceWorkload: sourceWorkload,
}
}
// Reconcile reconciles a rollout plan
func (r *Controller) Reconcile(ctx context.Context) (res reconcile.Result, status *v1alpha1.RolloutStatus) {
klog.InfoS("Reconcile the rollout plan", "rollout status", r.rolloutStatus,
"target workload", klog.KObj(r.targetWorkload))
if r.sourceWorkload != nil {
klog.InfoS("We will do rolling upgrades", "source workload", klog.KObj(r.sourceWorkload))
}
klog.InfoS("rollout status", "rollout state", r.rolloutStatus.RollingState, "batch rolling state",
r.rolloutStatus.BatchRollingState, "current batch", r.rolloutStatus.CurrentBatch, "upgraded Replicas",
r.rolloutStatus.UpgradedReplicas, "ready Replicas", r.rolloutStatus.UpgradedReadyReplicas)
defer func() {
klog.InfoS("Finished one round of reconciling rollout plan", "rollout state", status.RollingState,
"batch rolling state", status.BatchRollingState, "current batch", status.CurrentBatch,
"upgraded Replicas", status.UpgradedReplicas, "ready Replicas", status.UpgradedReadyReplicas,
"reconcile result ", res)
}()
status = r.rolloutStatus
defer func() {
if status.RollingState == v1alpha1.RolloutFailedState ||
status.RollingState == v1alpha1.RolloutSucceedState {
// no need to requeue if we reach the terminal states
res = reconcile.Result{}
} else {
res = reconcile.Result{
RequeueAfter: rolloutReconcileRequeueTime,
}
}
}()
workloadController, err := r.GetWorkloadController()
if err != nil {
r.rolloutStatus.RolloutFailed(err.Error())
r.recorder.Event(r.parentController, event.Warning("Unsupported workload", err))
return
}
switch r.rolloutStatus.RollingState {
case v1alpha1.VerifyingSpecState:
verified, err := workloadController.VerifySpec(ctx)
if err != nil {
// we can fail it right away, everything after initialized need to be finalized
r.rolloutStatus.RolloutFailed(err.Error())
} else if verified {
r.rolloutStatus.StateTransition(v1alpha1.RollingSpecVerifiedEvent)
}
case v1alpha1.InitializingState:
if err = r.initializeRollout(ctx); err == nil {
initialized, err := workloadController.Initialize(ctx)
if err != nil {
r.rolloutStatus.RolloutFailing(err.Error())
} else if initialized {
r.rolloutStatus.StateTransition(v1alpha1.RollingInitializedEvent)
}
}
case v1alpha1.RollingInBatchesState:
r.reconcileBatchInRolling(ctx, workloadController)
case v1alpha1.RolloutFailingState, v1alpha1.RolloutAbandoningState, v1alpha1.RolloutDeletingState:
if succeed := workloadController.Finalize(ctx, false); succeed {
r.finalizeRollout(ctx)
}
case v1alpha1.FinalisingState:
if succeed := workloadController.Finalize(ctx, true); succeed {
r.finalizeRollout(ctx)
}
case v1alpha1.RolloutSucceedState:
// Nothing to do
case v1alpha1.RolloutFailedState:
// Nothing to do
default:
panic(fmt.Sprintf("illegal rollout status %+v", r.rolloutStatus))
}
return res, r.rolloutStatus
}
// reconcile logic when we are in the middle of rollout, we have to go through finalizing state before succeed or fail
func (r *Controller) reconcileBatchInRolling(ctx context.Context, workloadController workloads.WorkloadController) {
if r.rolloutSpec.Paused {
r.recorder.Event(r.parentController, event.Normal("Rollout paused", "Rollout paused"))
r.rolloutStatus.SetConditions(v1alpha1.NewPositiveCondition(v1alpha1.BatchPaused))
return
}
switch r.rolloutStatus.BatchRollingState {
case v1alpha1.BatchInitializingState:
r.initializeOneBatch(ctx)
case v1alpha1.BatchInRollingState:
// still rolling the batch, the batch rolling is not completed yet
upgradeDone, err := workloadController.RolloutOneBatchPods(ctx)
if err != nil {
r.rolloutStatus.RolloutFailing(err.Error())
} else if upgradeDone {
r.rolloutStatus.StateTransition(v1alpha1.RolloutOneBatchEvent)
}
case v1alpha1.BatchVerifyingState:
// verifying if the application is ready to roll
// need to check if they meet the availability requirements in the rollout spec.
// TODO: evaluate any metrics/analysis
// TODO: We may need to go back to rollout again if the size of the resource can change behind our back
verified, err := workloadController.CheckOneBatchPods(ctx)
if err != nil {
r.rolloutStatus.RolloutFailing(err.Error())
} else if verified {
r.rolloutStatus.StateTransition(v1alpha1.OneBatchAvailableEvent)
}
case v1alpha1.BatchFinalizingState:
// finalize one batch
finalized, err := workloadController.FinalizeOneBatch(ctx)
if err != nil {
r.rolloutStatus.RolloutFailing(err.Error())
} else if finalized {
r.finalizeOneBatch(ctx)
}
case v1alpha1.BatchReadyState:
// all the pods in the are upgraded and their state are ready
// wait to move to the next batch if there are any
r.tryMovingToNextBatch()
default:
panic(fmt.Sprintf("illegal status %+v", r.rolloutStatus))
}
}
// all the common initialize work before we rollout
// TODO: fail the rollout if the webhook call is explicitly rejected (through http status code)
func (r *Controller) initializeRollout(ctx context.Context) error {
// call the pre-rollout webhooks
for _, rw := range r.rolloutSpec.RolloutWebhooks {
if rw.Type == v1alpha1.InitializeRolloutHook {
err := callWebhook(ctx, r.parentController, string(v1alpha1.InitializingState), rw)
if err != nil {
klog.ErrorS(err, "failed to invoke a webhook",
"webhook name", rw.Name, "webhook end point", rw.URL)
r.rolloutStatus.RolloutRetry("failed to invoke a webhook")
return err
}
klog.InfoS("successfully invoked a pre rollout webhook", "webhook name", rw.Name, "webhook end point",
rw.URL)
}
}
return nil
}
// all the common initialize work before we rollout one batch of resources
func (r *Controller) initializeOneBatch(ctx context.Context) {
rolloutHooks := r.gatherAllWebhooks()
// call all the pre-batch rollout webhooks
for _, rh := range rolloutHooks {
if rh.Type == v1alpha1.PreBatchRolloutHook {
err := callWebhook(ctx, r.parentController, string(v1alpha1.BatchInitializingState), rh)
if err != nil {
klog.ErrorS(err, "failed to invoke a webhook",
"webhook name", rh.Name, "webhook end point", rh.URL)
r.rolloutStatus.RolloutRetry("failed to invoke a webhook")
return
}
klog.InfoS("successfully invoked a pre batch webhook", "webhook name", rh.Name, "webhook end point",
rh.URL)
}
}
r.rolloutStatus.StateTransition(v1alpha1.InitializedOneBatchEvent)
}
func (r *Controller) gatherAllWebhooks() []v1alpha1.RolloutWebhook {
// we go through the rollout level webhooks first
rolloutHooks := r.rolloutSpec.RolloutWebhooks
// we then append the batch specific rollout webhooks to the overall webhooks
// order matters here
currentBatch := int(r.rolloutStatus.CurrentBatch)
rolloutHooks = append(rolloutHooks, r.rolloutSpec.RolloutBatches[currentBatch].BatchRolloutWebhooks...)
return rolloutHooks
}
// check if we can move to the next batch
func (r *Controller) tryMovingToNextBatch() {
if r.rolloutSpec.BatchPartition == nil || *r.rolloutSpec.BatchPartition > r.rolloutStatus.CurrentBatch {
klog.InfoS("ready to rollout the next batch", "current batch", r.rolloutStatus.CurrentBatch)
r.rolloutStatus.StateTransition(v1alpha1.BatchRolloutApprovedEvent)
} else {
klog.V(common.LogDebug).InfoS("the current batch is waiting to move on", "current batch",
r.rolloutStatus.CurrentBatch)
}
}
func (r *Controller) finalizeOneBatch(ctx context.Context) {
rolloutHooks := r.gatherAllWebhooks()
// call all the post-batch rollout webhooks
for _, rh := range rolloutHooks {
if rh.Type == v1alpha1.PostBatchRolloutHook {
err := callWebhook(ctx, r.parentController, string(v1alpha1.BatchFinalizingState), rh)
if err != nil {
klog.ErrorS(err, "failed to invoke a webhook",
"webhook name", rh.Name, "webhook end point", rh.URL)
r.rolloutStatus.RolloutRetry("failed to invoke a webhook")
return
}
klog.InfoS("successfully invoked a post batch webhook", "webhook name", rh.Name, "webhook end point",
rh.URL)
}
}
// calculate the next phase
currentBatch := int(r.rolloutStatus.CurrentBatch)
if currentBatch == len(r.rolloutSpec.RolloutBatches)-1 {
// this is the last batch, mark the rollout finalized
r.rolloutStatus.StateTransition(v1alpha1.AllBatchFinishedEvent)
r.recorder.Event(r.parentController, event.Normal("All batches rolled out",
fmt.Sprintf("upgrade pod = %d, total ready pod = %d", r.rolloutStatus.UpgradedReplicas,
r.rolloutStatus.UpgradedReadyReplicas)))
} else {
klog.InfoS("finished one batch rollout", "current batch", r.rolloutStatus.CurrentBatch)
// th
r.recorder.Event(r.parentController, event.Normal("Batch Finalized",
fmt.Sprintf("Batch %d is finalized and ready to go", r.rolloutStatus.CurrentBatch)))
r.rolloutStatus.StateTransition(v1alpha1.FinishedOneBatchEvent)
}
}
// all the common finalize work after we rollout
func (r *Controller) finalizeRollout(ctx context.Context) {
// call the post-rollout webhooks
for _, rw := range r.rolloutSpec.RolloutWebhooks {
if rw.Type == v1alpha1.FinalizeRolloutHook {
err := callWebhook(ctx, r.parentController, string(r.rolloutStatus.RollingState), rw)
if err != nil {
klog.ErrorS(err, "failed to invoke a webhook",
"webhook name", rw.Name, "webhook end point", rw.URL)
r.rolloutStatus.RolloutRetry("failed to invoke a post rollout webhook")
return
}
klog.InfoS("successfully invoked a post rollout webhook", "webhook name", rw.Name, "webhook end point",
rw.URL)
}
}
r.rolloutStatus.StateTransition(v1alpha1.RollingFinalizedEvent)
}
// GetWorkloadController pick the right workload controller to work on the workload
func (r *Controller) GetWorkloadController() (workloads.WorkloadController, error) {
kind := r.targetWorkload.GetObjectKind().GroupVersionKind().Kind
target := types.NamespacedName{
Namespace: r.targetWorkload.GetNamespace(),
Name: r.targetWorkload.GetName(),
}
var source types.NamespacedName
if r.sourceWorkload != nil {
source.Namespace = r.sourceWorkload.GetNamespace()
source.Name = r.sourceWorkload.GetName()
}
if r.targetWorkload.GroupVersionKind().Group == kruisev1.GroupVersion.Group {
// check if the target workload is CloneSet
if r.targetWorkload.GetKind() == reflect.TypeOf(kruisev1.CloneSet{}).Name() {
// check whether current rollout plan is for workload rolling or scaling
if r.sourceWorkload != nil {
klog.InfoS("using cloneset rollout controller for this rolloutplan", "source workload name", source.Name, "namespace",
source.Namespace, "target workload name", target.Name, "namespace",
target.Namespace)
return workloads.NewCloneSetRolloutController(r.client, r.recorder, r.parentController,
r.rolloutSpec, r.rolloutStatus, target), nil
}
klog.InfoS("using cloneset scale controller for this rolloutplan", "target workload name", target.Name, "namespace",
target.Namespace)
return workloads.NewCloneSetScaleController(r.client, r.recorder, r.parentController,
r.rolloutSpec, r.rolloutStatus, target), nil
}
}
if r.targetWorkload.GroupVersionKind().Group == apps.GroupName {
// check if the target workload is Deployment
if r.targetWorkload.GetKind() == reflect.TypeOf(apps.Deployment{}).Name() {
// check whether current rollout plan is for workload rolling or scaling
if r.sourceWorkload != nil {
klog.InfoS("using deployment rollout controller for this rolloutplan", "source workload name", source.Name, "namespace",
source.Namespace, "target workload name", target.Name, "namespace",
target.Namespace)
return workloads.NewDeploymentRolloutController(r.client, r.recorder, r.parentController,
r.rolloutSpec, r.rolloutStatus, source, target), nil
}
klog.InfoS("using deployment scale controller for this rolloutplan", "target workload name", target.Name, "namespace",
target.Namespace)
return workloads.NewDeploymentScaleController(r.client, r.recorder, r.parentController,
r.rolloutSpec, r.rolloutStatus, target), nil
}
// check if the target workload is StatefulSet
if r.targetWorkload.GetKind() == reflect.TypeOf(apps.StatefulSet{}).Name() {
// check whether current rollout plan is for workload rolling or scaling
if r.sourceWorkload != nil {
return workloads.NewStatefulSetRolloutController(r.client, r.recorder, r.parentController,
r.rolloutSpec, r.rolloutStatus, target), nil
}
return workloads.NewStatefulSetScaleController(r.client, r.recorder, r.parentController,
r.rolloutSpec, r.rolloutStatus, target), nil
}
}
return nil, fmt.Errorf("the workload kind `%s` is not supported", kind)
}

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 rollout
import (
"testing"
"k8s.io/utils/pointer"
"github.com/oam-dev/kubevela/apis/standard.oam.dev/v1alpha1"
)
func Test_TryMovingToNextBatch(t *testing.T) {
tests := map[string]struct {
r Controller
rolloutSpec *v1alpha1.RolloutPlan
rolloutStatus *v1alpha1.RolloutStatus
wantNextBatch int32
wantBatchRollingState v1alpha1.BatchRollingState
}{
"stay at the same batch": {
rolloutSpec: &v1alpha1.RolloutPlan{
BatchPartition: pointer.Int32(3),
},
rolloutStatus: &v1alpha1.RolloutStatus{
CurrentBatch: 2,
RollingState: v1alpha1.RollingInBatchesState,
BatchRollingState: v1alpha1.BatchReadyState,
},
wantNextBatch: 3,
wantBatchRollingState: v1alpha1.BatchInitializingState,
},
}
for name, tt := range tests {
t.Run(name, func(t *testing.T) {
r := &Controller{
rolloutSpec: tt.rolloutSpec,
rolloutStatus: tt.rolloutStatus,
}
r.tryMovingToNextBatch()
if r.rolloutStatus.CurrentBatch != tt.wantNextBatch {
t.Errorf("\n%s\n batch miss match: want batch `%d`, got batch:`%d`\n", name,
tt.wantNextBatch, r.rolloutStatus.CurrentBatch)
}
if r.rolloutStatus.BatchRollingState != tt.wantBatchRollingState {
t.Errorf("\n%s\nstate miss match: want state `%s`, got state:`%s`\n", name,
tt.wantBatchRollingState, r.rolloutStatus.BatchRollingState)
}
})
}
}

View File

@@ -1,131 +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 rollout
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"k8s.io/client-go/util/retry"
"k8s.io/klog/v2"
"github.com/oam-dev/kubevela/apis/standard.oam.dev/v1alpha1"
)
// issue an http call to the an end ponit
func makeHTTPRequest(ctx context.Context, webhookEndPoint, method string, payload interface{}) ([]byte, int, error) {
payloadBin, err := json.Marshal(payload)
if err != nil {
return nil, http.StatusInternalServerError, err
}
hook, err := url.Parse(webhookEndPoint)
if err != nil {
return nil, http.StatusInternalServerError, err
}
req, err := http.NewRequestWithContext(context.Background(), method, hook.String(), bytes.NewBuffer(payloadBin))
if err != nil {
return nil, http.StatusInternalServerError, err
}
req.Header.Set("Content-Type", "application/json")
// issue request with retry
var r *http.Response
var body []byte
err = retry.OnError(retry.DefaultBackoff,
func(error) bool {
// not sure what not to retry on
return true
}, func() error {
var requestErr error
r, requestErr = http.DefaultClient.Do(req.WithContext(ctx))
defer func() {
if r != nil {
_ = r.Body.Close()
}
}()
if requestErr != nil {
return requestErr
}
body, requestErr = io.ReadAll(r.Body)
if requestErr != nil {
return requestErr
}
if r.StatusCode >= http.StatusInternalServerError {
requestErr = fmt.Errorf("internal server error, status code = %d", r.StatusCode)
}
return requestErr
})
// failed even with retry
if err != nil {
if r != nil {
return nil, r.StatusCode, err
}
return nil, -1, err
}
return body, r.StatusCode, nil
}
// callWebhook does a HTTP POST to an external service and
// returns an error if the response status code is non-2xx
func callWebhook(ctx context.Context, resource klog.KMetadata, phase string, rw v1alpha1.RolloutWebhook) error {
payload := v1alpha1.RolloutWebhookPayload{
Name: resource.GetName(),
Namespace: resource.GetNamespace(),
Phase: phase,
}
if rw.Metadata != nil {
payload.Metadata = *rw.Metadata
}
// make the http request
if len(rw.Method) == 0 {
rw.Method = http.MethodPost
}
_, status, err := makeHTTPRequest(ctx, rw.URL, rw.Method, payload)
if err != nil {
return err
}
if len(rw.ExpectedStatus) == 0 {
if status > http.StatusAccepted {
err := fmt.Errorf("we fail the webhook request based on status, http status = %d", status)
return err
}
return nil
}
// check if the returned status is expected
accepted := false
for _, es := range rw.ExpectedStatus {
if es == status {
accepted = true
break
}
}
if !accepted {
err := fmt.Errorf("http request to the webhook not accepeted, http status = %d", status)
klog.ErrorS(err, "The status is not expected", "expected status", rw.ExpectedStatus)
return err
}
return nil
}

View File

@@ -1,246 +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 rollout
import (
"context"
"fmt"
"math/rand"
"net"
"net/http"
"net/http/httptest"
"strconv"
"testing"
appsv1 "k8s.io/api/apps/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/oam-dev/kubevela/apis/standard.oam.dev/v1alpha1"
"github.com/oam-dev/kubevela/pkg/oam"
)
const mockUrlBase = "127.0.0.1:"
func TestMakeHTTPRequest(t *testing.T) {
ctx := context.TODO()
type mockHTTPParameter struct {
method string
statusCode int
body string
}
type want struct {
err error
statusCode int
body string
}
tests := map[string]struct {
url string
method string
payload interface{}
httpParameter mockHTTPParameter
want want
}{
"Test normal case": {
method: http.MethodPost,
payload: "doesn't matter",
httpParameter: mockHTTPParameter{
method: http.MethodPost,
statusCode: http.StatusAccepted,
body: "all good",
},
want: want{
err: nil,
statusCode: http.StatusAccepted,
body: "all good",
},
},
"Test http failed case with retry": {
url: "127.0.0.1:13622",
method: http.MethodPost,
payload: "doesn't matter",
httpParameter: mockHTTPParameter{
method: http.MethodGet,
statusCode: http.StatusAccepted,
body: "doesn't matter",
},
want: want{
err: fmt.Errorf("internal server error, status code = %d", http.StatusNotImplemented),
statusCode: -1,
body: "",
},
},
"Test failed case with retry": {
method: http.MethodPost,
payload: "doesn't matter",
httpParameter: mockHTTPParameter{
method: http.MethodPost,
statusCode: http.StatusNotImplemented,
body: "please retry",
},
want: want{
err: fmt.Errorf("internal server error, status code = %d", http.StatusNotImplemented),
statusCode: http.StatusNotImplemented,
body: "",
},
},
"Test client error failed case": {
method: http.MethodPost,
payload: "doesn't matter",
httpParameter: mockHTTPParameter{
method: http.MethodPost,
statusCode: http.StatusBadRequest,
body: "bad request",
},
want: want{
err: nil,
statusCode: http.StatusBadRequest,
body: "bad request",
},
},
}
for testName, tt := range tests {
func(testName string) {
mockUrl := mockUrlBase + strconv.FormatInt(rand.Int63n(128)+2000, 10)
// generate a test server so we can capture and inspect the request
testServer := NewMock(tt.httpParameter.method, mockUrl, tt.httpParameter.statusCode, tt.httpParameter.body)
defer testServer.Close()
if len(tt.url) == 0 {
tt.url = mockUrl
}
gotReply, gotCode, gotErr := makeHTTPRequest(ctx, "http://"+tt.url, tt.method, tt.payload)
if gotCode != tt.want.statusCode {
t.Errorf("\n%s\nr.Reconcile(...): want code `%d`, got code:`%d` got err: %v \n", testName, tt.want.statusCode,
gotCode, gotErr)
}
if gotCode == -1 {
// we don't know exactly what error we should get when the network call failed
if gotErr == nil {
t.Errorf("\n%s\nr.Reconcile(...): want some error, got error:`%s`\n", testName, gotErr)
}
} else {
if (tt.want.err == nil && gotErr != nil) || (tt.want.err != nil && gotErr == nil) {
t.Errorf("\n%s\nr.Reconcile(...): want error `%s`, got error:`%s`\n", testName, tt.want.err, gotErr)
}
if tt.want.err != nil && gotErr != nil && gotErr.Error() != tt.want.err.Error() {
t.Errorf("\n%s\nr.Reconcile(...): want error `%s`, got error:`%s`\n", testName, tt.want.err, gotErr)
}
}
if string(gotReply) != tt.want.body {
t.Errorf("\n%s\nr.Reconcile(...): want reply `%s`, got reply:`%s`\n", testName, tt.want.body, string(gotReply))
}
}(testName)
}
}
func TestCallWebhook(t *testing.T) {
ctx := context.TODO()
body := "all good"
res := appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "name",
Namespace: "namespace",
},
}
type args struct {
resource oam.Object
phase string
rw v1alpha1.RolloutWebhook
}
tests := map[string]struct {
returnedStatusCode int
args args
wantErr error
}{
"Test success case": {
returnedStatusCode: http.StatusAccepted,
args: args{
resource: &res,
phase: string(v1alpha1.RollingInBatchesState),
rw: v1alpha1.RolloutWebhook{},
},
wantErr: nil,
},
"Test failed default case": {
returnedStatusCode: http.StatusAlreadyReported,
args: args{
resource: &res,
phase: string(v1alpha1.RollingInBatchesState),
rw: v1alpha1.RolloutWebhook{},
},
wantErr: fmt.Errorf("we fail the webhook request based on status, http status = %d", http.StatusAlreadyReported),
},
"Test expected treated as success case": {
returnedStatusCode: http.StatusAlreadyReported,
args: args{
resource: &res,
phase: string(v1alpha1.RollingInBatchesState),
rw: v1alpha1.RolloutWebhook{
ExpectedStatus: []int{http.StatusNoContent, http.StatusAlreadyReported},
},
},
wantErr: nil,
},
"Test not expected treated as failed case": {
returnedStatusCode: http.StatusGone,
args: args{
resource: &res,
phase: string(v1alpha1.RolloutFailedState),
rw: v1alpha1.RolloutWebhook{
ExpectedStatus: []int{http.StatusNoContent, http.StatusAlreadyReported},
},
},
wantErr: fmt.Errorf("http request to the webhook not accepeted, http status = %d", http.StatusGone),
},
}
for name, tt := range tests {
func(name string) {
url := mockUrlBase + strconv.FormatInt(rand.Int63n(4848)+2000, 10)
tt.args.rw.URL = "http://" + url
// generate a test server so we can capture and inspect the request
testServer := NewMock(http.MethodPost, url, tt.returnedStatusCode, body)
defer testServer.Close()
gotErr := callWebhook(ctx, tt.args.resource, tt.args.phase, tt.args.rw)
if (tt.wantErr == nil && gotErr != nil) || (tt.wantErr != nil && gotErr == nil) {
t.Errorf("\n%s\nr.Reconcile(...): want error `%s`, got error:`%s`\n", name, tt.wantErr, gotErr)
}
if tt.wantErr != nil && gotErr != nil && gotErr.Error() != tt.wantErr.Error() {
t.Errorf("\n%s\nr.Reconcile(...): want error `%s`, got error:`%s`\n", name, tt.wantErr, gotErr)
}
}(name)
}
}
func NewMock(method, mockUrl string, statusCode int, body string) *httptest.Server {
ts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
if req.Method == method {
w.WriteHeader(statusCode)
w.Write([]byte(body))
} else {
w.WriteHeader(http.StatusBadRequest)
}
}))
l, err := net.Listen("tcp", mockUrl)
if err != nil {
panic(err)
}
ts.Listener.Close()
ts.Listener = l
ts.Start()
return ts
}

View File

@@ -1,322 +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 workloads
import (
"context"
"fmt"
"github.com/crossplane/crossplane-runtime/pkg/event"
"github.com/pkg/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/klog/v2"
"sigs.k8s.io/controller-runtime/pkg/client"
"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"
)
// CloneSetRolloutController is responsible for handle rollout Cloneset type of workloads
type CloneSetRolloutController struct {
cloneSetController
}
// NewCloneSetRolloutController creates a new Cloneset rollout controller
func NewCloneSetRolloutController(client client.Client, recorder event.Recorder, parentController oam.Object,
rolloutSpec *v1alpha1.RolloutPlan, rolloutStatus *v1alpha1.RolloutStatus, workloadName types.NamespacedName) *CloneSetRolloutController {
return &CloneSetRolloutController{
cloneSetController: cloneSetController{
workloadController: workloadController{
client: client,
recorder: recorder,
parentController: parentController,
rolloutSpec: rolloutSpec,
rolloutStatus: rolloutStatus,
},
targetNamespacedName: workloadName,
},
}
}
// VerifySpec verifies that the target rollout resource is consistent with the rollout spec
func (c *CloneSetRolloutController) VerifySpec(ctx context.Context) (bool, error) {
var verifyErr error
defer func() {
if verifyErr != nil {
klog.Error(verifyErr)
c.recorder.Event(c.parentController, event.Warning("VerifyFailed", verifyErr))
}
}()
// fetch the cloneset and get its current size
currentReplicas, verifyErr := c.size(ctx)
if verifyErr != nil {
// do not fail the rollout because we can't get the resource
c.rolloutStatus.RolloutRetry(verifyErr.Error())
// nolint: nilerr
return false, nil
}
// the cloneset size has to be the same as the current size
if c.cloneSet.Spec.Replicas != nil && *c.cloneSet.Spec.Replicas != c.cloneSet.Status.Replicas {
verifyErr = fmt.Errorf("the cloneset is still scaling, target = %d, cloneset size = %d",
*c.cloneSet.Spec.Replicas, c.cloneSet.Status.Replicas)
// we can wait for the cloneset scale operation to finish
c.rolloutStatus.RolloutRetry(verifyErr.Error())
return false, nil
}
// make sure that the updateRevision is different from what we have already done
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)
}
// check if the rollout batch replicas added up to the Cloneset replicas
if verifyErr = c.verifyRolloutBatchReplicaValue(currentReplicas); verifyErr != nil {
return false, verifyErr
}
// record the size
klog.InfoS("record the target size", "total replicas", currentReplicas)
c.rolloutStatus.RolloutTargetSize = currentReplicas
c.rolloutStatus.RolloutOriginalSize = currentReplicas
// check if the cloneset is disabled
if !c.cloneSet.Spec.UpdateStrategy.Paused {
return false, fmt.Errorf("the cloneset %s is in the middle of updating, need to be paused first",
c.cloneSet.GetName())
}
// check if the cloneset has any controller
if controller := metav1.GetControllerOf(c.cloneSet); controller != nil {
return false, fmt.Errorf("the cloneset %s has a controller owner %s",
c.cloneSet.GetName(), controller.String())
}
// mark the rollout verified
c.recorder.Event(c.parentController, event.Normal("Rollout Verified",
"Rollout spec and the CloneSet resource are verified"))
// record the new pod template hash only if it succeeds
c.rolloutStatus.NewPodTemplateIdentifier = targetHash
return true, nil
}
// Initialize makes sure that the cloneset is under our control
func (c *CloneSetRolloutController) Initialize(ctx context.Context) (bool, error) {
totalReplicas, err := c.size(ctx)
if err != nil {
c.rolloutStatus.RolloutRetry(err.Error())
return false, nil
}
if controller := metav1.GetControllerOf(c.cloneSet); controller != nil {
if controller.Kind == v1alpha1.RolloutKind && controller.APIVersion == v1alpha1.SchemeGroupVersion.String() {
// it's already there
return true, nil
}
}
// add the parent controller to the owner of the cloneset
// before kicking start the update and start from every pod in the old version
clonePatch := client.MergeFrom(c.cloneSet.DeepCopy())
ref := metav1.NewControllerRef(c.parentController, c.parentController.GetObjectKind().GroupVersionKind())
c.cloneSet.SetOwnerReferences(append(c.cloneSet.GetOwnerReferences(), *ref))
c.cloneSet.Spec.UpdateStrategy.Paused = false
c.cloneSet.Spec.UpdateStrategy.Partition = &intstr.IntOrString{Type: intstr.Int, IntVal: totalReplicas}
// patch the CloneSet
if err := c.client.Patch(ctx, c.cloneSet, clonePatch, client.FieldOwner(c.parentController.GetUID())); err != nil {
c.recorder.Event(c.parentController, event.Warning("Failed to the start the cloneset update", err))
c.rolloutStatus.RolloutRetry(err.Error())
return false, nil
}
// mark the rollout initialized
c.recorder.Event(c.parentController, event.Normal("Rollout Initialized", "Rollout resource are initialized"))
return true, nil
}
// RolloutOneBatchPods calculates the number of pods we can upgrade once according to the rollout spec
// and then set the partition accordingly, return if we are done
func (c *CloneSetRolloutController) RolloutOneBatchPods(ctx context.Context) (bool, error) {
// calculate what's the total pods that should be upgraded given the currentBatch in the status
cloneSetSize, err := c.size(ctx)
if err != nil {
c.rolloutStatus.RolloutRetry(err.Error())
return false, nil
}
newPodTarget := calculateNewBatchTarget(c.rolloutSpec, 0, int(cloneSetSize), int(c.rolloutStatus.CurrentBatch))
// set the Partition as the desired number of pods in old revisions.
clonePatch := client.MergeFrom(c.cloneSet.DeepCopy())
c.cloneSet.Spec.UpdateStrategy.Partition = &intstr.IntOrString{Type: intstr.Int,
IntVal: cloneSetSize - int32(newPodTarget)}
// patch the Cloneset
if err = c.client.Patch(ctx, c.cloneSet, clonePatch, client.FieldOwner(c.parentController.GetUID())); err != nil {
c.recorder.Event(c.parentController, event.Warning("Failed to update the cloneset to upgrade", err))
c.rolloutStatus.RolloutRetry(err.Error())
return false, nil
}
// record the upgrade
klog.InfoS("upgraded one batch", "current batch", c.rolloutStatus.CurrentBatch)
c.recorder.Event(c.parentController, event.Normal("Batch Rollout",
fmt.Sprintf("Submitted upgrade quest for batch %d", c.rolloutStatus.CurrentBatch)))
c.rolloutStatus.UpgradedReplicas = int32(newPodTarget)
return true, nil
}
// CheckOneBatchPods checks to see if enough pods are upgraded according to the rollout plan
func (c *CloneSetRolloutController) CheckOneBatchPods(ctx context.Context) (bool, error) {
cloneSetSize, err := c.size(ctx)
if err != nil {
c.rolloutStatus.RolloutRetry(err.Error())
return false, nil
}
newPodTarget := calculateNewBatchTarget(c.rolloutSpec, 0, int(cloneSetSize), int(c.rolloutStatus.CurrentBatch))
// get the number of ready pod from cloneset
readyPodCount := int(c.cloneSet.Status.UpdatedReadyReplicas)
if len(c.rolloutSpec.RolloutBatches) <= int(c.rolloutStatus.CurrentBatch) {
err = errors.New("somehow, currentBatch number exceeded the rolloutBatches spec")
klog.ErrorS(err, "total batch", len(c.rolloutSpec.RolloutBatches), "current batch",
c.rolloutStatus.CurrentBatch)
return false, err
}
currentBatch := c.rolloutSpec.RolloutBatches[c.rolloutStatus.CurrentBatch]
unavail := 0
if currentBatch.MaxUnavailable != nil {
unavail, _ = intstr.GetValueFromIntOrPercent(currentBatch.MaxUnavailable, int(cloneSetSize), true)
}
klog.InfoS("checking the rolling out progress", "current batch", c.rolloutStatus.CurrentBatch,
"new pod count target", newPodTarget, "new ready pod count", readyPodCount,
"max unavailable pod allowed", unavail)
c.rolloutStatus.UpgradedReadyReplicas = int32(readyPodCount)
// we could overshoot in the revert case when many pods are already upgraded
if unavail+readyPodCount >= newPodTarget {
// record the successful upgrade
klog.InfoS("all pods in current batch are ready", "current batch", c.rolloutStatus.CurrentBatch)
c.recorder.Event(c.parentController, event.Normal("Batch Available",
fmt.Sprintf("Batch %d is available", c.rolloutStatus.CurrentBatch)))
return true, nil
}
// continue to verify
klog.InfoS("the batch is not ready yet", "current batch", c.rolloutStatus.CurrentBatch)
c.rolloutStatus.RolloutRetry("the batch is not ready yet")
return false, nil
}
// FinalizeOneBatch makes sure that the upgradedReplicas and current batch in the status are valid according to the spec
func (c *CloneSetRolloutController) FinalizeOneBatch(ctx context.Context) (bool, error) {
status := c.rolloutStatus
spec := c.rolloutSpec
if spec.BatchPartition != nil && *spec.BatchPartition < status.CurrentBatch {
err := fmt.Errorf("the current batch value in the status is greater than the batch partition")
klog.ErrorS(err, "we have moved past the user defined partition", "user specified batch partition",
*spec.BatchPartition, "current batch we are working on", status.CurrentBatch)
return false, err
}
upgradedReplicas := int(status.UpgradedReplicas)
currentBatch := int(status.CurrentBatch)
// calculate the lower bound of the possible pod count just before the current batch
podCount := calculateNewBatchTarget(c.rolloutSpec, 0, int(c.rolloutStatus.RolloutTargetSize), currentBatch-1)
// the recorded number should be at least as much as the all the pods before the current batch
if podCount > upgradedReplicas {
err := fmt.Errorf("the upgraded replica in the status is less than all the pods in the previous batch")
klog.ErrorS(err, "rollout status inconsistent", "upgraded num status", upgradedReplicas,
"pods in all the previous batches", podCount)
return false, err
}
// calculate the upper bound with the current batch
podCount = calculateNewBatchTarget(c.rolloutSpec, 0, int(c.rolloutStatus.RolloutTargetSize), currentBatch)
// the recorded number should be not as much as the all the pods including the active batch
if podCount < upgradedReplicas {
err := fmt.Errorf("the upgraded replica in the status is greater than all the pods in the current batch")
klog.ErrorS(err, "rollout status inconsistent", "total target size", c.rolloutStatus.RolloutTargetSize,
"upgraded num status", upgradedReplicas, "pods in the batches including the current batch", podCount)
return false, err
}
return true, nil
}
// Finalize makes sure the Cloneset is all upgraded
func (c *CloneSetRolloutController) Finalize(ctx context.Context, succeed bool) bool {
if err := c.fetchCloneSet(ctx); err != nil {
c.rolloutStatus.RolloutRetry(err.Error())
return false
}
clonePatch := client.MergeFrom(c.cloneSet.DeepCopy())
// remove the parent controller from the resources' owner list
var newOwnerList []metav1.OwnerReference
isOwner := false
for _, owner := range c.cloneSet.GetOwnerReferences() {
if owner.Kind == c.parentController.GetObjectKind().GroupVersionKind().Kind &&
owner.APIVersion == c.parentController.GetObjectKind().GroupVersionKind().GroupVersion().String() &&
owner.Controller != nil && *owner.Controller {
isOwner = true
continue
}
newOwnerList = append(newOwnerList, owner)
}
if !isOwner {
// nothing to do if we are already not the owner
klog.InfoS("the cloneset is already released and not controlled by rollout", "cloneSet", c.cloneSet.Name)
return true
}
c.cloneSet.SetOwnerReferences(newOwnerList)
// pause the resource when the rollout failed so we can try again next time
if !succeed {
c.cloneSet.Spec.UpdateStrategy.Paused = true
}
// patch the CloneSet
if err := c.client.Patch(ctx, c.cloneSet, clonePatch, client.FieldOwner(c.parentController.GetUID())); err != nil {
c.recorder.Event(c.parentController, event.Warning("Failed to the finalize the cloneset", err))
c.rolloutStatus.RolloutRetry(err.Error())
return false
}
// mark the resource finalized
c.recorder.Event(c.parentController, event.Normal("Rollout Finalized",
fmt.Sprintf("Rollout resource are finalized, succeed := %t", succeed)))
c.rolloutStatus.LastAppliedPodTemplateIdentifier = c.rolloutStatus.NewPodTemplateIdentifier
return true
}
// ---------------------------------------------
// The functions below are helper functions
// ---------------------------------------------
// check if the replicas in all the rollout batches add up to the right number
func (c *CloneSetRolloutController) verifyRolloutBatchReplicaValue(currentReplicas int32) error {
// the target size has to be the same as the cloneset size
if c.rolloutSpec.TargetSize != nil && *c.rolloutSpec.TargetSize != currentReplicas {
return fmt.Errorf("the rollout plan is attempting to scale the cloneset, target = %d, cloneset size = %d",
*c.rolloutSpec.TargetSize, currentReplicas)
}
// use a common function to check if the sum of all the batches can match the cloneset size
err := verifyBatchesWithRollout(c.rolloutSpec, currentReplicas)
if err != nil {
return err
}
return nil
}

View File

@@ -1,472 +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 workloads
import (
"fmt"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/crossplane/crossplane-runtime/pkg/event"
kruise "github.com/openkruise/kruise-api/apps/v1alpha1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/utils/pointer"
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/oam-dev/kubevela/apis/standard.oam.dev/v1alpha1"
"github.com/oam-dev/kubevela/pkg/oam/util"
)
var _ = Describe("cloneset controller", func() {
var (
c CloneSetRolloutController
ns corev1.Namespace
name string
namespace string
cloneSet kruise.CloneSet
namespacedName client.ObjectKey
)
BeforeEach(func() {
namespace = "rollout-ns"
name = "rollout1"
appRollout := v1alpha1.Rollout{TypeMeta: metav1.TypeMeta{APIVersion: v1alpha1.SchemeGroupVersion.String(), Kind: v1alpha1.RolloutKind}, ObjectMeta: metav1.ObjectMeta{Name: name}}
namespacedName = client.ObjectKey{Name: name, Namespace: namespace}
c = CloneSetRolloutController{
cloneSetController: cloneSetController{
workloadController: workloadController{
client: k8sClient,
rolloutSpec: &v1alpha1.RolloutPlan{
RolloutBatches: []v1alpha1.RolloutBatch{
{
Replicas: intstr.FromInt(1),
},
},
},
rolloutStatus: &v1alpha1.RolloutStatus{RollingState: v1alpha1.RolloutSucceedState},
parentController: &appRollout,
recorder: event.NewAPIRecorder(mgr.GetEventRecorderFor("Rollout")).
WithAnnotations("controller", "Rollout"),
},
targetNamespacedName: namespacedName,
},
}
cloneSet = kruise.CloneSet{
TypeMeta: metav1.TypeMeta{APIVersion: kruise.GroupVersion.String(), Kind: "CloneSet"},
ObjectMeta: metav1.ObjectMeta{Namespace: namespace, Name: name},
Spec: kruise.CloneSetSpec{
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"env": "staging"},
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{"env": "staging"}},
Spec: corev1.PodSpec{Containers: []corev1.Container{{Name: name, Image: "nginx"}}},
},
},
}
ns = corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: namespace,
},
}
By("Create a namespace")
Expect(k8sClient.Create(ctx, &ns)).Should(SatisfyAny(Succeed(), &util.AlreadyExistMatcher{}))
})
AfterEach(func() {
By("clean up")
k8sClient.Delete(ctx, &cloneSet)
})
Context("TestNewCloneSetRolloutController", func() {
It("init a CloneSet Rollout Controller", func() {
recorder := event.NewAPIRecorder(mgr.GetEventRecorderFor("AppRollout")).
WithAnnotations("controller", "AppRollout")
parentController := &v1alpha1.Rollout{ObjectMeta: metav1.ObjectMeta{Name: name}}
rolloutSpec := &v1alpha1.RolloutPlan{
RolloutBatches: []v1alpha1.RolloutBatch{{
Replicas: intstr.FromInt(1),
},
},
}
rolloutStatus := &v1alpha1.RolloutStatus{RollingState: v1alpha1.RolloutSucceedState}
workloadNamespacedName := client.ObjectKey{Name: name, Namespace: namespace}
got := NewCloneSetRolloutController(k8sClient, recorder, parentController, rolloutSpec, rolloutStatus, workloadNamespacedName)
c := &CloneSetRolloutController{
cloneSetController: cloneSetController{
workloadController: workloadController{
client: k8sClient,
recorder: recorder,
parentController: parentController,
rolloutSpec: rolloutSpec,
rolloutStatus: rolloutStatus,
},
targetNamespacedName: workloadNamespacedName,
},
}
Expect(got).Should(Equal(c))
})
})
Context("VerifySpec", func() {
It("could not fetch CloneSet workload", func() {
consistent, err := c.VerifySpec(ctx)
Expect(err).Should(BeNil())
Expect(consistent).Should(BeFalse())
})
It("verify rollout spec hash", func() {
By("Create a CloneSet")
cloneSet.Spec.UpdateStrategy.Paused = true
Expect(k8sClient.Create(ctx, &cloneSet)).Should(Succeed())
consistent, err := c.VerifySpec(ctx)
Expect(err).Should(BeNil())
Expect(consistent).Should(BeTrue())
})
It("the cloneset is in the middle of updating", func() {
By("Create a CloneSet")
Expect(k8sClient.Create(ctx, &cloneSet)).Should(Succeed())
By("setting a dummy pod identifier so it's different")
c.rolloutStatus.LastAppliedPodTemplateIdentifier = "abc"
By("verify should fail because it's not paused")
consistent, err := c.VerifySpec(ctx)
Expect(err).Should(Equal(fmt.Errorf("the cloneset rollout1 is in the middle of updating, need to be paused first")))
Expect(consistent).Should(BeFalse())
})
It("spec is valid", func() {
By("Create a CloneSet and set as paused")
cloneSet.Spec.UpdateStrategy.Paused = true
Expect(k8sClient.Create(ctx, &cloneSet)).Should(Succeed())
By("setting a dummy pod identifier so it's different")
c.rolloutStatus.LastAppliedPodTemplateIdentifier = "abc"
By("verify should pass and record the size")
consistent, err := c.VerifySpec(ctx)
Expect(err).Should(BeNil())
Expect(consistent).Should(BeTrue())
Expect(c.rolloutStatus.RolloutTargetSize).Should(BeEquivalentTo(1))
Expect(c.rolloutStatus.RolloutOriginalSize).Should(BeEquivalentTo(1))
})
})
Context("TestInitialize", func() {
BeforeEach(func() {
cloneSet.Spec.UpdateStrategy.Paused = true
})
It("could not fetch CloneSet workload", func() {
consistent, err := c.Initialize(ctx)
Expect(err).Should(BeNil())
Expect(consistent).Should(BeFalse())
})
It("failed to patch the owner of CloneSet", func() {
By("Create a CloneSet")
Expect(k8sClient.Create(ctx, &cloneSet)).Should(Succeed())
By("initialize will fail because cloneset has wrong owner reference")
initialized, err := c.Initialize(ctx)
Expect(initialized).Should(BeFalse())
Expect(err).Should(BeNil())
})
It("workload CloneSet is controlled by appRollout already", func() {
By("Create a CloneSet")
cloneSet.SetOwnerReferences([]metav1.OwnerReference{{
APIVersion: v1alpha1.SchemeGroupVersion.String(),
Kind: v1alpha1.RolloutKind,
Name: "def",
UID: "123456",
Controller: pointer.Bool(true),
}})
Expect(k8sClient.Create(ctx, &cloneSet)).Should(Succeed())
By("initialize succeed without patching")
initialized, err := c.Initialize(ctx)
Expect(initialized).Should(BeTrue())
Expect(err).Should(BeNil())
Expect(k8sClient.Get(ctx, c.targetNamespacedName, &cloneSet)).Should(Succeed())
Expect(len(cloneSet.GetOwnerReferences())).Should(BeEquivalentTo(1))
})
It("successfully initialized CloneSet", func() {
By("create cloneset")
Expect(k8sClient.Create(ctx, &cloneSet)).Should(Succeed())
By("initialize succeeds")
c.parentController.SetUID("1231586900")
initialized, err := c.Initialize(ctx)
Expect(initialized).Should(BeTrue())
Expect(err).Should(BeNil())
Expect(k8sClient.Get(ctx, c.targetNamespacedName, &cloneSet)).Should(Succeed())
Expect(len(cloneSet.GetOwnerReferences())).Should(BeEquivalentTo(1))
})
})
Context("TestRolloutOneBatchPods", func() {
It("could not fetch CloneSet workload", func() {
consistent, err := c.RolloutOneBatchPods(ctx)
Expect(err).Should(BeNil())
Expect(consistent).Should(BeFalse())
})
It("successfully rollout, current batch number is not equal to the expected one", func() {
By("Create a CloneSet")
cloneSet.Spec.Replicas = pointer.Int32(10)
Expect(k8sClient.Create(ctx, &cloneSet)).Should(Succeed())
By("rollout the second batch of current cloneset")
c.rolloutStatus.CurrentBatch = 1
c.rolloutSpec.RolloutBatches = []v1alpha1.RolloutBatch{
{
Replicas: intstr.FromInt(1),
},
{
Replicas: intstr.FromString("20%"),
},
{
Replicas: intstr.FromString("80%"),
},
}
done, err := c.RolloutOneBatchPods(ctx)
Expect(done).Should(BeTrue())
Expect(err).Should(BeNil())
Expect(c.rolloutStatus.UpgradedReplicas).Should(BeEquivalentTo(3))
Expect(k8sClient.Get(ctx, c.targetNamespacedName, &cloneSet)).Should(Succeed())
Expect(cloneSet.Spec.UpdateStrategy.Partition.IntValue()).Should(BeEquivalentTo(7))
})
})
Context("TestCheckOneBatchPods", func() {
BeforeEach(func() {
cloneSet.Spec.Replicas = pointer.Int32(10)
c.rolloutSpec.RolloutBatches = []v1alpha1.RolloutBatch{
{
Replicas: intstr.FromInt(2),
},
{
Replicas: intstr.FromString("20%"),
},
{
Replicas: intstr.FromString("80%"),
},
}
})
It("could not fetch CloneSet workload", func() {
consistent, err := c.CheckOneBatchPods(ctx)
Expect(err).Should(BeNil())
Expect(consistent).Should(BeFalse())
})
It("current ready Pod is less than expected", func() {
By("Create the CloneSet")
Expect(k8sClient.Create(ctx, &cloneSet)).Should(Succeed())
By("Update the CloneSet status")
cloneSet.Status.UpdatedReadyReplicas = 3
cloneSet.Status.UpdatedReplicas = 4
Expect(k8sClient.Status().Update(ctx, &cloneSet)).Should(Succeed())
By("checking should fail as not enough pod ready")
c.rolloutStatus.CurrentBatch = 1
done, err := c.CheckOneBatchPods(ctx)
Expect(done).Should(BeFalse())
Expect(err).Should(BeNil())
Expect(c.rolloutStatus.UpgradedReadyReplicas).Should(BeEquivalentTo(cloneSet.Status.UpdatedReadyReplicas))
})
It("failed to check batch Pod when current batch number exceeds the expected ones", func() {
By("Create a CloneSet")
Expect(k8sClient.Create(ctx, &cloneSet)).Should(Succeed())
By("checking")
c.rolloutStatus.CurrentBatch = 3
done, err := c.CheckOneBatchPods(ctx)
Expect(done).Should(BeFalse())
Expect(err.Error()).Should(ContainSubstring("currentBatch number exceeded the rolloutBatches spec"))
})
It("there are enough pods counting the unavailable", func() {
By("Create the CloneSet")
Expect(k8sClient.Create(ctx, &cloneSet)).Should(Succeed())
By("Update the CloneSet status")
cloneSet.Status.UpdatedReadyReplicas = 3
cloneSet.Status.UpdatedReplicas = 4
Expect(k8sClient.Status().Update(ctx, &cloneSet)).Should(Succeed())
c.rolloutStatus.CurrentBatch = 1
// set the rollout batch spec allow unavailable
perc := intstr.FromString("20%")
c.rolloutSpec.RolloutBatches = []v1alpha1.RolloutBatch{
{
Replicas: intstr.FromInt(2),
},
{
Replicas: perc,
MaxUnavailable: &perc,
},
{
Replicas: intstr.FromString("80%"),
},
}
By("checking one batch")
done, err := c.CheckOneBatchPods(ctx)
Expect(done).Should(BeTrue())
Expect(err).Should(BeNil())
Expect(c.rolloutStatus.UpgradedReadyReplicas).Should(BeEquivalentTo(cloneSet.Status.UpdatedReadyReplicas))
})
It("there are enough pods ready", func() {
By("Create the CloneSet")
Expect(k8sClient.Create(ctx, &cloneSet)).Should(Succeed())
By("Update the CloneSet status")
cloneSet.Status.UpdatedReadyReplicas = 10
cloneSet.Status.UpdatedReplicas = 10
Expect(k8sClient.Status().Update(ctx, &cloneSet)).Should(Succeed())
By("the second batch should pass when there are more pods upgraded already")
c.rolloutStatus.CurrentBatch = 1
done, err := c.CheckOneBatchPods(ctx)
Expect(done).Should(BeTrue())
Expect(err).Should(BeNil())
Expect(c.rolloutStatus.UpgradedReadyReplicas).Should(BeEquivalentTo(cloneSet.Status.UpdatedReadyReplicas))
By("checking the last batch")
c.rolloutStatus.CurrentBatch = 2
done, err = c.CheckOneBatchPods(ctx)
Expect(done).Should(BeTrue())
Expect(err).Should(BeNil())
Expect(c.rolloutStatus.UpgradedReadyReplicas).Should(BeEquivalentTo(cloneSet.Status.UpdatedReadyReplicas))
})
})
Context("TestFinalizeOneBatch", func() {
BeforeEach(func() {
c.rolloutStatus.RolloutTargetSize = 10
c.rolloutSpec.RolloutBatches = []v1alpha1.RolloutBatch{
{
Replicas: intstr.FromInt(2),
},
{
Replicas: intstr.FromString("20%"),
},
{
Replicas: intstr.FromString("80%"),
},
}
})
It("test illegal batch partition", func() {
By("finalizing one batch")
c.rolloutSpec.BatchPartition = pointer.Int32(2)
c.rolloutStatus.CurrentBatch = 3
done, err := c.FinalizeOneBatch(ctx)
Expect(done).Should(BeFalse())
Expect(err.Error()).Should(ContainSubstring("the current batch value in the status is greater than the batch partition"))
})
It("test too few upgraded", func() {
By("finalizing one batch")
c.rolloutStatus.UpgradedReplicas = 2
c.rolloutStatus.CurrentBatch = 2
done, err := c.FinalizeOneBatch(ctx)
Expect(done).Should(BeFalse())
Expect(err.Error()).Should(ContainSubstring("is less than all the pods in the previous batch"))
})
It("test too many upgraded", func() {
By("finalizing one batch")
c.rolloutStatus.UpgradedReplicas = 5
c.rolloutStatus.CurrentBatch = 1
done, err := c.FinalizeOneBatch(ctx)
Expect(done).Should(BeFalse())
Expect(err.Error()).Should(ContainSubstring("is greater than all the pods in the current batch"))
})
It("test upgraded in the range", func() {
By("finalizing one batch")
c.rolloutStatus.UpgradedReplicas = 3
c.rolloutStatus.CurrentBatch = 1
done, err := c.FinalizeOneBatch(ctx)
Expect(done).Should(BeTrue())
Expect(err).Should(BeNil())
})
})
Context("TestFinalize", func() {
It("failed to fetch CloneSet", func() {
By("finalizing")
finalized := c.Finalize(ctx, true)
Expect(finalized).Should(BeFalse())
})
It("Already finalize CloneSet", func() {
By("Create a CloneSet")
cloneSet.SetOwnerReferences([]metav1.OwnerReference{{
APIVersion: v1alpha1.SchemeGroupVersion.String(),
Kind: "notRollout",
Name: "def",
UID: "123456",
}})
Expect(k8sClient.Create(ctx, &cloneSet)).Should(Succeed())
By("finalizing without patch")
finalized := c.Finalize(ctx, true)
Expect(finalized).Should(BeTrue())
})
It("successfully to finalize CloneSet", func() {
By("Create a CloneSet")
cloneSet.SetOwnerReferences([]metav1.OwnerReference{
{
APIVersion: v1alpha1.SchemeGroupVersion.String(),
Kind: v1alpha1.RolloutKind,
Name: "def",
UID: "123456",
Controller: pointer.Bool(true),
},
{
APIVersion: corev1.SchemeGroupVersion.String(),
Kind: "Deployment",
Name: "def",
UID: "998877745",
},
})
Expect(k8sClient.Create(ctx, &cloneSet)).Should(Succeed())
By("finalizing with patch")
finalized := c.Finalize(ctx, false)
Expect(finalized).Should(BeTrue())
Expect(k8sClient.Get(ctx, c.targetNamespacedName, &cloneSet)).Should(Succeed())
Expect(len(cloneSet.GetOwnerReferences())).Should(BeEquivalentTo(1))
Expect(cloneSet.GetOwnerReferences()[0].Kind).Should(Equal("Deployment"))
Expect(cloneSet.Spec.UpdateStrategy.Paused).Should(BeTrue())
})
})
})

View File

@@ -1,101 +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 workloads
import (
"fmt"
"testing"
"github.com/crossplane/crossplane-runtime/pkg/test"
"github.com/google/go-cmp/cmp"
"k8s.io/apimachinery/pkg/util/intstr"
"github.com/oam-dev/kubevela/apis/standard.oam.dev/v1alpha1"
)
func TestVerifyRolloutBatchReplicaValue4CloneSet(t *testing.T) {
// Compared to `deployment_controller_test.go`, there is one case less as common is already 100% covered, so only an
// error and nil error for `err := VerifySumOfBatchSizes(c.rolloutSpec, totalReplicas)` is enough.
var int2 int32 = 2
cases := map[string]struct {
c *CloneSetRolloutController
totalReplicas int32
want error
}{
"ClonsetTargetSizeIsNotAvaialbe": {
c: &CloneSetRolloutController{
cloneSetController: cloneSetController{
workloadController: workloadController{
rolloutSpec: &v1alpha1.RolloutPlan{
TargetSize: &int2,
RolloutBatches: []v1alpha1.RolloutBatch{{
Replicas: intstr.FromInt(1),
},
},
},
},
},
},
totalReplicas: 3,
want: fmt.Errorf("the rollout plan is attempting to scale the cloneset, target = 2, cloneset size = 3"),
},
"BatchSizeMismatchesClonesetSize": {
c: &CloneSetRolloutController{
cloneSetController: cloneSetController{
workloadController: workloadController{
rolloutSpec: &v1alpha1.RolloutPlan{
RolloutBatches: []v1alpha1.RolloutBatch{{
Replicas: intstr.FromInt(1),
},
},
},
},
},
},
totalReplicas: 3,
want: fmt.Errorf("the rollout plan batch size mismatch, total batch size = 1, totalReplicas size = 3"),
},
"BatchSizeMatchesCloneSetSize": {
c: &CloneSetRolloutController{
cloneSetController: cloneSetController{
workloadController: workloadController{
rolloutSpec: &v1alpha1.RolloutPlan{
RolloutBatches: []v1alpha1.RolloutBatch{
{
Replicas: intstr.FromInt(1),
},
{
Replicas: intstr.FromInt(2),
},
},
},
},
},
},
totalReplicas: 3,
want: nil,
},
}
for name, tc := range cases {
t.Run(name, func(t *testing.T) {
err := tc.c.verifyRolloutBatchReplicaValue(tc.totalReplicas)
if diff := cmp.Diff(tc.want, err, test.EquateErrors()); diff != "" {
t.Errorf("\n%s\nverifyRolloutBatchReplicaValue(...): -want error, +got error:\n%s", name, diff)
}
})
}
}

View File

@@ -1,304 +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 workloads
import (
"context"
"fmt"
"github.com/crossplane/crossplane-runtime/pkg/event"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/klog/v2"
"k8s.io/utils/pointer"
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/oam-dev/kubevela/apis/standard.oam.dev/v1alpha1"
"github.com/oam-dev/kubevela/pkg/oam"
"github.com/oam-dev/kubevela/pkg/oam/util"
)
// CloneSetScaleController is responsible for handle scale Cloneset type of workloads
type CloneSetScaleController struct {
cloneSetController
}
// NewCloneSetScaleController creates CloneSet scale controller
func NewCloneSetScaleController(client client.Client, recorder event.Recorder, parentController oam.Object, rolloutSpec *v1alpha1.RolloutPlan, rolloutStatus *v1alpha1.RolloutStatus, workloadName types.NamespacedName) *CloneSetScaleController {
return &CloneSetScaleController{
cloneSetController: cloneSetController{
workloadController: workloadController{
client: client,
recorder: recorder,
parentController: parentController,
rolloutSpec: rolloutSpec,
rolloutStatus: rolloutStatus,
},
targetNamespacedName: workloadName,
},
}
}
// VerifySpec verifies that the cloneset is stable and can be scaled
func (s *CloneSetScaleController) VerifySpec(ctx context.Context) (bool, error) {
var verifyErr error
defer func() {
if verifyErr != nil {
klog.Error(verifyErr)
s.recorder.Event(s.parentController, event.Warning("VerifyFailed", verifyErr))
}
}()
// the rollout has to have a target size in the scale case
if s.rolloutSpec.TargetSize == nil {
return false, fmt.Errorf("the rollout plan is attempting to scale the cloneset %s without a target",
s.targetNamespacedName.Name)
}
// record the target size
s.rolloutStatus.RolloutTargetSize = *s.rolloutSpec.TargetSize
klog.InfoS("record the target size", "target size", *s.rolloutSpec.TargetSize)
// fetch the cloneset and get its current size
originalSize, verifyErr := s.size(ctx)
if verifyErr != nil {
// do not fail the rollout because we can't get the resource
s.rolloutStatus.RolloutRetry(verifyErr.Error())
// nolint: nilerr
return false, nil
}
s.rolloutStatus.RolloutOriginalSize = originalSize
klog.InfoS("record the original size", "original size", originalSize)
// check if the rollout batch replicas scale up/down to the replicas target
if verifyErr = verifyBatchesWithScale(s.rolloutSpec, int(originalSize),
int(s.rolloutStatus.RolloutTargetSize)); verifyErr != nil {
return false, verifyErr
}
// check if the cloneset is scaling
if originalSize != s.cloneSet.Status.Replicas {
verifyErr = fmt.Errorf("the cloneset %s is in the middle of scaling, target size = %d, real size = %d",
s.cloneSet.GetName(), originalSize, s.cloneSet.Status.Replicas)
// do not fail the rollout, we can wait
s.rolloutStatus.RolloutRetry(verifyErr.Error())
return false, nil
}
// check if the cloneset is upgrading
if !s.cloneSet.Spec.UpdateStrategy.Paused && s.cloneSet.Status.UpdatedReplicas != originalSize {
verifyErr = fmt.Errorf("the cloneset %s is in the middle of updating, target size = %d, updated pod = %d",
s.cloneSet.GetName(), originalSize, s.cloneSet.Status.UpdatedReplicas)
// do not fail the rollout, we can wait
s.rolloutStatus.RolloutRetry(verifyErr.Error())
return false, nil
}
// check if the cloneset has any controller
if controller := metav1.GetControllerOf(s.cloneSet); controller != nil {
return false, fmt.Errorf("the cloneset %s has a controller owner %s",
s.cloneSet.GetName(), controller.String())
}
// mark the scale verified
s.recorder.Event(s.parentController, event.Normal("Scale Verified",
"Rollout spec and the CloneSet resource are verified"))
return true, nil
}
// Initialize makes sure that the cloneset is under our control
func (s *CloneSetScaleController) Initialize(ctx context.Context) (bool, error) {
err := s.fetchCloneSet(ctx)
if err != nil {
s.rolloutStatus.RolloutRetry(err.Error())
// nolint: nilerr
return false, nil
}
if controller := metav1.GetControllerOf(s.cloneSet); controller != nil {
if controller.Kind == v1alpha1.RolloutKind && controller.APIVersion == v1alpha1.SchemeGroupVersion.String() {
// it's already there
return true, nil
}
}
// add the parent controller to the owner of the cloneset
clonePatch := client.MergeFrom(s.cloneSet.DeepCopy())
ref := metav1.NewControllerRef(s.parentController, s.parentController.GetObjectKind().GroupVersionKind())
s.cloneSet.SetOwnerReferences(append(s.cloneSet.GetOwnerReferences(), *ref))
s.cloneSet.Spec.UpdateStrategy.Paused = false
// patch the CloneSet
if err := s.client.Patch(ctx, s.cloneSet, clonePatch, client.FieldOwner(s.parentController.GetUID())); err != nil {
s.recorder.Event(s.parentController, event.Warning("Failed to the start the cloneset update", err))
s.rolloutStatus.RolloutRetry(err.Error())
return false, nil
}
// mark the rollout initialized
s.recorder.Event(s.parentController, event.Normal("Scale Initialized", "Cloneset is initialized"))
return true, nil
}
// RolloutOneBatchPods calculates the number of pods we can scale to according to the rollout spec
func (s *CloneSetScaleController) RolloutOneBatchPods(ctx context.Context) (bool, error) {
err := s.fetchCloneSet(ctx)
if err != nil {
s.rolloutStatus.RolloutRetry(err.Error())
// nolint: nilerr
return false, nil
}
clonePatch := client.MergeFrom(s.cloneSet.DeepCopy())
// set the replica according to the batch
newPodTarget := calculateNewBatchTarget(s.rolloutSpec, int(s.rolloutStatus.RolloutOriginalSize),
int(s.rolloutStatus.RolloutTargetSize), int(s.rolloutStatus.CurrentBatch))
s.cloneSet.Spec.Replicas = pointer.Int32(int32(newPodTarget))
// patch the Cloneset
if err := s.client.Patch(ctx, s.cloneSet, clonePatch, client.FieldOwner(s.parentController.GetUID())); err != nil {
s.recorder.Event(s.parentController, event.Warning("Failed to update the cloneset to upgrade", err))
s.rolloutStatus.RolloutRetry(err.Error())
return false, nil
}
// record the scale
klog.InfoS("scale one batch", "current batch", s.rolloutStatus.CurrentBatch)
s.recorder.Event(s.parentController, event.Normal("Batch Rollout",
fmt.Sprintf("Submitted scale quest for batch %d", s.rolloutStatus.CurrentBatch)))
s.rolloutStatus.UpgradedReplicas = int32(newPodTarget)
return true, nil
}
// CheckOneBatchPods checks to see if the pods are scaled according to the rollout plan
func (s *CloneSetScaleController) CheckOneBatchPods(ctx context.Context) (bool, error) {
err := s.fetchCloneSet(ctx)
if err != nil {
s.rolloutStatus.RolloutRetry(err.Error())
// nolint:nilerr
return false, nil
}
newPodTarget := calculateNewBatchTarget(s.rolloutSpec, int(s.rolloutStatus.RolloutOriginalSize),
int(s.rolloutStatus.RolloutTargetSize), int(s.rolloutStatus.CurrentBatch))
// get the number of ready pod from cloneset
// TODO: should we use the replica number when we shrink?
readyPodCount := int(s.cloneSet.Status.ReadyReplicas)
currentBatch := s.rolloutSpec.RolloutBatches[s.rolloutStatus.CurrentBatch]
unavail := 0
if currentBatch.MaxUnavailable != nil {
unavail, _ = intstr.GetValueFromIntOrPercent(currentBatch.MaxUnavailable,
util.Abs(int(s.rolloutStatus.RolloutTargetSize-s.rolloutStatus.RolloutOriginalSize)), true)
}
klog.InfoS("checking the scaling progress", "current batch", s.rolloutStatus.CurrentBatch,
"new pod count target", newPodTarget, "new ready pod count", readyPodCount,
"max unavailable pod allowed", unavail)
s.rolloutStatus.UpgradedReadyReplicas = int32(readyPodCount)
targetReached := false
// nolint
if s.rolloutStatus.RolloutOriginalSize <= s.rolloutStatus.RolloutTargetSize && unavail+readyPodCount >= newPodTarget {
targetReached = true
} else if s.rolloutStatus.RolloutOriginalSize > s.rolloutStatus.RolloutTargetSize && readyPodCount <= newPodTarget {
targetReached = true
}
if targetReached {
// record the successful upgrade
klog.InfoS("the current batch is ready", "current batch", s.rolloutStatus.CurrentBatch,
"target", newPodTarget, "readyPodCount", readyPodCount, "max unavailable allowed", unavail)
s.recorder.Event(s.parentController, event.Normal("Batch Available",
fmt.Sprintf("Batch %d is available", s.rolloutStatus.CurrentBatch)))
return true, nil
}
// continue to verify
klog.InfoS("the batch is not ready yet", "current batch", s.rolloutStatus.CurrentBatch,
"target", newPodTarget, "readyPodCount", readyPodCount, "max unavailable allowed", unavail)
s.rolloutStatus.RolloutRetry("the batch is not ready yet")
return false, nil
}
// FinalizeOneBatch makes sure that the current batch and replica count in the status are validate
func (s *CloneSetScaleController) FinalizeOneBatch(ctx context.Context) (bool, error) {
status := s.rolloutStatus
spec := s.rolloutSpec
if spec.BatchPartition != nil && *spec.BatchPartition < status.CurrentBatch {
err := fmt.Errorf("the current batch value in the status is greater than the batch partition")
klog.ErrorS(err, "we have moved past the user defined partition", "user specified batch partition",
*spec.BatchPartition, "current batch we are working on", status.CurrentBatch)
return false, err
}
// special case the equal case
if s.rolloutStatus.RolloutOriginalSize == s.rolloutStatus.RolloutTargetSize {
return true, nil
}
// we just make sure the target is right
finishedPodCount := int(status.UpgradedReplicas)
currentBatch := int(status.CurrentBatch)
// calculate the pod target just before the current batch
preBatchTarget := calculateNewBatchTarget(s.rolloutSpec, int(s.rolloutStatus.RolloutOriginalSize),
int(s.rolloutStatus.RolloutTargetSize), currentBatch-1)
// calculate the pod target with the current batch
curBatchTarget := calculateNewBatchTarget(s.rolloutSpec, int(s.rolloutStatus.RolloutOriginalSize),
int(s.rolloutStatus.RolloutTargetSize), currentBatch)
// the recorded number should be at least as much as the all the pods before the current batch
if finishedPodCount < util.Min(preBatchTarget, curBatchTarget) {
err := fmt.Errorf("the upgraded replica in the status is less than the lower bound")
klog.ErrorS(err, "rollout status inconsistent", "existing pod target", finishedPodCount,
"the lower bound", util.Min(preBatchTarget, curBatchTarget))
return false, err
}
// the recorded number should be not as much as the all the pods including the active batch
if finishedPodCount > util.Max(preBatchTarget, curBatchTarget) {
err := fmt.Errorf("the upgraded replica in the status is greater than the upper bound")
klog.ErrorS(err, "rollout status inconsistent", "existing pod target", finishedPodCount,
"the upper bound", util.Max(preBatchTarget, curBatchTarget))
return false, err
}
return true, nil
}
// Finalize makes sure the Cloneset is scaled and ready to use
func (s *CloneSetScaleController) Finalize(ctx context.Context, succeed bool) bool {
if err := s.fetchCloneSet(ctx); err != nil {
s.rolloutStatus.RolloutRetry(err.Error())
return false
}
clonePatch := client.MergeFrom(s.cloneSet.DeepCopy())
// remove the parent controller from the resources' owner list
var newOwnerList []metav1.OwnerReference
isOwner := false
for _, owner := range s.cloneSet.GetOwnerReferences() {
if owner.Kind == s.parentController.GetObjectKind().GroupVersionKind().Kind &&
owner.APIVersion == s.parentController.GetObjectKind().GroupVersionKind().GroupVersion().String() {
isOwner = true
continue
}
newOwnerList = append(newOwnerList, owner)
}
if !isOwner {
// nothing to do if we are already not the owner
klog.InfoS("the cloneset is already released and not controlled by rollout", "cloneSet", s.cloneSet.Name)
return true
}
s.cloneSet.SetOwnerReferences(newOwnerList)
// patch the CloneSet
if err := s.client.Patch(ctx, s.cloneSet, clonePatch, client.FieldOwner(s.parentController.GetUID())); err != nil {
s.recorder.Event(s.parentController, event.Warning("Failed to the finalize the cloneset", err))
s.rolloutStatus.RolloutRetry(err.Error())
return false
}
// mark the resource finalized
s.recorder.Event(s.parentController, event.Normal("Scale Finalized",
fmt.Sprintf("Scale resource are finalized, succeed := %t", succeed)))
return true
}

View File

@@ -1,483 +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 workloads
import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/crossplane/crossplane-runtime/pkg/event"
kruise "github.com/openkruise/kruise-api/apps/v1alpha1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/utils/pointer"
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/oam-dev/kubevela/apis/standard.oam.dev/v1alpha1"
"github.com/oam-dev/kubevela/pkg/oam/util"
)
var _ = Describe("cloneset controller", func() {
var (
s CloneSetScaleController
ns corev1.Namespace
name string
namespace string
cloneSet kruise.CloneSet
namespacedName client.ObjectKey
)
BeforeEach(func() {
namespace = "rollout-ns"
name = "rollout1"
appRollout := v1alpha1.Rollout{TypeMeta: metav1.TypeMeta{APIVersion: v1alpha1.SchemeGroupVersion.String(), Kind: v1alpha1.RolloutKind}, ObjectMeta: metav1.ObjectMeta{Name: name}}
namespacedName = client.ObjectKey{Name: name, Namespace: namespace}
s = CloneSetScaleController{
cloneSetController: cloneSetController{
workloadController: workloadController{
client: k8sClient,
rolloutSpec: &v1alpha1.RolloutPlan{
TargetSize: pointer.Int32(10),
RolloutBatches: []v1alpha1.RolloutBatch{
{
Replicas: intstr.FromInt(1),
},
{
Replicas: intstr.FromString("20%"),
},
{
Replicas: intstr.FromString("80%"),
},
},
},
rolloutStatus: &v1alpha1.RolloutStatus{RollingState: v1alpha1.RolloutSucceedState},
parentController: &appRollout,
recorder: event.NewAPIRecorder(mgr.GetEventRecorderFor("AppRollout")).
WithAnnotations("controller", "AppRollout"),
},
targetNamespacedName: namespacedName,
},
}
cloneSet = kruise.CloneSet{
TypeMeta: metav1.TypeMeta{APIVersion: kruise.GroupVersion.String(), Kind: "CloneSet"},
ObjectMeta: metav1.ObjectMeta{Namespace: namespace, Name: name},
Spec: kruise.CloneSetSpec{
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"env": "staging"},
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{"env": "staging"}},
Spec: corev1.PodSpec{Containers: []corev1.Container{{Name: name, Image: "nginx"}}},
},
},
}
ns = corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: namespace,
},
}
By("Create a namespace")
Expect(k8sClient.Create(ctx, &ns)).Should(SatisfyAny(Succeed(), &util.AlreadyExistMatcher{}))
})
AfterEach(func() {
By("clean up")
k8sClient.Delete(ctx, &cloneSet)
})
Context("TestNewCloneSetScaleController", func() {
It("init a CloneSet Scale Controller", func() {
recorder := event.NewAPIRecorder(mgr.GetEventRecorderFor("AppRollout")).
WithAnnotations("controller", "AppRollout")
parentController := &v1alpha1.Rollout{ObjectMeta: metav1.ObjectMeta{Name: name}}
rolloutSpec := &v1alpha1.RolloutPlan{
RolloutBatches: []v1alpha1.RolloutBatch{{
Replicas: intstr.FromInt(1),
},
},
}
rolloutStatus := &v1alpha1.RolloutStatus{RollingState: v1alpha1.RolloutSucceedState}
workloadNamespacedName := client.ObjectKey{Name: name, Namespace: namespace}
got := NewCloneSetScaleController(k8sClient, recorder, parentController, rolloutSpec, rolloutStatus, workloadNamespacedName)
controller := &CloneSetScaleController{
cloneSetController: cloneSetController{
workloadController: workloadController{
client: k8sClient,
recorder: recorder,
parentController: parentController,
rolloutSpec: rolloutSpec,
rolloutStatus: rolloutStatus,
},
targetNamespacedName: workloadNamespacedName,
}}
Expect(got).Should(Equal(controller))
})
})
Context("VerifySpec", func() {
It("rollout need a target size", func() {
s.rolloutSpec.TargetSize = nil
ligit, err := s.VerifySpec(ctx)
Expect(ligit).Should(BeFalse())
Expect(err.Error()).Should(ContainSubstring("without a target"))
})
It("could not fetch CloneSet workload", func() {
ligit, err := s.VerifySpec(ctx)
Expect(ligit).Should(BeFalse())
Expect(err).Should(BeNil())
})
It("rollout batch doesn't fit scale target", func() {
By("Create a CloneSet")
cloneSet.Spec.Replicas = pointer.Int32(15)
Expect(k8sClient.Create(ctx, &cloneSet)).Should(Succeed())
By("Verify should fail as the scale batches don't match")
s.rolloutSpec.RolloutBatches[2].Replicas = intstr.FromInt(10)
consistent, err := s.VerifySpec(ctx)
Expect(err).ShouldNot(BeNil())
Expect(consistent).Should(BeFalse())
})
It("the cloneset is in the middle of scaling", func() {
By("Create a CloneSet")
Expect(k8sClient.Create(ctx, &cloneSet)).Should(Succeed())
By("verify should fail because replica does not match")
consistent, err := s.VerifySpec(ctx)
Expect(err).Should(BeNil())
Expect(consistent).Should(BeFalse())
})
It("the cloneset is in the middle of updating", func() {
By("Create a CloneSet and set as paused")
Expect(k8sClient.Create(ctx, &cloneSet)).Should(Succeed())
By("Update the CloneSet status")
cloneSet.Status.Replicas = 1
Expect(k8sClient.Status().Update(ctx, &cloneSet)).Should(Succeed())
By("verify should fail because replica are not upgraded")
consistent, err := s.VerifySpec(ctx)
Expect(err).Should(BeNil())
Expect(consistent).Should(BeFalse())
})
It("spec is valid", func() {
By("Create a CloneSet and set as paused")
cloneSet.Spec.UpdateStrategy.Paused = true
Expect(k8sClient.Create(ctx, &cloneSet)).Should(Succeed())
By("Update the CloneSet status")
cloneSet.Status.Replicas = 1
cloneSet.Status.UpdatedReplicas = 1
cloneSet.Status.UpdatedReadyReplicas = 1
Expect(k8sClient.Status().Update(ctx, &cloneSet)).Should(Succeed())
By("verify should pass and record the size")
consistent, err := s.VerifySpec(ctx)
Expect(err).Should(BeNil())
Expect(consistent).Should(BeTrue())
Expect(s.rolloutStatus.RolloutTargetSize).Should(BeEquivalentTo(10))
Expect(s.rolloutStatus.RolloutOriginalSize).Should(BeEquivalentTo(1))
})
})
Context("TestInitialize", func() {
BeforeEach(func() {
cloneSet.Spec.UpdateStrategy.Paused = true
})
It("could not fetch CloneSet workload", func() {
consistent, err := s.Initialize(ctx)
Expect(err).Should(BeNil())
Expect(consistent).Should(BeFalse())
})
It("failed to patch the owner of CloneSet", func() {
By("Create a CloneSet")
Expect(k8sClient.Create(ctx, &cloneSet)).Should(Succeed())
By("initialize will fail because cloneset has wrong owner reference")
initialized, err := s.Initialize(ctx)
Expect(initialized).Should(BeFalse())
Expect(err).Should(BeNil())
})
It("workload CloneSet is controlled by appRollout already", func() {
By("Create a CloneSet")
cloneSet.SetOwnerReferences([]metav1.OwnerReference{{
APIVersion: v1alpha1.SchemeGroupVersion.String(),
Kind: v1alpha1.RolloutKind,
Name: "def",
UID: "123456",
Controller: pointer.Bool(true),
}})
Expect(k8sClient.Create(ctx, &cloneSet)).Should(Succeed())
By("initialize succeed without patching")
initialized, err := s.Initialize(ctx)
Expect(initialized).Should(BeTrue())
Expect(err).Should(BeNil())
})
It("successfully initialized CloneSet", func() {
By("create cloneset")
Expect(k8sClient.Create(ctx, &cloneSet)).Should(Succeed())
By("initialize succeeds")
s.parentController.SetUID("1231586900")
initialized, err := s.Initialize(ctx)
Expect(initialized).Should(BeTrue())
Expect(err).Should(BeNil())
})
})
Context("TestRolloutOneBatchPods", func() {
It("could not fetch CloneSet workload", func() {
consistent, err := s.RolloutOneBatchPods(ctx)
Expect(err).Should(BeNil())
Expect(consistent).Should(BeFalse())
})
It("successfully rollout, current batch number is not equal to the expected one", func() {
By("Create a CloneSet")
Expect(k8sClient.Create(ctx, &cloneSet)).Should(Succeed())
By("rollout the second batch of current cloneset")
s.rolloutStatus.CurrentBatch = 1
s.rolloutStatus.RolloutOriginalSize = 0
s.rolloutStatus.RolloutTargetSize = 10
done, err := s.RolloutOneBatchPods(ctx)
Expect(done).Should(BeTrue())
Expect(err).Should(BeNil())
Expect(s.rolloutStatus.UpgradedReplicas).Should(BeEquivalentTo(3))
Expect(k8sClient.Get(ctx, s.targetNamespacedName, &cloneSet)).Should(Succeed())
Expect(*cloneSet.Spec.Replicas).Should(BeEquivalentTo(3))
})
})
Context("TestCheckOneBatchPods", func() {
It("could not fetch CloneSet workload", func() {
consistent, err := s.CheckOneBatchPods(ctx)
Expect(err).Should(BeNil())
Expect(consistent).Should(BeFalse())
})
It("current ready Pod is less than expected during increase", func() {
By("Create the CloneSet")
Expect(k8sClient.Create(ctx, &cloneSet)).Should(Succeed())
By("Update the CloneSet status")
cloneSet.Status.ReadyReplicas = 3
Expect(k8sClient.Status().Update(ctx, &cloneSet)).Should(Succeed())
By("checking should fail as not enough pod ready")
s.rolloutStatus.CurrentBatch = 1
s.rolloutStatus.RolloutOriginalSize = 2
s.rolloutStatus.RolloutTargetSize = 10
done, err := s.CheckOneBatchPods(ctx)
Expect(done).Should(BeFalse())
Expect(err).Should(BeNil())
Expect(s.rolloutStatus.UpgradedReadyReplicas).Should(BeEquivalentTo(cloneSet.Status.ReadyReplicas))
// set the rollout batch spec allow unavailable
perc := intstr.FromString("20%")
s.rolloutSpec.RolloutBatches[1] = v1alpha1.RolloutBatch{
Replicas: perc,
MaxUnavailable: &perc,
}
By("checking one batch should succeed with unavailble allowed")
done, err = s.CheckOneBatchPods(ctx)
Expect(done).Should(BeTrue())
Expect(err).Should(BeNil())
Expect(s.rolloutStatus.UpgradedReadyReplicas).Should(BeEquivalentTo(cloneSet.Status.ReadyReplicas))
})
It("current ready Pod is more than expected during decrease", func() {
By("Create the CloneSet")
Expect(k8sClient.Create(ctx, &cloneSet)).Should(Succeed())
By("Update the CloneSet status")
cloneSet.Status.ReadyReplicas = 10
Expect(k8sClient.Status().Update(ctx, &cloneSet)).Should(Succeed())
By("checking should fail as not enough pod ready")
s.rolloutStatus.CurrentBatch = 1
s.rolloutStatus.RolloutOriginalSize = 12
s.rolloutStatus.RolloutTargetSize = 5
done, err := s.CheckOneBatchPods(ctx)
Expect(done).Should(BeFalse())
Expect(err).Should(BeNil())
Expect(s.rolloutStatus.UpgradedReadyReplicas).Should(BeEquivalentTo(cloneSet.Status.ReadyReplicas))
// set the rollout batch spec allow unavailable
perc := intstr.FromString("20%")
s.rolloutSpec.RolloutBatches[1] = v1alpha1.RolloutBatch{
Replicas: perc,
MaxUnavailable: &perc,
}
By("checking one batch should still fail even with unavailble allowed")
done, err = s.CheckOneBatchPods(ctx)
Expect(done).Should(BeFalse())
Expect(err).Should(BeNil())
Expect(s.rolloutStatus.UpgradedReadyReplicas).Should(BeEquivalentTo(cloneSet.Status.ReadyReplicas))
})
It("there are more pods shrunk during decrease", func() {
By("Create the CloneSet")
Expect(k8sClient.Create(ctx, &cloneSet)).Should(Succeed())
By("Update the CloneSet status")
cloneSet.Status.ReadyReplicas = 8
Expect(k8sClient.Status().Update(ctx, &cloneSet)).Should(Succeed())
By("checking should pass even with not enough pod ready")
s.rolloutStatus.CurrentBatch = 1
s.rolloutStatus.RolloutOriginalSize = 12
s.rolloutStatus.RolloutTargetSize = 5
done, err := s.CheckOneBatchPods(ctx)
Expect(done).Should(BeTrue())
Expect(err).Should(BeNil())
Expect(s.rolloutStatus.UpgradedReadyReplicas).Should(BeEquivalentTo(cloneSet.Status.ReadyReplicas))
})
})
Context("TestFinalizeOneBatch", func() {
BeforeEach(func() {
s.rolloutSpec.RolloutBatches[0] = v1alpha1.RolloutBatch{
Replicas: intstr.FromInt(2),
}
})
It("test illegal batch partition", func() {
By("finalizing one batch")
s.rolloutSpec.BatchPartition = pointer.Int32(2)
s.rolloutStatus.CurrentBatch = 3
done, err := s.FinalizeOneBatch(ctx)
Expect(done).Should(BeFalse())
Expect(err.Error()).Should(ContainSubstring("the current batch value in the status is greater than the batch partition"))
})
It("test finalize during increase", func() {
By("finalizing one batch with not enough")
s.rolloutStatus.UpgradedReplicas = 6
s.rolloutStatus.CurrentBatch = 1
s.rolloutStatus.RolloutOriginalSize = 5
s.rolloutStatus.RolloutTargetSize = 12
done, err := s.FinalizeOneBatch(ctx)
Expect(done).Should(BeFalse())
Expect(err.Error()).Should(ContainSubstring(" upgraded replica in the status is less than the lower bound"))
By("finalizing one batch with just enough")
s.rolloutStatus.UpgradedReplicas = 7
done, err = s.FinalizeOneBatch(ctx)
Expect(done).Should(BeTrue())
Expect(err).Should(BeNil())
By("finalizing one batch with all")
s.rolloutStatus.UpgradedReplicas = 9
done, err = s.FinalizeOneBatch(ctx)
Expect(done).Should(BeTrue())
Expect(err).Should(BeNil())
By("finalizing one batch with more than")
s.rolloutStatus.UpgradedReplicas = 12
done, err = s.FinalizeOneBatch(ctx)
Expect(done).Should(BeFalse())
Expect(err.Error()).Should(ContainSubstring("upgraded replica in the status is greater than the upper bound"))
})
It("test finalize during decrease", func() {
By("finalizing one batch with too many")
s.rolloutStatus.UpgradedReplicas = 13
s.rolloutStatus.CurrentBatch = 1
s.rolloutStatus.RolloutOriginalSize = 14
s.rolloutStatus.RolloutTargetSize = 2
done, err := s.FinalizeOneBatch(ctx)
Expect(done).Should(BeFalse())
Expect(err.Error()).Should(ContainSubstring("upgraded replica in the status is greater than the upper bound"))
By("finalizing one batch with just enough")
s.rolloutStatus.UpgradedReplicas = 12
done, err = s.FinalizeOneBatch(ctx)
Expect(done).Should(BeTrue())
Expect(err).Should(BeNil())
By("finalizing one batch with all")
s.rolloutStatus.UpgradedReplicas = 9
done, err = s.FinalizeOneBatch(ctx)
Expect(done).Should(BeTrue())
Expect(err).Should(BeNil())
By("finalizing one batch with not enough")
s.rolloutStatus.UpgradedReplicas = 8
done, err = s.FinalizeOneBatch(ctx)
Expect(done).Should(BeFalse())
Expect(err.Error()).Should(ContainSubstring(" upgraded replica in the status is less than the lower bound"))
})
})
Context("TestFinalize", func() {
It("failed to fetch CloneSet", func() {
By("finalizing")
finalized := s.Finalize(ctx, true)
Expect(finalized).Should(BeFalse())
})
It("Already finalize CloneSet", func() {
By("Create a CloneSet")
cloneSet.SetOwnerReferences([]metav1.OwnerReference{{
APIVersion: v1alpha1.SchemeGroupVersion.String(),
Kind: "notRollout",
Name: "def",
UID: "123456",
}})
Expect(k8sClient.Create(ctx, &cloneSet)).Should(Succeed())
By("finalizing without patch")
finalized := s.Finalize(ctx, true)
Expect(finalized).Should(BeTrue())
})
It("successfully to finalize CloneSet", func() {
By("Create a CloneSet")
cloneSet.SetOwnerReferences([]metav1.OwnerReference{
{
APIVersion: v1alpha1.SchemeGroupVersion.String(),
Kind: v1alpha1.RolloutKind,
Name: "def",
UID: "123456",
},
{
APIVersion: corev1.SchemeGroupVersion.String(),
Kind: "Deployment",
Name: "def",
UID: "998877745",
},
})
Expect(k8sClient.Create(ctx, &cloneSet)).Should(Succeed())
By("finalizing with patch")
finalized := s.Finalize(ctx, false)
Expect(finalized).Should(BeTrue())
Expect(k8sClient.Get(ctx, s.targetNamespacedName, &cloneSet)).Should(Succeed())
Expect(len(cloneSet.GetOwnerReferences())).Should(BeEquivalentTo(1))
Expect(cloneSet.GetOwnerReferences()[0].Kind).Should(Equal("Deployment"))
})
})
})

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