Merge pull request #62516 from nicksardo/expand-id

Automatic merge from submit-queue (batch tested with PRs 62060, 62516). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

[GCE] Add new formats to resource parser and self link creator

**What this PR does / why we need it**:
- Expands the set of parse-able strings for resource IDs, while also simplifying the code. Note that these are acceptable values for some fields in GCP API.
  - global/networks/my-network
  - regions/us-central1/subnetworks/my-sub
  - zones/us-central1-a/instances/my-hacker-instance
- Fixes the SelfLink function to return links for regions and zones:
  - https://www.googleapis.com/compute/v1/projects/proj4/regions/us-central1
- Generates helper functions to create a ResourceID for each resource
- Generates a unit test that ensures all links can be generated and all generated links can be parsed.
- Fixes an ILB test which creates a malformed URL.

**Special notes for your reviewer**:
/assign rramkumar1

**Release note**:
```release-note
NONE
```
This commit is contained in:
Kubernetes Submit Queue 2018-05-02 18:12:06 -07:00 committed by GitHub
commit c968d99ee5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 528 additions and 67 deletions

View File

@ -13152,3 +13152,147 @@ func (g *GCEZones) List(ctx context.Context, fl *filter.F) ([]*ga.Zone, error) {
return all, nil
}
// NewAddressesResourceID creates a ResourceID for the Addresses resource.
func NewAddressesResourceID(project, region, name string) *ResourceID {
key := meta.RegionalKey(name, region)
return &ResourceID{project, "addresses", key}
}
// NewBackendServicesResourceID creates a ResourceID for the BackendServices resource.
func NewBackendServicesResourceID(project, name string) *ResourceID {
key := meta.GlobalKey(name)
return &ResourceID{project, "backendServices", key}
}
// NewDisksResourceID creates a ResourceID for the Disks resource.
func NewDisksResourceID(project, zone, name string) *ResourceID {
key := meta.ZonalKey(name, zone)
return &ResourceID{project, "disks", key}
}
// NewFirewallsResourceID creates a ResourceID for the Firewalls resource.
func NewFirewallsResourceID(project, name string) *ResourceID {
key := meta.GlobalKey(name)
return &ResourceID{project, "firewalls", key}
}
// NewForwardingRulesResourceID creates a ResourceID for the ForwardingRules resource.
func NewForwardingRulesResourceID(project, region, name string) *ResourceID {
key := meta.RegionalKey(name, region)
return &ResourceID{project, "forwardingRules", key}
}
// NewGlobalAddressesResourceID creates a ResourceID for the GlobalAddresses resource.
func NewGlobalAddressesResourceID(project, name string) *ResourceID {
key := meta.GlobalKey(name)
return &ResourceID{project, "addresses", key}
}
// NewGlobalForwardingRulesResourceID creates a ResourceID for the GlobalForwardingRules resource.
func NewGlobalForwardingRulesResourceID(project, name string) *ResourceID {
key := meta.GlobalKey(name)
return &ResourceID{project, "forwardingRules", key}
}
// NewHealthChecksResourceID creates a ResourceID for the HealthChecks resource.
func NewHealthChecksResourceID(project, name string) *ResourceID {
key := meta.GlobalKey(name)
return &ResourceID{project, "healthChecks", key}
}
// NewHttpHealthChecksResourceID creates a ResourceID for the HttpHealthChecks resource.
func NewHttpHealthChecksResourceID(project, name string) *ResourceID {
key := meta.GlobalKey(name)
return &ResourceID{project, "httpHealthChecks", key}
}
// NewHttpsHealthChecksResourceID creates a ResourceID for the HttpsHealthChecks resource.
func NewHttpsHealthChecksResourceID(project, name string) *ResourceID {
key := meta.GlobalKey(name)
return &ResourceID{project, "httpsHealthChecks", key}
}
// NewInstanceGroupsResourceID creates a ResourceID for the InstanceGroups resource.
func NewInstanceGroupsResourceID(project, zone, name string) *ResourceID {
key := meta.ZonalKey(name, zone)
return &ResourceID{project, "instanceGroups", key}
}
// NewInstancesResourceID creates a ResourceID for the Instances resource.
func NewInstancesResourceID(project, zone, name string) *ResourceID {
key := meta.ZonalKey(name, zone)
return &ResourceID{project, "instances", key}
}
// NewNetworkEndpointGroupsResourceID creates a ResourceID for the NetworkEndpointGroups resource.
func NewNetworkEndpointGroupsResourceID(project, zone, name string) *ResourceID {
key := meta.ZonalKey(name, zone)
return &ResourceID{project, "networkEndpointGroups", key}
}
// NewProjectsResourceID creates a ResourceID for the Projects resource.
func NewProjectsResourceID(project string) *ResourceID {
var key *meta.Key
return &ResourceID{project, "projects", key}
}
// NewRegionBackendServicesResourceID creates a ResourceID for the RegionBackendServices resource.
func NewRegionBackendServicesResourceID(project, region, name string) *ResourceID {
key := meta.RegionalKey(name, region)
return &ResourceID{project, "backendServices", key}
}
// NewRegionDisksResourceID creates a ResourceID for the RegionDisks resource.
func NewRegionDisksResourceID(project, region, name string) *ResourceID {
key := meta.RegionalKey(name, region)
return &ResourceID{project, "disks", key}
}
// NewRegionsResourceID creates a ResourceID for the Regions resource.
func NewRegionsResourceID(project, name string) *ResourceID {
key := meta.GlobalKey(name)
return &ResourceID{project, "regions", key}
}
// NewRoutesResourceID creates a ResourceID for the Routes resource.
func NewRoutesResourceID(project, name string) *ResourceID {
key := meta.GlobalKey(name)
return &ResourceID{project, "routes", key}
}
// NewSslCertificatesResourceID creates a ResourceID for the SslCertificates resource.
func NewSslCertificatesResourceID(project, name string) *ResourceID {
key := meta.GlobalKey(name)
return &ResourceID{project, "sslCertificates", key}
}
// NewTargetHttpProxiesResourceID creates a ResourceID for the TargetHttpProxies resource.
func NewTargetHttpProxiesResourceID(project, name string) *ResourceID {
key := meta.GlobalKey(name)
return &ResourceID{project, "targetHttpProxies", key}
}
// NewTargetHttpsProxiesResourceID creates a ResourceID for the TargetHttpsProxies resource.
func NewTargetHttpsProxiesResourceID(project, name string) *ResourceID {
key := meta.GlobalKey(name)
return &ResourceID{project, "targetHttpsProxies", key}
}
// NewTargetPoolsResourceID creates a ResourceID for the TargetPools resource.
func NewTargetPoolsResourceID(project, region, name string) *ResourceID {
key := meta.RegionalKey(name, region)
return &ResourceID{project, "targetPools", key}
}
// NewUrlMapsResourceID creates a ResourceID for the UrlMaps resource.
func NewUrlMapsResourceID(project, name string) *ResourceID {
key := meta.GlobalKey(name)
return &ResourceID{project, "urlMaps", key}
}
// NewZonesResourceID creates a ResourceID for the Zones resource.
func NewZonesResourceID(project, name string) *ResourceID {
key := meta.GlobalKey(name)
return &ResourceID{project, "zones", key}
}

