Skip to content

Commit

Permalink
Clean up functions and add slice utility functions (GoogleCloudPlatfo…
Browse files Browse the repository at this point in the history
…rm#10210)

* Clean up function all_resourcerefs

* Add slice utility functions

* Change sensitive_props as resource method
  • Loading branch information
zli82016 authored and cmfeng committed Apr 5, 2024
1 parent 1b880f3 commit 5e93475
Show file tree
Hide file tree
Showing 4 changed files with 185 additions and 44 deletions.
45 changes: 4 additions & 41 deletions mmv1/api/resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -389,11 +389,6 @@ def all_nested_properties(props)
nested
end

# Returns all resourcerefs at any depth
def all_resourcerefs
resourcerefs_for_properties(all_user_properties, self)
end

# All settable properties in the resource.
# Fingerprints aren't *really" settable properties, but they behave like one.
# At Create, they have no value but they can just be read in anyways, and after a Read
Expand Down Expand Up @@ -425,6 +420,10 @@ def root_properties
end
end

def sensitive_props
all_nested_properties(root_properties).select(&:sensitive)
end

# Return the product-level async object, or the resource-specific one
# if one exists.
def async
Expand Down Expand Up @@ -770,41 +769,5 @@ def validate_identity
if all_user_properties.select { |p| p.name == i }.empty?
end
end

# Given an array of properties, return all ResourceRefs contained within
# Requires:
# props- a list of props
# original_object - the original object containing props. This is to
# avoid self-referencing objects.
def resourcerefs_for_properties(props, original_obj)
rrefs = []
props.each do |p|
# We need to recurse on ResourceRefs to get all levels
# We do not want to recurse on resourcerefs of type self to avoid
# infinite loop.
if p.is_a? Api::Type::ResourceRef
# We want to avoid a circular reference
# This reference may be the next reference or have some number of refs
# in between it.
next if p.resource_ref == original_obj
next if p.resource_ref == p.__resource

rrefs << p
rrefs.concat(resourcerefs_for_properties(p.resource_ref
.required_properties,
original_obj))
elsif !p.nested_properties.nil?
rrefs.concat(resourcerefs_for_properties(p.nested_properties, original_obj))
elsif p.is_a? Api::Type::Array
if p.item_type.is_a? Api::Type::ResourceRef
rrefs << p.item_type
rrefs.concat(resourcerefs_for_properties(p.item_type.resource_ref
.required_properties,
original_obj))
end
end
end
rrefs.uniq
end
end
end
41 changes: 41 additions & 0 deletions mmv1/google/slice_utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright 2024 Google Inc.
// 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 google

// Returns a new slice containing all of the elements
// for which the test function returns true in the original slice
func Select[T any](S []T, test func(T) bool) (ret []T) {
for _, s := range S {
if test(s) {
ret = append(ret, s)
}
}
return
}

// Returns a new slice containing all of the elements
// for which the test function returns false in the original slice
func Reject[T any](S []T, test func(T) bool) (ret []T) {
for _, s := range S {
if !test(s) {
ret = append(ret, s)
}
}
return
}

// Concat two slices
func Concat[T any](S1 []T, S2 []T) (ret []T) {
return append(S1, S2...)
}
138 changes: 138 additions & 0 deletions mmv1/google/slice_utils_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package google

import (
"reflect"
"testing"
)

func TestSliceSelect(t *testing.T) {
t.Parallel()

cases := []struct {
description string
S []int
testFun func(int) bool
expected int
}{
{
description: "interger slice selects even numbers",
S: []int{0, 1, 2},
testFun: func(n int) bool {
return n%2 == 0
},
expected: 2,
},
{
description: "empty slice",
S: make([]int, 0),
testFun: func(n int) bool {
return n%2 == 0
},
expected: 0,
},
{
description: "nil slice",
S: nil,
testFun: func(n int) bool {
return n%2 == 0
},
expected: 0,
},
}

for _, tc := range cases {
tc := tc

t.Run(tc.description, func(t *testing.T) {
t.Parallel()

if got, want := len(Select(tc.S, tc.testFun)), tc.expected; !reflect.DeepEqual(got, want) {
t.Errorf("expected %v to be %v", got, want)
}
})
}
}

func TestSliceReject(t *testing.T) {
t.Parallel()

cases := []struct {
description string
S []int
testFun func(int) bool
expected int
}{
{
description: "interger slice rejects even numbers",
S: []int{0, 1, 2},
testFun: func(n int) bool {
return n%2 == 0
},
expected: 1,
},
{
description: "empty slice",
S: make([]int, 0),
testFun: func(n int) bool {
return n%2 == 0
},
expected: 0,
},
{
description: "nil slice",
S: nil,
testFun: func(n int) bool {
return n%2 == 0
},
expected: 0,
},
}

for _, tc := range cases {
tc := tc

t.Run(tc.description, func(t *testing.T) {
t.Parallel()

if got, want := len(Reject(tc.S, tc.testFun)), tc.expected; !reflect.DeepEqual(got, want) {
t.Errorf("expected %v to be %v", got, want)
}
})
}
}

func TestSliceConcat(t *testing.T) {
t.Parallel()

cases := []struct {
description string
S1 []int
S2 []int
expected int
}{
{
description: "interger slice rejects even numbers",
S1: []int{0, 1, 2},
S2: []int{3, 4},
expected: 5,
},
{
description: "empty slice",
S1: nil,
S2: make([]int, 0),
expected: 0,
},
}

for _, tc := range cases {
tc := tc

t.Run(tc.description, func(t *testing.T) {
t.Parallel()

if got, want := len(Concat(tc.S1, tc.S2)), tc.expected; !reflect.DeepEqual(got, want) {
t.Errorf("expected %v to be %v", got, want)
}
})
}
}
5 changes: 2 additions & 3 deletions mmv1/templates/terraform/resource.html.markdown.erb
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
tf_subcategory = (object.__product.display_name)
terraform_name = object.legacy_name || "google_#{tf_product}_#{object.name.underscore}"
properties = object.all_user_properties
sensitive_props = object.all_nested_properties(object.root_properties).select(&:sensitive)
# In order of preference, use TF override,
# general defined timeouts, or default Timeouts
timeouts = object.timeouts
Expand Down Expand Up @@ -87,9 +86,9 @@ To get more information about <%= object.name -%>, see:
~> **Note:** <%= object.docs.note -%>
<%- end -%>
<%- if !sensitive_props.empty? -%>
<%- if !object.sensitive_props.empty? -%>
<%-
sense_props = sensitive_props.map! {|prop| "`"+prop.lineage+"`"}.join(', ')
sense_props = object.sensitive_props.map! {|prop| "`"+prop.lineage+"`"}.join(', ')
-%>

~> **Warning:** All arguments including the following potentially sensitive
Expand Down

0 comments on commit 5e93475

Please sign in to comment.