diff --git a/cmd/kops/create_cluster.go b/cmd/kops/create_cluster.go index a1242f80b7..7d92ed489e 100644 --- a/cmd/kops/create_cluster.go +++ b/cmd/kops/create_cluster.go @@ -808,9 +808,23 @@ func RunCreateCluster(f *util.Factory, out io.Writer, c *CreateClusterOptions) e } } + // Populate project if c.Project != "" { cluster.Spec.Project = c.Project } + if api.CloudProviderID(cluster.Spec.CloudProvider) == api.CloudProviderGCE { + if cluster.Spec.Project == "" { + project, err := gce.DefaultProject() + if err != nil { + glog.Warningf("unable to get default google cloud project: %v", err) + } else if project == "" { + glog.Warningf("default google cloud project not set (try `gcloud config set project `") + } else { + glog.Infof("using google cloud project: %s", project) + } + cluster.Spec.Project = project + } + } if c.KubernetesVersion != "" { cluster.Spec.KubernetesVersion = c.KubernetesVersion diff --git a/upup/pkg/fi/cloudup/gce/gce_cloud.go b/upup/pkg/fi/cloudup/gce/gce_cloud.go index e59610b958..9dee2d25b8 100644 --- a/upup/pkg/fi/cloudup/gce/gce_cloud.go +++ b/upup/pkg/fi/cloudup/gce/gce_cloud.go @@ -17,11 +17,12 @@ limitations under the License. package gce import ( + "bytes" "fmt" "net/http" - "strings" - "os" + "os/exec" + "strings" "github.com/golang/glog" "golang.org/x/net/context" @@ -79,6 +80,37 @@ func (c *gceCloudImplementation) ProviderID() kops.CloudProviderID { var gceCloudInstances map[string]GCECloud = make(map[string]GCECloud) +// DefaultProject returns the current project configured in the gcloud SDK, ("", nil) if no project was set +func DefaultProject() (string, error) { + // The default project isn't usually defined by the google cloud APIs, + // for example the Application Default Credential won't have ProjectID set. + // If we're running on a GCP instance, we can get it from the metadata service, + // but the normal kops CLI usage is running locally with gcloud configuration with a project, + // so we use that value. + cmd := exec.Command("gcloud", "config", "get-value", "project") + + env := os.Environ() + cmd.Env = env + var stdout bytes.Buffer + cmd.Stdout = &stdout + + var stderr bytes.Buffer + cmd.Stderr = &stderr + + human := strings.Join(cmd.Args, " ") + glog.V(2).Infof("Running command: %s", human) + err := cmd.Run() + if err != nil { + glog.Infof("error running %s", human) + glog.Info(stdout.String()) + glog.Info(stderr.String()) + return "", fmt.Errorf("error running %s: %v", human, err) + } + + projectID := strings.TrimSpace(stdout.String()) + return projectID, err +} + func NewGCECloud(region string, project string, labels map[string]string) (GCECloud, error) { i := gceCloudInstances[region+"::"+project] if i != nil {