@@ -21,12 +21,14 @@ import (
2121 "fmt"
2222 "os"
2323
24- "github.com/oam-dev/terraform-controller/api/v1beta2"
25- "github.com/oam-dev/terraform-controller/controllers/util"
2624 "github.com/pkg/errors"
2725 v1 "k8s.io/api/core/v1"
2826 "k8s.io/klog/v2"
2927 "sigs.k8s.io/controller-runtime/pkg/client"
28+
29+ "github.com/oam-dev/terraform-controller/api/v1beta2"
30+ "github.com/oam-dev/terraform-controller/controllers/util"
31+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3032)
3133
3234const (
@@ -47,19 +49,31 @@ type K8SBackend struct {
4749 SecretSuffix string
4850 // SecretNS is the namespace of the Terraform backend secret
4951 SecretNS string
52+ // LegacySecretSuffix is the same as SecretSuffix, but only used when `--controller-namespace` is specified
53+ LegacySecretSuffix string
5054}
5155
52- func newDefaultK8SBackend (suffix string , client client.Client , namespace string ) * K8SBackend {
56+ func newDefaultK8SBackend (configuration * v1beta2. Configuration , client client.Client , controllerNSSpecified bool ) * K8SBackend {
5357 ns := os .Getenv ("TERRAFORM_BACKEND_NAMESPACE" )
5458 if ns == "" {
55- ns = namespace
59+ ns = configuration .GetNamespace ()
60+ }
61+
62+ var (
63+ suffix = configuration .Spec .Backend .SecretSuffix
64+ legacySuffix string
65+ )
66+ if controllerNSSpecified {
67+ legacySuffix = suffix
68+ suffix = string (configuration .GetUID ())
5669 }
5770 hcl := renderK8SBackendHCL (suffix , ns )
5871 return & K8SBackend {
59- Client : client ,
60- HCLCode : hcl ,
61- SecretSuffix : suffix ,
62- SecretNS : ns ,
72+ Client : client ,
73+ HCLCode : hcl ,
74+ SecretSuffix : suffix ,
75+ SecretNS : ns ,
76+ LegacySecretSuffix : legacySuffix ,
6377 }
6478}
6579
@@ -95,15 +109,23 @@ terraform {
95109 return fmt .Sprintf (fmtStr , suffix , ns )
96110}
97111
98- func (k K8SBackend ) secretName () string {
112+ func (k * K8SBackend ) secretName () string {
99113 return fmt .Sprintf (TFBackendSecret , terraformWorkspace , k .SecretSuffix )
100114}
101115
116+ func (k * K8SBackend ) legacySecretName () string {
117+ return fmt .Sprintf (TFBackendSecret , terraformWorkspace , k .LegacySecretSuffix )
118+ }
119+
102120// GetTFStateJSON gets Terraform state json from the Terraform kubernetes backend
103121func (k * K8SBackend ) GetTFStateJSON (ctx context.Context ) ([]byte , error ) {
104122 var s = v1.Secret {}
105- if err := k .Client .Get (ctx , client.ObjectKey {Name : k .secretName (), Namespace : k .SecretNS }, & s ); err != nil {
106- return nil , errors .Wrap (err , "terraform state file backend secret is not generated" )
123+ // Try to get legacy secret first, if it doesn't exist, try to get new secret
124+ err := k .Client .Get (ctx , client.ObjectKey {Name : k .legacySecretName (), Namespace : k .SecretNS }, & s )
125+ if err != nil {
126+ if err = k .Client .Get (ctx , client.ObjectKey {Name : k .secretName (), Namespace : k .SecretNS }, & s ); err != nil {
127+ return nil , errors .Wrap (err , "terraform state file backend secret is not generated" )
128+ }
107129 }
108130 tfStateData , ok := s .Data [TerraformStateNameInSecret ]
109131 if ! ok {
@@ -119,8 +141,15 @@ func (k *K8SBackend) GetTFStateJSON(ctx context.Context) ([]byte, error) {
119141
120142// CleanUp will delete the Terraform kubernetes backend secret when deleting the configuration object
121143func (k * K8SBackend ) CleanUp (ctx context.Context ) error {
122- klog .InfoS ("Deleting the secret which stores Kubernetes backend" , "Name" , k .secretName ())
144+ klog .InfoS ("Deleting the legacy secret which stores Kubernetes backend" , "Name" , k .legacySecretName ())
123145 var kubernetesBackendSecret v1.Secret
146+ if err := k .Client .Get (ctx , client.ObjectKey {Name : k .legacySecretName (), Namespace : k .SecretNS }, & kubernetesBackendSecret ); err == nil {
147+ if err := k .Client .Delete (ctx , & kubernetesBackendSecret ); err != nil {
148+ return err
149+ }
150+ }
151+
152+ klog .InfoS ("Deleting the secret which stores Kubernetes backend" , "Name" , k .secretName ())
124153 if err := k .Client .Get (ctx , client.ObjectKey {Name : k .secretName (), Namespace : k .SecretNS }, & kubernetesBackendSecret ); err == nil {
125154 if err := k .Client .Delete (ctx , & kubernetesBackendSecret ); err != nil {
126155 return err
@@ -131,8 +160,40 @@ func (k *K8SBackend) CleanUp(ctx context.Context) error {
131160
132161// HCL returns the backend hcl code string
133162func (k * K8SBackend ) HCL () string {
163+ if k .LegacySecretSuffix != "" {
164+ err := k .migrateLegacySecret ()
165+ if err != nil {
166+ klog .ErrorS (err , "Failed to migrate legacy secret" )
167+ }
168+ }
169+
134170 if k .HCLCode == "" {
135171 k .HCLCode = renderK8SBackendHCL (k .SecretSuffix , k .SecretNS )
136172 }
137173 return k .HCLCode
138174}
175+
176+ // migrateLegacySecret will migrate the legacy secret to the new secret if the legacy secret exists
177+ // This is needed when the --controller-namespace is specified and restart the controller
178+ func (k * K8SBackend ) migrateLegacySecret () error {
179+ ctx := context .TODO ()
180+ s := v1.Secret {}
181+ if err := k .Client .Get (ctx , client.ObjectKey {Name : k .legacySecretName (), Namespace : k .SecretNS }, & s ); err == nil {
182+ klog .InfoS ("Migrating legacy secret to new secret" , "LegacyName" , k .legacySecretName (), "NewName" , k .secretName (), "Namespace" , k .SecretNS )
183+ newSecret := v1.Secret {
184+ ObjectMeta : metav1.ObjectMeta {
185+ Name : k .secretName (),
186+ Namespace : k .SecretNS ,
187+ },
188+ Data : s .Data ,
189+ }
190+ err = k .Client .Create (ctx , & newSecret )
191+ if err != nil {
192+ return errors .Wrapf (err , "Fail to create new secret, Name: %s, Namespace: %s" , k .secretName (), k .SecretNS )
193+ } else if err = k .Client .Delete (ctx , & s ); err != nil {
194+ // Only delete the legacy secret if the new secret is successfully created
195+ return errors .Wrapf (err , "Fail to delete legacy secret, Name: %s, Namespace: %s" , k .legacySecretName (), k .SecretNS )
196+ }
197+ }
198+ return nil
199+ }
0 commit comments