1717package container
1818
1919import (
20+ "context"
2021 "fmt"
2122 "log"
2223 "regexp"
@@ -33,6 +34,7 @@ import (
3334 "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource"
3435 transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport"
3536
37+ compute "google.golang.org/api/compute/v0.beta"
3638 container "google.golang.org/api/container/v1beta1"
3739)
3840
@@ -60,13 +62,13 @@ func (nodePoolCache *nodePoolCache) get(nodePool string) (*container.NodePool, e
6062}
6163
6264func (nodePoolCache * nodePoolCache ) refreshIfNeeded (d * schema.ResourceData , config * transport_tpg.Config , userAgent string , nodePoolInfo * NodePoolInformation , name string ) error {
65+ nodePoolCache .mutex .Lock ()
66+ defer nodePoolCache .mutex .Unlock ()
67+
6368 if ! nodePoolCache .needsRefresh (nodePoolInfo .fullyQualifiedName (name )) {
6469 return nil
6570 }
6671
67- nodePoolCache .mutex .Lock ()
68- defer nodePoolCache .mutex .Unlock ()
69-
7072 parent := fmt .Sprintf ("projects/%s/locations/%s/clusters/%s" , nodePoolInfo .project , nodePoolInfo .location , nodePoolInfo .cluster )
7173 clusterNodePoolsListCall := config .NewContainerClient (userAgent ).Projects .Locations .Clusters .NodePools .List (parent )
7274 if config .UserProjectOverride {
@@ -88,8 +90,6 @@ func (nodePoolCache *nodePoolCache) refreshIfNeeded(d *schema.ResourceData, conf
8890}
8991
9092func (nodePoolCache * nodePoolCache ) needsRefresh (nodePool string ) bool {
91- nodePoolCache .mutex .RLock ()
92- defer nodePoolCache .mutex .RUnlock ()
9393 np , ok := nodePoolCache .nodePools [nodePool ]
9494 if ! ok {
9595 return true
@@ -103,11 +103,80 @@ func (nodePoolCache *nodePoolCache) remove(nodePool string) {
103103 delete (nodePoolCache .nodePools , nodePool )
104104}
105105
106- var npCache = & nodePoolCache {
107- nodePools : make (map [string ]* nodePoolWithUpdateTime ),
108- ttl : 30 * time .Second ,
106+ type instanceGroupManagerWithUpdateTime struct {
107+ instanceGroupManager * compute.InstanceGroupManager
108+ updateTime time.Time
109+ }
110+
111+ type instanceGroupManagerCache struct {
112+ instanceGroupManagers map [string ]* instanceGroupManagerWithUpdateTime
113+ ttl time.Duration
114+ mutex sync.RWMutex
109115}
110116
117+ func (instanceGroupManagerCache * instanceGroupManagerCache ) get (fullyQualifiedName string ) (* compute.InstanceGroupManager , bool ) {
118+ instanceGroupManagerCache .mutex .RLock ()
119+ defer instanceGroupManagerCache .mutex .RUnlock ()
120+ igm , ok := instanceGroupManagerCache .instanceGroupManagers [fullyQualifiedName ]
121+ if ! ok {
122+ return nil , false
123+ }
124+ return igm .instanceGroupManager , true
125+ }
126+
127+ func (instanceGroupManagerCache * instanceGroupManagerCache ) refreshIfNeeded (d * schema.ResourceData , config * transport_tpg.Config , userAgent string , npName string , igmUrl string ) error {
128+ instanceGroupManagerCache .mutex .Lock ()
129+ defer instanceGroupManagerCache .mutex .Unlock ()
130+
131+ matches := instanceGroupManagerURL .FindStringSubmatch (igmUrl )
132+ if len (matches ) < 4 {
133+ return fmt .Errorf ("Error reading instance group manager URL %q" , igmUrl )
134+ }
135+
136+ if ! instanceGroupManagerCache .needsRefresh (matches [0 ]) {
137+ return nil
138+ }
139+
140+ updateTime := time .Now ()
141+ err := config .NewComputeClient (userAgent ).InstanceGroupManagers .List (matches [1 ], matches [2 ]).Pages (context .Background (), instanceGroupManagerCache .processList (updateTime ))
142+ if err != nil {
143+ return transport_tpg .HandleNotFoundError (err , d , fmt .Sprintf ("InstanceGroupManagers for node pool %q" , npName ))
144+ }
145+ return nil
146+ }
147+
148+ func (instanceGroupManagerCache * instanceGroupManagerCache ) processList (updateTime time.Time ) func (* compute.InstanceGroupManagerList ) error {
149+ return func (igmList * compute.InstanceGroupManagerList ) error {
150+ for _ , instanceGroupManager := range igmList .Items {
151+ fullyQualifiedName := instanceGroupManagerURL .FindString (instanceGroupManager .SelfLink )
152+ instanceGroupManagerCache .instanceGroupManagers [fullyQualifiedName ] = & instanceGroupManagerWithUpdateTime {
153+ instanceGroupManager : instanceGroupManager ,
154+ updateTime : updateTime ,
155+ }
156+ }
157+ return nil
158+ }
159+ }
160+
161+ func (instanceGroupManagerCache * instanceGroupManagerCache ) needsRefresh (fullyQualifiedName string ) bool {
162+ igm , ok := instanceGroupManagerCache .instanceGroupManagers [fullyQualifiedName ]
163+ if ! ok {
164+ return true
165+ }
166+ return time .Since (igm .updateTime ) > instanceGroupManagerCache .ttl
167+ }
168+
169+ var (
170+ npCache = & nodePoolCache {
171+ nodePools : make (map [string ]* nodePoolWithUpdateTime ),
172+ ttl : 30 * time .Second ,
173+ }
174+ igmCache = & instanceGroupManagerCache {
175+ instanceGroupManagers : make (map [string ]* instanceGroupManagerWithUpdateTime ),
176+ ttl : 30 * time .Second ,
177+ }
178+ )
179+
111180func ResourceContainerNodePool () * schema.Resource {
112181 return & schema.Resource {
113182 Create : resourceContainerNodePoolCreate ,
@@ -790,7 +859,9 @@ func resourceContainerNodePoolRead(d *schema.ResourceData, meta interface{}) err
790859
791860 name := getNodePoolName (d .Id ())
792861
793- npCache .refreshIfNeeded (d , config , userAgent , nodePoolInfo , name )
862+ if err := npCache .refreshIfNeeded (d , config , userAgent , nodePoolInfo , name ); err != nil {
863+ return err
864+ }
794865 nodePool , err := npCache .get (nodePoolInfo .fullyQualifiedName (name ))
795866 if err != nil {
796867 log .Printf ("[WARN] Removing %s because it's gone" , fmt .Sprintf ("NodePool %q from cluster %q" , name , nodePoolInfo .cluster ))
@@ -953,7 +1024,9 @@ func resourceContainerNodePoolExists(d *schema.ResourceData, meta interface{}) (
9531024 }
9541025
9551026 name := getNodePoolName (d .Id ())
956- npCache .refreshIfNeeded (d , config , userAgent , nodePoolInfo , name )
1027+ if err := npCache .refreshIfNeeded (d , config , userAgent , nodePoolInfo , name ); err != nil {
1028+ return false , err
1029+ }
9571030 _ , err = npCache .get (nodePoolInfo .fullyQualifiedName (name ))
9581031 if err != nil {
9591032 log .Printf ("[WARN] Removing %s because it's gone" , fmt .Sprintf ("NodePool %q from cluster %q" , name , nodePoolInfo .cluster ))
@@ -1215,13 +1288,17 @@ func flattenNodePool(d *schema.ResourceData, config *transport_tpg.Config, np *c
12151288 if len (matches ) < 4 {
12161289 return nil , fmt .Errorf ("Error reading instance group manage URL '%q'" , url )
12171290 }
1218- igm , err := config .NewComputeClient (userAgent ).InstanceGroupManagers .Get (matches [1 ], matches [2 ], matches [3 ]).Do ()
1219- if transport_tpg .IsGoogleApiErrorWithCode (err , 404 ) {
1220- // The IGM URL in is stale; don't include it
1291+ if strings .HasPrefix ("gk3" , matches [3 ]) {
1292+ // IGM is autopilot so we know it will not be found, skip it
12211293 continue
12221294 }
1223- if err != nil {
1224- return nil , fmt .Errorf ("Error reading instance group manager returned as an instance group URL: %q" , err )
1295+ if err := igmCache .refreshIfNeeded (d , config , userAgent , np .Name , url ); err != nil {
1296+ return nil , err
1297+ }
1298+ igm , ok := igmCache .get (matches [0 ])
1299+ if ! ok {
1300+ // The IGM URL is stale; don't include it
1301+ continue
12251302 }
12261303 size += int (igm .TargetSize )
12271304 igmUrls = append (igmUrls , url )
0 commit comments