Skip to content

Commit 0d37ae2

Browse files
fix: Stop data sources from generating kubeconfig tokens on every plan (#2269)
* fix: Stop data sources from generating kubeconfig tokens on every plan Cluster data sources called the Rancher generateKubeconfig API on every plan and apply, creating a new API token each time. Over time this leads to accumulation of large numbers of orphaned tokens. * fix: Default generate_kube_config to true to avoid breaking change Kubeconfig generation on cluster data sources now defaults to enabled, preserving existing behavior. A deprecation warning is logged when generation is active, noting that the default will change to false in a future version.
1 parent 0871f7c commit 0d37ae2

4 files changed

Lines changed: 94 additions & 8 deletions

File tree

aspell_custom.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ azure
88
backport
99
cognito
1010
config
11+
datasource
1112
destructuring
1213
eks
1314
eslint

rancher2/data_source_rancher2_cluster.go

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@ package rancher2
22

33
import (
44
"fmt"
5+
"log"
56

7+
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
68
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
9+
managementClient "github.com/rancher/rancher/pkg/client/generated/management/v3"
710
)
811

912
func dataSourceRancher2Cluster() *schema.Resource {
@@ -31,6 +34,12 @@ func dataSourceRancher2Cluster() *schema.Resource {
3134
Type: schema.TypeString,
3235
Computed: true,
3336
},
37+
"generate_kube_config": {
38+
Type: schema.TypeBool,
39+
Optional: true,
40+
Default: true,
41+
Description: "Generate a kubeconfig for the cluster. Set to false to avoid creating a new API token on each plan/apply. Default will change to false in a future version.",
42+
},
3443
"ca_cert": {
3544
Type: schema.TypeString,
3645
Computed: true,
@@ -209,5 +218,51 @@ func dataSourceRancher2ClusterRead(d *schema.ResourceData, meta interface{}) err
209218

210219
d.SetId(clusters.Data[0].ID)
211220

212-
return resourceRancher2ClusterRead(d, meta)
221+
return resource.Retry(d.Timeout(schema.TimeoutRead), func() *resource.RetryError {
222+
cluster := &Cluster{}
223+
err = client.APIBaseClient.ByID(managementClient.ClusterType, d.Id(), cluster)
224+
if err != nil {
225+
if IsNotFound(err) || IsForbidden(err) {
226+
log.Printf("[INFO] Cluster ID %s not found.", d.Id())
227+
d.SetId("")
228+
return nil
229+
}
230+
return resource.NonRetryableError(err)
231+
}
232+
233+
clusterRegistrationToken, err := findClusterRegistrationToken(client, cluster.ID)
234+
if err != nil && !IsForbidden(err) {
235+
return resource.NonRetryableError(err)
236+
}
237+
238+
defaultProjectID, systemProjectID, err := meta.(*Config).GetClusterSpecialProjectsID(cluster.ID)
239+
if err != nil && !IsForbidden(err) {
240+
return resource.NonRetryableError(err)
241+
}
242+
243+
var kubeConfig *managementClient.GenerateKubeConfigOutput
244+
generateKubeConfig := d.Get("generate_kube_config").(bool)
245+
if generateKubeConfig {
246+
log.Printf("[WARN] Generating kubeconfig for cluster %s creates a new API token. Set generate_kube_config = false if you don't need kube_config. The default will change to false in a future version.", cluster.ID)
247+
kubeConfig, err = getClusterKubeconfig(meta.(*Config), cluster.ID, d.Get("kube_config").(string))
248+
if err != nil && !IsForbidden(err) {
249+
return resource.NonRetryableError(err)
250+
}
251+
}
252+
if kubeConfig == nil {
253+
kubeConfig = &managementClient.GenerateKubeConfigOutput{}
254+
}
255+
256+
if err = flattenCluster(
257+
d,
258+
cluster,
259+
clusterRegistrationToken,
260+
kubeConfig,
261+
defaultProjectID,
262+
systemProjectID); err != nil {
263+
return resource.NonRetryableError(err)
264+
}
265+
266+
return nil
267+
})
213268
}

rancher2/data_source_rancher2_cluster_v2.go

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package rancher2
22

33
import (
4+
"log"
5+
46
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
57
)
68

@@ -75,6 +77,12 @@ func dataSourceRancher2ClusterV2() *schema.Resource {
7577
Computed: true,
7678
Sensitive: true,
7779
},
80+
"generate_kube_config": {
81+
Type: schema.TypeBool,
82+
Optional: true,
83+
Default: true,
84+
Description: "Generate a kubeconfig for the cluster. Set to false to avoid creating a new API token on each plan/apply. Default will change to false in a future version.",
85+
},
7886
"cluster_v1_id": {
7987
Type: schema.TypeString,
8088
Computed: true,
@@ -100,5 +108,25 @@ func dataSourceRancher2ClusterV2Read(d *schema.ResourceData, meta interface{}) e
100108
namespace := d.Get("fleet_namespace").(string)
101109
d.SetId(namespace + clusterV2ClusterIDsep + name)
102110

103-
return resourceRancher2ClusterV2Read(d, meta)
111+
log.Printf("[INFO] Refreshing Cluster V2 %s", d.Id())
112+
113+
cluster, err := getClusterV2ByID(meta.(*Config), d.Id())
114+
if err != nil {
115+
if IsNotFound(err) || IsForbidden(err) || IsNotAccessibleByID(err) {
116+
log.Printf("[INFO] Cluster V2 %s not found", d.Id())
117+
d.SetId("")
118+
return nil
119+
}
120+
return err
121+
}
122+
d.Set("cluster_v1_id", cluster.Status.ClusterName)
123+
generateKubeConfig := d.Get("generate_kube_config").(bool)
124+
if generateKubeConfig {
125+
log.Printf("[WARN] Generating kubeconfig for cluster %s creates a new API token. Set generate_kube_config = false if you don't need kube_config. The default will change to false in a future version.", d.Id())
126+
}
127+
err = setClusterV2LegacyData(d, meta.(*Config), generateKubeConfig)
128+
if err != nil {
129+
return err
130+
}
131+
return flattenClusterV2(d, cluster)
104132
}

rancher2/resource_rancher2_cluster_v2.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ func resourceRancher2ClusterV2Read(d *schema.ResourceData, meta interface{}) err
146146
return err
147147
}
148148
d.Set("cluster_v1_id", cluster.Status.ClusterName)
149-
err = setClusterV2LegacyData(d, meta.(*Config))
149+
err = setClusterV2LegacyData(d, meta.(*Config), true)
150150
if err != nil {
151151
return err
152152
}
@@ -376,7 +376,7 @@ func waitForClusterV2State(c *Config, id, state string, interval time.Duration)
376376
}
377377
}
378378

379-
func setClusterV2LegacyData(d *schema.ResourceData, c *Config) error {
379+
func setClusterV2LegacyData(d *schema.ResourceData, c *Config, generateKubeConfig bool) error {
380380
format := "Setting cluster V2 legacy data: %w"
381381

382382
if c == nil {
@@ -412,11 +412,13 @@ func setClusterV2LegacyData(d *schema.ResourceData, c *Config) error {
412412
return fmt.Errorf(format, err)
413413
}
414414

415-
kubeConfig, err := getClusterKubeconfig(c, cluster.ID, d.Get("kube_config").(string))
416-
if err != nil {
417-
return fmt.Errorf(format, err)
415+
if generateKubeConfig {
416+
kubeConfig, err := getClusterKubeconfig(c, cluster.ID, d.Get("kube_config").(string))
417+
if err != nil {
418+
return fmt.Errorf(format, err)
419+
}
420+
d.Set("kube_config", kubeConfig.Config)
418421
}
419-
d.Set("kube_config", kubeConfig.Config)
420422

421423
return nil
422424
}

0 commit comments

Comments
 (0)