View File

@ -28,7 +28,6 @@ import (
"log"
"os"
"os/exec"
"sort"
"text/template"
"time"
@ -986,6 +985,38 @@ func (g *{{.GCEWrapType}}) {{.FcnArgs}} {
}
}
// genTypes generates the type wrappers.
func genResourceIDs(wr io.Writer) {
const text = `
// New{{.Service}}ResourceID creates a ResourceID for the {{.Service}} resource.
{{- if .KeyIsProject}}
func New{{.Service}}ResourceID(project string) *ResourceID {
var key *meta.Key
{{- else}}
{{- if .KeyIsGlobal}}
func New{{.Service}}ResourceID(project, name string) *ResourceID {
key := meta.GlobalKey(name)
{{- end}}
{{- if .KeyIsRegional}}
func New{{.Service}}ResourceID(project, region, name string) *ResourceID {
key := meta.RegionalKey(name, region)
{{- end}}
{{- if .KeyIsZonal}}
func New{{.Service}}ResourceID(project, zone, name string) *ResourceID {
key := meta.ZonalKey(name, zone)
{{- end -}}
{{end}}
return &ResourceID{project, "{{.Resource}}", key}
}
`
tmpl := template.Must(template.New("resourceIDs").Parse(text))
for _, sg := range meta.SortedServicesGroups {
if err := tmpl.Execute(wr, sg.ServiceInfo()); err != nil {
panic(err)
}
}
}
func genUnitTestHeader(wr io.Writer) {
const text = `/*
Copyright {{.Year}} The Kubernetes Authors.
@ -1238,20 +1269,86 @@ func Test{{.Service}}Group(t *testing.T) {
}
`
tmpl := template.Must(template.New("unittest").Parse(text))
// Sort keys so the output will be stable.
var keys []string
for k := range meta.AllServicesByGroup {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
s := meta.AllServicesByGroup[k]
if err := tmpl.Execute(wr, s); err != nil {
for _, sg := range meta.SortedServicesGroups {
if err := tmpl.Execute(wr, sg); err != nil {
panic(err)
}
}
}
func genUnitTestResourceIDConversion(wr io.Writer) {
const text = `
func TestResourceIDConversion(t *testing.T) {
t.Parallel()
for _, id := range []*ResourceID{
{{- range .Groups}}
{{- with .ServiceInfo}}
{{- if .KeyIsProject}}
New{{.Service}}ResourceID("my-{{.Resource}}-resource"),
{{- else}}
{{- if .KeyIsGlobal}}
New{{.Service}}ResourceID("some-project", "my-{{.Resource}}-resource"),
{{- end}}
{{- if .KeyIsRegional}}
New{{.Service}}ResourceID("some-project", "us-central1", "my-{{.Resource}}-resource"),
{{- end}}
{{- if .KeyIsZonal}}
New{{.Service}}ResourceID("some-project", "us-east1-b", "my-{{.Resource}}-resource"),
{{- end -}}
{{end -}}
{{end -}}
{{end}}
} {
t.Run(id.Resource, func(t *testing.T) {
// Test conversion to and from full URL.
fullURL := id.SelfLink(meta.VersionGA)
parsedID, err := ParseResourceURL(fullURL)
if err != nil {
t.Errorf("ParseResourceURL(%s) = _, %v, want nil", fullURL, err)
}
if !reflect.DeepEqual(id, parsedID) {
t.Errorf("SelfLink(%+v) -> ParseResourceURL(%s) = %+v, want original ID", id, fullURL, parsedID)
}
// Test conversion to and from relative resource name.
relativeName := id.RelativeResourceName()
parsedID, err = ParseResourceURL(relativeName)
if err != nil {
t.Errorf("ParseResourceURL(%s) = _, %v, want nil", relativeName, err)
}
if !reflect.DeepEqual(id, parsedID) {
t.Errorf("RelativeResourceName(%+v) -> ParseResourceURL(%s) = %+v, want original ID", id, relativeName, parsedID)
}
// Do not test ResourcePath for projects.
if id.Resource == "projects" {
return
}
// Test conversion to and from resource path.
resourcePath := id.ResourcePath()
parsedID, err = ParseResourceURL(resourcePath)
if err != nil {
t.Errorf("ParseResourceURL(%s) = _, %v, want nil", resourcePath, err)
}
id.ProjectID = ""
if !reflect.DeepEqual(id, parsedID) {
t.Errorf("ResourcePath(%+v) -> ParseResourceURL(%s) = %+v, want %+v", id, resourcePath, parsedID, id)
}
})
}
}
`
data := struct {
Groups []*meta.ServiceGroup
}{meta.SortedServicesGroups}
tmpl := template.Must(template.New("unittest-resourceIDs").Parse(text))
if err := tmpl.Execute(wr, data); err != nil {
panic(err)
}
}
func main() {
flag.Parse()
@ -1262,9 +1359,11 @@ func main() {
genHeader(out)
genStubs(out)
genTypes(out)
genResourceIDs(out)
case "test":
genUnitTestHeader(out)
genUnitTestServices(out)
genUnitTestResourceIDConversion(out)
default:
log.Fatalf("Invalid -mode: %q", flags.mode)
}

View File

@ -1807,3 +1807,72 @@ func TestZonesGroup(t *testing.T) {
// Delete not found.
}
func TestResourceIDConversion(t *testing.T) {
t.Parallel()
for _, id := range []*ResourceID{
NewAddressesResourceID("some-project", "us-central1", "my-addresses-resource"),
NewBackendServicesResourceID("some-project", "my-backendServices-resource"),
NewDisksResourceID("some-project", "us-east1-b", "my-disks-resource"),
NewFirewallsResourceID("some-project", "my-firewalls-resource"),
NewForwardingRulesResourceID("some-project", "us-central1", "my-forwardingRules-resource"),
NewGlobalAddressesResourceID("some-project", "my-addresses-resource"),
NewGlobalForwardingRulesResourceID("some-project", "my-forwardingRules-resource"),
NewHealthChecksResourceID("some-project", "my-healthChecks-resource"),
NewHttpHealthChecksResourceID("some-project", "my-httpHealthChecks-resource"),
NewHttpsHealthChecksResourceID("some-project", "my-httpsHealthChecks-resource"),
NewInstanceGroupsResourceID("some-project", "us-east1-b", "my-instanceGroups-resource"),
NewInstancesResourceID("some-project", "us-east1-b", "my-instances-resource"),
NewNetworkEndpointGroupsResourceID("some-project", "us-east1-b", "my-networkEndpointGroups-resource"),
NewProjectsResourceID("my-projects-resource"),
NewRegionBackendServicesResourceID("some-project", "us-central1", "my-backendServices-resource"),
NewRegionDisksResourceID("some-project", "us-central1", "my-disks-resource"),
NewRegionsResourceID("some-project", "my-regions-resource"),
NewRoutesResourceID("some-project", "my-routes-resource"),
NewSslCertificatesResourceID("some-project", "my-sslCertificates-resource"),
NewTargetHttpProxiesResourceID("some-project", "my-targetHttpProxies-resource"),
NewTargetHttpsProxiesResourceID("some-project", "my-targetHttpsProxies-resource"),
NewTargetPoolsResourceID("some-project", "us-central1", "my-targetPools-resource"),
NewUrlMapsResourceID("some-project", "my-urlMaps-resource"),
NewZonesResourceID("some-project", "my-zones-resource"),
} {
t.Run(id.Resource, func(t *testing.T) {
// Test conversion to and from full URL.
fullURL := id.SelfLink(meta.VersionGA)
parsedID, err := ParseResourceURL(fullURL)
if err != nil {
t.Errorf("ParseResourceURL(%s) = _, %v, want nil", fullURL, err)
}
if !reflect.DeepEqual(id, parsedID) {
t.Errorf("SelfLink(%+v) -> ParseResourceURL(%s) = %+v, want original ID", id, fullURL, parsedID)
}
// Test conversion to and from relative resource name.
relativeName := id.RelativeResourceName()
parsedID, err = ParseResourceURL(relativeName)
if err != nil {
t.Errorf("ParseResourceURL(%s) = _, %v, want nil", relativeName, err)
}
if !reflect.DeepEqual(id, parsedID) {
t.Errorf("RelativeResourceName(%+v) -> ParseResourceURL(%s) = %+v, want original ID", id, relativeName, parsedID)
}
// Do not test ResourcePath for projects.
if id.Resource == "projects" {
return
}
// Test conversion to and from resource path.
resourcePath := id.ResourcePath()
parsedID, err = ParseResourceURL(resourcePath)
if err != nil {
t.Errorf("ParseResourceURL(%s) = _, %v, want nil", resourcePath, err)
}
id.ProjectID = ""
if !reflect.DeepEqual(id, parsedID) {
t.Errorf("ResourcePath(%+v) -> ParseResourceURL(%s) = %+v, want %+v", id, resourcePath, parsedID, id)
}
})
}
}

View File

@ -20,6 +20,7 @@ import (
"errors"
"fmt"
"reflect"
"sort"
)
// ServiceInfo defines the entry for a Service that code will be generated for.
@ -159,6 +160,13 @@ func (i *ServiceInfo) KeyIsZonal() bool {
return i.keyType == Zonal
}
// KeyIsProject is true if the key represents the project resource.
func (i *ServiceInfo) KeyIsProject() bool {
// Projects are a special resource for ResourceId because there is no 'key' value. This func
// is used by the generator to not accept a key parameter.
return i.Service == "Projects"
}
// MakeKey returns the call used to create the appropriate key type.
func (i *ServiceInfo) MakeKey(name, location string) string {
switch i.keyType {
@ -220,15 +228,20 @@ type ServiceGroup struct {
GA *ServiceInfo
}
// Service returns any ServiceInfo object belonging to the ServiceGroup.
// Service returns any ServiceInfo string belonging to the ServiceGroup.
func (sg *ServiceGroup) Service() string {
return sg.ServiceInfo().Service
}
// ServiceInfo returns any ServiceInfo object belonging to the ServiceGroup.
func (sg *ServiceGroup) ServiceInfo() *ServiceInfo {
switch {
case sg.GA != nil:
return sg.GA.Service
return sg.GA
case sg.Alpha != nil:
return sg.Alpha.Service
return sg.Alpha
case sg.Beta != nil:
return sg.Beta.Service
return sg.Beta
default:
panic(errors.New("service group is empty"))
}
@ -272,6 +285,16 @@ func groupServices(services []*ServiceInfo) map[string]*ServiceGroup {
// AllServicesByGroup is a map of service name to ServicesGroup.
var AllServicesByGroup map[string]*ServiceGroup
// SortedServicesGroups is a slice of Servicegroup sorted by Service name.
var SortedServicesGroups []*ServiceGroup
func init() {
AllServicesByGroup = groupServices(AllServices)
for _, sg := range AllServicesByGroup {
SortedServicesGroups = append(SortedServicesGroups, sg)
}
sort.Slice(SortedServicesGroups, func(i, j int) bool {
return SortedServicesGroups[i].Service() < SortedServicesGroups[j].Service()
})
}

View File

@ -25,9 +25,9 @@ import (
)
const (
gaPrefix = "https://www.googleapis.com/compute/v1/"
alphaPrefix = "https://www.googleapis.com/compute/alpha/"
betaPrefix = "https://www.googleapis.com/compute/beta/"
gaPrefix = "https://www.googleapis.com/compute/v1"
alphaPrefix = "https://www.googleapis.com/compute/alpha"
betaPrefix = "https://www.googleapis.com/compute/beta"
)
// ResourceID identifies a GCE resource as parsed from compute resource URL.
@ -51,8 +51,27 @@ func (r *ResourceID) Equal(other *ResourceID) bool {
return false
}
// RelativeResourceName returns the relative resource name string
// representing this ResourceID.
func (r *ResourceID) RelativeResourceName() string {
return RelativeResourceName(r.ProjectID, r.Resource, r.Key)
}
// ResourcePath returns the resource path representing this ResourceID.
func (r *ResourceID) ResourcePath() string {
return ResourcePath(r.Resource, r.Key)
}
func (r *ResourceID) SelfLink(ver meta.Version) string {
return SelfLink(ver, r.ProjectID, r.Resource, r.Key)
}
// ParseResourceURL parses resource URLs of the following formats:
//
// global/<res>/<name>
// regions/<region>/<res>/<name>
// zones/<zone>/<res>/<name>
// projects/<proj>
// projects/<proj>/global/<res>/<name>
// projects/<proj>/regions/<region>/<res>/<name>
// projects/<proj>/zones/<zone>/<res>/<name>
@ -62,64 +81,63 @@ func (r *ResourceID) Equal(other *ResourceID) bool {
func ParseResourceURL(url string) (*ResourceID, error) {
errNotValid := fmt.Errorf("%q is not a valid resource URL", url)
// Remove the prefix up to ...projects/
// Trim prefix off URL leaving "projects/..."
projectsIndex := strings.Index(url, "/projects/")
if projectsIndex >= 0 {
url = url[projectsIndex+1:]
}
parts := strings.Split(url, "/")
if len(parts) < 2 || parts[0] != "projects" {
if len(parts) < 2 || len(parts) > 6 {
return nil, errNotValid
}
ret := &ResourceID{ProjectID: parts[1]}
if len(parts) == 2 {
ret := &ResourceID{}
scopedName := parts
if parts[0] == "projects" {
ret.Resource = "projects"
return ret, nil
}
ret.ProjectID = parts[1]
scopedName = parts[2:]
if len(parts) < 4 {
return nil, errNotValid
}
if len(parts) == 4 {
switch parts[2] {
case "regions":
ret.Resource = "regions"
ret.Key = meta.GlobalKey(parts[3])
if len(scopedName) == 0 {
return ret, nil
case "zones":
ret.Resource = "zones"
ret.Key = meta.GlobalKey(parts[3])
}
}
switch scopedName[0] {
case "global":
if len(scopedName) != 3 {
return nil, errNotValid
}
ret.Resource = scopedName[1]
ret.Key = meta.GlobalKey(scopedName[2])
return ret, nil
case "regions":
switch len(scopedName) {
case 2:
ret.Resource = "regions"
ret.Key = meta.GlobalKey(scopedName[1])
return ret, nil
case 4:
ret.Resource = scopedName[2]
ret.Key = meta.RegionalKey(scopedName[3], scopedName[1])
return ret, nil
default:
return nil, errNotValid
}
}
switch parts[2] {
case "global":
if len(parts) != 5 {
return nil, errNotValid
}
ret.Resource = parts[3]
ret.Key = meta.GlobalKey(parts[4])
return ret, nil
case "regions":
if len(parts) != 6 {
return nil, errNotValid
}
ret.Resource = parts[4]
ret.Key = meta.RegionalKey(parts[5], parts[3])
return ret, nil
case "zones":
if len(parts) != 6 {
switch len(scopedName) {
case 2:
ret.Resource = "zones"
ret.Key = meta.GlobalKey(scopedName[1])
return ret, nil
case 4:
ret.Resource = scopedName[2]
ret.Key = meta.ZonalKey(scopedName[3], scopedName[1])
return ret, nil
default:
return nil, errNotValid
}
ret.Resource = parts[4]
ret.Key = meta.ZonalKey(parts[5], parts[3])
return ret, nil
}
return nil, errNotValid
}
@ -132,6 +150,38 @@ func copyViaJSON(dest, src interface{}) error {
return json.Unmarshal(bytes, dest)
}
// ResourcePath returns the path starting from the location.
// Example: regions/us-central1/subnetworks/my-subnet
func ResourcePath(resource string, key *meta.Key) string {
switch resource {
case "zones", "regions":
return fmt.Sprintf("%s/%s", resource, key.Name)
case "projects":
return "invalid-resource"
}
switch key.Type() {
case meta.Zonal:
return fmt.Sprintf("zones/%s/%s/%s", key.Zone, resource, key.Name)
case meta.Regional:
return fmt.Sprintf("regions/%s/%s/%s", key.Region, resource, key.Name)
case meta.Global:
return fmt.Sprintf("global/%s/%s", resource, key.Name)
}
return "invalid-key-type"
}
// RelativeResourceName returns the path starting from project.
// Example: projects/my-project/regions/us-central1/subnetworks/my-subnet
func RelativeResourceName(project, resource string, key *meta.Key) string {
switch resource {
case "projects":
return fmt.Sprintf("projects/%s", project)
default:
return fmt.Sprintf("projects/%s/%s", project, ResourcePath(resource, key))
}
}
// SelfLink returns the self link URL for the given object.
func SelfLink(ver meta.Version, project, resource string, key *meta.Key) string {
var prefix string
@ -146,13 +196,6 @@ func SelfLink(ver meta.Version, project, resource string, key *meta.Key) string
prefix = "invalid-prefix"
}
switch key.Type() {
case meta.Zonal:
return fmt.Sprintf("%sprojects/%s/zones/%s/%s/%s", prefix, project, key.Zone, resource, key.Name)
case meta.Regional:
return fmt.Sprintf("%sprojects/%s/regions/%s/%s/%s", prefix, project, key.Region, resource, key.Name)
case meta.Global:
return fmt.Sprintf("%sprojects/%s/%s/%s", prefix, project, resource, key.Name)
}
return "invalid-self-link"
return fmt.Sprintf("%s/%s", prefix, RelativeResourceName(project, resource, key))
}

View File

@ -23,6 +23,54 @@ import (
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta"
)
func TestEqualResourceID(t *testing.T) {
t.Parallel()
for _, tc := range []struct {
a *ResourceID
b *ResourceID
}{
{
a: &ResourceID{"some-gce-project", "projects", nil},
b: &ResourceID{"some-gce-project", "projects", nil},
},
{
a: &ResourceID{"", "networks", meta.GlobalKey("my-net")},
b: &ResourceID{"", "networks", meta.GlobalKey("my-net")},
},
{
a: &ResourceID{"some-gce-project", "projects", meta.GlobalKey("us-central1")},
b: &ResourceID{"some-gce-project", "projects", meta.GlobalKey("us-central1")},
},
} {
if !tc.a.Equal(tc.b) {
t.Errorf("%v.Equal(%v) = false, want true", tc.a, tc.b)
}
}
for _, tc := range []struct {
a *ResourceID
b *ResourceID
}{
{
a: &ResourceID{"some-gce-project", "projects", nil},
b: &ResourceID{"some-other-project", "projects", nil},
},
{
a: &ResourceID{"some-gce-project", "projects", nil},
b: &ResourceID{"some-gce-project", "projects", meta.GlobalKey("us-central1")},
},
{
a: &ResourceID{"some-gce-project", "networks", meta.GlobalKey("us-central1")},
b: &ResourceID{"some-gce-project", "projects", meta.GlobalKey("us-central1")},
},
} {
if tc.a.Equal(tc.b) {
t.Errorf("%v.Equal(%v) = true, want false", tc.a, tc.b)
}
}
}
func TestParseResourceURL(t *testing.T) {
t.Parallel()
@ -90,6 +138,18 @@ func TestParseResourceURL(t *testing.T) {
"projects/some-gce-project/zones/us-central1-c/instances/instance-1",
&ResourceID{"some-gce-project", "instances", meta.ZonalKey("instance-1", "us-central1-c")},
},
{
"global/networks/my-network",
&ResourceID{"", "networks", meta.GlobalKey("my-network")},
},
{
"regions/us-central1/subnetworks/my-subnet",
&ResourceID{"", "subnetworks", meta.RegionalKey("my-subnet", "us-central1")},
},
{
"zones/us-central1-c/instances/instance-1",
&ResourceID{"", "instances", meta.ZonalKey("instance-1", "us-central1-c")},
},
} {
r, err := ParseResourceURL(tc.in)
if err != nil {
@ -112,7 +172,9 @@ func TestParseResourceURL(t *testing.T) {
"/a/b/c/d/e/f",
"https://www.googleapis.com/compute/v1/projects/some-gce-project/global",
"projects/some-gce-project/global",
"projects/some-gce-project/global/foo",
"projects/some-gce-project/global/foo/bar/baz",
"projects/some-gce-project/regions/us-central1/res",
"projects/some-gce-project/zones/us-central1-c/res",
"projects/some-gce-project/zones/us-central1-c/res/name/extra",
} {
@ -198,7 +260,28 @@ func TestSelfLink(t *testing.T) {
"proj4",
"urlMaps",
meta.GlobalKey("key3"),
"https://www.googleapis.com/compute/v1/projects/proj4/urlMaps/key3",
"https://www.googleapis.com/compute/v1/projects/proj4/global/urlMaps/key3",
},
{
meta.VersionGA,
"proj4",
"projects",
nil,
"https://www.googleapis.com/compute/v1/projects/proj4",
},
{
meta.VersionGA,
"proj4",
"regions",
meta.GlobalKey("us-central1"),
"https://www.googleapis.com/compute/v1/projects/proj4/regions/us-central1",
},
{
meta.VersionGA,
"proj4",
"zones",
meta.GlobalKey("us-central1-a"),
"https://www.googleapis.com/compute/v1/projects/proj4/zones/us-central1-a",
},
} {
if link := SelfLink(tc.ver, tc.project, tc.resource, tc.key); link != tc.want {

View File

@ -321,7 +321,7 @@ func TestUpdateInternalLoadBalancerBackendServices(t *testing.T) {
assert.Equal(
t,
bs.HealthChecks,
[]string{fmt.Sprintf("%s/healthChecks/k8s-%s-node", url_base, vals.ClusterID)},
[]string{fmt.Sprintf("%s/global/healthChecks/k8s-%s-node", url_base, vals.ClusterID)},
)
}