diff --git a/pkg/backends/backends.go b/pkg/backends/backends.go index 86126dd8e3..603971c02f 100644 --- a/pkg/backends/backends.go +++ b/pkg/backends/backends.go @@ -74,7 +74,7 @@ func (b *Backends) Create(sp utils.ServicePort, hcLink string) (*composite.Backe HealthChecks: []string{hcLink}, } ensureDescription(be, &sp) - if err := composite.CreateBackendService(be, b.cloud, meta.GlobalKey(be.Name)); err != nil { + if err := composite.CreateBackendService(b.cloud, meta.GlobalKey(be.Name), be); err != nil { return nil, err } // Note: We need to perform a GCE call to re-fetch the object we just created @@ -87,7 +87,7 @@ func (b *Backends) Create(sp utils.ServicePort, hcLink string) (*composite.Backe func (b *Backends) Update(be *composite.BackendService) error { // Ensure the backend service has the proper version before updating. be.Version = features.VersionFromDescription(be.Description) - if err := composite.UpdateBackendService(be, b.cloud, meta.GlobalKey(be.Name)); err != nil { + if err := composite.UpdateBackendService(b.cloud, meta.GlobalKey(be.Name), be); err != nil { return err } return nil @@ -95,7 +95,7 @@ func (b *Backends) Update(be *composite.BackendService) error { // Get implements Pool. func (b *Backends) Get(name string, version meta.Version) (*composite.BackendService, error) { - be, err := composite.GetBackendService(version, b.cloud, meta.GlobalKey(name)) + be, err := composite.GetBackendService(b.cloud, meta.GlobalKey(name), version) if err != nil { return nil, err } @@ -104,7 +104,7 @@ func (b *Backends) Get(name string, version meta.Version) (*composite.BackendSer // the existing backend service. versionRequired := features.VersionFromDescription(be.Description) if features.IsLowerVersion(versionRequired, version) { - be, err = composite.GetBackendService(versionRequired, b.cloud, meta.GlobalKey(name)) + be, err = composite.GetBackendService(b.cloud, meta.GlobalKey(name), versionRequired) if err != nil { return nil, err } diff --git a/pkg/composite/composite.go b/pkg/composite/composite.go index 951a752b93..99a57ad6f3 100644 --- a/pkg/composite/composite.go +++ b/pkg/composite/composite.go @@ -21,7 +21,8 @@ package composite import ( "fmt" - gcecloud "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" + cloudprovider "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/filter" "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta" computealpha "google.golang.org/api/compute/v0.alpha" computebeta "google.golang.org/api/compute/v0.beta" @@ -2014,6 +2015,95 @@ type ServiceAccountJwtAccessCredentials struct { NullFields []string `json:"-"` } +// SslCertificate is a composite type wrapping the Alpha, Beta, and GA methods for its GCE equivalent +type SslCertificate struct { + // Version keeps track of the intended compute version for this SslCertificate. + // Note that the compute API's do not contain this field. It is for our + // own bookkeeping purposes. + Version meta.Version `json:"-"` + // ResourceType keeps track of the intended type of the service (e.g. Global) + // This is also an internal field purely for bookkeeping purposes + ResourceType meta.KeyType `json:"-"` + + // A local certificate file. The certificate must be in PEM format. The + // certificate chain must be no greater than 5 certs long. The chain + // must include at least one intermediate cert. + Certificate string `json:"certificate,omitempty"` + // [Output Only] Creation timestamp in RFC3339 text format. + CreationTimestamp string `json:"creationTimestamp,omitempty"` + // An optional description of this resource. Provide this property when + // you create the resource. + Description string `json:"description,omitempty"` + // [Output Only] Expire time of the certificate. RFC3339 + ExpireTime string `json:"expireTime,omitempty"` + // [Output Only] The unique identifier for the resource. This identifier + // is defined by the server. + Id uint64 `json:"id,omitempty,string"` + // [Output Only] Type of the resource. Always compute#sslCertificate for + // SSL certificates. + Kind string `json:"kind,omitempty"` + // Configuration and status of a managed SSL certificate. + Managed *SslCertificateManagedSslCertificate `json:"managed,omitempty"` + // Name of the resource. Provided by the client when the resource is + // created. The name must be 1-63 characters long, and comply with + // RFC1035. Specifically, the name must be 1-63 characters long and + // match the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` which means + // the first character must be a lowercase letter, and all following + // characters must be a dash, lowercase letter, or digit, except the + // last character, which cannot be a dash. + Name string `json:"name,omitempty"` + // A write-only private key in PEM format. Only insert requests will + // include this field. + PrivateKey string `json:"privateKey,omitempty"` + // [Output Only] URL of the region where the regional SSL Certificate + // resides. This field is not applicable to global SSL Certificate. + Region string `json:"region,omitempty"` + // [Output only] Server-defined URL for the resource. + SelfLink string `json:"selfLink,omitempty"` + // [Output Only] Server-defined URL for this resource with the resource + // id. + SelfLinkWithId string `json:"selfLinkWithId,omitempty"` + // Configuration and status of a self-managed SSL certificate. + SelfManaged *SslCertificateSelfManagedSslCertificate `json:"selfManaged,omitempty"` + // [Output Only] Domains associated with the certificate via Subject + // Alternative Name. + SubjectAlternativeNames []string `json:"subjectAlternativeNames,omitempty"` + // (Optional) Specifies the type of SSL certificate, either + // "SELF_MANAGED" or "MANAGED". If not specified, the certificate is + // self-managed and the fields certificate and private_key are used. + Type string `json:"type,omitempty"` + googleapi.ServerResponse `json:"-"` + ForceSendFields []string `json:"-"` + NullFields []string `json:"-"` +} + +// SslCertificateManagedSslCertificate is a composite type wrapping the Alpha, Beta, and GA methods for its GCE equivalent +type SslCertificateManagedSslCertificate struct { + // [Output only] Detailed statuses of the domains specified for managed + // certificate resource. + DomainStatus map[string]string `json:"domainStatus,omitempty"` + // The domains for which a managed SSL certificate will be generated. + // Currently only single-domain certs are supported. + Domains []string `json:"domains,omitempty"` + // [Output only] Status of the managed certificate resource. + Status string `json:"status,omitempty"` + ForceSendFields []string `json:"-"` + NullFields []string `json:"-"` +} + +// SslCertificateSelfManagedSslCertificate is a composite type wrapping the Alpha, Beta, and GA methods for its GCE equivalent +type SslCertificateSelfManagedSslCertificate struct { + // A local certificate file. The certificate must be in PEM format. The + // certificate chain must be no greater than 5 certs long. The chain + // must include at least one intermediate cert. + Certificate string `json:"certificate,omitempty"` + // A write-only private key in PEM format. Only insert requests will + // include this field. + PrivateKey string `json:"privateKey,omitempty"` + ForceSendFields []string `json:"-"` + NullFields []string `json:"-"` +} + // TCPHealthCheck is a composite type wrapping the Alpha, Beta, and GA methods for its GCE equivalent type TCPHealthCheck struct { // The TCP port number for the health check request. The default value @@ -2397,8 +2487,8 @@ type WeightedBackendService struct { NullFields []string `json:"-"` } -func CreateBackendService(backendService *BackendService, cloud *gce.Cloud, key *meta.Key) error { - ctx, cancel := gcecloud.ContextWithCallTimeout() +func CreateBackendService(gceCloud *gce.Cloud, key *meta.Key, backendService *BackendService) error { + ctx, cancel := cloudprovider.ContextWithCallTimeout() defer cancel() mc := compositemetrics.NewMetricContext("BackendService", "create", key.Region, key.Zone, string(backendService.Version)) @@ -2408,12 +2498,14 @@ func CreateBackendService(backendService *BackendService, cloud *gce.Cloud, key if err != nil { return err } - klog.V(3).Infof("Creating alpha BackendService %v", alpha.Name) switch key.Type() { case meta.Regional: - return mc.Observe(cloud.Compute().AlphaRegionBackendServices().Insert(ctx, key, alpha)) + klog.V(3).Infof("Creating alpha region BackendService %v", alpha.Name) + alpha.Region = key.Region + return mc.Observe(gceCloud.Compute().AlphaRegionBackendServices().Insert(ctx, key, alpha)) default: - return mc.Observe(cloud.Compute().AlphaBackendServices().Insert(ctx, key, alpha)) + klog.V(3).Infof("Creating alpha BackendService %v", alpha.Name) + return mc.Observe(gceCloud.Compute().AlphaBackendServices().Insert(ctx, key, alpha)) } case meta.VersionBeta: beta, err := backendService.ToBeta() @@ -2421,34 +2513,34 @@ func CreateBackendService(backendService *BackendService, cloud *gce.Cloud, key return err } klog.V(3).Infof("Creating beta BackendService %v", beta.Name) - return mc.Observe(cloud.Compute().BetaBackendServices().Insert(ctx, key, beta)) + return mc.Observe(gceCloud.Compute().BetaBackendServices().Insert(ctx, key, beta)) default: ga, err := backendService.ToGA() if err != nil { return err } klog.V(3).Infof("Creating ga BackendService %v", ga.Name) - return mc.Observe(cloud.Compute().BackendServices().Insert(ctx, key, ga)) + return mc.Observe(gceCloud.Compute().BackendServices().Insert(ctx, key, ga)) } } -func UpdateBackendService(backendService *BackendService, cloud *gce.Cloud, key *meta.Key) error { - ctx, cancel := gcecloud.ContextWithCallTimeout() +func UpdateBackendService(gceCloud *gce.Cloud, key *meta.Key, backendService *BackendService) error { + ctx, cancel := cloudprovider.ContextWithCallTimeout() defer cancel() mc := compositemetrics.NewMetricContext("BackendService", "update", key.Region, key.Zone, string(backendService.Version)) - switch backendService.Version { case meta.VersionAlpha: alpha, err := backendService.ToAlpha() if err != nil { return err } - klog.V(3).Infof("Updating alpha BackendService %v", alpha.Name) switch key.Type() { case meta.Regional: - return mc.Observe(cloud.Compute().AlphaRegionBackendServices().Update(ctx, key, alpha)) + klog.V(3).Infof("Updating alpha region BackendService %v", alpha.Name) + return mc.Observe(gceCloud.Compute().AlphaRegionBackendServices().Update(ctx, key, alpha)) default: - return mc.Observe(cloud.Compute().AlphaBackendServices().Update(ctx, key, alpha)) + klog.V(3).Infof("Updating alpha BackendService %v", alpha.Name) + return mc.Observe(gceCloud.Compute().AlphaBackendServices().Update(ctx, key, alpha)) } case meta.VersionBeta: beta, err := backendService.ToBeta() @@ -2456,19 +2548,43 @@ func UpdateBackendService(backendService *BackendService, cloud *gce.Cloud, key return err } klog.V(3).Infof("Updating beta BackendService %v", beta.Name) - return mc.Observe(cloud.Compute().BetaBackendServices().Update(ctx, key, beta)) + return mc.Observe(gceCloud.Compute().BetaBackendServices().Update(ctx, key, beta)) default: ga, err := backendService.ToGA() if err != nil { return err } klog.V(3).Infof("Updating ga BackendService %v", ga.Name) - return mc.Observe(cloud.Compute().BackendServices().Update(ctx, key, ga)) + return mc.Observe(gceCloud.Compute().BackendServices().Update(ctx, key, ga)) + } +} + +func DeleteBackendService(gceCloud *gce.Cloud, key *meta.Key, version meta.Version) error { + ctx, cancel := cloudprovider.ContextWithCallTimeout() + defer cancel() + mc := compositemetrics.NewMetricContext("BackendService", "delete", key.Region, key.Zone, string(version)) + + switch version { + case meta.VersionAlpha: + switch key.Type() { + case meta.Regional: + klog.V(3).Infof("Deleting alpha region BackendService %v", key.Name) + return mc.Observe(gceCloud.Compute().AlphaRegionBackendServices().Delete(ctx, key)) + default: + klog.V(3).Infof("Deleting alpha BackendService %v", key.Name) + return mc.Observe(gceCloud.Compute().AlphaBackendServices().Delete(ctx, key)) + } + case meta.VersionBeta: + klog.V(3).Infof("Deleting beta BackendService %v", key.Name) + return mc.Observe(gceCloud.Compute().BetaBackendServices().Delete(ctx, key)) + default: + klog.V(3).Infof("Deleting ga BackendService %v", key.Name) + return mc.Observe(gceCloud.Compute().BackendServices().Delete(ctx, key)) } } -func GetBackendService(version meta.Version, cloud *gce.Cloud, key *meta.Key) (*BackendService, error) { - ctx, cancel := gcecloud.ContextWithCallTimeout() +func GetBackendService(gceCloud *gce.Cloud, key *meta.Key, version meta.Version) (*BackendService, error) { + ctx, cancel := cloudprovider.ContextWithCallTimeout() defer cancel() mc := compositemetrics.NewMetricContext("BackendService", "get", key.Region, key.Zone, string(version)) @@ -2478,19 +2594,79 @@ func GetBackendService(version meta.Version, cloud *gce.Cloud, key *meta.Key) (* case meta.VersionAlpha: switch key.Type() { case meta.Regional: - gceObj, err = cloud.Compute().AlphaRegionBackendServices().Get(ctx, key) + klog.V(3).Infof("Getting alpha region BackendService %v", key.Name) + gceObj, err = gceCloud.Compute().AlphaRegionBackendServices().Get(ctx, key) default: - gceObj, err = cloud.Compute().AlphaBackendServices().Get(ctx, key) + klog.V(3).Infof("Getting alpha BackendService %v", key.Name) + gceObj, err = gceCloud.Compute().AlphaBackendServices().Get(ctx, key) } case meta.VersionBeta: - gceObj, err = cloud.Compute().BetaBackendServices().Get(ctx, key) + klog.V(3).Infof("Getting beta BackendService %v", key.Name) + gceObj, err = gceCloud.Compute().BetaBackendServices().Get(ctx, key) default: - gceObj, err = cloud.Compute().BackendServices().Get(ctx, key) + klog.V(3).Infof("Getting ga BackendService %v", key.Name) + gceObj, err = gceCloud.Compute().BackendServices().Get(ctx, key) } if err != nil { return nil, mc.Observe(err) } - return ToBackendService(gceObj) + compositeType, err := ToBackendService(gceObj) + if err != nil { + return nil, err + } + + compositeType.Version = version + return compositeType, nil +} + +func ListBackendServices(gceCloud *gce.Cloud, key *meta.Key, version meta.Version) ([]*BackendService, error) { + ctx, cancel := cloudprovider.ContextWithCallTimeout() + defer cancel() + mc := compositemetrics.NewMetricContext("BackendService", "get", key.Region, key.Zone, string(version)) + + var gceObjs interface{} + var err error + switch version { + case meta.VersionAlpha: + switch key.Type() { + case meta.Regional: + klog.V(3).Infof("Listing alpha region BackendService") + gceObjs, err = gceCloud.Compute().AlphaRegionBackendServices().List(ctx, key.Region, filter.None) + default: + klog.V(3).Infof("Listing alpha BackendService") + gceObjs, err = gceCloud.Compute().AlphaBackendServices().List(ctx, filter.None) + } + case meta.VersionBeta: + klog.V(3).Infof("Listing beta BackendService") + gceObjs, err = gceCloud.Compute().BetaBackendServices().List(ctx, filter.None) + default: + klog.V(3).Infof("Listing ga BackendService") + gceObjs, err = gceCloud.Compute().BackendServices().List(ctx, filter.None) + } + if err != nil { + return nil, mc.Observe(err) + } + + compositeObjs, err := ToBackendServiceList(gceObjs) + if err != nil { + return nil, err + } + for _, obj := range compositeObjs { + obj.Version = version + } + return compositeObjs, nil +} + +// ToBackendServiceList converts a list of compute alpha, beta or GA +// BackendService into a list of our composite type. +func ToBackendServiceList(objs interface{}) ([]*BackendService, error) { + result := []*BackendService{} + + err := copyViaJSON(&result, objs) + if err != nil { + return nil, fmt.Errorf("could not copy object %v to list of BackendService via JSON: %v", objs, err) + } + return result, nil } // ToBackendService converts a compute alpha, beta or GA @@ -2562,8 +2738,8 @@ func (backendService *BackendService) ToGA() (*compute.BackendService, error) { return ga, nil } -func CreateForwardingRule(forwardingRule *ForwardingRule, cloud *gce.Cloud, key *meta.Key) error { - ctx, cancel := gcecloud.ContextWithCallTimeout() +func CreateForwardingRule(gceCloud *gce.Cloud, key *meta.Key, forwardingRule *ForwardingRule) error { + ctx, cancel := cloudprovider.ContextWithCallTimeout() defer cancel() mc := compositemetrics.NewMetricContext("ForwardingRule", "create", key.Region, key.Zone, string(forwardingRule.Version)) @@ -2573,42 +2749,46 @@ func CreateForwardingRule(forwardingRule *ForwardingRule, cloud *gce.Cloud, key if err != nil { return err } - klog.V(3).Infof("Creating alpha ForwardingRule %v", alpha.Name) switch key.Type() { case meta.Regional: - return mc.Observe(cloud.Compute().AlphaForwardingRules().Insert(ctx, key, alpha)) + klog.V(3).Infof("Creating alpha region ForwardingRule %v", alpha.Name) + alpha.Region = key.Region + return mc.Observe(gceCloud.Compute().AlphaForwardingRules().Insert(ctx, key, alpha)) default: - return mc.Observe(cloud.Compute().AlphaGlobalForwardingRules().Insert(ctx, key, alpha)) + klog.V(3).Infof("Creating alpha ForwardingRule %v", alpha.Name) + return mc.Observe(gceCloud.Compute().AlphaGlobalForwardingRules().Insert(ctx, key, alpha)) } case meta.VersionBeta: beta, err := forwardingRule.ToBeta() if err != nil { return err } - klog.V(3).Infof("Creating beta ForwardingRule %v", beta.Name) switch key.Type() { case meta.Regional: - return mc.Observe(cloud.Compute().BetaForwardingRules().Insert(ctx, key, beta)) + klog.V(3).Infof("Creating beta region ForwardingRule %v", beta.Name) + return mc.Observe(gceCloud.Compute().BetaForwardingRules().Insert(ctx, key, beta)) default: - return mc.Observe(cloud.Compute().BetaGlobalForwardingRules().Insert(ctx, key, beta)) + klog.V(3).Infof("Creating beta ForwardingRule %v", beta.Name) + return mc.Observe(gceCloud.Compute().BetaGlobalForwardingRules().Insert(ctx, key, beta)) } default: ga, err := forwardingRule.ToGA() if err != nil { return err } - klog.V(3).Infof("Creating ga ForwardingRule %v", ga.Name) switch key.Type() { case meta.Regional: - return mc.Observe(cloud.Compute().ForwardingRules().Insert(ctx, key, ga)) + klog.V(3).Infof("Creating ga region ForwardingRule %v", ga.Name) + return mc.Observe(gceCloud.Compute().ForwardingRules().Insert(ctx, key, ga)) default: - return mc.Observe(cloud.Compute().GlobalForwardingRules().Insert(ctx, key, ga)) + klog.V(3).Infof("Creating ga ForwardingRule %v", ga.Name) + return mc.Observe(gceCloud.Compute().GlobalForwardingRules().Insert(ctx, key, ga)) } } } -func GetForwardingRule(name string, version meta.Version, cloud *gce.Cloud, key *meta.Key) (*ForwardingRule, error) { - ctx, cancel := gcecloud.ContextWithCallTimeout() +func GetForwardingRule(gceCloud *gce.Cloud, key *meta.Key, version meta.Version) (*ForwardingRule, error) { + ctx, cancel := cloudprovider.ContextWithCallTimeout() defer cancel() mc := compositemetrics.NewMetricContext("ForwardingRule", "get", key.Region, key.Zone, string(version)) @@ -2618,29 +2798,142 @@ func GetForwardingRule(name string, version meta.Version, cloud *gce.Cloud, key case meta.VersionAlpha: switch key.Type() { case meta.Regional: - gceObj, err = cloud.Compute().AlphaForwardingRules().Get(ctx, key) + klog.V(3).Infof("Getting alpha region ForwardingRule %v", key.Name) + gceObj, err = gceCloud.Compute().AlphaForwardingRules().Get(ctx, key) + default: + klog.V(3).Infof("Getting alpha ForwardingRule %v", key.Name) + gceObj, err = gceCloud.Compute().AlphaGlobalForwardingRules().Get(ctx, key) + } + case meta.VersionBeta: + switch key.Type() { + case meta.Regional: + klog.V(3).Infof("Getting beta region ForwardingRule %v", key.Name) + gceObj, err = gceCloud.Compute().BetaForwardingRules().Get(ctx, key) + default: + klog.V(3).Infof("Getting beta ForwardingRule %v", key.Name) + gceObj, err = gceCloud.Compute().BetaGlobalForwardingRules().Get(ctx, key) + } + default: + switch key.Type() { + case meta.Regional: + klog.V(3).Infof("Getting ga region ForwardingRule %v", key.Name) + gceObj, err = gceCloud.Compute().ForwardingRules().Get(ctx, key) + default: + klog.V(3).Infof("Getting ga ForwardingRule %v", key.Name) + gceObj, err = gceCloud.Compute().GlobalForwardingRules().Get(ctx, key) + } + } + if err != nil { + return nil, mc.Observe(err) + } + compositeType, err := ToForwardingRule(gceObj) + if err != nil { + return nil, err + } + + if key.Type() == meta.Regional { + compositeType.ResourceType = meta.Regional + } + + compositeType.Version = version + return compositeType, nil +} + +func ListForwardingRules(gceCloud *gce.Cloud, key *meta.Key, version meta.Version) ([]*ForwardingRule, error) { + ctx, cancel := cloudprovider.ContextWithCallTimeout() + defer cancel() + mc := compositemetrics.NewMetricContext("ForwardingRule", "get", key.Region, key.Zone, string(version)) + + var gceObjs interface{} + var err error + switch version { + case meta.VersionAlpha: + switch key.Type() { + case meta.Regional: + klog.V(3).Infof("Listing alpha region ForwardingRule") + gceObjs, err = gceCloud.Compute().AlphaForwardingRules().List(ctx, key.Region, filter.None) default: - gceObj, err = cloud.Compute().AlphaGlobalForwardingRules().Get(ctx, key) + klog.V(3).Infof("Listing alpha ForwardingRule") + gceObjs, err = gceCloud.Compute().AlphaGlobalForwardingRules().List(ctx, filter.None) } case meta.VersionBeta: switch key.Type() { case meta.Regional: - gceObj, err = cloud.Compute().BetaForwardingRules().Get(ctx, key) + klog.V(3).Infof("Listing beta region ForwardingRule") + gceObjs, err = gceCloud.Compute().BetaForwardingRules().List(ctx, key.Region, filter.None) default: - gceObj, err = cloud.Compute().BetaGlobalForwardingRules().Get(ctx, key) + klog.V(3).Infof("Listing beta ForwardingRule") + gceObjs, err = gceCloud.Compute().BetaGlobalForwardingRules().List(ctx, filter.None) } default: switch key.Type() { case meta.Regional: - gceObj, err = cloud.Compute().ForwardingRules().Get(ctx, key) + klog.V(3).Infof("Listing ga region ForwardingRule") + gceObjs, err = gceCloud.Compute().ForwardingRules().List(ctx, key.Region, filter.None) default: - gceObj, err = cloud.Compute().GlobalForwardingRules().Get(ctx, key) + klog.V(3).Infof("Listing ga ForwardingRule") + gceObjs, err = gceCloud.Compute().GlobalForwardingRules().List(ctx, filter.None) } } if err != nil { return nil, mc.Observe(err) } - return ToForwardingRule(gceObj) + compositeObjs, err := ToForwardingRuleList(gceObjs) + if err != nil { + return nil, err + } + for _, obj := range compositeObjs { + obj.Version = version + } + return compositeObjs, nil +} + +func DeleteForwardingRule(gceCloud *gce.Cloud, key *meta.Key, version meta.Version) error { + ctx, cancel := cloudprovider.ContextWithCallTimeout() + defer cancel() + mc := compositemetrics.NewMetricContext("ForwardingRule", "delete", key.Region, key.Zone, string(version)) + + switch version { + case meta.VersionAlpha: + switch key.Type() { + case meta.Regional: + klog.V(3).Infof("Deleting alpha region ForwardingRule %v", key.Name) + return mc.Observe(gceCloud.Compute().AlphaForwardingRules().Delete(ctx, key)) + default: + klog.V(3).Infof("Deleting alpha ForwardingRule %v", key.Name) + return mc.Observe(gceCloud.Compute().AlphaGlobalForwardingRules().Delete(ctx, key)) + } + case meta.VersionBeta: + switch key.Type() { + case meta.Regional: + klog.V(3).Infof("Deleting beta region ForwardingRule %v", key.Name) + return mc.Observe(gceCloud.Compute().BetaForwardingRules().Delete(ctx, key)) + default: + klog.V(3).Infof("Deleting beta ForwardingRule %v", key.Name) + return mc.Observe(gceCloud.Compute().BetaGlobalForwardingRules().Delete(ctx, key)) + } + default: + switch key.Type() { + case meta.Regional: + klog.V(3).Infof("Deleting ga region ForwardingRule %v", key.Name) + return mc.Observe(gceCloud.Compute().ForwardingRules().Delete(ctx, key)) + default: + klog.V(3).Infof("Deleting ga ForwardingRule %v", key.Name) + return mc.Observe(gceCloud.Compute().GlobalForwardingRules().Delete(ctx, key)) + } + } +} + +// ToForwardingRuleList converts a list of compute alpha, beta or GA +// ForwardingRule into a list of our composite type. +func ToForwardingRuleList(objs interface{}) ([]*ForwardingRule, error) { + result := []*ForwardingRule{} + + err := copyViaJSON(&result, objs) + if err != nil { + return nil, fmt.Errorf("Could not copy object %v to list of ForwardingRule via JSON: %v", objs, err) + } + return result, nil } // ToForwardingRule converts a compute alpha, beta or GA @@ -2691,8 +2984,8 @@ func (forwardingRule *ForwardingRule) ToGA() (*compute.ForwardingRule, error) { return ga, nil } -func CreateHealthCheck(healthCheck *HealthCheck, cloud *gce.Cloud, key *meta.Key) error { - ctx, cancel := gcecloud.ContextWithCallTimeout() +func CreateHealthCheck(gceCloud *gce.Cloud, key *meta.Key, healthCheck *HealthCheck) error { + ctx, cancel := cloudprovider.ContextWithCallTimeout() defer cancel() mc := compositemetrics.NewMetricContext("HealthCheck", "create", key.Region, key.Zone, string(healthCheck.Version)) @@ -2702,12 +2995,14 @@ func CreateHealthCheck(healthCheck *HealthCheck, cloud *gce.Cloud, key *meta.Key if err != nil { return err } - klog.V(3).Infof("Creating alpha HealthCheck %v", alpha.Name) switch key.Type() { case meta.Regional: - return mc.Observe(cloud.Compute().AlphaRegionHealthChecks().Insert(ctx, key, alpha)) + klog.V(3).Infof("Creating alpha region HealthCheck %v", alpha.Name) + alpha.Region = key.Region + return mc.Observe(gceCloud.Compute().AlphaRegionHealthChecks().Insert(ctx, key, alpha)) default: - return mc.Observe(cloud.Compute().AlphaHealthChecks().Insert(ctx, key, alpha)) + klog.V(3).Infof("Creating alpha HealthCheck %v", alpha.Name) + return mc.Observe(gceCloud.Compute().AlphaHealthChecks().Insert(ctx, key, alpha)) } case meta.VersionBeta: beta, err := healthCheck.ToBeta() @@ -2715,34 +3010,34 @@ func CreateHealthCheck(healthCheck *HealthCheck, cloud *gce.Cloud, key *meta.Key return err } klog.V(3).Infof("Creating beta HealthCheck %v", beta.Name) - return mc.Observe(cloud.Compute().BetaHealthChecks().Insert(ctx, key, beta)) + return mc.Observe(gceCloud.Compute().BetaHealthChecks().Insert(ctx, key, beta)) default: ga, err := healthCheck.ToGA() if err != nil { return err } klog.V(3).Infof("Creating ga HealthCheck %v", ga.Name) - return mc.Observe(cloud.Compute().HealthChecks().Insert(ctx, key, ga)) + return mc.Observe(gceCloud.Compute().HealthChecks().Insert(ctx, key, ga)) } } -func UpdateHealthCheck(healthCheck *HealthCheck, cloud *gce.Cloud, key *meta.Key) error { - ctx, cancel := gcecloud.ContextWithCallTimeout() +func UpdateHealthCheck(gceCloud *gce.Cloud, key *meta.Key, healthCheck *HealthCheck) error { + ctx, cancel := cloudprovider.ContextWithCallTimeout() defer cancel() mc := compositemetrics.NewMetricContext("HealthCheck", "update", key.Region, key.Zone, string(healthCheck.Version)) - switch healthCheck.Version { case meta.VersionAlpha: alpha, err := healthCheck.ToAlpha() if err != nil { return err } - klog.V(3).Infof("Updating alpha HealthCheck %v", alpha.Name) switch key.Type() { case meta.Regional: - return mc.Observe(cloud.Compute().AlphaRegionHealthChecks().Update(ctx, key, alpha)) + klog.V(3).Infof("Updating alpha region HealthCheck %v", alpha.Name) + return mc.Observe(gceCloud.Compute().AlphaRegionHealthChecks().Update(ctx, key, alpha)) default: - return mc.Observe(cloud.Compute().AlphaHealthChecks().Update(ctx, key, alpha)) + klog.V(3).Infof("Updating alpha HealthCheck %v", alpha.Name) + return mc.Observe(gceCloud.Compute().AlphaHealthChecks().Update(ctx, key, alpha)) } case meta.VersionBeta: beta, err := healthCheck.ToBeta() @@ -2750,19 +3045,43 @@ func UpdateHealthCheck(healthCheck *HealthCheck, cloud *gce.Cloud, key *meta.Key return err } klog.V(3).Infof("Updating beta HealthCheck %v", beta.Name) - return mc.Observe(cloud.Compute().BetaHealthChecks().Update(ctx, key, beta)) + return mc.Observe(gceCloud.Compute().BetaHealthChecks().Update(ctx, key, beta)) default: ga, err := healthCheck.ToGA() if err != nil { return err } klog.V(3).Infof("Updating ga HealthCheck %v", ga.Name) - return mc.Observe(cloud.Compute().HealthChecks().Update(ctx, key, ga)) + return mc.Observe(gceCloud.Compute().HealthChecks().Update(ctx, key, ga)) } } -func GetHealthCheck(version meta.Version, cloud *gce.Cloud, key *meta.Key) (*HealthCheck, error) { - ctx, cancel := gcecloud.ContextWithCallTimeout() +func DeleteHealthCheck(gceCloud *gce.Cloud, key *meta.Key, version meta.Version) error { + ctx, cancel := cloudprovider.ContextWithCallTimeout() + defer cancel() + mc := compositemetrics.NewMetricContext("HealthCheck", "delete", key.Region, key.Zone, string(version)) + + switch version { + case meta.VersionAlpha: + switch key.Type() { + case meta.Regional: + klog.V(3).Infof("Deleting alpha region HealthCheck %v", key.Name) + return mc.Observe(gceCloud.Compute().AlphaRegionHealthChecks().Delete(ctx, key)) + default: + klog.V(3).Infof("Deleting alpha HealthCheck %v", key.Name) + return mc.Observe(gceCloud.Compute().AlphaHealthChecks().Delete(ctx, key)) + } + case meta.VersionBeta: + klog.V(3).Infof("Deleting beta HealthCheck %v", key.Name) + return mc.Observe(gceCloud.Compute().BetaHealthChecks().Delete(ctx, key)) + default: + klog.V(3).Infof("Deleting ga HealthCheck %v", key.Name) + return mc.Observe(gceCloud.Compute().HealthChecks().Delete(ctx, key)) + } +} + +func GetHealthCheck(gceCloud *gce.Cloud, key *meta.Key, version meta.Version) (*HealthCheck, error) { + ctx, cancel := cloudprovider.ContextWithCallTimeout() defer cancel() mc := compositemetrics.NewMetricContext("HealthCheck", "get", key.Region, key.Zone, string(version)) @@ -2772,19 +3091,79 @@ func GetHealthCheck(version meta.Version, cloud *gce.Cloud, key *meta.Key) (*Hea case meta.VersionAlpha: switch key.Type() { case meta.Regional: - gceObj, err = cloud.Compute().AlphaRegionHealthChecks().Get(ctx, key) + klog.V(3).Infof("Getting alpha region HealthCheck %v", key.Name) + gceObj, err = gceCloud.Compute().AlphaRegionHealthChecks().Get(ctx, key) + default: + klog.V(3).Infof("Getting alpha HealthCheck %v", key.Name) + gceObj, err = gceCloud.Compute().AlphaHealthChecks().Get(ctx, key) + } + case meta.VersionBeta: + klog.V(3).Infof("Getting beta HealthCheck %v", key.Name) + gceObj, err = gceCloud.Compute().BetaHealthChecks().Get(ctx, key) + default: + klog.V(3).Infof("Getting ga HealthCheck %v", key.Name) + gceObj, err = gceCloud.Compute().HealthChecks().Get(ctx, key) + } + if err != nil { + return nil, mc.Observe(err) + } + compositeType, err := ToHealthCheck(gceObj) + if err != nil { + return nil, err + } + + compositeType.Version = version + return compositeType, nil +} + +func ListHealthChecks(gceCloud *gce.Cloud, key *meta.Key, version meta.Version) ([]*HealthCheck, error) { + ctx, cancel := cloudprovider.ContextWithCallTimeout() + defer cancel() + mc := compositemetrics.NewMetricContext("HealthCheck", "get", key.Region, key.Zone, string(version)) + + var gceObjs interface{} + var err error + switch version { + case meta.VersionAlpha: + switch key.Type() { + case meta.Regional: + klog.V(3).Infof("Listing alpha region HealthCheck") + gceObjs, err = gceCloud.Compute().AlphaRegionHealthChecks().List(ctx, key.Region, filter.None) default: - gceObj, err = cloud.Compute().AlphaHealthChecks().Get(ctx, key) + klog.V(3).Infof("Listing alpha HealthCheck") + gceObjs, err = gceCloud.Compute().AlphaHealthChecks().List(ctx, filter.None) } case meta.VersionBeta: - gceObj, err = cloud.Compute().BetaHealthChecks().Get(ctx, key) + klog.V(3).Infof("Listing beta HealthCheck") + gceObjs, err = gceCloud.Compute().BetaHealthChecks().List(ctx, filter.None) default: - gceObj, err = cloud.Compute().HealthChecks().Get(ctx, key) + klog.V(3).Infof("Listing ga HealthCheck") + gceObjs, err = gceCloud.Compute().HealthChecks().List(ctx, filter.None) } if err != nil { return nil, mc.Observe(err) } - return ToHealthCheck(gceObj) + + compositeObjs, err := ToHealthCheckList(gceObjs) + if err != nil { + return nil, err + } + for _, obj := range compositeObjs { + obj.Version = version + } + return compositeObjs, nil +} + +// ToHealthCheckList converts a list of compute alpha, beta or GA +// HealthCheck into a list of our composite type. +func ToHealthCheckList(objs interface{}) ([]*HealthCheck, error) { + result := []*HealthCheck{} + + err := copyViaJSON(&result, objs) + if err != nil { + return nil, fmt.Errorf("could not copy object %v to list of HealthCheck via JSON: %v", objs, err) + } + return result, nil } // ToHealthCheck converts a compute alpha, beta or GA @@ -2835,8 +3214,203 @@ func (healthCheck *HealthCheck) ToGA() (*compute.HealthCheck, error) { return ga, nil } -func CreateTargetHttpProxy(targetHttpProxy *TargetHttpProxy, cloud *gce.Cloud, key *meta.Key) error { - ctx, cancel := gcecloud.ContextWithCallTimeout() +func CreateSslCertificate(gceCloud *gce.Cloud, key *meta.Key, sslCertificate *SslCertificate) error { + ctx, cancel := cloudprovider.ContextWithCallTimeout() + defer cancel() + mc := compositemetrics.NewMetricContext("SslCertificate", "create", key.Region, key.Zone, string(sslCertificate.Version)) + + switch sslCertificate.Version { + case meta.VersionAlpha: + alpha, err := sslCertificate.ToAlpha() + if err != nil { + return err + } + switch key.Type() { + case meta.Regional: + klog.V(3).Infof("Creating alpha region SslCertificate %v", alpha.Name) + alpha.Region = key.Region + return mc.Observe(gceCloud.Compute().AlphaRegionSslCertificates().Insert(ctx, key, alpha)) + default: + klog.V(3).Infof("Creating alpha SslCertificate %v", alpha.Name) + return mc.Observe(gceCloud.Compute().AlphaSslCertificates().Insert(ctx, key, alpha)) + } + case meta.VersionBeta: + beta, err := sslCertificate.ToBeta() + if err != nil { + return err + } + klog.V(3).Infof("Creating beta SslCertificate %v", beta.Name) + return mc.Observe(gceCloud.Compute().BetaSslCertificates().Insert(ctx, key, beta)) + default: + ga, err := sslCertificate.ToGA() + if err != nil { + return err + } + klog.V(3).Infof("Creating ga SslCertificate %v", ga.Name) + return mc.Observe(gceCloud.Compute().SslCertificates().Insert(ctx, key, ga)) + } +} + +func DeleteSslCertificate(gceCloud *gce.Cloud, key *meta.Key, version meta.Version) error { + ctx, cancel := cloudprovider.ContextWithCallTimeout() + defer cancel() + mc := compositemetrics.NewMetricContext("SslCertificate", "delete", key.Region, key.Zone, string(version)) + + switch version { + case meta.VersionAlpha: + switch key.Type() { + case meta.Regional: + klog.V(3).Infof("Deleting alpha region SslCertificate %v", key.Name) + return mc.Observe(gceCloud.Compute().AlphaRegionSslCertificates().Delete(ctx, key)) + default: + klog.V(3).Infof("Deleting alpha SslCertificate %v", key.Name) + return mc.Observe(gceCloud.Compute().AlphaSslCertificates().Delete(ctx, key)) + } + case meta.VersionBeta: + klog.V(3).Infof("Deleting beta SslCertificate %v", key.Name) + return mc.Observe(gceCloud.Compute().BetaSslCertificates().Delete(ctx, key)) + default: + klog.V(3).Infof("Deleting ga SslCertificate %v", key.Name) + return mc.Observe(gceCloud.Compute().SslCertificates().Delete(ctx, key)) + } +} + +func GetSslCertificate(gceCloud *gce.Cloud, key *meta.Key, version meta.Version) (*SslCertificate, error) { + ctx, cancel := cloudprovider.ContextWithCallTimeout() + defer cancel() + mc := compositemetrics.NewMetricContext("SslCertificate", "get", key.Region, key.Zone, string(version)) + + var gceObj interface{} + var err error + switch version { + case meta.VersionAlpha: + switch key.Type() { + case meta.Regional: + klog.V(3).Infof("Getting alpha region SslCertificate %v", key.Name) + gceObj, err = gceCloud.Compute().AlphaRegionSslCertificates().Get(ctx, key) + default: + klog.V(3).Infof("Getting alpha SslCertificate %v", key.Name) + gceObj, err = gceCloud.Compute().AlphaSslCertificates().Get(ctx, key) + } + case meta.VersionBeta: + klog.V(3).Infof("Getting beta SslCertificate %v", key.Name) + gceObj, err = gceCloud.Compute().BetaSslCertificates().Get(ctx, key) + default: + klog.V(3).Infof("Getting ga SslCertificate %v", key.Name) + gceObj, err = gceCloud.Compute().SslCertificates().Get(ctx, key) + } + if err != nil { + return nil, mc.Observe(err) + } + compositeType, err := ToSslCertificate(gceObj) + if err != nil { + return nil, err + } + + compositeType.Version = version + return compositeType, nil +} + +func ListSslCertificates(gceCloud *gce.Cloud, key *meta.Key, version meta.Version) ([]*SslCertificate, error) { + ctx, cancel := cloudprovider.ContextWithCallTimeout() + defer cancel() + mc := compositemetrics.NewMetricContext("SslCertificate", "get", key.Region, key.Zone, string(version)) + + var gceObjs interface{} + var err error + switch version { + case meta.VersionAlpha: + switch key.Type() { + case meta.Regional: + klog.V(3).Infof("Listing alpha region SslCertificate") + gceObjs, err = gceCloud.Compute().AlphaRegionSslCertificates().List(ctx, key.Region, filter.None) + default: + klog.V(3).Infof("Listing alpha SslCertificate") + gceObjs, err = gceCloud.Compute().AlphaSslCertificates().List(ctx, filter.None) + } + case meta.VersionBeta: + klog.V(3).Infof("Listing beta SslCertificate") + gceObjs, err = gceCloud.Compute().BetaSslCertificates().List(ctx, filter.None) + default: + klog.V(3).Infof("Listing ga SslCertificate") + gceObjs, err = gceCloud.Compute().SslCertificates().List(ctx, filter.None) + } + if err != nil { + return nil, mc.Observe(err) + } + + compositeObjs, err := ToSslCertificateList(gceObjs) + if err != nil { + return nil, err + } + for _, obj := range compositeObjs { + obj.Version = version + } + return compositeObjs, nil +} + +// ToSslCertificateList converts a list of compute alpha, beta or GA +// SslCertificate into a list of our composite type. +func ToSslCertificateList(objs interface{}) ([]*SslCertificate, error) { + result := []*SslCertificate{} + + err := copyViaJSON(&result, objs) + if err != nil { + return nil, fmt.Errorf("could not copy object %v to list of SslCertificate via JSON: %v", objs, err) + } + return result, nil +} + +// ToSslCertificate converts a compute alpha, beta or GA +// SslCertificate into our composite type. +func ToSslCertificate(obj interface{}) (*SslCertificate, error) { + sslCertificate := &SslCertificate{} + err := copyViaJSON(sslCertificate, obj) + if err != nil { + return nil, fmt.Errorf("could not copy object %+v to SslCertificate via JSON: %v", obj, err) + } + + return sslCertificate, nil +} + +// ToAlpha converts our composite type into an alpha type. +// This alpha type can be used in GCE API calls. +func (sslCertificate *SslCertificate) ToAlpha() (*computealpha.SslCertificate, error) { + alpha := &computealpha.SslCertificate{} + err := copyViaJSON(alpha, sslCertificate) + if err != nil { + return nil, fmt.Errorf("error converting SslCertificate to compute alpha type via JSON: %v", err) + } + + return alpha, nil +} + +// ToBeta converts our composite type into an beta type. +// This beta type can be used in GCE API calls. +func (sslCertificate *SslCertificate) ToBeta() (*computebeta.SslCertificate, error) { + beta := &computebeta.SslCertificate{} + err := copyViaJSON(beta, sslCertificate) + if err != nil { + return nil, fmt.Errorf("error converting SslCertificate to compute beta type via JSON: %v", err) + } + + return beta, nil +} + +// ToGA converts our composite type into an ga type. +// This ga type can be used in GCE API calls. +func (sslCertificate *SslCertificate) ToGA() (*compute.SslCertificate, error) { + ga := &compute.SslCertificate{} + err := copyViaJSON(ga, sslCertificate) + if err != nil { + return nil, fmt.Errorf("error converting SslCertificate to compute ga type via JSON: %v", err) + } + + return ga, nil +} + +func CreateTargetHttpProxy(gceCloud *gce.Cloud, key *meta.Key, targetHttpProxy *TargetHttpProxy) error { + ctx, cancel := cloudprovider.ContextWithCallTimeout() defer cancel() mc := compositemetrics.NewMetricContext("TargetHttpProxy", "create", key.Region, key.Zone, string(targetHttpProxy.Version)) @@ -2846,12 +3420,14 @@ func CreateTargetHttpProxy(targetHttpProxy *TargetHttpProxy, cloud *gce.Cloud, k if err != nil { return err } - klog.V(3).Infof("Creating alpha TargetHttpProxy %v", alpha.Name) switch key.Type() { case meta.Regional: - return mc.Observe(cloud.Compute().AlphaRegionTargetHttpProxies().Insert(ctx, key, alpha)) + klog.V(3).Infof("Creating alpha region TargetHttpProxy %v", alpha.Name) + alpha.Region = key.Region + return mc.Observe(gceCloud.Compute().AlphaRegionTargetHttpProxies().Insert(ctx, key, alpha)) default: - return mc.Observe(cloud.Compute().AlphaTargetHttpProxies().Insert(ctx, key, alpha)) + klog.V(3).Infof("Creating alpha TargetHttpProxy %v", alpha.Name) + return mc.Observe(gceCloud.Compute().AlphaTargetHttpProxies().Insert(ctx, key, alpha)) } case meta.VersionBeta: beta, err := targetHttpProxy.ToBeta() @@ -2859,19 +3435,43 @@ func CreateTargetHttpProxy(targetHttpProxy *TargetHttpProxy, cloud *gce.Cloud, k return err } klog.V(3).Infof("Creating beta TargetHttpProxy %v", beta.Name) - return mc.Observe(cloud.Compute().BetaTargetHttpProxies().Insert(ctx, key, beta)) + return mc.Observe(gceCloud.Compute().BetaTargetHttpProxies().Insert(ctx, key, beta)) default: ga, err := targetHttpProxy.ToGA() if err != nil { return err } klog.V(3).Infof("Creating ga TargetHttpProxy %v", ga.Name) - return mc.Observe(cloud.Compute().TargetHttpProxies().Insert(ctx, key, ga)) + return mc.Observe(gceCloud.Compute().TargetHttpProxies().Insert(ctx, key, ga)) } } -func GetTargetHttpProxy(version meta.Version, cloud *gce.Cloud, key *meta.Key) (*TargetHttpProxy, error) { - ctx, cancel := gcecloud.ContextWithCallTimeout() +func DeleteTargetHttpProxy(gceCloud *gce.Cloud, key *meta.Key, version meta.Version) error { + ctx, cancel := cloudprovider.ContextWithCallTimeout() + defer cancel() + mc := compositemetrics.NewMetricContext("TargetHttpProxy", "delete", key.Region, key.Zone, string(version)) + + switch version { + case meta.VersionAlpha: + switch key.Type() { + case meta.Regional: + klog.V(3).Infof("Deleting alpha region TargetHttpProxy %v", key.Name) + return mc.Observe(gceCloud.Compute().AlphaRegionTargetHttpProxies().Delete(ctx, key)) + default: + klog.V(3).Infof("Deleting alpha TargetHttpProxy %v", key.Name) + return mc.Observe(gceCloud.Compute().AlphaTargetHttpProxies().Delete(ctx, key)) + } + case meta.VersionBeta: + klog.V(3).Infof("Deleting beta TargetHttpProxy %v", key.Name) + return mc.Observe(gceCloud.Compute().BetaTargetHttpProxies().Delete(ctx, key)) + default: + klog.V(3).Infof("Deleting ga TargetHttpProxy %v", key.Name) + return mc.Observe(gceCloud.Compute().TargetHttpProxies().Delete(ctx, key)) + } +} + +func GetTargetHttpProxy(gceCloud *gce.Cloud, key *meta.Key, version meta.Version) (*TargetHttpProxy, error) { + ctx, cancel := cloudprovider.ContextWithCallTimeout() defer cancel() mc := compositemetrics.NewMetricContext("TargetHttpProxy", "get", key.Region, key.Zone, string(version)) @@ -2881,19 +3481,79 @@ func GetTargetHttpProxy(version meta.Version, cloud *gce.Cloud, key *meta.Key) ( case meta.VersionAlpha: switch key.Type() { case meta.Regional: - gceObj, err = cloud.Compute().AlphaRegionTargetHttpProxies().Get(ctx, key) + klog.V(3).Infof("Getting alpha region TargetHttpProxy %v", key.Name) + gceObj, err = gceCloud.Compute().AlphaRegionTargetHttpProxies().Get(ctx, key) default: - gceObj, err = cloud.Compute().AlphaTargetHttpProxies().Get(ctx, key) + klog.V(3).Infof("Getting alpha TargetHttpProxy %v", key.Name) + gceObj, err = gceCloud.Compute().AlphaTargetHttpProxies().Get(ctx, key) } case meta.VersionBeta: - gceObj, err = cloud.Compute().BetaTargetHttpProxies().Get(ctx, key) + klog.V(3).Infof("Getting beta TargetHttpProxy %v", key.Name) + gceObj, err = gceCloud.Compute().BetaTargetHttpProxies().Get(ctx, key) default: - gceObj, err = cloud.Compute().TargetHttpProxies().Get(ctx, key) + klog.V(3).Infof("Getting ga TargetHttpProxy %v", key.Name) + gceObj, err = gceCloud.Compute().TargetHttpProxies().Get(ctx, key) } if err != nil { return nil, mc.Observe(err) } - return ToTargetHttpProxy(gceObj) + compositeType, err := ToTargetHttpProxy(gceObj) + if err != nil { + return nil, err + } + + compositeType.Version = version + return compositeType, nil +} + +func ListTargetHttpProxies(gceCloud *gce.Cloud, key *meta.Key, version meta.Version) ([]*TargetHttpProxy, error) { + ctx, cancel := cloudprovider.ContextWithCallTimeout() + defer cancel() + mc := compositemetrics.NewMetricContext("TargetHttpProxy", "get", key.Region, key.Zone, string(version)) + + var gceObjs interface{} + var err error + switch version { + case meta.VersionAlpha: + switch key.Type() { + case meta.Regional: + klog.V(3).Infof("Listing alpha region TargetHttpProxy") + gceObjs, err = gceCloud.Compute().AlphaRegionTargetHttpProxies().List(ctx, key.Region, filter.None) + default: + klog.V(3).Infof("Listing alpha TargetHttpProxy") + gceObjs, err = gceCloud.Compute().AlphaTargetHttpProxies().List(ctx, filter.None) + } + case meta.VersionBeta: + klog.V(3).Infof("Listing beta TargetHttpProxy") + gceObjs, err = gceCloud.Compute().BetaTargetHttpProxies().List(ctx, filter.None) + default: + klog.V(3).Infof("Listing ga TargetHttpProxy") + gceObjs, err = gceCloud.Compute().TargetHttpProxies().List(ctx, filter.None) + } + if err != nil { + return nil, mc.Observe(err) + } + + compositeObjs, err := ToTargetHttpProxyList(gceObjs) + if err != nil { + return nil, err + } + for _, obj := range compositeObjs { + obj.Version = version + } + return compositeObjs, nil +} + +// ToTargetHttpProxyList converts a list of compute alpha, beta or GA +// TargetHttpProxy into a list of our composite type. +func ToTargetHttpProxyList(objs interface{}) ([]*TargetHttpProxy, error) { + result := []*TargetHttpProxy{} + + err := copyViaJSON(&result, objs) + if err != nil { + return nil, fmt.Errorf("could not copy object %v to list of TargetHttpProxy via JSON: %v", objs, err) + } + return result, nil } // ToTargetHttpProxy converts a compute alpha, beta or GA @@ -2944,8 +3604,8 @@ func (targetHttpProxy *TargetHttpProxy) ToGA() (*compute.TargetHttpProxy, error) return ga, nil } -func CreateTargetHttpsProxy(targetHttpsProxy *TargetHttpsProxy, cloud *gce.Cloud, key *meta.Key) error { - ctx, cancel := gcecloud.ContextWithCallTimeout() +func CreateTargetHttpsProxy(gceCloud *gce.Cloud, key *meta.Key, targetHttpsProxy *TargetHttpsProxy) error { + ctx, cancel := cloudprovider.ContextWithCallTimeout() defer cancel() mc := compositemetrics.NewMetricContext("TargetHttpsProxy", "create", key.Region, key.Zone, string(targetHttpsProxy.Version)) @@ -2955,12 +3615,14 @@ func CreateTargetHttpsProxy(targetHttpsProxy *TargetHttpsProxy, cloud *gce.Cloud if err != nil { return err } - klog.V(3).Infof("Creating alpha TargetHttpsProxy %v", alpha.Name) switch key.Type() { case meta.Regional: - return mc.Observe(cloud.Compute().AlphaRegionTargetHttpsProxies().Insert(ctx, key, alpha)) + klog.V(3).Infof("Creating alpha region TargetHttpsProxy %v", alpha.Name) + alpha.Region = key.Region + return mc.Observe(gceCloud.Compute().AlphaRegionTargetHttpsProxies().Insert(ctx, key, alpha)) default: - return mc.Observe(cloud.Compute().AlphaTargetHttpsProxies().Insert(ctx, key, alpha)) + klog.V(3).Infof("Creating alpha TargetHttpsProxy %v", alpha.Name) + return mc.Observe(gceCloud.Compute().AlphaTargetHttpsProxies().Insert(ctx, key, alpha)) } case meta.VersionBeta: beta, err := targetHttpsProxy.ToBeta() @@ -2968,19 +3630,43 @@ func CreateTargetHttpsProxy(targetHttpsProxy *TargetHttpsProxy, cloud *gce.Cloud return err } klog.V(3).Infof("Creating beta TargetHttpsProxy %v", beta.Name) - return mc.Observe(cloud.Compute().BetaTargetHttpsProxies().Insert(ctx, key, beta)) + return mc.Observe(gceCloud.Compute().BetaTargetHttpsProxies().Insert(ctx, key, beta)) default: ga, err := targetHttpsProxy.ToGA() if err != nil { return err } klog.V(3).Infof("Creating ga TargetHttpsProxy %v", ga.Name) - return mc.Observe(cloud.Compute().TargetHttpsProxies().Insert(ctx, key, ga)) + return mc.Observe(gceCloud.Compute().TargetHttpsProxies().Insert(ctx, key, ga)) + } +} + +func DeleteTargetHttpsProxy(gceCloud *gce.Cloud, key *meta.Key, version meta.Version) error { + ctx, cancel := cloudprovider.ContextWithCallTimeout() + defer cancel() + mc := compositemetrics.NewMetricContext("TargetHttpsProxy", "delete", key.Region, key.Zone, string(version)) + + switch version { + case meta.VersionAlpha: + switch key.Type() { + case meta.Regional: + klog.V(3).Infof("Deleting alpha region TargetHttpsProxy %v", key.Name) + return mc.Observe(gceCloud.Compute().AlphaRegionTargetHttpsProxies().Delete(ctx, key)) + default: + klog.V(3).Infof("Deleting alpha TargetHttpsProxy %v", key.Name) + return mc.Observe(gceCloud.Compute().AlphaTargetHttpsProxies().Delete(ctx, key)) + } + case meta.VersionBeta: + klog.V(3).Infof("Deleting beta TargetHttpsProxy %v", key.Name) + return mc.Observe(gceCloud.Compute().BetaTargetHttpsProxies().Delete(ctx, key)) + default: + klog.V(3).Infof("Deleting ga TargetHttpsProxy %v", key.Name) + return mc.Observe(gceCloud.Compute().TargetHttpsProxies().Delete(ctx, key)) } } -func GetTargetHttpsProxy(version meta.Version, cloud *gce.Cloud, key *meta.Key) (*TargetHttpsProxy, error) { - ctx, cancel := gcecloud.ContextWithCallTimeout() +func GetTargetHttpsProxy(gceCloud *gce.Cloud, key *meta.Key, version meta.Version) (*TargetHttpsProxy, error) { + ctx, cancel := cloudprovider.ContextWithCallTimeout() defer cancel() mc := compositemetrics.NewMetricContext("TargetHttpsProxy", "get", key.Region, key.Zone, string(version)) @@ -2990,19 +3676,79 @@ func GetTargetHttpsProxy(version meta.Version, cloud *gce.Cloud, key *meta.Key) case meta.VersionAlpha: switch key.Type() { case meta.Regional: - gceObj, err = cloud.Compute().AlphaRegionTargetHttpsProxies().Get(ctx, key) + klog.V(3).Infof("Getting alpha region TargetHttpsProxy %v", key.Name) + gceObj, err = gceCloud.Compute().AlphaRegionTargetHttpsProxies().Get(ctx, key) default: - gceObj, err = cloud.Compute().AlphaTargetHttpsProxies().Get(ctx, key) + klog.V(3).Infof("Getting alpha TargetHttpsProxy %v", key.Name) + gceObj, err = gceCloud.Compute().AlphaTargetHttpsProxies().Get(ctx, key) } case meta.VersionBeta: - gceObj, err = cloud.Compute().BetaTargetHttpsProxies().Get(ctx, key) + klog.V(3).Infof("Getting beta TargetHttpsProxy %v", key.Name) + gceObj, err = gceCloud.Compute().BetaTargetHttpsProxies().Get(ctx, key) default: - gceObj, err = cloud.Compute().TargetHttpsProxies().Get(ctx, key) + klog.V(3).Infof("Getting ga TargetHttpsProxy %v", key.Name) + gceObj, err = gceCloud.Compute().TargetHttpsProxies().Get(ctx, key) } if err != nil { return nil, mc.Observe(err) } - return ToTargetHttpsProxy(gceObj) + compositeType, err := ToTargetHttpsProxy(gceObj) + if err != nil { + return nil, err + } + + compositeType.Version = version + return compositeType, nil +} + +func ListTargetHttpsProxies(gceCloud *gce.Cloud, key *meta.Key, version meta.Version) ([]*TargetHttpsProxy, error) { + ctx, cancel := cloudprovider.ContextWithCallTimeout() + defer cancel() + mc := compositemetrics.NewMetricContext("TargetHttpsProxy", "get", key.Region, key.Zone, string(version)) + + var gceObjs interface{} + var err error + switch version { + case meta.VersionAlpha: + switch key.Type() { + case meta.Regional: + klog.V(3).Infof("Listing alpha region TargetHttpsProxy") + gceObjs, err = gceCloud.Compute().AlphaRegionTargetHttpsProxies().List(ctx, key.Region, filter.None) + default: + klog.V(3).Infof("Listing alpha TargetHttpsProxy") + gceObjs, err = gceCloud.Compute().AlphaTargetHttpsProxies().List(ctx, filter.None) + } + case meta.VersionBeta: + klog.V(3).Infof("Listing beta TargetHttpsProxy") + gceObjs, err = gceCloud.Compute().BetaTargetHttpsProxies().List(ctx, filter.None) + default: + klog.V(3).Infof("Listing ga TargetHttpsProxy") + gceObjs, err = gceCloud.Compute().TargetHttpsProxies().List(ctx, filter.None) + } + if err != nil { + return nil, mc.Observe(err) + } + + compositeObjs, err := ToTargetHttpsProxyList(gceObjs) + if err != nil { + return nil, err + } + for _, obj := range compositeObjs { + obj.Version = version + } + return compositeObjs, nil +} + +// ToTargetHttpsProxyList converts a list of compute alpha, beta or GA +// TargetHttpsProxy into a list of our composite type. +func ToTargetHttpsProxyList(objs interface{}) ([]*TargetHttpsProxy, error) { + result := []*TargetHttpsProxy{} + + err := copyViaJSON(&result, objs) + if err != nil { + return nil, fmt.Errorf("could not copy object %v to list of TargetHttpsProxy via JSON: %v", objs, err) + } + return result, nil } // ToTargetHttpsProxy converts a compute alpha, beta or GA @@ -3053,8 +3799,8 @@ func (targetHttpsProxy *TargetHttpsProxy) ToGA() (*compute.TargetHttpsProxy, err return ga, nil } -func CreateUrlMap(urlMap *UrlMap, cloud *gce.Cloud, key *meta.Key) error { - ctx, cancel := gcecloud.ContextWithCallTimeout() +func CreateUrlMap(gceCloud *gce.Cloud, key *meta.Key, urlMap *UrlMap) error { + ctx, cancel := cloudprovider.ContextWithCallTimeout() defer cancel() mc := compositemetrics.NewMetricContext("UrlMap", "create", key.Region, key.Zone, string(urlMap.Version)) @@ -3064,12 +3810,14 @@ func CreateUrlMap(urlMap *UrlMap, cloud *gce.Cloud, key *meta.Key) error { if err != nil { return err } - klog.V(3).Infof("Creating alpha UrlMap %v", alpha.Name) switch key.Type() { case meta.Regional: - return mc.Observe(cloud.Compute().AlphaRegionUrlMaps().Insert(ctx, key, alpha)) + klog.V(3).Infof("Creating alpha region UrlMap %v", alpha.Name) + alpha.Region = key.Region + return mc.Observe(gceCloud.Compute().AlphaRegionUrlMaps().Insert(ctx, key, alpha)) default: - return mc.Observe(cloud.Compute().AlphaUrlMaps().Insert(ctx, key, alpha)) + klog.V(3).Infof("Creating alpha UrlMap %v", alpha.Name) + return mc.Observe(gceCloud.Compute().AlphaUrlMaps().Insert(ctx, key, alpha)) } case meta.VersionBeta: beta, err := urlMap.ToBeta() @@ -3077,34 +3825,34 @@ func CreateUrlMap(urlMap *UrlMap, cloud *gce.Cloud, key *meta.Key) error { return err } klog.V(3).Infof("Creating beta UrlMap %v", beta.Name) - return mc.Observe(cloud.Compute().BetaUrlMaps().Insert(ctx, key, beta)) + return mc.Observe(gceCloud.Compute().BetaUrlMaps().Insert(ctx, key, beta)) default: ga, err := urlMap.ToGA() if err != nil { return err } klog.V(3).Infof("Creating ga UrlMap %v", ga.Name) - return mc.Observe(cloud.Compute().UrlMaps().Insert(ctx, key, ga)) + return mc.Observe(gceCloud.Compute().UrlMaps().Insert(ctx, key, ga)) } } -func UpdateUrlMap(urlMap *UrlMap, cloud *gce.Cloud, key *meta.Key) error { - ctx, cancel := gcecloud.ContextWithCallTimeout() +func UpdateUrlMap(gceCloud *gce.Cloud, key *meta.Key, urlMap *UrlMap) error { + ctx, cancel := cloudprovider.ContextWithCallTimeout() defer cancel() mc := compositemetrics.NewMetricContext("UrlMap", "update", key.Region, key.Zone, string(urlMap.Version)) - switch urlMap.Version { case meta.VersionAlpha: alpha, err := urlMap.ToAlpha() if err != nil { return err } - klog.V(3).Infof("Updating alpha UrlMap %v", alpha.Name) switch key.Type() { case meta.Regional: - return mc.Observe(cloud.Compute().AlphaRegionUrlMaps().Update(ctx, key, alpha)) + klog.V(3).Infof("Updating alpha region UrlMap %v", alpha.Name) + return mc.Observe(gceCloud.Compute().AlphaRegionUrlMaps().Update(ctx, key, alpha)) default: - return mc.Observe(cloud.Compute().AlphaUrlMaps().Update(ctx, key, alpha)) + klog.V(3).Infof("Updating alpha UrlMap %v", alpha.Name) + return mc.Observe(gceCloud.Compute().AlphaUrlMaps().Update(ctx, key, alpha)) } case meta.VersionBeta: beta, err := urlMap.ToBeta() @@ -3112,19 +3860,43 @@ func UpdateUrlMap(urlMap *UrlMap, cloud *gce.Cloud, key *meta.Key) error { return err } klog.V(3).Infof("Updating beta UrlMap %v", beta.Name) - return mc.Observe(cloud.Compute().BetaUrlMaps().Update(ctx, key, beta)) + return mc.Observe(gceCloud.Compute().BetaUrlMaps().Update(ctx, key, beta)) default: ga, err := urlMap.ToGA() if err != nil { return err } klog.V(3).Infof("Updating ga UrlMap %v", ga.Name) - return mc.Observe(cloud.Compute().UrlMaps().Update(ctx, key, ga)) + return mc.Observe(gceCloud.Compute().UrlMaps().Update(ctx, key, ga)) } } -func GetUrlMap(version meta.Version, cloud *gce.Cloud, key *meta.Key) (*UrlMap, error) { - ctx, cancel := gcecloud.ContextWithCallTimeout() +func DeleteUrlMap(gceCloud *gce.Cloud, key *meta.Key, version meta.Version) error { + ctx, cancel := cloudprovider.ContextWithCallTimeout() + defer cancel() + mc := compositemetrics.NewMetricContext("UrlMap", "delete", key.Region, key.Zone, string(version)) + + switch version { + case meta.VersionAlpha: + switch key.Type() { + case meta.Regional: + klog.V(3).Infof("Deleting alpha region UrlMap %v", key.Name) + return mc.Observe(gceCloud.Compute().AlphaRegionUrlMaps().Delete(ctx, key)) + default: + klog.V(3).Infof("Deleting alpha UrlMap %v", key.Name) + return mc.Observe(gceCloud.Compute().AlphaUrlMaps().Delete(ctx, key)) + } + case meta.VersionBeta: + klog.V(3).Infof("Deleting beta UrlMap %v", key.Name) + return mc.Observe(gceCloud.Compute().BetaUrlMaps().Delete(ctx, key)) + default: + klog.V(3).Infof("Deleting ga UrlMap %v", key.Name) + return mc.Observe(gceCloud.Compute().UrlMaps().Delete(ctx, key)) + } +} + +func GetUrlMap(gceCloud *gce.Cloud, key *meta.Key, version meta.Version) (*UrlMap, error) { + ctx, cancel := cloudprovider.ContextWithCallTimeout() defer cancel() mc := compositemetrics.NewMetricContext("UrlMap", "get", key.Region, key.Zone, string(version)) @@ -3134,19 +3906,79 @@ func GetUrlMap(version meta.Version, cloud *gce.Cloud, key *meta.Key) (*UrlMap, case meta.VersionAlpha: switch key.Type() { case meta.Regional: - gceObj, err = cloud.Compute().AlphaRegionUrlMaps().Get(ctx, key) + klog.V(3).Infof("Getting alpha region UrlMap %v", key.Name) + gceObj, err = gceCloud.Compute().AlphaRegionUrlMaps().Get(ctx, key) default: - gceObj, err = cloud.Compute().AlphaUrlMaps().Get(ctx, key) + klog.V(3).Infof("Getting alpha UrlMap %v", key.Name) + gceObj, err = gceCloud.Compute().AlphaUrlMaps().Get(ctx, key) } case meta.VersionBeta: - gceObj, err = cloud.Compute().BetaUrlMaps().Get(ctx, key) + klog.V(3).Infof("Getting beta UrlMap %v", key.Name) + gceObj, err = gceCloud.Compute().BetaUrlMaps().Get(ctx, key) default: - gceObj, err = cloud.Compute().UrlMaps().Get(ctx, key) + klog.V(3).Infof("Getting ga UrlMap %v", key.Name) + gceObj, err = gceCloud.Compute().UrlMaps().Get(ctx, key) } if err != nil { return nil, mc.Observe(err) } - return ToUrlMap(gceObj) + compositeType, err := ToUrlMap(gceObj) + if err != nil { + return nil, err + } + + compositeType.Version = version + return compositeType, nil +} + +func ListUrlMaps(gceCloud *gce.Cloud, key *meta.Key, version meta.Version) ([]*UrlMap, error) { + ctx, cancel := cloudprovider.ContextWithCallTimeout() + defer cancel() + mc := compositemetrics.NewMetricContext("UrlMap", "get", key.Region, key.Zone, string(version)) + + var gceObjs interface{} + var err error + switch version { + case meta.VersionAlpha: + switch key.Type() { + case meta.Regional: + klog.V(3).Infof("Listing alpha region UrlMap") + gceObjs, err = gceCloud.Compute().AlphaRegionUrlMaps().List(ctx, key.Region, filter.None) + default: + klog.V(3).Infof("Listing alpha UrlMap") + gceObjs, err = gceCloud.Compute().AlphaUrlMaps().List(ctx, filter.None) + } + case meta.VersionBeta: + klog.V(3).Infof("Listing beta UrlMap") + gceObjs, err = gceCloud.Compute().BetaUrlMaps().List(ctx, filter.None) + default: + klog.V(3).Infof("Listing ga UrlMap") + gceObjs, err = gceCloud.Compute().UrlMaps().List(ctx, filter.None) + } + if err != nil { + return nil, mc.Observe(err) + } + + compositeObjs, err := ToUrlMapList(gceObjs) + if err != nil { + return nil, err + } + for _, obj := range compositeObjs { + obj.Version = version + } + return compositeObjs, nil +} + +// ToUrlMapList converts a list of compute alpha, beta or GA +// UrlMap into a list of our composite type. +func ToUrlMapList(objs interface{}) ([]*UrlMap, error) { + result := []*UrlMap{} + + err := copyViaJSON(&result, objs) + if err != nil { + return nil, fmt.Errorf("could not copy object %v to list of UrlMap via JSON: %v", objs, err) + } + return result, nil } // ToUrlMap converts a compute alpha, beta or GA diff --git a/pkg/composite/composite_test.go b/pkg/composite/composite_test.go index e35b334e86..2f10835937 100644 --- a/pkg/composite/composite_test.go +++ b/pkg/composite/composite_test.go @@ -797,6 +797,121 @@ func TestServiceAccountJwtAccessCredentials(t *testing.T) { t.Fatal(err) } } +func TestSslCertificate(t *testing.T) { + // Use reflection to verify that our composite type contains all the + // same fields as the alpha type. + compositeType := reflect.TypeOf(SslCertificate{}) + alphaType := reflect.TypeOf(computealpha.SslCertificate{}) + betaType := reflect.TypeOf(computebeta.SslCertificate{}) + gaType := reflect.TypeOf(compute.SslCertificate{}) + + // For the composite type, remove the Version field from consideration + compositeTypeNumFields := compositeType.NumField() - 2 + if compositeTypeNumFields != alphaType.NumField() { + t.Fatalf("%v should contain %v fields. Got %v", alphaType.Name(), alphaType.NumField(), compositeTypeNumFields) + } + + // Compare all the fields by doing a lookup since we can't guarantee that they'll be in the same order + // Make sure that composite type is strictly alpha fields + internal bookkeeping + for i := 2; i < compositeType.NumField(); i++ { + lookupField, found := alphaType.FieldByName(compositeType.Field(i).Name) + if !found { + t.Fatal(fmt.Errorf("Field %v not present in alpha type %v", compositeType.Field(i), alphaType)) + } + if err := compareFields(compositeType.Field(i), lookupField); err != nil { + t.Fatal(err) + } + } + + // Verify that all beta fields are in composite type + if err := typeEquality(betaType, compositeType, false); err != nil { + t.Fatal(err) + } + + // Verify that all GA fields are in composite type + if err := typeEquality(gaType, compositeType, false); err != nil { + t.Fatal(err) + } +} + +func TestToSslCertificate(t *testing.T) { + testCases := []struct { + input interface{} + expected *SslCertificate + }{ + { + computealpha.SslCertificate{}, + &SslCertificate{}, + }, + { + computebeta.SslCertificate{}, + &SslCertificate{}, + }, + { + compute.SslCertificate{}, + &SslCertificate{}, + }, + } + for _, testCase := range testCases { + result, _ := ToSslCertificate(testCase.input) + if !reflect.DeepEqual(result, testCase.expected) { + t.Fatalf("ToSslCertificate(input) = \ninput = %s\n%s\nwant = \n%s", pretty.Sprint(testCase.input), pretty.Sprint(result), pretty.Sprint(testCase.expected)) + } + } +} + +func TestSslCertificateToAlpha(t *testing.T) { + composite := SslCertificate{} + expected := &computealpha.SslCertificate{} + result, err := composite.ToAlpha() + if err != nil { + t.Fatalf("SslCertificate.ToAlpha() error: %v", err) + } + + if !reflect.DeepEqual(result, expected) { + t.Fatalf("SslCertificate.ToAlpha() = \ninput = %s\n%s\nwant = \n%s", pretty.Sprint(composite), pretty.Sprint(result), pretty.Sprint(expected)) + } +} +func TestSslCertificateToBeta(t *testing.T) { + composite := SslCertificate{} + expected := &computebeta.SslCertificate{} + result, err := composite.ToBeta() + if err != nil { + t.Fatalf("SslCertificate.ToBeta() error: %v", err) + } + + if !reflect.DeepEqual(result, expected) { + t.Fatalf("SslCertificate.ToBeta() = \ninput = %s\n%s\nwant = \n%s", pretty.Sprint(composite), pretty.Sprint(result), pretty.Sprint(expected)) + } +} +func TestSslCertificateToGA(t *testing.T) { + composite := SslCertificate{} + expected := &compute.SslCertificate{} + result, err := composite.ToGA() + if err != nil { + t.Fatalf("SslCertificate.ToGA() error: %v", err) + } + + if !reflect.DeepEqual(result, expected) { + t.Fatalf("SslCertificate.ToGA() = \ninput = %s\n%s\nwant = \n%s", pretty.Sprint(composite), pretty.Sprint(result), pretty.Sprint(expected)) + } +} + +func TestSslCertificateManagedSslCertificate(t *testing.T) { + compositeType := reflect.TypeOf(SslCertificateManagedSslCertificate{}) + alphaType := reflect.TypeOf(computealpha.SslCertificateManagedSslCertificate{}) + if err := typeEquality(compositeType, alphaType, true); err != nil { + t.Fatal(err) + } +} + +func TestSslCertificateSelfManagedSslCertificate(t *testing.T) { + compositeType := reflect.TypeOf(SslCertificateSelfManagedSslCertificate{}) + alphaType := reflect.TypeOf(computealpha.SslCertificateSelfManagedSslCertificate{}) + if err := typeEquality(compositeType, alphaType, true); err != nil { + t.Fatal(err) + } +} func TestTCPHealthCheck(t *testing.T) { compositeType := reflect.TypeOf(TCPHealthCheck{}) diff --git a/pkg/composite/gen/main.go b/pkg/composite/gen/main.go index 4d2a01e7a9..4cca795a0d 100644 --- a/pkg/composite/gen/main.go +++ b/pkg/composite/gen/main.go @@ -83,10 +83,11 @@ import ( computebeta "google.golang.org/api/compute/v0.beta" compute "google.golang.org/api/compute/v1" "google.golang.org/api/googleapi" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce" "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta" - gcecloud "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/filter" + cloudprovider "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" compositemetrics "k8s.io/ingress-gce/pkg/composite/metrics" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce" ) ` tmpl := template.Must(template.New("header").Parse(text)) @@ -188,8 +189,8 @@ func genTypes(wr io.Writer) { } // genFuncs() generates helper methods attached to composite structs. -// TODO: (shance) generated CRUD functions should take a meta.Key object to allow easier use of global and regional resources // TODO: (shance) Fix force send fields hack +// TODO: (shance) Have To*() Functions set ResourceType and Version fields func genFuncs(wr io.Writer) { const text = ` {{$All := .All}} @@ -198,10 +199,59 @@ func genFuncs(wr io.Writer) { {{range $type := $All}} {{if .IsMainService}} {{if .IsDefaultRegionalService}} - func Create{{.Name}}({{.VarName}} *{{.Name}}, cloud *gce.Cloud, key *meta.Key) error { - ctx, cancel := gcecloud.ContextWithCallTimeout() - defer cancel() - mc := compositemetrics.NewMetricContext("{{.Name}}", "create", key.Region, key.Zone, string({{.VarName}}.Version)) + func Create{{.Name}}(gceCloud *gce.Cloud, key *meta.Key, {{.VarName}} *{{.Name}}) error { + ctx, cancel := cloudprovider.ContextWithCallTimeout() + defer cancel() + mc := compositemetrics.NewMetricContext("{{.Name}}", "create", key.Region, key.Zone, string({{.VarName}}.Version)) + + switch {{.VarName}}.Version { + case meta.VersionAlpha: + alpha, err := {{.VarName}}.ToAlpha() + if err != nil { + return err + } + switch key.Type() { + case meta.Regional: + klog.V(3).Infof("Creating alpha region {{.Name}} %v", alpha.Name) + alpha.Region = key.Region + return mc.Observe(gceCloud.Compute().Alpha{{.GetCloudProviderName}}().Insert(ctx, key, alpha)) + default: + klog.V(3).Infof("Creating alpha {{.Name}} %v", alpha.Name) + return mc.Observe(gceCloud.Compute().AlphaGlobal{{.GetCloudProviderName}}().Insert(ctx, key, alpha)) + } + case meta.VersionBeta: + beta, err := {{.VarName}}.ToBeta() + if err != nil { + return err + } + switch key.Type() { + case meta.Regional: + klog.V(3).Infof("Creating beta region {{.Name}} %v", beta.Name) + return mc.Observe(gceCloud.Compute().Beta{{.GetCloudProviderName}}().Insert(ctx, key, beta)) + default: + klog.V(3).Infof("Creating beta {{.Name}} %v", beta.Name) + return mc.Observe(gceCloud.Compute().BetaGlobal{{.GetCloudProviderName}}().Insert(ctx, key, beta)) + } + default: + ga, err := {{.VarName}}.ToGA() + if err != nil { + return err + } + switch key.Type() { + case meta.Regional: + klog.V(3).Infof("Creating ga region {{.Name}} %v", ga.Name) + return mc.Observe(gceCloud.Compute().{{.GetCloudProviderName}}().Insert(ctx, key, ga)) + default: + klog.V(3).Infof("Creating ga {{.Name}} %v", ga.Name) + return mc.Observe(gceCloud.Compute().Global{{.GetCloudProviderName}}().Insert(ctx, key, ga)) + }} +} + +{{if .HasUpdate}} +func Update{{.Name}}(gceCloud *gce.Cloud, key *meta.Key, {{.VarName}} *{{.Name}}) error { + ctx, cancel := cloudprovider.ContextWithCallTimeout() + defer cancel() + mc := compositemetrics.NewMetricContext("{{.Name}}", "update", key.Region, key.Zone, string({{.VarName}}.Version)) switch {{.VarName}}.Version { case meta.VersionAlpha: @@ -209,124 +259,195 @@ func genFuncs(wr io.Writer) { if err != nil { return err } - klog.V(3).Infof("Creating alpha {{.Name}} %v", alpha.Name) switch key.Type() { case meta.Regional: - return mc.Observe(cloud.Compute().Alpha{{.GetCloudProviderName}}().Insert(ctx, key, alpha)) + klog.V(3).Infof("Updating alpha region {{.Name}} %v", alpha.Name) + return mc.Observe(gceCloud.Compute().Alpha{{.GetCloudProviderName}}().Update(ctx, key, alpha)) default: - return mc.Observe(cloud.Compute().AlphaGlobal{{.GetCloudProviderName}}().Insert(ctx, key, alpha)) - } + klog.V(3).Infof("Updating alpha {{.Name}} %v", alpha.Name) + return mc.Observe(gceCloud.Compute().AlphaGlobal{{.GetCloudProviderName}}().Update(ctx, key, alpha)) + } case meta.VersionBeta: beta, err := {{.VarName}}.ToBeta() if err != nil { return err } - klog.V(3).Infof("Creating beta {{.Name}} %v", beta.Name) switch key.Type() { case meta.Regional: - return mc.Observe(cloud.Compute().Beta{{.GetCloudProviderName}}().Insert(ctx, key, beta)) + klog.V(3).Infof("Updating beta region {{.Name}} %v", beta.Name) + return mc.Observe(gceCloud.Compute().Beta{{.GetCloudProviderName}}().Update(ctx, key, beta)) default: - return mc.Observe(cloud.Compute().BetaGlobal{{.GetCloudProviderName}}().Insert(ctx, key, beta)) - } - default: + klog.V(3).Infof("Updating beta {{.Name}} %v", beta.Name) + return mc.Observe(gceCloud.Compute().BetaGlobal{{.GetCloudProviderName}}().Update(ctx, key, beta)) + } default: ga, err := {{.VarName}}.ToGA() if err != nil { return err } - klog.V(3).Infof("Creating ga {{.Name}} %v", ga.Name) switch key.Type() { case meta.Regional: - return mc.Observe(cloud.Compute().{{.GetCloudProviderName}}().Insert(ctx, key, ga)) + klog.V(3).Infof("Updating ga region {{.Name}} %v", ga.Name) + return mc.Observe(gceCloud.Compute().{{.GetCloudProviderName}}().Update(ctx, key, ga)) default: - return mc.Observe(cloud.Compute().Global{{.GetCloudProviderName}}().Insert(ctx, key, ga)) - } } + klog.V(3).Infof("Updating ga {{.Name}} %v", ga.Name) + return mc.Observe(gceCloud.Compute().Global{{.GetCloudProviderName}}().Update(ctx, key, ga)) + } + } } +{{- end}} -{{if .HasUpdate}} -func Update{{.Name}}({{.VarName}} *{{.Name}}, cloud *gce.Cloud, key *meta.Key) error { - ctx, cancel := gcecloud.ContextWithCallTimeout() +func Get{{.Name}}(gceCloud *gce.Cloud, key *meta.Key, version meta.Version) (*{{.Name}}, error) { + ctx, cancel := cloudprovider.ContextWithCallTimeout() defer cancel() - mc := compositemetrics.NewMetricContext("{{.Name}}", "update", key.Region, key.Zone, string({{.VarName}}.Version)) + mc := compositemetrics.NewMetricContext("{{.Name}}", "get", key.Region, key.Zone, string(version)) - switch {{.VarName}}.Version { + var gceObj interface{} + var err error + switch version { case meta.VersionAlpha: - alpha, err := {{.VarName}}.ToAlpha() - if err != nil { - return err - } - klog.V(3).Infof("Updating alpha {{.Name}} %v", alpha.Name) switch key.Type() { case meta.Regional: - return mc.Observe(cloud.Compute().Alpha{{.GetCloudProviderName}}().Update(ctx, key, alpha)) + klog.V(3).Infof("Getting alpha region {{.Name}} %v", key.Name) + gceObj, err = gceCloud.Compute().Alpha{{.GetCloudProviderName}}().Get(ctx, key) default: - return mc.Observe(cloud.Compute().AlphaGlobal{{.GetCloudProviderName}}().Update(ctx, key, alpha)) + klog.V(3).Infof("Getting alpha {{.Name}} %v", key.Name) + gceObj, err = gceCloud.Compute().AlphaGlobal{{.GetCloudProviderName}}().Get(ctx, key) } case meta.VersionBeta: - beta, err := {{.VarName}}.ToBeta() - if err != nil { - return err - } - klog.V(3).Infof("Updating beta {{.Name}} %v", beta.Name) switch key.Type() { case meta.Regional: - return mc.Observe(cloud.Compute().Beta{{.GetCloudProviderName}}().Update(ctx, key, beta)) + klog.V(3).Infof("Getting beta region {{.Name}} %v", key.Name) + gceObj, err = gceCloud.Compute().Beta{{.GetCloudProviderName}}().Get(ctx, key) default: - return mc.Observe(cloud.Compute().BetaGlobal{{.GetCloudProviderName}}().Update(ctx, key, beta)) - } default: - ga, err := {{.VarName}}.ToGA() - if err != nil { - return err + klog.V(3).Infof("Getting beta {{.Name}} %v", key.Name) + gceObj, err = gceCloud.Compute().BetaGlobal{{.GetCloudProviderName}}().Get(ctx, key) } - klog.V(3).Infof("Updating ga {{.Name}} %v", ga.Name) + default: switch key.Type() { case meta.Regional: - return mc.Observe(cloud.Compute().{{.GetCloudProviderName}}().Update(ctx, key, ga)) + klog.V(3).Infof("Getting ga region {{.Name}} %v", key.Name) + gceObj, err = gceCloud.Compute().{{.GetCloudProviderName}}().Get(ctx, key) default: - return mc.Observe(cloud.Compute().Global{{.GetCloudProviderName}}().Update(ctx, key, ga)) + klog.V(3).Infof("Getting ga {{.Name}} %v", key.Name) + gceObj, err = gceCloud.Compute().Global{{.GetCloudProviderName}}().Get(ctx, key) } } + if err != nil { + return nil, mc.Observe(err) + } + compositeType, err := To{{.Name}}(gceObj) + if err != nil { + return nil, err + } + + if key.Type() == meta.Regional { + compositeType.ResourceType = meta.Regional + } + + compositeType.Version = version + return compositeType, nil } -{{- end}} -func Get{{.Name}}(name string, version meta.Version, cloud *gce.Cloud, key *meta.Key) (*{{.Name}}, error) { - ctx, cancel := gcecloud.ContextWithCallTimeout() +func List{{.GetCloudProviderName}}(gceCloud *gce.Cloud, key *meta.Key, version meta.Version) ([]*{{.Name}}, error) { + ctx, cancel := cloudprovider.ContextWithCallTimeout() defer cancel() mc := compositemetrics.NewMetricContext("{{.Name}}", "get", key.Region, key.Zone, string(version)) - var gceObj interface{} + var gceObjs interface{} var err error switch version { case meta.VersionAlpha: switch key.Type() { case meta.Regional: - gceObj, err = cloud.Compute().Alpha{{.GetCloudProviderName}}().Get(ctx, key) + klog.V(3).Infof("Listing alpha region {{.Name}}") + gceObjs, err = gceCloud.Compute().Alpha{{.GetCloudProviderName}}().List(ctx, key.Region, filter.None) default: - gceObj, err = cloud.Compute().AlphaGlobal{{.GetCloudProviderName}}().Get(ctx, key) + klog.V(3).Infof("Listing alpha {{.Name}}") + gceObjs, err = gceCloud.Compute().AlphaGlobal{{.GetCloudProviderName}}().List(ctx, filter.None) } case meta.VersionBeta: switch key.Type() { case meta.Regional: - gceObj, err = cloud.Compute().Beta{{.GetCloudProviderName}}().Get(ctx, key) + klog.V(3).Infof("Listing beta region {{.Name}}") + gceObjs, err = gceCloud.Compute().Beta{{.GetCloudProviderName}}().List(ctx, key.Region, filter.None) default: - gceObj, err = cloud.Compute().BetaGlobal{{.GetCloudProviderName}}().Get(ctx, key) + klog.V(3).Infof("Listing beta {{.Name}}") + gceObjs, err = gceCloud.Compute().BetaGlobal{{.GetCloudProviderName}}().List(ctx, filter.None) } default: switch key.Type() { case meta.Regional: - gceObj, err = cloud.Compute().{{.GetCloudProviderName}}().Get(ctx, key) + klog.V(3).Infof("Listing ga region {{.Name}}") + gceObjs, err = gceCloud.Compute().{{.GetCloudProviderName}}().List(ctx, key.Region, filter.None) default: - gceObj, err = cloud.Compute().Global{{.GetCloudProviderName}}().Get(ctx, key) + klog.V(3).Infof("Listing ga {{.Name}}") + gceObjs, err = gceCloud.Compute().Global{{.GetCloudProviderName}}().List(ctx, filter.None) } } if err != nil { return nil, mc.Observe(err) } - return To{{.Name}}(gceObj) + compositeObjs, err := To{{.Name}}List(gceObjs) + if err != nil { + return nil, err + } + for _, obj := range compositeObjs { + obj.Version = version + } + return compositeObjs, nil +} + +func Delete{{.Name}}(gceCloud *gce.Cloud, key *meta.Key, version meta.Version) error { + ctx, cancel := cloudprovider.ContextWithCallTimeout() + defer cancel() + mc := compositemetrics.NewMetricContext("{{.Name}}", "delete", key.Region, key.Zone, string(version)) + + switch version { + case meta.VersionAlpha: + switch key.Type() { + case meta.Regional: + klog.V(3).Infof("Deleting alpha region {{.Name}} %v", key.Name) + return mc.Observe(gceCloud.Compute().Alpha{{.GetCloudProviderName}}().Delete(ctx, key)) + default: + klog.V(3).Infof("Deleting alpha {{.Name}} %v", key.Name) + return mc.Observe(gceCloud.Compute().AlphaGlobal{{.GetCloudProviderName}}().Delete(ctx, key)) + } + case meta.VersionBeta: + switch key.Type() { + case meta.Regional: + klog.V(3).Infof("Deleting beta region {{.Name}} %v", key.Name) + return mc.Observe(gceCloud.Compute().Beta{{.GetCloudProviderName}}().Delete(ctx, key)) + default: + klog.V(3).Infof("Deleting beta {{.Name}} %v", key.Name) + return mc.Observe(gceCloud.Compute().BetaGlobal{{.GetCloudProviderName}}().Delete(ctx, key)) + } + default: + switch key.Type() { + case meta.Regional: + klog.V(3).Infof("Deleting ga region {{.Name}} %v", key.Name) + return mc.Observe(gceCloud.Compute().{{.GetCloudProviderName}}().Delete(ctx, key)) + default: + klog.V(3).Infof("Deleting ga {{.Name}} %v", key.Name) + return mc.Observe(gceCloud.Compute().Global{{.GetCloudProviderName}}().Delete(ctx, key)) + } + } +} + +// To{{.Name}}List converts a list of compute alpha, beta or GA +// {{.Name}} into a list of our composite type. +func To{{.Name}}List(objs interface{}) ([]*{{.Name}}, error) { + result := []*{{.Name}}{} + + err := copyViaJSON(&result, objs) + if err != nil { + return nil, fmt.Errorf("Could not copy object %v to list of {{.Name}} via JSON: %v", objs, err) + } + return result, nil } {{ else }} -func Create{{.Name}}({{.VarName}} *{{.Name}}, cloud *gce.Cloud, key *meta.Key) error { - ctx, cancel := gcecloud.ContextWithCallTimeout() +func Create{{.Name}}(gceCloud *gce.Cloud, key *meta.Key, {{.VarName}} *{{.Name}}) error { + ctx, cancel := cloudprovider.ContextWithCallTimeout() defer cancel() mc := compositemetrics.NewMetricContext("{{.Name}}", "create", key.Region, key.Zone, string({{.VarName}}.Version)) @@ -336,12 +457,14 @@ func Create{{.Name}}({{.VarName}} *{{.Name}}, cloud *gce.Cloud, key *meta.Key) e if err != nil { return err } - klog.V(3).Infof("Creating alpha {{.Name}} %v", alpha.Name) switch key.Type() { case meta.Regional: - return mc.Observe(cloud.Compute().AlphaRegion{{.GetCloudProviderName}}().Insert(ctx, key, alpha)) + klog.V(3).Infof("Creating alpha region {{.Name}} %v", alpha.Name) + alpha.Region = key.Region + return mc.Observe(gceCloud.Compute().AlphaRegion{{.GetCloudProviderName}}().Insert(ctx, key, alpha)) default: - return mc.Observe(cloud.Compute().Alpha{{.GetCloudProviderName}}().Insert(ctx, key, alpha)) + klog.V(3).Infof("Creating alpha {{.Name}} %v", alpha.Name) + return mc.Observe(gceCloud.Compute().Alpha{{.GetCloudProviderName}}().Insert(ctx, key, alpha)) } case meta.VersionBeta: beta, err := {{.VarName}}.ToBeta() @@ -349,35 +472,35 @@ func Create{{.Name}}({{.VarName}} *{{.Name}}, cloud *gce.Cloud, key *meta.Key) e return err } klog.V(3).Infof("Creating beta {{.Name}} %v", beta.Name) - return mc.Observe(cloud.Compute().Beta{{.GetCloudProviderName}}().Insert(ctx, key, beta)) + return mc.Observe(gceCloud.Compute().Beta{{.GetCloudProviderName}}().Insert(ctx, key, beta)) default: ga, err := {{.VarName}}.ToGA() if err != nil { return err } klog.V(3).Infof("Creating ga {{.Name}} %v", ga.Name) - return mc.Observe(cloud.Compute().{{.GetCloudProviderName}}().Insert(ctx, key, ga)) + return mc.Observe(gceCloud.Compute().{{.GetCloudProviderName}}().Insert(ctx, key, ga)) } } {{if .HasUpdate}} -func Update{{.Name}}({{.VarName}} *{{.Name}}, cloud *gce.Cloud, key *meta.Key) error { - ctx, cancel := gcecloud.ContextWithCallTimeout() +func Update{{.Name}}(gceCloud *gce.Cloud, key *meta.Key, {{.VarName}} *{{.Name}}) error { + ctx, cancel := cloudprovider.ContextWithCallTimeout() defer cancel() mc := compositemetrics.NewMetricContext("{{.Name}}", "update", key.Region, key.Zone, string({{.VarName}}.Version)) - switch {{.VarName}}.Version { case meta.VersionAlpha: alpha, err := {{.VarName}}.ToAlpha() if err != nil { return err } - klog.V(3).Infof("Updating alpha {{.Name}} %v", alpha.Name) switch key.Type() { case meta.Regional: - return mc.Observe(cloud.Compute().AlphaRegion{{.GetCloudProviderName}}().Update(ctx, key, alpha)) + klog.V(3).Infof("Updating alpha region {{.Name}} %v", alpha.Name) + return mc.Observe(gceCloud.Compute().AlphaRegion{{.GetCloudProviderName}}().Update(ctx, key, alpha)) default: - return mc.Observe(cloud.Compute().Alpha{{.GetCloudProviderName}}().Update(ctx, key, alpha)) + klog.V(3).Infof("Updating alpha {{.Name}} %v", alpha.Name) + return mc.Observe(gceCloud.Compute().Alpha{{.GetCloudProviderName}}().Update(ctx, key, alpha)) } case meta.VersionBeta: beta, err := {{.VarName}}.ToBeta() @@ -385,20 +508,44 @@ func Update{{.Name}}({{.VarName}} *{{.Name}}, cloud *gce.Cloud, key *meta.Key) e return err } klog.V(3).Infof("Updating beta {{.Name}} %v", beta.Name) - return mc.Observe(cloud.Compute().Beta{{.GetCloudProviderName}}().Update(ctx, key, beta)) + return mc.Observe(gceCloud.Compute().Beta{{.GetCloudProviderName}}().Update(ctx, key, beta)) default: ga, err := {{.VarName}}.ToGA() if err != nil { return err } klog.V(3).Infof("Updating ga {{.Name}} %v", ga.Name) - return mc.Observe(cloud.Compute().{{.GetCloudProviderName}}().Update(ctx, key, ga)) + return mc.Observe(gceCloud.Compute().{{.GetCloudProviderName}}().Update(ctx, key, ga)) } } {{- end}} -func Get{{.Name}}(version meta.Version, cloud *gce.Cloud, key *meta.Key) (*{{.Name}}, error) { - ctx, cancel := gcecloud.ContextWithCallTimeout() +func Delete{{.Name}}(gceCloud *gce.Cloud, key *meta.Key, version meta.Version) error { + ctx, cancel := cloudprovider.ContextWithCallTimeout() + defer cancel() + mc := compositemetrics.NewMetricContext("{{.Name}}", "delete", key.Region, key.Zone, string(version)) + + switch version { + case meta.VersionAlpha: + switch key.Type() { + case meta.Regional: + klog.V(3).Infof("Deleting alpha region {{.Name}} %v", key.Name) + return mc.Observe(gceCloud.Compute().AlphaRegion{{.GetCloudProviderName}}().Delete(ctx, key)) + default: + klog.V(3).Infof("Deleting alpha {{.Name}} %v", key.Name) + return mc.Observe(gceCloud.Compute().Alpha{{.GetCloudProviderName}}().Delete(ctx, key)) + } + case meta.VersionBeta: + klog.V(3).Infof("Deleting beta {{.Name}} %v", key.Name) + return mc.Observe(gceCloud.Compute().Beta{{.GetCloudProviderName}}().Delete(ctx, key)) + default: + klog.V(3).Infof("Deleting ga {{.Name}} %v", key.Name) + return mc.Observe(gceCloud.Compute().{{.GetCloudProviderName}}().Delete(ctx, key)) + } +} + +func Get{{.Name}}(gceCloud *gce.Cloud, key *meta.Key, version meta.Version) (*{{.Name}}, error) { + ctx, cancel := cloudprovider.ContextWithCallTimeout() defer cancel() mc := compositemetrics.NewMetricContext("{{.Name}}", "get", key.Region, key.Zone, string(version)) @@ -407,23 +554,83 @@ func Get{{.Name}}(version meta.Version, cloud *gce.Cloud, key *meta.Key) (*{{.Na switch version { case meta.VersionAlpha: switch key.Type() { - case meta.Regional: - gceObj, err = cloud.Compute().AlphaRegion{{.GetCloudProviderName}}().Get(ctx, key) - default: - gceObj, err = cloud.Compute().Alpha{{.GetCloudProviderName}}().Get(ctx, key) + case meta.Regional: + klog.V(3).Infof("Getting alpha region {{.Name}} %v", key.Name) + gceObj, err = gceCloud.Compute().AlphaRegion{{.GetCloudProviderName}}().Get(ctx, key) + default: + klog.V(3).Infof("Getting alpha {{.Name}} %v", key.Name) + gceObj, err = gceCloud.Compute().Alpha{{.GetCloudProviderName}}().Get(ctx, key) } case meta.VersionBeta: - gceObj, err = cloud.Compute().Beta{{.GetCloudProviderName}}().Get(ctx, key) + klog.V(3).Infof("Getting beta {{.Name}} %v", key.Name) + gceObj, err = gceCloud.Compute().Beta{{.GetCloudProviderName}}().Get(ctx, key) default: - gceObj, err = cloud.Compute().{{.GetCloudProviderName}}().Get(ctx, key) + klog.V(3).Infof("Getting ga {{.Name}} %v", key.Name) + gceObj, err = gceCloud.Compute().{{.GetCloudProviderName}}().Get(ctx, key) } if err != nil { return nil, mc.Observe(err) } - return To{{.Name}}(gceObj) + compositeType, err := To{{.Name}}(gceObj) + if err != nil { + return nil, err + } + + compositeType.Version = version + return compositeType, nil } -{{- end}} +func List{{.GetCloudProviderName}}(gceCloud *gce.Cloud, key *meta.Key, version meta.Version) ([]*{{.Name}}, error) { + ctx, cancel := cloudprovider.ContextWithCallTimeout() + defer cancel() + mc := compositemetrics.NewMetricContext("{{.Name}}", "get", key.Region, key.Zone, string(version)) + + var gceObjs interface{} + var err error + switch version { + case meta.VersionAlpha: + switch key.Type() { + case meta.Regional: + klog.V(3).Infof("Listing alpha region {{.Name}}") + gceObjs, err = gceCloud.Compute().AlphaRegion{{.GetCloudProviderName}}().List(ctx, key.Region, filter.None) + default: + klog.V(3).Infof("Listing alpha {{.Name}}") + gceObjs, err = gceCloud.Compute().Alpha{{.GetCloudProviderName}}().List(ctx, filter.None) + } + case meta.VersionBeta: + klog.V(3).Infof("Listing beta {{.Name}}") + gceObjs, err = gceCloud.Compute().Beta{{.GetCloudProviderName}}().List(ctx, filter.None) + default: + klog.V(3).Infof("Listing ga {{.Name}}") + gceObjs, err = gceCloud.Compute().{{.GetCloudProviderName}}().List(ctx, filter.None) + } + if err != nil { + return nil, mc.Observe(err) + } + + compositeObjs, err := To{{.Name}}List(gceObjs) + if err != nil { + return nil, err + } + for _, obj := range compositeObjs { + obj.Version = version + } + return compositeObjs, nil +} + +// To{{.Name}}List converts a list of compute alpha, beta or GA +// {{.Name}} into a list of our composite type. +func To{{.Name}}List(objs interface{}) ([]*{{.Name}}, error) { + result := []*{{.Name}}{} + + err := copyViaJSON(&result, objs) + if err != nil { + return nil, fmt.Errorf("could not copy object %v to list of {{.Name}} via JSON: %v", objs, err) + } + return result, nil +} + +{{- end}} // To{{.Name}} converts a compute alpha, beta or GA // {{.Name}} into our composite type. diff --git a/pkg/composite/manual.go b/pkg/composite/manual.go new file mode 100644 index 0000000000..9aa8006cd2 --- /dev/null +++ b/pkg/composite/manual.go @@ -0,0 +1,153 @@ +/* +Copyright 2019 The Kubernetes Authors. + +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. +*/ + +// This file includes all the handwritten functions from the composite library +package composite + +import ( + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta" + computealpha "google.golang.org/api/compute/v0.alpha" + computebeta "google.golang.org/api/compute/v0.beta" + "google.golang.org/api/compute/v1" + "k8s.io/ingress-gce/pkg/composite/metrics" + "k8s.io/klog" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce" +) + +// TODO: (shance) below functions should be generated +// SetUrlMapForTargetHttpsProxy() sets the UrlMap for a target https proxy +func SetUrlMapForTargetHttpsProxy(gceCloud *gce.Cloud, key *meta.Key, targetHttpsProxy *TargetHttpsProxy, urlMapLink string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := metrics.NewMetricContext("TargetHttpsProxy", "set_url_map", key.Region, key.Zone, string(targetHttpsProxy.Version)) + + // Set name in case it is not present in the key + key.Name = targetHttpsProxy.Name + klog.V(3).Infof("setting URLMap for TargetHttpsProxy %v", targetHttpsProxy.Name) + + switch targetHttpsProxy.Version { + case meta.VersionAlpha: + ref := &computealpha.UrlMapReference{UrlMap: urlMapLink} + switch key.Type() { + case meta.Regional: + return mc.Observe(gceCloud.Compute().AlphaRegionTargetHttpsProxies().SetUrlMap(ctx, key, ref)) + default: + return mc.Observe(gceCloud.Compute().AlphaTargetHttpsProxies().SetUrlMap(ctx, key, ref)) + } + case meta.VersionBeta: + ref := &computebeta.UrlMapReference{UrlMap: urlMapLink} + return mc.Observe(gceCloud.Compute().BetaTargetHttpsProxies().SetUrlMap(ctx, key, ref)) + default: + ref := &compute.UrlMapReference{UrlMap: urlMapLink} + return mc.Observe(gceCloud.Compute().TargetHttpsProxies().SetUrlMap(ctx, key, ref)) + } +} + +// SetSslCertificateForTargetHttpsProxy() sets the SSL Certificate for a target https proxy +func SetSslCertificateForTargetHttpsProxy(gceCloud *gce.Cloud, key *meta.Key, targetHttpsProxy *TargetHttpsProxy, sslCertURLs []string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := metrics.NewMetricContext("TargetHttpsProxy", "set_ssl_certificate", key.Region, key.Zone, string(targetHttpsProxy.Version)) + + // Set name in case it is not present in the key + key.Name = targetHttpsProxy.Name + klog.V(3).Infof("setting URLMap for TargetHttpsProxy %v", targetHttpsProxy.Name) + + switch targetHttpsProxy.Version { + case meta.VersionAlpha: + switch key.Type() { + case meta.Regional: + req := &computealpha.RegionTargetHttpsProxiesSetSslCertificatesRequest{SslCertificates: sslCertURLs} + return mc.Observe(gceCloud.Compute().AlphaRegionTargetHttpsProxies().SetSslCertificates(ctx, key, req)) + default: + req := &computealpha.TargetHttpsProxiesSetSslCertificatesRequest{SslCertificates: sslCertURLs} + return mc.Observe(gceCloud.Compute().AlphaTargetHttpsProxies().SetSslCertificates(ctx, key, req)) + } + case meta.VersionBeta: + req := &computebeta.TargetHttpsProxiesSetSslCertificatesRequest{SslCertificates: sslCertURLs} + return mc.Observe(gceCloud.Compute().BetaTargetHttpsProxies().SetSslCertificates(ctx, key, req)) + default: + req := &compute.TargetHttpsProxiesSetSslCertificatesRequest{SslCertificates: sslCertURLs} + return mc.Observe(gceCloud.Compute().TargetHttpsProxies().SetSslCertificates(ctx, key, req)) + } +} + +// SetUrlMapForTargetHttpProxy() sets the url map for a target proxy +func SetUrlMapForTargetHttpProxy(gceCloud *gce.Cloud, key *meta.Key, targetHttpProxy *TargetHttpProxy, urlMapLink string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := metrics.NewMetricContext("TargetHttpProxy", "set_url_map", key.Region, key.Zone, string(targetHttpProxy.Version)) + + // Set name in case it is not present in the key + key.Name = targetHttpProxy.Name + klog.V(3).Infof("setting URLMap for TargetHttpProxy %v", targetHttpProxy.Name) + + switch targetHttpProxy.Version { + case meta.VersionAlpha: + ref := &computealpha.UrlMapReference{UrlMap: urlMapLink} + switch key.Type() { + case meta.Regional: + return mc.Observe(gceCloud.Compute().AlphaRegionTargetHttpProxies().SetUrlMap(ctx, key, ref)) + default: + return mc.Observe(gceCloud.Compute().AlphaTargetHttpProxies().SetUrlMap(ctx, key, ref)) + } + case meta.VersionBeta: + ref := &computebeta.UrlMapReference{UrlMap: urlMapLink} + return mc.Observe(gceCloud.Compute().BetaTargetHttpProxies().SetUrlMap(ctx, key, ref)) + default: + ref := &compute.UrlMapReference{UrlMap: urlMapLink} + return mc.Observe(gceCloud.Compute().TargetHttpProxies().SetUrlMap(ctx, key, ref)) + } +} + +// SetProxyForForwardingRule() sets the target proxy for a forwarding rule +func SetProxyForForwardingRule(gceCloud *gce.Cloud, key *meta.Key, forwardingRule *ForwardingRule, targetProxyLink string) error { + ctx, cancel := cloud.ContextWithCallTimeout() + defer cancel() + mc := metrics.NewMetricContext("ForwardingRule", "set_proxy", key.Region, key.Zone, string(forwardingRule.Version)) + + // Set name in case it is not present in the key + key.Name = forwardingRule.Name + klog.V(3).Infof("setting proxy for forwarding rule ForwardingRule %v", forwardingRule.Name) + + switch forwardingRule.Version { + case meta.VersionAlpha: + target := &computealpha.TargetReference{Target: targetProxyLink} + switch key.Type() { + case meta.Regional: + return mc.Observe(gceCloud.Compute().AlphaForwardingRules().SetTarget(ctx, key, target)) + default: + return mc.Observe(gceCloud.Compute().AlphaGlobalForwardingRules().SetTarget(ctx, key, target)) + } + case meta.VersionBeta: + target := &computebeta.TargetReference{Target: targetProxyLink} + switch key.Type() { + case meta.Regional: + return mc.Observe(gceCloud.Compute().BetaForwardingRules().SetTarget(ctx, key, target)) + default: + return mc.Observe(gceCloud.Compute().BetaGlobalForwardingRules().SetTarget(ctx, key, target)) + } + default: + target := &compute.TargetReference{Target: targetProxyLink} + switch key.Type() { + case meta.Regional: + return mc.Observe(gceCloud.Compute().ForwardingRules().SetTarget(ctx, key, target)) + default: + return mc.Observe(gceCloud.Compute().GlobalForwardingRules().SetTarget(ctx, key, target)) + } + } +} diff --git a/pkg/composite/meta/meta.go b/pkg/composite/meta/meta.go index 91678a9d81..c1c0208db2 100644 --- a/pkg/composite/meta/meta.go +++ b/pkg/composite/meta/meta.go @@ -42,6 +42,7 @@ var MainServices = map[string]string{ "UrlMap": "UrlMaps", "TargetHttpProxy": "TargetHttpProxies", "TargetHttpsProxy": "TargetHttpsProxies", + "SslCertificate": "SslCertificates", } // TODO: (shance) Replace this with data gathered from meta.AllServices @@ -50,6 +51,7 @@ var NoUpdate = sets.NewString( "ForwardingRule", "TargetHttpProxy", "TargetHttpsProxy", + "SslCertificate", ) var Versions = map[string]string{ diff --git a/pkg/composite/utils.go b/pkg/composite/utils.go index a8f9e2d353..533fbee6cd 100644 --- a/pkg/composite/utils.go +++ b/pkg/composite/utils.go @@ -19,9 +19,127 @@ package composite import ( "encoding/json" "fmt" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce" "reflect" ) +// CreateKey() is a helper function for creating a meta.Key when interacting with the +// composite functions. For regional resourceTypes, this function looks up +// the region of the gceCloud object. You should use this wherever possible to avoid +// creating a resource in the wrong region or creating a global resource accidentally. +// TODO: (shance) implement zonal +func CreateKey(gceCloud *gce.Cloud, name string, resourceType meta.KeyType) (*meta.Key, error) { + switch resourceType { + case meta.Regional: + region := gceCloud.Region() + if region == "" { + return nil, fmt.Errorf("error getting region") + } + return meta.RegionalKey(name, region), nil + case meta.Global: + return meta.GlobalKey(name), nil + } + + return nil, fmt.Errorf("error creating key, invalid resource type: %s", resourceType) +} + +// TODO: (shance) generate this +// ListAllUrlMaps() merges all configured List() calls into one list of composite UrlMaps +func ListAllUrlMaps(gceCloud *gce.Cloud) ([]*UrlMap, error) { + resultMap := map[string]*UrlMap{} + key1, err := CreateKey(gceCloud, "", meta.Global) + if err != nil { + return nil, err + } + key2, err := CreateKey(gceCloud, "", meta.Regional) + if err != nil { + return nil, err + } + + // List ga-global and regional-alpha + versions := []meta.Version{meta.VersionGA, meta.VersionAlpha} + keys := []*meta.Key{key1, key2} + + for i := range versions { + list, err := ListUrlMaps(gceCloud, keys[i], versions[i]) + if err != nil { + return nil, fmt.Errorf("error listing all urlmaps: %v", err) + } + for _, um := range list { + resultMap[um.SelfLink] = um + } + } + + // Convert map to slice + result := []*UrlMap{} + for _, um := range resultMap { + result = append(result, um) + } + + return result, nil +} + +// TODO: (shance) generate this +// ListAllUrlMaps() merges all configured List() calls into one list of composite UrlMaps +func ListAllBackendServices(gceCloud *gce.Cloud) ([]*BackendService, error) { + resultMap := map[string]*BackendService{} + key1, err := CreateKey(gceCloud, "", meta.Global) + if err != nil { + return nil, err + } + key2, err := CreateKey(gceCloud, "", meta.Regional) + if err != nil { + return nil, err + } + + // List ga-global and regional-alpha + versions := []meta.Version{meta.VersionGA, meta.VersionAlpha} + keys := []*meta.Key{key1, key2} + + for i := range versions { + list, err := ListBackendServices(gceCloud, keys[i], versions[i]) + if err != nil { + return nil, fmt.Errorf("error listing all urlmaps: %v", err) + } + for _, bs := range list { + resultMap[bs.SelfLink] = bs + } + } + + // Convert map to slice + result := []*BackendService{} + for _, bs := range resultMap { + result = append(result, bs) + } + return result, nil +} + +// IsRegionalUrlMap() returns if the url map is regional +func IsRegionalUrlMap(um *UrlMap) (bool, error) { + if um != nil { + return IsRegionalResource(um.SelfLink) + } + return false, nil +} + +// IsRegionalResource() returns true if the resource URL is regional +func IsRegionalResource(selfLink string) (bool, error) { + // Figure out if cluster is regional + // Update L7 if its regional so we can delete the right resources + resourceID, err := cloud.ParseResourceURL(selfLink) + if err != nil { + return false, fmt.Errorf("error parsing self-link for url-map %s: %v", selfLink, err) + } + + if resourceID.Key.Region != "" { + return true, nil + } + + return false, nil +} + // compareFields verifies that two fields in a struct have the same relevant metadata. // Note: This comparison ignores field offset, index, and pkg path, all of which don't matter. func compareFields(s1, s2 reflect.StructField) error { diff --git a/pkg/composite/utils_test.go b/pkg/composite/utils_test.go new file mode 100644 index 0000000000..06889fd628 --- /dev/null +++ b/pkg/composite/utils_test.go @@ -0,0 +1,116 @@ +/* +Copyright 2019 The Kubernetes Authors. + +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 composite + +import ( + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce" + "reflect" + "testing" +) + +func TestCreateKey(t *testing.T) { + testCases := []struct { + desc string + resourceType meta.KeyType + expected *meta.Key + wantErr bool + }{ + { + desc: "Global Key", + resourceType: meta.Global, + expected: meta.GlobalKey("test"), + }, + { + desc: "Regional Key", + resourceType: meta.Regional, + expected: meta.RegionalKey("test", gce.DefaultTestClusterValues().Region), + }, + { + desc: "Zonal Key", + resourceType: meta.Zonal, + expected: nil, + wantErr: true, + }, + } + fakeGCE := gce.NewFakeGCECloud(gce.DefaultTestClusterValues()) + + for _, tc := range testCases { + t.Run(tc.desc, func(t *testing.T) { + result, err := CreateKey(fakeGCE, "test", tc.resourceType) + + if tc.wantErr { + if err == nil { + t.Fatalf("err = nil, want non-nil") + } else { + return + } + } + + if err != nil { + t.Fatalf("CreateKey(fakeGCE, test, %s) = %v, want %v", tc.resourceType, err, tc.expected) + } + + if !reflect.DeepEqual(result, tc.expected) { + t.Fatalf("CreateKey(fakeGCE, test, %s) = %v, want %v", tc.resourceType, result, tc.expected) + } + }) + } +} + +func TestIsRegionalResource(t *testing.T) { + testCases := []struct { + desc string + selfLink string + expected bool + wantErr bool + }{ + { + desc: "Regional resource", + selfLink: "https://www.googleapis.com/compute/alpha/projects/gke-dev/regions/us-central1/urlMaps/desc", + expected: true, + }, + { + desc: "Global resource", + selfLink: "https://www.googleapis.com/compute/alpha/projects/gke-dev/global/urlMaps/desc", + expected: false, + }, + { + desc: "Invalid resource", + selfLink: "a/b/c/d/e/f/", + expected: false, + wantErr: true, + }, + } + for _, tc := range testCases { + t.Run(tc.desc, func(t *testing.T) { + result, err := IsRegionalResource(tc.selfLink) + + if tc.wantErr { + if err == nil { + t.Fatalf("err = nil, want non-nil") + } else { + return + } + } + + if err != nil || result != tc.expected { + t.Fatalf("IsRegionalResource(%v) = %v, want %v", tc.selfLink, err, tc.expected) + } + }) + } +} diff --git a/pkg/controller/controller.go b/pkg/controller/controller.go index eadc110fdd..98e6aa177b 100644 --- a/pkg/controller/controller.go +++ b/pkg/controller/controller.go @@ -105,6 +105,7 @@ func NewLoadBalancerController( healthChecker := healthchecks.NewHealthChecker(ctx.Cloud, ctx.HealthCheckPath, ctx.DefaultBackendHealthCheckPath, ctx.ClusterNamer, ctx.DefaultBackendSvcPortID.Service) instancePool := instances.NewNodePool(ctx.Cloud, ctx.ClusterNamer) + backendPool := backends.NewPool(ctx.Cloud, ctx.ClusterNamer) lbc := LoadBalancerController{