// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // To run these tests, set GCLOUD_TESTS_GOLANG_PROJECT_ID env var to your GCP projectID package compute import ( "context" "fmt" "net/http" "net/http/httptest" "strings" "testing" "time" "google.golang.org/api/option" "cloud.google.com/go/internal" "github.com/googleapis/gax-go/v2" "github.com/google/go-cmp/cmp" "cloud.google.com/go/internal/testutil" "cloud.google.com/go/internal/uid" "google.golang.org/api/iterator" computepb "google.golang.org/genproto/googleapis/cloud/compute/v1" "google.golang.org/protobuf/proto" ) var projectId = testutil.ProjID() var defaultZone = "us-central1-a" var image = "projects/debian-cloud/global/images/family/debian-10" func TestCreateGetPutPatchListInstance(t *testing.T) { if testing.Short() { t.Skip("skipping smoke test in short mode") } space := uid.NewSpace("gogapic", nil) name := space.New() ctx := context.Background() c, err := NewInstancesRESTClient(ctx) if err != nil { t.Fatal(err) } createRequest := &computepb.InsertInstanceRequest{ Project: projectId, Zone: defaultZone, InstanceResource: &computepb.Instance{ Name: &name, Description: proto.String("тест"), MachineType: proto.String(fmt.Sprintf("https://www.googleapis.com/compute/v1/projects/%s/zones/%s/machineTypes/n1-standard-1", projectId, defaultZone)), Disks: []*computepb.AttachedDisk{ { AutoDelete: proto.Bool(true), Boot: proto.Bool(true), Type: proto.String(computepb.AttachedDisk_PERSISTENT.String()), InitializeParams: &computepb.AttachedDiskInitializeParams{ SourceImage: proto.String(image), }, }, }, NetworkInterfaces: []*computepb.NetworkInterface{ { AccessConfigs: []*computepb.AccessConfig{ { Name: proto.String("default"), }, }, }, }, }, } insert, err := c.Insert(ctx, createRequest) if err != nil { t.Fatal(err) } err = insert.Wait(ctx) defer ForceDeleteInstance(ctx, name, c) if err != nil { t.Fatal(err) } getRequest := &computepb.GetInstanceRequest{ Project: projectId, Zone: defaultZone, Instance: name, } get, err := c.Get(ctx, getRequest) if err != nil { t.Fatal(err) } if get.GetName() != name { t.Fatalf("expected instance name: %s, got: %s", name, get.GetName()) } if get.GetDescription() != "тест" { t.Fatalf("expected instance description: %s, got: %s", "тест", get.GetDescription()) } if secureBootEnabled := get.GetShieldedInstanceConfig().GetEnableSecureBoot(); secureBootEnabled { t.Fatalf("expected instance secure boot: %t, got: %t", false, get.GetShieldedInstanceConfig().GetEnableSecureBoot()) } get.Description = proto.String("updated") updateRequest := &computepb.UpdateInstanceRequest{ Instance: name, InstanceResource: get, Project: projectId, Zone: defaultZone, } updateOp, err := c.Update(ctx, updateRequest) if err != nil { t.Error(err) } err = updateOp.Wait(ctx) if err != nil { t.Fatal(err) } patchReq := &computepb.UpdateShieldedInstanceConfigInstanceRequest{ Instance: name, Project: projectId, Zone: defaultZone, ShieldedInstanceConfigResource: &computepb.ShieldedInstanceConfig{ EnableSecureBoot: proto.Bool(true), }, } patchOp, err := c.UpdateShieldedInstanceConfig(ctx, patchReq) if err != nil { return } err = patchOp.Wait(ctx) if err != nil { t.Fatal(err) } fetched, err := c.Get(ctx, getRequest) if err != nil { t.Fatal(err) } if fetched.GetDescription() != "updated" { t.Fatal(fmt.Sprintf("expected instance description: %s, got: %s", "updated", fetched.GetDescription())) } if secureBootEnabled := fetched.GetShieldedInstanceConfig().GetEnableSecureBoot(); !secureBootEnabled { t.Fatal(fmt.Sprintf("expected instance secure boot: %t, got: %t", true, secureBootEnabled)) } listRequest := &computepb.ListInstancesRequest{ Project: projectId, Zone: defaultZone, } itr := c.List(ctx, listRequest) if err != nil { t.Fatal(err) } found := false element, err := itr.Next() for err == nil { if element.GetName() == name { found = true } element, err = itr.Next() } if err != nil && err != iterator.Done { t.Fatal(err) } if !found { t.Error("Couldn't find the instance in list response") } deleteInstanceRequest := &computepb.DeleteInstanceRequest{ Project: projectId, Zone: defaultZone, Instance: name, } _, err = c.Delete(ctx, deleteInstanceRequest) if err != nil { t.Error(err) } } func ForceDeleteInstance(ctx context.Context, name string, client *InstancesClient) { deleteInstanceRequest := &computepb.DeleteInstanceRequest{ Project: projectId, Zone: defaultZone, Instance: name, } client.Delete(ctx, deleteInstanceRequest) } func TestCreateGetRemoveSecurityPolicies(t *testing.T) { if testing.Short() { t.Skip("skipping smoke test in short mode") } space := uid.NewSpace("gogapic", nil) name := space.New() ctx := context.Background() c, err := NewSecurityPoliciesRESTClient(ctx) if err != nil { t.Fatal(err) } action := "allow" matcher := &computepb.SecurityPolicyRuleMatcher{ Config: &computepb.SecurityPolicyRuleMatcherConfig{ SrcIpRanges: []string{ "*", }, }, VersionedExpr: proto.String(computepb.SecurityPolicyRuleMatcher_SRC_IPS_V1.String()), } securityPolicyRule := &computepb.SecurityPolicyRule{ Action: &action, Priority: proto.Int32(0), Description: proto.String("test rule"), Match: matcher, } securityPolicyRuleDefault := &computepb.SecurityPolicyRule{ Action: &action, Priority: proto.Int32(2147483647), Description: proto.String("default rule"), Match: matcher, } insertRequest := &computepb.InsertSecurityPolicyRequest{ Project: projectId, SecurityPolicyResource: &computepb.SecurityPolicy{ Name: &name, Rules: []*computepb.SecurityPolicyRule{ securityPolicyRule, securityPolicyRuleDefault, }, }, } insert, err := c.Insert(ctx, insertRequest) if err != nil { t.Fatal(err) } err = insert.Wait(ctx) defer ForceDeleteSecurityPolicy(ctx, name, c) if err != nil { t.Fatal(err) } removeRuleRequest := &computepb.RemoveRuleSecurityPolicyRequest{ Priority: proto.Int32(0), Project: projectId, SecurityPolicy: name, } rule, err := c.RemoveRule(ctx, removeRuleRequest) if err != nil { t.Error(err) } err = rule.Wait(ctx) if err != nil { t.Fatal(err) } getRequest := &computepb.GetSecurityPolicyRequest{ Project: projectId, SecurityPolicy: name, } get, err := c.Get(ctx, getRequest) if err != nil { t.Error(err) } if len(get.GetRules()) != 1 { t.Fatalf("expected count for rules: %d, got: %d", 1, len(get.GetRules())) } deleteRequest := &computepb.DeleteSecurityPolicyRequest{ Project: projectId, SecurityPolicy: name, } _, err = c.Delete(ctx, deleteRequest) if err != nil { t.Error(err) } } func ForceDeleteSecurityPolicy(ctx context.Context, name string, client *SecurityPoliciesClient) { deleteRequest := &computepb.DeleteSecurityPolicyRequest{ Project: projectId, SecurityPolicy: name, } client.Delete(ctx, deleteRequest) } func TestPaginationWithMaxRes(t *testing.T) { if testing.Short() { t.Skip("skipping smoke test in short mode") } ctx := context.Background() c, err := NewAcceleratorTypesRESTClient(ctx) if err != nil { t.Fatal(err) } req := &computepb.ListAcceleratorTypesRequest{ Project: projectId, Zone: defaultZone, MaxResults: proto.Uint32(1), } itr := c.List(ctx, req) found := false element, err := itr.Next() for err == nil { if element.GetName() == "nvidia-tesla-t4" { found = true break } element, err = itr.Next() } if err != nil && err != iterator.Done { t.Fatal(err) } if !found { t.Error("Couldn't find the accelerator in the response") } } func TestPaginationDefault(t *testing.T) { if testing.Short() { t.Skip("skipping smoke test in short mode") } ctx := context.Background() c, err := NewAcceleratorTypesRESTClient(ctx) if err != nil { t.Fatal(err) } req := &computepb.ListAcceleratorTypesRequest{ Project: projectId, Zone: defaultZone, } itr := c.List(ctx, req) found := false element, err := itr.Next() for err == nil { if element.GetName() == "nvidia-tesla-t4" { found = true break } element, err = itr.Next() } if err != nil && err != iterator.Done { t.Fatal(err) } if !found { t.Error("Couldn't find the accelerator in the response") } } func TestPaginationMapResponse(t *testing.T) { if testing.Short() { t.Skip("skipping smoke test in short mode") } ctx := context.Background() c, err := NewAcceleratorTypesRESTClient(ctx) if err != nil { t.Fatal(err) } req := &computepb.AggregatedListAcceleratorTypesRequest{ Project: projectId, } itr := c.AggregatedList(ctx, req) found := false element, err := itr.Next() for err == nil { if element.Key == "zones/us-central1-a" { types := element.Value.GetAcceleratorTypes() for _, item := range types { if item.GetName() == "nvidia-tesla-t4" { found = true break } } } element, err = itr.Next() } if err != iterator.Done { t.Fatal(err) } if !found { t.Error("Couldn't find the accelerator in the response") } } func TestPaginationMapResponseMaxRes(t *testing.T) { if testing.Short() { t.Skip("skipping smoke test in short mode") } ctx := context.Background() c, err := NewAcceleratorTypesRESTClient(ctx) if err != nil { t.Fatal(err) } req := &computepb.AggregatedListAcceleratorTypesRequest{ Project: projectId, MaxResults: proto.Uint32(10), } itr := c.AggregatedList(ctx, req) found := false element, err := itr.Next() for err == nil { if element.Key == "zones/us-central1-a" { types := element.Value.GetAcceleratorTypes() for _, item := range types { if item.GetName() == "nvidia-tesla-t4" { found = true break } } } element, err = itr.Next() } if err != iterator.Done { t.Fatal(err) } if !found { t.Error("Couldn't find the accelerator in the response") } } func TestCapitalLetter(t *testing.T) { if testing.Short() { t.Skip("skipping smoke test in short mode") } ctx := context.Background() c, err := NewFirewallsRESTClient(ctx) if err != nil { t.Fatal(err) } space := uid.NewSpace("gogapic", nil) name := space.New() allowed := []*computepb.Allowed{ { IPProtocol: proto.String("tcp"), Ports: []string{ "80", }, }, } res := &computepb.Firewall{ SourceRanges: []string{ "0.0.0.0/0", }, Name: proto.String(name), Allowed: allowed, } req := &computepb.InsertFirewallRequest{ Project: projectId, FirewallResource: res, } insert, err := c.Insert(ctx, req) if err != nil { t.Fatal(err) } err = insert.Wait(ctx) if err != nil { t.Fatal(err) } defer func() { timeoutCtx, cancel := context.WithTimeout(ctx, 5*time.Minute) defer cancel() err = internal.Retry(timeoutCtx, gax.Backoff{}, func() (stop bool, err error) { _, err = c.Delete(timeoutCtx, &computepb.DeleteFirewallRequest{ Project: projectId, Firewall: name, }) return err == nil, err }) if err != nil { t.Error(err) } }() fetched, err := c.Get(ctx, &computepb.GetFirewallRequest{ Project: projectId, Firewall: name, }) if err != nil { t.Error(err) } if diff := cmp.Diff(fetched.GetAllowed(), allowed, cmp.Comparer(proto.Equal)); diff != "" { t.Fatalf("got(-),want(+):\n%s", diff) } } func TestHeaders(t *testing.T) { ctx := context.Background() svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { contentType := r.Header.Get("Content-Type") xGoog := r.Header.Get("X-Goog-Api-Client") if contentType != "application/json" { t.Fatalf("Content-Type header was %s, expected `application/json`.", contentType) } if !strings.Contains(xGoog, "rest/") { t.Fatal("X-Goog-Api-Client header doesn't contain `rest/`") } })) defer svr.Close() opts := []option.ClientOption{ option.WithEndpoint(svr.URL), option.WithoutAuthentication(), } c, err := NewAcceleratorTypesRESTClient(ctx, opts...) if err != nil { t.Fatal(err) } _, err = c.Get(ctx, &computepb.GetAcceleratorTypeRequest{ AcceleratorType: "test", Project: "test", Zone: "test", }) if err != nil { return } } func TestInstanceGroupResize(t *testing.T) { // we test a required query-param field set to 0 if testing.Short() { t.Skip("skipping smoke test in short mode") } ctx := context.Background() instanceTemplatesClient, err := NewInstanceTemplatesRESTClient(ctx) if err != nil { t.Fatal(err) } instanceGroupManagersClient, err := NewInstanceGroupManagersRESTClient(ctx) if err != nil { t.Fatal(err) } space := uid.NewSpace("gogapic", nil) templateName := space.New() managerName := space.New() templateResource := &computepb.InstanceTemplate{ Name: proto.String(templateName), Properties: &computepb.InstanceProperties{ MachineType: proto.String("n2-standard-2"), Disks: []*computepb.AttachedDisk{ { AutoDelete: proto.Bool(true), Boot: proto.Bool(true), Type: proto.String(computepb.AttachedDisk_PERSISTENT.String()), InitializeParams: &computepb.AttachedDiskInitializeParams{ SourceImage: proto.String(image), }, }, }, NetworkInterfaces: []*computepb.NetworkInterface{ { AccessConfigs: []*computepb.AccessConfig{ { Name: proto.String("default"), Type: proto.String(computepb.AccessConfig_ONE_TO_ONE_NAT.String()), }, }, }, }, }, } insertOp, err := instanceTemplatesClient.Insert( ctx, &computepb.InsertInstanceTemplateRequest{ Project: projectId, InstanceTemplateResource: templateResource, }) if err != nil { t.Fatal(err) } err = insertOp.Wait(ctx) if err != nil { t.Fatal(err) } defer func() { _, err = instanceTemplatesClient.Delete( ctx, &computepb.DeleteInstanceTemplateRequest{ Project: projectId, InstanceTemplate: templateName, }) if err != nil { t.Error(err) } }() igmResource := &computepb.InstanceGroupManager{ BaseInstanceName: proto.String("gogapic"), TargetSize: proto.Int32(1), InstanceTemplate: proto.String(insertOp.Proto().GetTargetLink()), Name: proto.String(managerName), } insertOp, err = instanceGroupManagersClient.Insert( ctx, &computepb.InsertInstanceGroupManagerRequest{ Project: projectId, Zone: defaultZone, InstanceGroupManagerResource: igmResource, }, ) if err != nil { t.Fatal(err) } err = insertOp.Wait(ctx) if err != nil { t.Fatal(err) } defer func() { timeoutCtx, cancel := context.WithTimeout(ctx, 5*time.Minute) defer cancel() deleteOp, err := instanceGroupManagersClient.Delete( timeoutCtx, &computepb.DeleteInstanceGroupManagerRequest{ Zone: defaultZone, Project: projectId, InstanceGroupManager: managerName, }) if err != nil { t.Error(err) } err = internal.Retry(timeoutCtx, gax.Backoff{}, func() (stop bool, err error) { err = deleteOp.Wait(ctx) return deleteOp.Done(), err }) if err != nil { t.Error(err) } }() fetched, err := instanceGroupManagersClient.Get( ctx, &computepb.GetInstanceGroupManagerRequest{ Project: projectId, Zone: defaultZone, InstanceGroupManager: managerName, }) if err != nil { t.Fatal(err) } if fetched.GetTargetSize() != 1 { t.Fatalf("expected target size: %d, got: %d", 1, fetched.GetTargetSize()) } resizeOperation, err := instanceGroupManagersClient.Resize( ctx, &computepb.ResizeInstanceGroupManagerRequest{ Project: projectId, Size: 0, Zone: defaultZone, InstanceGroupManager: managerName, }) if err != nil { t.Fatal(err) } err = resizeOperation.Wait(ctx) if err != nil { t.Fatal(err) } fetched, err = instanceGroupManagersClient.Get( ctx, &computepb.GetInstanceGroupManagerRequest{ Project: projectId, Zone: defaultZone, InstanceGroupManager: managerName, }) if err != nil { t.Fatal(err) } if fetched.GetTargetSize() != 0 { t.Fatalf("expected target size: %d, got: %d", 0, fetched.GetTargetSize()) } }