// Copyright 2014 Google Inc. All Rights Reserved. // // 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 container contains a Google Container Engine client. // // For more information about the API, // see https://cloud.google.com/container-engine/docs package container // import "google.golang.org/cloud/container" import ( "errors" "net/http" "time" "golang.org/x/net/context" raw "google.golang.org/api/container/v1" "google.golang.org/cloud/internal" ) type Type string var ( TypeCreate Type = Type("createCluster") TypeDelete Type = Type("deleteCluster") ) type Status string var ( Done = Status("done") Pending = Status("pending") Running = Status("running") Error = Status("error") Provisioning = Status("provisioning") Stopping = Status("stopping") ) // Resource is a Google Container Engine cluster resource. type Resource struct { // Name is the name of this cluster. The name must be unique // within this project and zone, and can be up to 40 characters. Name string // Description is the description of the cluster. Optional. Description string // Zone is the Google Compute Engine zone in which the cluster resides. Zone string // Status is the current status of the cluster. It could either be // StatusError, StatusProvisioning, StatusRunning or StatusStopping. Status Status // Num is the number of the nodes in this cluster resource. Num int64 // APIVersion is the version of the Kubernetes master and kubelets running // in this cluster. Allowed value is 0.4.2, or leave blank to // pick up the latest stable release. APIVersion string // Endpoint is the IP address of this cluster's Kubernetes master. // The endpoint can be accessed at https://username:password@endpoint/. // See Username and Password fields for the username and password information. Endpoint string // Username is the username to use when accessing the Kubernetes master endpoint. Username string // Password is the password to use when accessing the Kubernetes master endpoint. Password string // ContainerIPv4CIDR is the IP addresses of the container pods in // this cluster, in CIDR notation (e.g. 1.2.3.4/29). ContainerIPv4CIDR string // ServicesIPv4CIDR is the IP addresses of the Kubernetes services in this // cluster, in CIDR notation (e.g. 1.2.3.4/29). Service addresses are // always in the 10.0.0.0/16 range. ServicesIPv4CIDR string // MachineType is a Google Compute Engine machine type (e.g. n1-standard-1). // If none set, the default type is used while creating a new cluster. MachineType string // This field is ignored. It was removed from the underlying container API in v1. SourceImage string // Created is the creation time of this cluster. Created time.Time } func resourceFromRaw(c *raw.Cluster) *Resource { if c == nil { return nil } r := &Resource{ Name: c.Name, Description: c.Description, Zone: c.Zone, Status: Status(c.Status), Num: c.InitialNodeCount, APIVersion: c.InitialClusterVersion, Endpoint: c.Endpoint, Username: c.MasterAuth.Username, Password: c.MasterAuth.Password, ContainerIPv4CIDR: c.ClusterIpv4Cidr, ServicesIPv4CIDR: c.ServicesIpv4Cidr, MachineType: c.NodeConfig.MachineType, } r.Created, _ = time.Parse(time.RFC3339, c.CreateTime) return r } func resourcesFromRaw(c []*raw.Cluster) []*Resource { r := make([]*Resource, len(c)) for i, val := range c { r[i] = resourceFromRaw(val) } return r } // Op represents a Google Container Engine API operation. type Op struct { // Name is the name of the operation. Name string // Zone is the Google Compute Engine zone. Zone string // This field is ignored. It was removed from the underlying container API in v1. TargetURL string // Type is the operation type. It could be either be TypeCreate or TypeDelete. Type Type // Status is the current status of this operation. It could be either // OpDone or OpPending. Status Status } func opFromRaw(o *raw.Operation) *Op { if o == nil { return nil } return &Op{ Name: o.Name, Zone: o.Zone, Type: Type(o.OperationType), Status: Status(o.Status), } } func opsFromRaw(o []*raw.Operation) []*Op { ops := make([]*Op, len(o)) for i, val := range o { ops[i] = opFromRaw(val) } return ops } // Clusters returns a list of cluster resources from the specified zone. // If no zone is specified, it returns all clusters under the user project. func Clusters(ctx context.Context, zone string) ([]*Resource, error) { s := rawService(ctx) if zone == "" { resp, err := s.Projects.Zones.Clusters.List(internal.ProjID(ctx), "-").Do() if err != nil { return nil, err } return resourcesFromRaw(resp.Clusters), nil } resp, err := s.Projects.Zones.Clusters.List(internal.ProjID(ctx), zone).Do() if err != nil { return nil, err } return resourcesFromRaw(resp.Clusters), nil } // Cluster returns metadata about the specified cluster. func Cluster(ctx context.Context, zone, name string) (*Resource, error) { s := rawService(ctx) resp, err := s.Projects.Zones.Clusters.Get(internal.ProjID(ctx), zone, name).Do() if err != nil { return nil, err } return resourceFromRaw(resp), nil } // CreateCluster creates a new cluster with the provided metadata // in the specified zone. func CreateCluster(ctx context.Context, zone string, resource *Resource) (*Resource, error) { panic("not implemented") } // DeleteCluster deletes a cluster. func DeleteCluster(ctx context.Context, zone, name string) error { s := rawService(ctx) _, err := s.Projects.Zones.Clusters.Delete(internal.ProjID(ctx), zone, name).Do() return err } // Operations returns a list of operations from the specified zone. // If no zone is specified, it looks up for all of the operations // that are running under the user's project. func Operations(ctx context.Context, zone string) ([]*Op, error) { s := rawService(ctx) if zone == "" { resp, err := s.Projects.Zones.Operations.List(internal.ProjID(ctx), "-").Do() if err != nil { return nil, err } return opsFromRaw(resp.Operations), nil } resp, err := s.Projects.Zones.Operations.List(internal.ProjID(ctx), zone).Do() if err != nil { return nil, err } return opsFromRaw(resp.Operations), nil } // Operation returns an operation. func Operation(ctx context.Context, zone, name string) (*Op, error) { s := rawService(ctx) resp, err := s.Projects.Zones.Operations.Get(internal.ProjID(ctx), zone, name).Do() if err != nil { return nil, err } if resp.StatusMessage != "" { return nil, errors.New(resp.StatusMessage) } return opFromRaw(resp), nil } func rawService(ctx context.Context) *raw.Service { return internal.Service(ctx, "container", func(hc *http.Client) interface{} { svc, _ := raw.New(hc) return svc }).(*raw.Service) }