Skip to content

Commit 8e71ecd

Browse files
authored
Add e2e tests for k8s rollback plugin and fix the bug (#5683)
Signed-off-by: Shinnosuke Sawada-Dazai <[email protected]>
1 parent f51a364 commit 8e71ecd

File tree

2 files changed

+219
-1
lines changed

2 files changed

+219
-1
lines changed

pkg/app/pipedv1/plugin/kubernetes/deployment/rollback.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,11 @@ func (p *Plugin) executeK8sRollbackStage(ctx context.Context, input *sdk.Execute
7272
}
7373
}
7474

75-
// Add variant annotations to all manifests.
75+
// Add variant labels and annotations to all manifests.
7676
for i := range manifests {
77+
manifests[i].AddLabels(map[string]string{
78+
variantLabel: primaryVariant,
79+
})
7780
manifests[i].AddAnnotations(map[string]string{
7881
variantLabel: primaryVariant,
7982
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
// Copyright 2025 The PipeCD Authors.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package deployment
16+
17+
import (
18+
"os"
19+
"path/filepath"
20+
"testing"
21+
22+
"github.com/stretchr/testify/assert"
23+
"github.com/stretchr/testify/require"
24+
"go.uber.org/zap/zaptest"
25+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26+
"k8s.io/apimachinery/pkg/runtime/schema"
27+
28+
kubeConfigPkg "github.com/pipe-cd/pipecd/pkg/app/pipedv1/plugin/kubernetes/config"
29+
"github.com/pipe-cd/pipecd/pkg/plugin/logpersister/logpersistertest"
30+
"github.com/pipe-cd/pipecd/pkg/plugin/sdk"
31+
"github.com/pipe-cd/pipecd/pkg/plugin/toolregistry/toolregistrytest"
32+
)
33+
34+
func TestPlugin_executeK8sRollbackStage_NoPreviousDeployment(t *testing.T) {
35+
t.Parallel()
36+
37+
// Initialize tool registry
38+
testRegistry := toolregistrytest.NewTestToolRegistry(t)
39+
40+
// Initialize deploy target config and dynamic client for assertions with envtest
41+
dtConfig, _ := setupTestDeployTargetConfigAndDynamicClient(t)
42+
43+
// Read the application config from the example file
44+
cfg, err := os.ReadFile(filepath.Join(examplesDir(), "kubernetes", "simple", "app.pipecd.yaml"))
45+
require.NoError(t, err)
46+
47+
// Prepare the input
48+
input := &sdk.ExecuteStageInput{
49+
Request: sdk.ExecuteStageRequest{
50+
StageName: "K8S_ROLLBACK",
51+
StageConfig: []byte(``),
52+
RunningDeploymentSource: sdk.DeploymentSource{
53+
CommitHash: "", // Empty commit hash indicates no previous deployment
54+
},
55+
TargetDeploymentSource: sdk.DeploymentSource{
56+
ApplicationDirectory: filepath.Join(examplesDir(), "kubernetes", "simple"),
57+
CommitHash: "0123456789",
58+
ApplicationConfig: cfg,
59+
ApplicationConfigFilename: "app.pipecd.yaml",
60+
},
61+
Deployment: sdk.Deployment{
62+
PipedID: "piped-id",
63+
ApplicationID: "app-id",
64+
},
65+
},
66+
Client: sdk.NewClient(nil, "kubernetes", "", "", logpersistertest.NewTestLogPersister(t), testRegistry),
67+
Logger: zaptest.NewLogger(t),
68+
}
69+
70+
plugin := &Plugin{}
71+
status := plugin.executeK8sRollbackStage(t.Context(), input, []*sdk.DeployTarget[kubeConfigPkg.KubernetesDeployTargetConfig]{
72+
{
73+
Name: "default",
74+
Config: *dtConfig,
75+
},
76+
})
77+
78+
assert.Equal(t, sdk.StageStatusFailure, status)
79+
}
80+
81+
func TestPlugin_executeK8sRollbackStage_SuccessfulRollback(t *testing.T) {
82+
t.Parallel()
83+
84+
// Initialize tool registry
85+
testRegistry := toolregistrytest.NewTestToolRegistry(t)
86+
87+
// Initialize deploy target config and dynamic client for assertions with envtest
88+
dtConfig, dynamicClient := setupTestDeployTargetConfigAndDynamicClient(t)
89+
90+
// Read the application config from the example file
91+
cfg, err := os.ReadFile(filepath.Join(examplesDir(), "kubernetes", "simple", "app.pipecd.yaml"))
92+
require.NoError(t, err)
93+
94+
// Prepare the input
95+
input := &sdk.ExecuteStageInput{
96+
Request: sdk.ExecuteStageRequest{
97+
StageName: "K8S_ROLLBACK",
98+
StageConfig: []byte(``),
99+
RunningDeploymentSource: sdk.DeploymentSource{
100+
ApplicationDirectory: filepath.Join(examplesDir(), "kubernetes", "simple"),
101+
CommitHash: "previous-hash",
102+
ApplicationConfig: cfg,
103+
ApplicationConfigFilename: "app.pipecd.yaml",
104+
},
105+
TargetDeploymentSource: sdk.DeploymentSource{
106+
ApplicationDirectory: filepath.Join(examplesDir(), "kubernetes", "simple"),
107+
CommitHash: "0123456789",
108+
ApplicationConfig: cfg,
109+
ApplicationConfigFilename: "app.pipecd.yaml",
110+
},
111+
Deployment: sdk.Deployment{
112+
PipedID: "piped-id",
113+
ApplicationID: "app-id",
114+
},
115+
},
116+
Client: sdk.NewClient(nil, "kubernetes", "", "", logpersistertest.NewTestLogPersister(t), testRegistry),
117+
Logger: zaptest.NewLogger(t),
118+
}
119+
120+
plugin := &Plugin{}
121+
status := plugin.executeK8sRollbackStage(t.Context(), input, []*sdk.DeployTarget[kubeConfigPkg.KubernetesDeployTargetConfig]{
122+
{
123+
Name: "default",
124+
Config: *dtConfig,
125+
},
126+
})
127+
128+
assert.Equal(t, sdk.StageStatusSuccess, status)
129+
130+
// Verify the deployment was rolled back
131+
deployment, err := dynamicClient.Resource(schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"}).Namespace("default").Get(t.Context(), "simple", metav1.GetOptions{})
132+
require.NoError(t, err)
133+
134+
// Verify labels and annotations
135+
assert.Equal(t, "piped", deployment.GetLabels()["pipecd.dev/managed-by"])
136+
assert.Equal(t, "piped-id", deployment.GetLabels()["pipecd.dev/piped"])
137+
assert.Equal(t, "app-id", deployment.GetLabels()["pipecd.dev/application"])
138+
assert.Equal(t, "previous-hash", deployment.GetLabels()["pipecd.dev/commit-hash"])
139+
140+
assert.Equal(t, "piped", deployment.GetAnnotations()["pipecd.dev/managed-by"])
141+
assert.Equal(t, "piped-id", deployment.GetAnnotations()["pipecd.dev/piped"])
142+
assert.Equal(t, "app-id", deployment.GetAnnotations()["pipecd.dev/application"])
143+
assert.Equal(t, "apps/v1", deployment.GetAnnotations()["pipecd.dev/original-api-version"])
144+
assert.Equal(t, "apps:Deployment::simple", deployment.GetAnnotations()["pipecd.dev/resource-key"])
145+
assert.Equal(t, "previous-hash", deployment.GetAnnotations()["pipecd.dev/commit-hash"])
146+
}
147+
148+
func TestPlugin_executeK8sRollbackStage_WithVariantLabels(t *testing.T) {
149+
t.Parallel()
150+
151+
// Initialize tool registry
152+
testRegistry := toolregistrytest.NewTestToolRegistry(t)
153+
154+
// Initialize deploy target config and dynamic client for assertions with envtest
155+
dtConfig, dynamicClient := setupTestDeployTargetConfigAndDynamicClient(t)
156+
157+
// Read the application config and modify it to include variant labels
158+
cfg, err := os.ReadFile(filepath.Join(examplesDir(), "kubernetes", "simple", "app.pipecd.yaml"))
159+
require.NoError(t, err)
160+
161+
// Prepare the input
162+
input := &sdk.ExecuteStageInput{
163+
Request: sdk.ExecuteStageRequest{
164+
StageName: "K8S_ROLLBACK",
165+
StageConfig: []byte(``),
166+
RunningDeploymentSource: sdk.DeploymentSource{
167+
ApplicationDirectory: filepath.Join(examplesDir(), "kubernetes", "simple"),
168+
CommitHash: "previous-hash",
169+
ApplicationConfig: cfg,
170+
ApplicationConfigFilename: "app.pipecd.yaml",
171+
},
172+
TargetDeploymentSource: sdk.DeploymentSource{
173+
ApplicationDirectory: filepath.Join(examplesDir(), "kubernetes", "simple"),
174+
CommitHash: "0123456789",
175+
ApplicationConfig: cfg,
176+
ApplicationConfigFilename: "app.pipecd.yaml",
177+
},
178+
Deployment: sdk.Deployment{
179+
PipedID: "piped-id",
180+
ApplicationID: "app-id",
181+
},
182+
},
183+
Client: sdk.NewClient(nil, "kubernetes", "", "", logpersistertest.NewTestLogPersister(t), testRegistry),
184+
Logger: zaptest.NewLogger(t),
185+
}
186+
187+
plugin := &Plugin{}
188+
status := plugin.executeK8sRollbackStage(t.Context(), input, []*sdk.DeployTarget[kubeConfigPkg.KubernetesDeployTargetConfig]{
189+
{
190+
Name: "default",
191+
Config: *dtConfig,
192+
},
193+
})
194+
195+
assert.Equal(t, sdk.StageStatusSuccess, status)
196+
197+
// Verify the deployment was rolled back with variant labels
198+
deployment, err := dynamicClient.Resource(schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"}).Namespace("default").Get(t.Context(), "simple", metav1.GetOptions{})
199+
require.NoError(t, err)
200+
201+
// Verify labels and annotations
202+
assert.Equal(t, "piped", deployment.GetLabels()["pipecd.dev/managed-by"])
203+
assert.Equal(t, "piped-id", deployment.GetLabels()["pipecd.dev/piped"])
204+
assert.Equal(t, "app-id", deployment.GetLabels()["pipecd.dev/application"])
205+
assert.Equal(t, "previous-hash", deployment.GetLabels()["pipecd.dev/commit-hash"])
206+
assert.Equal(t, "primary", deployment.GetLabels()["pipecd.dev/variant"])
207+
208+
assert.Equal(t, "piped", deployment.GetAnnotations()["pipecd.dev/managed-by"])
209+
assert.Equal(t, "piped-id", deployment.GetAnnotations()["pipecd.dev/piped"])
210+
assert.Equal(t, "app-id", deployment.GetAnnotations()["pipecd.dev/application"])
211+
assert.Equal(t, "apps/v1", deployment.GetAnnotations()["pipecd.dev/original-api-version"])
212+
assert.Equal(t, "apps:Deployment::simple", deployment.GetAnnotations()["pipecd.dev/resource-key"])
213+
assert.Equal(t, "previous-hash", deployment.GetAnnotations()["pipecd.dev/commit-hash"])
214+
assert.Equal(t, "primary", deployment.GetAnnotations()["pipecd.dev/variant"])
215+
}

0 commit comments

Comments
 (0)