Feat: disable component revision for component wo rollout (#4281)

Signed-off-by: Somefive <yd219913@alibaba-inc.com>
This commit is contained in:
Somefive
2022-06-30 16:22:46 +08:00
committed by GitHub
parent 7a87e6e632
commit de37545a12
9 changed files with 45 additions and 31 deletions
+1
View File
@@ -93,6 +93,7 @@ helm install --create-namespace -n vela-system kubevela kubevela/vela-core --wai
| `optimize.enableInMemoryWorkflowContext` | Optimize workflow by use in-memory context. | `false` |
| `optimize.disableResourceApplyDoubleCheck` | Optimize workflow by ignoring resource double check after apply. | `false` |
| `optimize.enableResourceTrackerDeleteOnlyTrigger` | Optimize resourcetracker by only trigger reconcile when resourcetracker is deleted. | `true` |
| `featureGates.enableLegacyComponentRevision` | if disabled, only component with rollout trait will create component revisions | `false` |
### MultiCluster parameters
@@ -217,6 +217,7 @@ spec:
- "--max-workflow-step-error-retry-times={{ .Values.workflow.step.errorRetryTimes }}"
- "--feature-gates=EnableSuspendOnFailure={{- .Values.workflow.enableSuspendOnFailure | toString -}}"
- "--feature-gates=AuthenticateApplication={{- .Values.authentication.enabled | toString -}}"
- "--feature-gates=LegacyComponentRevision={{- .Values.featureGates.enableLegacyComponentRevision | toString -}}"
{{ if .Values.authentication.enabled }}
{{ if .Values.authentication.withUser }}
- "--authentication-with-user"
+4
View File
@@ -109,6 +109,10 @@ optimize:
disableResourceApplyDoubleCheck: false
enableResourceTrackerDeleteOnlyTrigger: true
##@param featureGates.enableLegacyComponentRevision if disabled, only component with rollout trait will create component revisions
featureGates:
enableLegacyComponentRevision: false
## @section MultiCluster parameters
## @param multicluster.enabled Whether to enable multi-cluster
@@ -334,7 +334,7 @@ func (h *AppHandler) prepareWorkloadAndManifests(ctx context.Context,
if err := af.SetOAMContract(manifest); err != nil {
return nil, nil, errors.WithMessage(err, "SetOAMContract")
}
if err := h.HandleComponentsRevision(ctx, []*types.ComponentManifest{manifest}); err != nil {
if err := h.HandleComponentsRevision(contextWithComponent(ctx, &comp), []*types.ComponentManifest{manifest}); err != nil {
return nil, nil, errors.WithMessage(err, "HandleComponentsRevision")
}
@@ -31,6 +31,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
ktypes "k8s.io/apimachinery/pkg/types"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/klog/v2"
"k8s.io/utils/pointer"
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -46,6 +47,7 @@ import (
"github.com/oam-dev/kubevela/pkg/component"
"github.com/oam-dev/kubevela/pkg/controller/utils"
"github.com/oam-dev/kubevela/pkg/cue/model"
"github.com/oam-dev/kubevela/pkg/features"
monitorContext "github.com/oam-dev/kubevela/pkg/monitor/context"
"github.com/oam-dev/kubevela/pkg/monitor/metrics"
"github.com/oam-dev/kubevela/pkg/multicluster"
@@ -69,8 +71,35 @@ const (
ManifestKeyScopes = "Scopes"
// ComponentRevisionNamespaceContextKey is the key in context that defines the override namespace of component revision
ComponentRevisionNamespaceContextKey = contextKey("component-revision-namespace")
// ComponentContextKey is the key in context that records the component
ComponentContextKey = contextKey("component")
)
const rolloutTraitName = "rollout"
// contextWithComponent records ApplicationComponent in context
func contextWithComponent(ctx context.Context, component *common.ApplicationComponent) context.Context {
return context.WithValue(ctx, ComponentContextKey, component)
}
// componentInContext extract ApplicationComponent from context
func componentInContext(ctx context.Context) *common.ApplicationComponent {
comp, _ := ctx.Value(ComponentContextKey).(*common.ApplicationComponent)
return comp
}
func _containsRolloutTrait(ctx context.Context) bool {
comp := componentInContext(ctx)
if comp != nil {
for _, trait := range comp.Traits {
if trait.Type == rolloutTraitName {
return true
}
}
}
return false
}
var (
// DisableAllComponentRevision disable component revision creation
DisableAllComponentRevision = false
@@ -709,6 +738,9 @@ func (h *AppHandler) createControllerRevision(ctx context.Context, cm *types.Com
Data: *util.Object2RawExtension(comp),
}
common.NewOAMObjectReferenceFromObject(cm.StandardWorkload).AddLabelsToObject(cr)
if !utilfeature.DefaultMutableFeatureGate.Enabled(features.LegacyComponentRevision) && !_containsRolloutTrait(ctx) {
return nil
}
return h.resourceKeeper.DispatchComponentRevision(ctx, cr)
}
@@ -37,6 +37,7 @@ import (
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/rest"
"k8s.io/utils/pointer"
@@ -52,6 +53,7 @@ import (
"github.com/oam-dev/kubevela/apis/standard.oam.dev/v1alpha1"
"github.com/oam-dev/kubevela/pkg/appfile"
"github.com/oam-dev/kubevela/pkg/cue/packages"
"github.com/oam-dev/kubevela/pkg/features"
"github.com/oam-dev/kubevela/pkg/oam/discoverymapper"
// +kubebuilder:scaffold:imports
)
@@ -165,6 +167,7 @@ var _ = BeforeSuite(func(done Done) {
Expect(err).NotTo(HaveOccurred())
}()
close(done)
Expect(utilfeature.DefaultMutableFeatureGate.Set(fmt.Sprintf("%s=true", features.LegacyComponentRevision))).Should(Succeed())
}, 120)
var _ = AfterSuite(func() {
+3
View File
@@ -35,6 +35,8 @@ const (
LegacyResourceTrackerGC featuregate.Feature = "LegacyResourceTrackerGC"
// EnableSuspendOnFailure enable suspend on workflow failure
EnableSuspendOnFailure featuregate.Feature = "EnableSuspendOnFailure"
// LegacyComponentRevision if enabled, create component revision even no rollout trait attached
LegacyComponentRevision featuregate.Feature = "LegacyComponentRevision"
// Edge Features
@@ -48,6 +50,7 @@ var defaultFeatureGates = map[featuregate.Feature]featuregate.FeatureSpec{
DeprecatedObjectLabelSelector: {Default: false, PreRelease: featuregate.Alpha},
LegacyResourceTrackerGC: {Default: false, PreRelease: featuregate.Beta},
EnableSuspendOnFailure: {Default: false, PreRelease: featuregate.Alpha},
LegacyComponentRevision: {Default: false, PreRelease: featuregate.Alpha},
AuthenticateApplication: {Default: false, PreRelease: featuregate.Alpha},
}
@@ -255,10 +255,6 @@ var _ = Describe("Test multicluster scenario", func() {
deploys = &appsv1.DeploymentList{}
g.Expect(k8sClient.List(workerCtx, deploys, client.InNamespace(prodNamespace))).Should(Succeed())
g.Expect(len(deploys.Items)).Should(Equal(2))
// check component revision
compRevs := &appsv1.ControllerRevisionList{}
g.Expect(k8sClient.List(workerCtx, compRevs, client.InNamespace(prodNamespace))).Should(Succeed())
g.Expect(len(compRevs.Items)).Should(Equal(2))
}, time.Minute).Should(Succeed())
Expect(hubDeployName).Should(Equal("data-worker"))
// delete application
@@ -273,10 +269,6 @@ var _ = Describe("Test multicluster scenario", func() {
deploys = &appsv1.DeploymentList{}
g.Expect(k8sClient.List(workerCtx, deploys, client.InNamespace(namespace))).Should(Succeed())
g.Expect(len(deploys.Items)).Should(Equal(0))
// check component revision
compRevs := &appsv1.ControllerRevisionList{}
g.Expect(k8sClient.List(workerCtx, compRevs, client.InNamespace(prodNamespace))).Should(Succeed())
g.Expect(len(compRevs.Items)).Should(Equal(0))
}, time.Minute).Should(Succeed())
})
-22
View File
@@ -208,23 +208,6 @@ var _ = Describe("Application Normal tests", func() {
time.Second*60, time.Millisecond*500).Should(BeNil())
}
verifyComponentRevision := func(compName string, revisionNum int64) {
By("Verify Component revision")
expectCompRevName := fmt.Sprintf("%s-v%d", compName, revisionNum)
Eventually(
func() error {
gotCR := &v1.ControllerRevision{}
if err := k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: expectCompRevName}, gotCR); err != nil {
return err
}
if gotCR.Revision != revisionNum {
return fmt.Errorf("expect revision %d != real %d", revisionNum, gotCR.Revision)
}
return nil
},
time.Second*10, time.Millisecond*500).Should(BeNil())
}
BeforeEach(func() {
By("Start to run a test, clean up previous resources")
namespaceName = "app-normal-e2e-test" + "-" + strconv.FormatInt(rand.Int63(), 16)
@@ -243,25 +226,21 @@ var _ = Describe("Application Normal tests", func() {
applyApp("app1.yaml")
By("Apply the application rollout go directly to the target")
verifyWorkloadRunningExpected("myweb", 1, "stefanprodan/podinfo:4.0.3")
verifyComponentRevision("myweb", 1)
By("Update app with trait")
updateApp("app2.yaml")
By("Apply the application rollout go directly to the target")
verifyWorkloadRunningExpected("myweb", 2, "stefanprodan/podinfo:4.0.3")
verifyComponentRevision("myweb", 2)
By("Update app with trait updated")
updateApp("app3.yaml")
By("Apply the application rollout go directly to the target")
verifyWorkloadRunningExpected("myweb", 3, "stefanprodan/podinfo:4.0.3")
verifyComponentRevision("myweb", 3)
By("Update app with trait and workload image updated")
updateApp("app4.yaml")
By("Apply the application rollout go directly to the target")
verifyWorkloadRunningExpected("myweb", 1, "stefanprodan/podinfo:5.0.2")
verifyComponentRevision("myweb", 4)
})
It("Test app have component with multiple same type traits", func() {
@@ -402,7 +381,6 @@ var _ = Describe("Application Normal tests", func() {
By("Checking an application status")
verifyWorkloadRunningExpected("myweb", 1, "stefanprodan/podinfo:4.0.3")
verifyComponentRevision("myweb", 1)
Expect(k8sClient.Delete(ctx, &newApp)).Should(Succeed())
Eventually(func(g Gomega) {