Skip to content

Commit

Permalink
Merge pull request GoogleCloudPlatform#2223 from gemmahou/mock-comput…
Browse files Browse the repository at this point in the history
…einstance

MockGCP: Support for ComputeInstance
  • Loading branch information
google-oss-prow[bot] authored Jul 4, 2024
2 parents 4cda964 + b2f9862 commit b2b3257
Show file tree
Hide file tree
Showing 20 changed files with 4,684 additions and 37 deletions.
1 change: 1 addition & 0 deletions config/tests/samples/create/harness.go
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,7 @@ func MaybeSkip(t *testing.T, name string, resources []*unstructured.Unstructured
case schema.GroupKind{Group: "compute.cnrm.cloud.google.com", Kind: "ComputeAddress"}:
case schema.GroupKind{Group: "compute.cnrm.cloud.google.com", Kind: "ComputeDisk"}:
case schema.GroupKind{Group: "compute.cnrm.cloud.google.com", Kind: "ComputeHealthCheck"}:
case schema.GroupKind{Group: "compute.cnrm.cloud.google.com", Kind: "ComputeInstance"}:
case schema.GroupKind{Group: "compute.cnrm.cloud.google.com", Kind: "ComputeNetwork"}:
case schema.GroupKind{Group: "compute.cnrm.cloud.google.com", Kind: "ComputeNodeGroup"}:
case schema.GroupKind{Group: "compute.cnrm.cloud.google.com", Kind: "ComputeNodeTemplate"}:
Expand Down
67 changes: 47 additions & 20 deletions mockgcp/mock_http_roundtrip.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,14 +215,27 @@ func (m *mockRoundTripper) prefilterRequest(req *http.Request) error {
return fmt.Errorf("error reading request body: %w", err)
}

s := requestBody.String()
if requestBody.Len() != 0 {
o := make(map[string]any)
if err := json.Unmarshal(requestBody.Bytes(), &o); err != nil {
return fmt.Errorf("parsing json: %w", err)
}

s, err := m.modifyUpdateMask(s)
if err != nil {
return err
}
if err := m.modifyUpdateMask(o); err != nil {
return err
}

req.Body = io.NopCloser(strings.NewReader(s))
if err := pruneNilArrays(o); err != nil {
return err
}

b, err := json.Marshal(o)
if err != nil {
return fmt.Errorf("building json: %w", err)
}

req.Body = io.NopCloser(bytes.NewBuffer(b))
}
}
return nil
}
Expand All @@ -233,16 +246,7 @@ func (m *mockRoundTripper) prefilterRequest(req *http.Request) error {
// However, because GCP APIs seem to accept display_name or displayName over JSON.
// If we don't map display_name => displayName, the proto validation will reject it.
// e.g. https://github.com/grpc-ecosystem/grpc-gateway/issues/2239
func (m *mockRoundTripper) modifyUpdateMask(s string) (string, error) {
if len(s) == 0 {
return "", nil
}

o := make(map[string]any)
if err := json.Unmarshal([]byte(s), &o); err != nil {
return "", fmt.Errorf("parsing json: %w", err)
}

func (m *mockRoundTripper) modifyUpdateMask(o map[string]any) error {
for k, v := range o {
switch k {
case "updateMask":
Expand All @@ -257,11 +261,34 @@ func (m *mockRoundTripper) modifyUpdateMask(s string) (string, error) {
o[k] = strings.Join(tokens, ",")
}
}
b, err := json.Marshal(o)
if err != nil {
return "", fmt.Errorf("building json: %w", err)

return nil
}

// pruneNilArrays replaces [nil] => []
// For some reason terraform sends [nil], which is not really valid
func pruneNilArrays(o map[string]any) error {
for k, v := range o {
if v == nil {
continue
}
switch v := v.(type) {
case map[string]any:
if err := pruneNilArrays(v); err != nil {
return err
}
case []any:
if len(v) == 1 && v[0] == nil {
o[k] = []any{}
}
case string, int64, bool, float64:
// ignore
default:
return fmt.Errorf("unhandled type %T", v)
}
}
return string(b), nil

return nil
}

// roundTripIAMPolicy serves the IAM policy verbs (e.g. :getIamPolicy)
Expand Down
14 changes: 14 additions & 0 deletions mockgcp/mockcompute/disksv1.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,20 @@ func (s *DisksV1) Insert(ctx context.Context, req *pb.InsertDiskRequest) (*pb.Op
obj.PhysicalBlockSizeBytes = PtrTo(int64(4096))
}

if obj.SourceImage != nil {
tokens := strings.Split(*obj.SourceImage, "/")
if len(tokens) == 2 {
// debian-cloud/debian-11
obj.SourceImage = PtrTo("https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-11-bullseye-v20231010")
obj.SourceImageId = PtrTo("2443108620951880213")
}
if len(tokens) == 6 {
// projects/debian-cloud/global/images/family/debian-11
obj.SourceImage = PtrTo("https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-11-bullseye-v20231010")
obj.SourceImageId = PtrTo("2443108620951880213")
}
}

if err := s.storage.Create(ctx, fqn, obj); err != nil {
return nil, err
}
Expand Down
60 changes: 60 additions & 0 deletions mockgcp/mockcompute/imagesv1.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Copyright 2022 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
//
// 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 mockcompute

import (
"context"

pb "github.com/GoogleCloudPlatform/k8s-config-connector/mockgcp/generated/mockgcp/cloud/compute/v1"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)

type ImagesV1 struct {
*MockService
pb.UnimplementedImagesServer
}

func (s *ImagesV1) GetFromFamily(ctx context.Context, req *pb.GetFromFamilyImageRequest) (*pb.Image, error) {
obj := &pb.Image{}

// Details from gcloud compute images describe-from-family debian-11 --project debian-cloud --log-http
obj.Kind = PtrTo("compute#image")
obj.Name = PtrTo("debian-11-bullseye-v20231010")
obj.Description = PtrTo("Debian, Debian GNU/Linux, 11 (bullseye), amd64 built on 20231010")
obj.SelfLink = PtrTo("https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-11-bullseye-v20231010")
obj.Family = PtrTo("debian-11")
obj.Status = PtrTo("UP")

return obj, nil
}

func (s *ImagesV1) Get(ctx context.Context, req *pb.GetImageRequest) (*pb.Image, error) {
// {
// "error": {
// "code": 404,
// "message": "The resource 'projects/debian-cloud/global/images/debian-11' was not found",
// "errors": [
// {
// "message": "The resource 'projects/debian-cloud/global/images/debian-11' was not found",
// "domain": "global",
// "reason": "notFound"
// }
// ]
// }
// }

return nil, status.Errorf(codes.NotFound, "image not found")
}
Loading

0 comments on commit b2b3257

Please sign in to comment.