in internal/policygen/load.go [164:214]
func loadResourcesFromCloudStorageBucket(ctx context.Context, path string) ([]*states.Resource, error) {
// Trim the 'gs://' prefix and split the path into the bucket name and cloud storage file path.
bucketName := strings.SplitN(strings.TrimPrefix(path, "gs://"), "/", 2)[0]
log.Printf("Reading state files from Cloud Storage bucket %q", bucketName)
client, err := storage.NewClient(ctx, option.WithScopes(storage.ScopeReadOnly))
if err != nil {
return nil, fmt.Errorf("start cloud storage client: %v", err)
}
bucket := client.Bucket(bucketName)
// Stat the bucket, check existence and caller permission.
if _, err := bucket.Attrs(ctx); err != nil {
return nil, fmt.Errorf("read bucket: %v", err)
}
var names []string
it := bucket.Objects(ctx, &storage.Query{})
for {
attrs, err := it.Next()
if err == iterator.Done {
break
}
if err != nil {
return nil, err
}
name := attrs.Name
if filepath.Ext(name) != terraform.StateFileExtension {
continue
}
names = append(names, name)
}
var allResources []*states.Resource
for _, name := range names {
log.Printf("reading remote file: gs://%s/%s", bucketName, name)
obj := bucket.Object(name)
r, err := obj.NewReader(ctx)
if err != nil {
return nil, err
}
defer r.Close()
resources, err := terraform.ResourcesFromState(r)
if err != nil {
return nil, err
}
allResources = append(allResources, resources...)
}
return allResources, nil
}