gcloud/cloudresourcemanager.go (194 lines of code) (raw):

// Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package gcloud import ( "fmt" "os/exec" "sort" "strconv" "strings" "time" "google.golang.org/api/cloudresourcemanager/v1" ) func (c *Client) getCloudResourceManagerService() (*cloudresourcemanager.Service, error) { var err error svc := c.services.resourceManager if svc != nil { return svc, nil } svc, err = cloudresourcemanager.NewService(c.ctx, c.opts) if err != nil { return nil, fmt.Errorf("could not retrieve service: %w", err) } svc.UserAgent = c.userAgent c.services.resourceManager = svc return svc, nil } // ProjectNumberGet will get the project_number for the input projectid func (c *Client) ProjectNumberGet(id string) (string, error) { resp := "" svc, err := c.getCloudResourceManagerService() if err != nil { return resp, err } results, err := svc.Projects.Get(id).Do() if err != nil { return resp, err } resp = strconv.Itoa(int(results.ProjectNumber)) return resp, nil } // ProjectParentGet returns the parent of an input project func (c *Client) ProjectParentGet(id string) (*cloudresourcemanager.ResourceId, error) { svc, err := c.getCloudResourceManagerService() if err != nil { return nil, err } results, err := svc.Projects.Get(id).Do() if err != nil { return nil, err } return results.Parent, nil } // ProjectList gets a list of the ProjectList a user has access to func (c *Client) ProjectList() ([]ProjectWithBilling, error) { resp := []ProjectWithBilling{} i := c.get("ProjectList") switch val := i.(type) { case []ProjectWithBilling: return val, nil } svc, err := c.getCloudResourceManagerService() if err != nil { return resp, err } results, err := svc.Projects.List().Filter("lifecycleState=ACTIVE").Do() if err != nil { return resp, err } pwb, err := c.ProjectListWithBilling(results.Projects) if err != nil { return resp, err } sort.Slice(pwb, func(i, j int) bool { return strings.ToLower(pwb[i].Name) < strings.ToLower(pwb[j].Name) }) c.save("ProjectList", pwb) return pwb, nil } // ProjectWithBilling is a project with it's billing status type ProjectWithBilling struct { Name string ID string BillingEnabled bool } // ProjectCreate does the work of actually creating a new project in your // GCP account func (c *Client) ProjectCreate(project, parent, parentType string) error { svc, err := c.getCloudResourceManagerService() if err != nil { return err } par := &cloudresourcemanager.ResourceId{} if parent != "" && parentType != "" { par.Id = parent par.Type = parentType } proj := cloudresourcemanager.Project{ Name: project, ProjectId: project, Parent: par, } result, err := svc.Projects.Create(&proj).Do() if err != nil { if strings.Contains(err.Error(), "project_id must be at most 30 characters long") { return ErrorProjectCreateTooLong } if strings.Contains(err.Error(), "must be at least 6 characters long") { return ErrorProjectCreateTooShort } if strings.Contains(err.Error(), "project_id contains invalid characters") { return ErrorProjectInvalidCharacters } if strings.Contains(err.Error(), "entity already exists") { return ErrorProjectAlreadyExists } return err } for i := 0; i < 20; i++ { op, err := svc.Operations.Get(result.Name).Do() if err != nil { return fmt.Errorf("could not poll for project completion: %s", err) } if op.Done { if op.Error != nil { return fmt.Errorf("project creation was unsuccessful, reason: %s ", op.Error.Message) } return nil } time.Sleep(2 * time.Second) } return ErrorProjectCreateTooLong } // ProjectGet returns the details of a single project func (c *Client) ProjectGet(project string) (*cloudresourcemanager.Project, error) { svc, err := c.getCloudResourceManagerService() if err != nil { return nil, err } proj, err := svc.Projects.Get(project).Do() if err != nil { return nil, err } return proj, nil } // ProjectDelete does the work of actually deleting an existing project in // your GCP account func (c *Client) ProjectDelete(project string) error { svc, err := c.getCloudResourceManagerService() if err != nil { return err } _, err = svc.Projects.Delete(project).Do() if err != nil { return err } return nil } // ProjectGrantIAMRole grants a given principal a given role in a given project func (c *Client) ProjectGrantIAMRole(project, role, principal string) error { svc, err := c.getCloudResourceManagerService() if err != nil { return err } getReq := cloudresourcemanager.GetIamPolicyRequest{} policy, err := svc.Projects.GetIamPolicy(project, &getReq).Do() if err != nil { return fmt.Errorf("cannot get iam policy for project (%s): %s", project, err) } b := cloudresourcemanager.Binding{} b.Role = role b.Members = append(b.Members, principal) policy.Bindings = append(policy.Bindings, &b) setReq := cloudresourcemanager.SetIamPolicyRequest{} setReq.Policy = policy if _, err = svc.Projects.SetIamPolicy(project, &setReq).Do(); err != nil { return fmt.Errorf("cannot set iam policy role (%s) for project (%s): %s", role, project, err) } return nil } // ProjectIDGet gets the currently set default project func (c Client) ProjectIDGet() (string, error) { cmd := exec.Command("gcloud", "config", "get-value", "project") out, err := cmd.Output() if err != nil { return "", fmt.Errorf("cannot get project id: %s ", err) } return strings.TrimSpace(string(out)), nil } // ProjectIDSet sets the currently set default project func (c *Client) ProjectIDSet(project string) error { cmd := exec.Command("gcloud", "config", "set", "project", project) _, err := cmd.Output() if err != nil { return fmt.Errorf("cannot set project id: %s ", err) } return nil } // ProjectExists confirms that a project actually exists func (c *Client) ProjectExists(project string) bool { svc, err := c.getCloudResourceManagerService() if err != nil { return false } _, err = svc.Projects.Get(project).Do() if err != nil { return false } return true }