Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compute/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ require (
cloud.google.com/go/storage v1.43.0
github.com/GoogleCloudPlatform/golang-samples v0.0.0-20240724083556-7f760db013b7
github.com/google/uuid v1.6.0
github.com/googleapis/gax-go/v2 v2.13.0
google.golang.org/api v0.193.0
google.golang.org/protobuf v1.34.2
)
Expand All @@ -23,7 +24,6 @@ require (
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/google/s2a-go v0.1.8 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
github.com/googleapis/gax-go/v2 v2.13.0 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect
Expand Down
79 changes: 79 additions & 0 deletions compute/reservations/create_shared_reservation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Copyright 2024 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.

package snippets

// [START compute_reservation_create_shared]
import (
"context"
"fmt"
"io"

computepb "cloud.google.com/go/compute/apiv1/computepb"
"google.golang.org/protobuf/proto"
)

// Creates shared reservation from given template in particular zone
func createSharedReservation(w io.Writer, client ClientInterface, projectID, baseProjectId, zone, reservationName, sourceTemplate string) error {
// client, err := compute.NewReservationsRESTClient(ctx)
// projectID := "your_project_id". Destination of sharing.
// baseProjectId := "your_project_id2". Project where the reservation will be created.
// zone := "us-west3-a"
// reservationName := "your_reservation_name"
// sourceTemplate: existing template path. Following formats are allowed:
// - projects/{project_id}/global/instanceTemplates/{template_name}
// - projects/{project_id}/regions/{region}/instanceTemplates/{template_name}
// - https://www.googleapis.com/compute/v1/projects/{project_id}/global/instanceTemplates/instanceTemplate
// - https://www.googleapis.com/compute/v1/projects/{project_id}/regions/{region}/instanceTemplates/instanceTemplate

ctx := context.Background()

shareSettings := map[string]*computepb.ShareSettingsProjectConfig{
projectID: {ProjectId: proto.String(projectID)},
}

req := &computepb.InsertReservationRequest{
Project: baseProjectId,
ReservationResource: &computepb.Reservation{
Name: proto.String(reservationName),
Zone: proto.String(zone),
SpecificReservation: &computepb.AllocationSpecificSKUReservation{
Count: proto.Int64(2),
SourceInstanceTemplate: proto.String(sourceTemplate),
},
ShareSettings: &computepb.ShareSettings{
ProjectMap: shareSettings,
ShareType: proto.String("SPECIFIC_PROJECTS"),
},
},
Zone: zone,
}

op, err := client.Insert(ctx, req)
if err != nil {
return fmt.Errorf("unable to create reservation: %w", err)
}

if op != nil {
if err = op.Wait(ctx); err != nil {
return fmt.Errorf("unable to wait for the operation: %w", err)
}
}

fmt.Fprintf(w, "Reservation created\n")

return nil
}

// [END compute_reservation_create_shared]
45 changes: 45 additions & 0 deletions compute/reservations/mock_shared_project.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright 2024 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.

// Mock objects for shared project

package snippets

import (
"context"

compute "cloud.google.com/go/compute/apiv1"
computepb "cloud.google.com/go/compute/apiv1/computepb"
gax "github.com/googleapis/gax-go/v2"
)

type ClientInterface interface {
Close() error
Delete(context.Context, *computepb.DeleteReservationRequest, ...gax.CallOption) (*compute.Operation, error)
Insert(context.Context, *computepb.InsertReservationRequest, ...gax.CallOption) (*compute.Operation, error)
}

type ReservationsClient struct{}

func (client ReservationsClient) Close() error {
return nil
}

func (client ReservationsClient) Insert(context.Context, *computepb.InsertReservationRequest, ...gax.CallOption) (*compute.Operation, error) {
return nil, nil
}

func (client ReservationsClient) Delete(context.Context, *computepb.DeleteReservationRequest, ...gax.CallOption) (*compute.Operation, error) {
return nil, nil
}
41 changes: 40 additions & 1 deletion compute/reservations/reservations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@ func TestReservations(t *testing.T) {
templateName := fmt.Sprintf("test-template-%v-%v", time.Now().Format("01-02-2006"), r.Int())

var buf bytes.Buffer

err := createTemplate(tc.ProjectID, templateName)
if err != nil {
t.Errorf("createTemplate got err: %v", err)
Expand Down Expand Up @@ -200,4 +199,44 @@ func TestReservations(t *testing.T) {
t.Errorf("deleteReservation got err: %v", err)
}
})

t.Run("Shared reservation CRUD", func(t *testing.T) {
reservationName := fmt.Sprintf("test-reservation-%v-%v", time.Now().Format("01-02-2006"), r.Int())
baseProjectID := tc.ProjectID
// This test require 2 projects, therefore one of them is mocked.
// If you want to make a real test, please adjust projectID accordingly and uncomment reservationsClient creation.
// Make sure that base project has proper permissions to share reservations.
// See: https://cloud.google.com/compute/docs/instances/reservations-shared#shared_reservation_constraint
destinationProjectID := "some-project"
ctx := context.Background()

want := "Reservation created"

// Uncomment line below if you want to run the test without mocks
// reservationsClient, err := compute.NewReservationsRESTClient(ctx)
reservationsClient := ReservationsClient{}
if err != nil {
t.Errorf("Couldn't create reservationsClient, err: %v", err)
}
defer reservationsClient.Close()

if err := createSharedReservation(&buf, reservationsClient, destinationProjectID, baseProjectID, zone, reservationName, *sourceTemplate.SelfLink); err != nil {
t.Errorf("createSharedReservation got err: %v", err)
}
if got := buf.String(); !strings.Contains(got, want) {
t.Errorf("createSharedReservation got %s, want %s", got, want)
}
buf.Reset()

req := &computepb.DeleteReservationRequest{
Project: baseProjectID,
Reservation: reservationName,
Zone: zone,
}

_, err = reservationsClient.Delete(ctx, req)
if err != nil {
t.Errorf("unable to delete reservation: %v", err)
}
})
}
Loading