Skip to content

Commit d2e6f21

Browse files
wujiuye吴就业
andauthored
fix: The execution of the terraformDestroy method fails and the appli… (#366)
Co-authored-by: 吴就业 <wujiuye@lizhi.fm>
1 parent a8a6504 commit d2e6f21

File tree

2 files changed

+171
-6
lines changed

2 files changed

+171
-6
lines changed

controllers/configuration_controller.go

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -183,11 +183,19 @@ func (r *ConfigurationReconciler) Reconcile(ctx context.Context, req ctrl.Reques
183183
}
184184
}
185185

186-
if err := r.terraformDestroy(ctx, configuration, meta); err != nil {
187-
if err.Error() == types.MessageDestroyJobNotCompleted {
188-
return ctrl.Result{RequeueAfter: 3 * time.Second}, nil
186+
// If no tfState has been generated, then perform a quick cleanup without dispatching destroying job.
187+
if meta.isTFStateGenerated(ctx) {
188+
if err := r.terraformDestroy(ctx, configuration, meta); err != nil {
189+
if err.Error() == types.MessageDestroyJobNotCompleted {
190+
return ctrl.Result{RequeueAfter: 3 * time.Second}, nil
191+
}
192+
return ctrl.Result{RequeueAfter: 3 * time.Second}, errors.Wrap(err, "continue reconciling to destroy cloud resource")
193+
}
194+
} else {
195+
klog.Infof("No need to execute terraform destroy command, because tfstate file not found: %s/%s", configuration.Namespace, configuration.Name)
196+
if err := r.cleanUpSubResources(ctx, configuration, meta); err != nil {
197+
klog.Warningf("Ignoring error when clean up sub-resources, for no resource is actually created: %s", err)
189198
}
190-
return ctrl.Result{RequeueAfter: 3 * time.Second}, errors.Wrap(err, "continue reconciling to destroy cloud resource")
191199
}
192200

193201
configuration, err := tfcfg.Get(ctx, r.Client, req.NamespacedName)
@@ -1135,6 +1143,24 @@ type TFState struct {
11351143
Outputs map[string]TfStateProperty `json:"outputs"`
11361144
}
11371145

1146+
func (meta *TFConfigurationMeta) isTFStateGenerated(ctx context.Context) bool {
1147+
// 1. exist backend
1148+
if meta.Backend == nil {
1149+
return false
1150+
}
1151+
// 2. and exist tfstate file
1152+
tfStateJSON, err := meta.Backend.GetTFStateJSON(ctx)
1153+
if err != nil {
1154+
return false
1155+
}
1156+
// 3. and outputs not empty
1157+
var tfState TFState
1158+
if err = json.Unmarshal(tfStateJSON, &tfState); err != nil {
1159+
return false
1160+
}
1161+
return len(tfState.Outputs) > 0
1162+
}
1163+
11381164
//nolint:funlen
11391165
func (meta *TFConfigurationMeta) getTFOutputs(ctx context.Context, k8sClient client.Client, configuration v1beta2.Configuration) (map[string]v1beta2.Property, error) {
11401166
var tfStateJSON []byte

controllers/configuration_controller_test.go

Lines changed: 141 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,7 @@ func TestConfigurationReconcile(t *testing.T) {
512512
},
513513
}
514514

515-
stateData, _ := base64.StdEncoding.DecodeString("H4sIAAAAAAAA/0SMwa7CIBBF9/0KMutH80ArDb9ijKHDYEhqMQO4afrvBly4POfc3H0QAt7EOaYNrDj/NS7E7ELi5/1XQI3/o4beM3F0K1ihO65xI/egNsLThLPRWi6agkR/CVIppaSZJrfgbBx6//1ItbxqyWDFfnTBlFNlpKaut+EYPgEAAP//xUXpvZsAAAA=")
515+
stateData, _ := base64.StdEncoding.DecodeString("H4sIAAAAAAAA/4SQzarbMBCF934KoXUdPKNf+1VKCWNp5AocO8hyaSl592KlcBd3cZfnHPHpY/52QshfXI68b3IS+tuVK5dCaS+P+8ci4TbcULb94JJplZPAFte8MS18PQrKBO8Q+xk59SHa1AMA9M4YmoN3FGJ8M/azPs96yElcCkLIsG+V8sblnqOc3uXlRuvZ0GxSSuiCRUYbw2gGHRFGPxitEgJYQDQ0a68I2ChNo1cAZJ2bR20UtW8bsv55NuJRS94W2erXe5X5QQs3A/FZ4fhJaOwUgZTVMRjto1HGpSGSQuuD955hdDDPcR6NY1ZpQJ/YwagTRAvBpsi8LXn7Pa1U+ahfWHX/zWThYz9L4Otg3390r+5fAAAA//8hmcuNuQEAAA==")
516516

517517
backendSecret := &corev1.Secret{
518518
ObjectMeta: metav1.ObjectMeta{
@@ -578,6 +578,13 @@ func TestConfigurationReconcile(t *testing.T) {
578578
},
579579
Spec: v1beta2.ConfigurationSpec{
580580
HCL: "c",
581+
Backend: &v1beta2.Backend{
582+
BackendType: "kubernetes",
583+
Kubernetes: &v1beta2.KubernetesBackendConf{
584+
SecretSuffix: "a",
585+
Namespace: &backendSecret.Namespace,
586+
},
587+
},
581588
},
582589
Status: v1beta2.ConfigurationStatus{
583590
Apply: v1beta2.ConfigurationApplyStatus{
@@ -601,7 +608,7 @@ func TestConfigurationReconcile(t *testing.T) {
601608
}
602609

603610
r4 := &ConfigurationReconciler{}
604-
r4.Client = fake.NewClientBuilder().WithScheme(s).WithObjects(secret, provider, configuration4, destroyJob4).Build()
611+
r4.Client = fake.NewClientBuilder().WithScheme(s).WithObjects(secret, provider, configuration4, destroyJob4, backendSecret).Build()
605612

606613
configuration5 := &v1beta2.Configuration{
607614
ObjectMeta: metav1.ObjectMeta{
@@ -1824,6 +1831,138 @@ func TestTfStatePropertyToToProperty(t *testing.T) {
18241831
}
18251832
}
18261833

1834+
func TestIsTFStateGenerated(t *testing.T) {
1835+
type args struct {
1836+
ctx context.Context
1837+
k8sClient client.Client
1838+
configuration v1beta2.Configuration
1839+
meta *TFConfigurationMeta
1840+
}
1841+
type want struct {
1842+
generated bool
1843+
}
1844+
1845+
ctx := context.Background()
1846+
1847+
k8sClient1 := fake.NewClientBuilder().Build()
1848+
meta1 := &TFConfigurationMeta{
1849+
Backend: &backend.K8SBackend{
1850+
Client: k8sClient1,
1851+
SecretSuffix: "a",
1852+
SecretNS: "default",
1853+
},
1854+
}
1855+
1856+
secret2 := &corev1.Secret{
1857+
ObjectMeta: metav1.ObjectMeta{
1858+
Name: "tfstate-default-a",
1859+
Namespace: "default",
1860+
},
1861+
Type: corev1.SecretTypeOpaque,
1862+
}
1863+
k8sClient2 := fake.NewClientBuilder().WithObjects(secret2).Build()
1864+
meta2 := &TFConfigurationMeta{
1865+
Backend: &backend.K8SBackend{
1866+
Client: k8sClient2,
1867+
SecretSuffix: "a",
1868+
SecretNS: "default",
1869+
},
1870+
}
1871+
1872+
tfStateData3, _ := base64.StdEncoding.DecodeString("H4sIAAAAAAAA/0SMwa7CIBBF9/0KMutH80ArDb9ijKHDYEhqMQO4afrvBly4POfc3H0QAt7EOaYNrDj/NS7E7ELi5/1XQI3/o4beM3F0K1ihO65xI/egNsLThLPRWi6agkR/CVIppaSZJrfgbBx6//1ItbxqyWDFfnTBlFNlpKaut+EYPgEAAP//xUXpvZsAAAA=")
1873+
secret3 := &corev1.Secret{
1874+
ObjectMeta: metav1.ObjectMeta{
1875+
Name: "tfstate-default-a",
1876+
Namespace: "default",
1877+
},
1878+
Data: map[string][]byte{
1879+
"tfstate": tfStateData3,
1880+
},
1881+
Type: corev1.SecretTypeOpaque,
1882+
}
1883+
k8sClient3 := fake.NewClientBuilder().WithObjects(secret3).Build()
1884+
meta3 := &TFConfigurationMeta{
1885+
Backend: &backend.K8SBackend{
1886+
Client: k8sClient3,
1887+
SecretSuffix: "a",
1888+
SecretNS: "default",
1889+
},
1890+
}
1891+
1892+
tfStateData4, _ := base64.StdEncoding.DecodeString("H4sIAAAAAAAA/4SQzarbMBCF934KoXUdPKNf+1VKCWNp5AocO8hyaSl592KlcBd3cZfnHPHpY/52QshfXI68b3IS+tuVK5dCaS+P+8ci4TbcULb94JJplZPAFte8MS18PQrKBO8Q+xk59SHa1AMA9M4YmoN3FGJ8M/azPs96yElcCkLIsG+V8sblnqOc3uXlRuvZ0GxSSuiCRUYbw2gGHRFGPxitEgJYQDQ0a68I2ChNo1cAZJ2bR20UtW8bsv55NuJRS94W2erXe5X5QQs3A/FZ4fhJaOwUgZTVMRjto1HGpSGSQuuD955hdDDPcR6NY1ZpQJ/YwagTRAvBpsi8LXn7Pa1U+ahfWHX/zWThYz9L4Otg3390r+5fAAAA//8hmcuNuQEAAA==")
1893+
secret4 := &corev1.Secret{
1894+
ObjectMeta: metav1.ObjectMeta{
1895+
Name: "tfstate-default-a",
1896+
Namespace: "default",
1897+
},
1898+
Data: map[string][]byte{
1899+
"tfstate": tfStateData4,
1900+
},
1901+
Type: corev1.SecretTypeOpaque,
1902+
}
1903+
k8sClient4 := fake.NewClientBuilder().WithObjects(secret4).Build()
1904+
meta4 := &TFConfigurationMeta{
1905+
Backend: &backend.K8SBackend{
1906+
Client: k8sClient4,
1907+
SecretSuffix: "a",
1908+
SecretNS: "default",
1909+
},
1910+
}
1911+
1912+
testcases := map[string]struct {
1913+
args args
1914+
want want
1915+
}{
1916+
"could not find backend secret": {
1917+
args: args{
1918+
ctx: ctx,
1919+
k8sClient: k8sClient1,
1920+
meta: meta1,
1921+
},
1922+
want: want{
1923+
generated: false,
1924+
},
1925+
},
1926+
"no data in a backend secret": {
1927+
args: args{
1928+
ctx: ctx,
1929+
k8sClient: k8sClient2,
1930+
meta: meta2,
1931+
},
1932+
want: want{
1933+
generated: false,
1934+
},
1935+
},
1936+
"outputs in the backend secret are empty.": {
1937+
args: args{
1938+
ctx: ctx,
1939+
k8sClient: k8sClient3,
1940+
meta: meta3,
1941+
},
1942+
want: want{
1943+
generated: false,
1944+
},
1945+
},
1946+
"outputs in the backend secret are not empty": {
1947+
args: args{
1948+
ctx: ctx,
1949+
k8sClient: k8sClient4,
1950+
meta: meta4,
1951+
},
1952+
want: want{
1953+
generated: true,
1954+
},
1955+
},
1956+
}
1957+
1958+
for name, tc := range testcases {
1959+
t.Run(name, func(t *testing.T) {
1960+
generated := tc.args.meta.isTFStateGenerated(tc.args.ctx)
1961+
assert.Equal(t, tc.want.generated, generated)
1962+
})
1963+
}
1964+
}
1965+
18271966
func TestGetTFOutputs(t *testing.T) {
18281967
type args struct {
18291968
ctx context.Context

0 commit comments

Comments
 (0)