github.com/verrazzano/verrazzano@v1.7.1/cluster-operator/apis/clusters/v1alpha1/common_webhook_test.go (about)

     1  // Copyright (c) 2023, Oracle and/or its affiliates.
     2  // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
     3  
     4  package v1alpha1
     5  
     6  import (
     7  	"context"
     8  	"github.com/oracle/oci-go-sdk/v53/core"
     9  	"github.com/stretchr/testify/assert"
    10  	"github.com/verrazzano/verrazzano/cluster-operator/controllers/quickcreate/controller/oci"
    11  	ocifake "github.com/verrazzano/verrazzano/cluster-operator/controllers/quickcreate/controller/oci/fake"
    12  	vzerror "github.com/verrazzano/verrazzano/cluster-operator/internal/errors"
    13  	corev1 "k8s.io/api/core/v1"
    14  	"k8s.io/client-go/kubernetes/scheme"
    15  	"os"
    16  	clipkg "sigs.k8s.io/controller-runtime/pkg/client"
    17  	"sigs.k8s.io/controller-runtime/pkg/client/fake"
    18  	"sigs.k8s.io/yaml"
    19  	"testing"
    20  )
    21  
    22  func testValidationContextWithOCIClient(cli clipkg.Client, ociClient oci.Client) *validationContext {
    23  	return &validationContext{
    24  		Ctx: context.TODO(),
    25  		Cli: cli,
    26  		OCIClientGetter: func(creds *oci.Credentials) (oci.Client, error) {
    27  			return ociClient, nil
    28  		},
    29  		CredentialsLoader: &ocifake.CredentialsLoaderImpl{
    30  			Credentials: &oci.Credentials{},
    31  		},
    32  		Errors: &vzerror.ErrorAggregator{},
    33  	}
    34  }
    35  
    36  func testValidationContext(cli clipkg.Client) *validationContext {
    37  	return testValidationContextWithOCIClient(cli, nil)
    38  }
    39  
    40  func testOCNEConfigMap() (*corev1.ConfigMap, error) {
    41  	d, err := os.ReadFile("../../../controllers/quickcreate/controller/ocne/testdata/ocne-versions.yaml")
    42  	if err != nil {
    43  		return nil, err
    44  	}
    45  	cm := &corev1.ConfigMap{}
    46  	if err := yaml.Unmarshal(d, cm); err != nil {
    47  		return nil, err
    48  	}
    49  	return cm, nil
    50  }
    51  
    52  func TestAddOCINodeErrors(t *testing.T) {
    53  	var (
    54  		flexShape    = "VM.Standard.E4.Flex"
    55  		nonFlexShape = "BM.Standard.E5"
    56  		one          = 1
    57  		fifty        = 50
    58  	)
    59  	var tests = []struct {
    60  		name     string
    61  		node     OCINode
    62  		hasError bool
    63  	}{
    64  		{
    65  			"no error when ocpus/memory are not provided for a flex shape",
    66  			OCINode{
    67  				Shape:         &flexShape,
    68  				OCPUs:         &one,
    69  				MemoryGbs:     &one,
    70  				BootVolumeGbs: &fifty,
    71  				Replicas:      &one,
    72  			},
    73  			false,
    74  		},
    75  		{
    76  			"no error when ocpus/memory are provided for a flex shape",
    77  			OCINode{
    78  				Shape:         &flexShape,
    79  				OCPUs:         &one,
    80  				MemoryGbs:     &one,
    81  				BootVolumeGbs: &fifty,
    82  				Replicas:      &one,
    83  			},
    84  			false,
    85  		},
    86  		{
    87  			"error when providing ocpus without flex shape",
    88  			OCINode{
    89  				Shape:         &nonFlexShape,
    90  				OCPUs:         &one,
    91  				BootVolumeGbs: &fifty,
    92  				Replicas:      &one,
    93  			},
    94  			true,
    95  		},
    96  		{
    97  			"error when providing memory without flex shape",
    98  			OCINode{
    99  				Shape:         &nonFlexShape,
   100  				MemoryGbs:     &one,
   101  				BootVolumeGbs: &fifty,
   102  				Replicas:      &one,
   103  			},
   104  			true,
   105  		},
   106  	}
   107  
   108  	for _, tt := range tests {
   109  		t.Run(tt.name, func(t *testing.T) {
   110  			ctx := testValidationContext(nil)
   111  			addOCINodeErrors(ctx, tt.node, "")
   112  			assert.Equal(t, tt.hasError, ctx.Errors.HasError())
   113  		})
   114  	}
   115  }
   116  
   117  func TestAddOCINetworkErrors(t *testing.T) {
   118  	var (
   119  		vcnID    = "my-vcn"
   120  		subnetID = "my-subnet"
   121  		lbSubnet = Subnet{
   122  			Role: SubnetRoleServiceLB,
   123  			ID:   subnetID,
   124  		}
   125  		workerSubnet = Subnet{
   126  			Role: SubnetRoleWorker,
   127  			ID:   subnetID,
   128  		}
   129  		cpSubnet = Subnet{
   130  			Role: SubnetRoleControlPlane,
   131  			ID:   subnetID,
   132  		}
   133  		cpeSubnet = Subnet{
   134  			Role: SubnetRoleControlPlaneEndpoint,
   135  			ID:   subnetID,
   136  		}
   137  		subnets = []Subnet{
   138  			workerSubnet,
   139  			lbSubnet,
   140  			cpSubnet,
   141  			cpeSubnet,
   142  		}
   143  	)
   144  	ociClient := &ocifake.ClientImpl{
   145  		VCN: &core.Vcn{
   146  			Id: &vcnID,
   147  		},
   148  	}
   149  	var tests = []struct {
   150  		name     string
   151  		network  *Network
   152  		hasError bool
   153  	}{
   154  		{
   155  			"no error when using creating a VCN without existing VCN/subnet ids",
   156  			&Network{
   157  				CreateVCN: true,
   158  			},
   159  			false,
   160  		},
   161  		{
   162  			"error when creating a VCN, but a VCN id is supplied",
   163  			&Network{
   164  				CreateVCN: true,
   165  				VCN:       vcnID,
   166  			},
   167  			true,
   168  		},
   169  		{
   170  			"error when creating a VCN, but subnets are supplied",
   171  			&Network{
   172  				CreateVCN: true,
   173  				Subnets:   subnets,
   174  			},
   175  			true,
   176  		},
   177  		{
   178  			"error when using an existing a VCN, and not enough subnets are supplied",
   179  			&Network{
   180  				CreateVCN: false,
   181  				VCN:       vcnID,
   182  				Subnets:   []Subnet{workerSubnet},
   183  			},
   184  			true,
   185  		},
   186  		{
   187  			"no error when using an existing vcn and subnets",
   188  			&Network{
   189  				CreateVCN: false,
   190  				VCN:       vcnID,
   191  				Subnets:   subnets,
   192  			},
   193  			false,
   194  		},
   195  		{
   196  			"error when vcn is not found",
   197  			&Network{
   198  				CreateVCN: false,
   199  				VCN:       "unknown",
   200  				Subnets:   subnets,
   201  			},
   202  			true,
   203  		},
   204  	}
   205  
   206  	for _, tt := range tests {
   207  		t.Run(tt.name, func(t *testing.T) {
   208  			ctx := testValidationContext(nil)
   209  			addOCINetworkErrors(ctx, ociClient, tt.network, 4, "")
   210  			assert.Equal(t, tt.hasError, ctx.Errors.HasError())
   211  		})
   212  	}
   213  }
   214  
   215  func TestAddOCNEErrors(t *testing.T) {
   216  	ocneConfigMap, err := testOCNEConfigMap()
   217  	assert.NoError(t, err)
   218  	ocneVersion := "1.7"
   219  	cliWithCM := fake.NewClientBuilder().WithObjects(ocneConfigMap).WithScheme(scheme.Scheme).Build()
   220  	var tests = []struct {
   221  		name        string
   222  		ocneVersion string
   223  
   224  		cli      clipkg.Client
   225  		hasError bool
   226  	}{
   227  		{"no errors when using valid OCNE version and configmap is present",
   228  			ocneVersion,
   229  
   230  			cliWithCM,
   231  			false,
   232  		},
   233  		{"error when using invalid OCNE version",
   234  			"boom",
   235  
   236  			cliWithCM,
   237  			true,
   238  		},
   239  		{"error when OCNE Versions are not presnet",
   240  			ocneVersion,
   241  
   242  			fake.NewClientBuilder().WithScheme(scheme.Scheme).Build(),
   243  			true,
   244  		},
   245  	}
   246  
   247  	for _, tt := range tests {
   248  		t.Run(tt.name, func(t *testing.T) {
   249  			ctx := testValidationContext(tt.cli)
   250  			addOCNEErrors(ctx, OCNE{
   251  				Version: tt.ocneVersion,
   252  			}, "")
   253  			assert.Equal(t, tt.hasError, ctx.Errors.HasError())
   254  		})
   255  	}
   256  }
   257  
   258  func TestAddProxyErrors(t *testing.T) {
   259  	var tests = []struct {
   260  		name     string
   261  		proxy    *Proxy
   262  		hasError bool
   263  	}{
   264  		{
   265  			"no error when proxy is nil",
   266  			nil,
   267  			false,
   268  		},
   269  		{
   270  			"no error when proxy has valid urls",
   271  			&Proxy{
   272  				HTTPProxy:  "http://foo.com",
   273  				HTTPSProxy: "https://foo.com",
   274  				NoProxy:    "",
   275  			},
   276  			false,
   277  		},
   278  		{
   279  			"error when proxy has invalid urls",
   280  			&Proxy{
   281  				HTTPProxy: "x",
   282  			},
   283  			true,
   284  		},
   285  	}
   286  	for _, tt := range tests {
   287  		t.Run(tt.name, func(t *testing.T) {
   288  			ctx := testValidationContext(nil)
   289  			addProxyErrors(ctx, tt.proxy, "")
   290  			assert.Equal(t, tt.hasError, ctx.Errors.HasError())
   291  		})
   292  	}
   293  }
   294  
   295  func TestAddPrivateRegistryErrors(t *testing.T) {
   296  	var tests = []struct {
   297  		name            string
   298  		privateRegistry *PrivateRegistry
   299  		hasError        bool
   300  	}{
   301  		{
   302  			"no error when private registry is nil",
   303  			nil,
   304  			false,
   305  		},
   306  		{
   307  			"no error when private registry has valid urls",
   308  			&PrivateRegistry{
   309  				URL: "http://my-registry.com:80",
   310  			},
   311  			false,
   312  		},
   313  		{
   314  			"error when private registry has invalid urls",
   315  			&PrivateRegistry{
   316  				URL: "x",
   317  			},
   318  			true,
   319  		},
   320  	}
   321  	for _, tt := range tests {
   322  		t.Run(tt.name, func(t *testing.T) {
   323  			ctx := testValidationContext(nil)
   324  			addPrivateRegistryErrors(ctx, tt.privateRegistry, "")
   325  			assert.Equal(t, tt.hasError, ctx.Errors.HasError())
   326  		})
   327  	}
   328  }