cmd/cloudshell_open/project.go (74 lines of code) (raw):
// Copyright 2019 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
//
// https://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 main
import (
"context"
"errors"
"fmt"
"sort"
"github.com/AlecAivazis/survey/v2"
"github.com/fatih/color"
"google.golang.org/api/cloudresourcemanager/v1"
)
var (
surveyIconOpts = survey.WithIcons(func(icons *survey.IconSet) {
icons.Question = survey.Icon{Text: questionPrefix}
icons.Error = survey.Icon{Text: errorPrefix}
icons.SelectFocus = survey.Icon{Text: questionSelectFocusIcon}
icons.HelpInput = survey.Icon{Text: "Arrows to navigate"}
})
)
func listProjects() ([]string, error) {
client, err := cloudresourcemanager.NewService(context.TODO())
if err != nil {
return nil, fmt.Errorf("failed to initialize cloudresourcemanager client: %w", err)
}
var out []string
if err := client.Projects.List().PageSize(1000).Pages(context.TODO(), func(resp *cloudresourcemanager.ListProjectsResponse) error {
for _, p := range resp.Projects {
if p.LifecycleState == "ACTIVE" {
out = append(out, p.ProjectId)
}
}
return nil
}); err != nil {
return nil, fmt.Errorf("failed to list GCP projects: %w", err)
}
sort.Strings(out)
return out, nil
}
func promptProject(projects []string) (string, error) {
if len(projects) == 0 {
return "", errors.New("cannot prompt with an empty list of projects")
} else if len(projects) == 1 {
ok, err := confirmProject(projects[0])
if err != nil {
return "", err
} else if !ok {
return "", fmt.Errorf("not allowed to use project %s", projects[0])
}
return projects[0], nil
}
return promptMultipleProjects(projects)
}
func confirmProject(project string) (bool, error) {
var ok bool
projectLabel := color.New(color.Bold, color.FgHiCyan).Sprint(project)
if err := survey.AskOne(&survey.Confirm{
Default: true,
Message: fmt.Sprintf("Would you like to use existing GCP project %v to deploy this app?", projectLabel),
}, &ok, surveyIconOpts); err != nil {
return false, fmt.Errorf("could not prompt for confirmation using project %s: %+v", project, err)
}
return ok, nil
}
func promptMultipleProjects(projects []string) (string, error) {
var p string
if err := survey.AskOne(&survey.Select{
Message: "Choose a project or press ctrl-c to create a new project:",
Options: projects,
}, &p,
surveyIconOpts,
); err != nil {
return p, fmt.Errorf("could not choose a project: %+v", err)
}
return p, nil
}