github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/provider/oci/common_integration_test.go (about)

     1  // Copyright 2018 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package oci_test
     5  
     6  import (
     7  	"context"
     8  	stdcontext "context"
     9  	"fmt"
    10  	"time"
    11  
    12  	"github.com/juju/clock/testclock"
    13  	gitjujutesting "github.com/juju/testing"
    14  	jc "github.com/juju/testing/checkers"
    15  	"github.com/juju/version/v2"
    16  	ociCore "github.com/oracle/oci-go-sdk/v65/core"
    17  	ociIdentity "github.com/oracle/oci-go-sdk/v65/identity"
    18  	gomock "go.uber.org/mock/gomock"
    19  	gc "gopkg.in/check.v1"
    20  
    21  	"github.com/juju/juju/core/arch"
    22  	"github.com/juju/juju/environs"
    23  	environscloudspec "github.com/juju/juju/environs/cloudspec"
    24  	"github.com/juju/juju/environs/config"
    25  	"github.com/juju/juju/environs/tags"
    26  	"github.com/juju/juju/provider/oci"
    27  	ocitesting "github.com/juju/juju/provider/oci/testing"
    28  	jujutesting "github.com/juju/juju/testing"
    29  	"github.com/juju/juju/tools"
    30  )
    31  
    32  var clk = testclock.NewClock(time.Time{})
    33  var advancingClock = testclock.AutoAdvancingClock{clk, clk.Advance}
    34  
    35  func makeToolsList(series string) tools.List {
    36  	var toolsVersion version.Binary
    37  	toolsVersion.Number = version.MustParse("2.4.0")
    38  	toolsVersion.Arch = arch.AMD64
    39  	toolsVersion.Release = series
    40  	return tools.List{{
    41  		Version: toolsVersion,
    42  		URL:     fmt.Sprintf("http://example.com/tools/juju-%s.tgz", toolsVersion),
    43  		SHA256:  "1234567890abcdef",
    44  		Size:    1024,
    45  	}}
    46  }
    47  
    48  func makeListSecurityListsRequestResponse(seclistDetails []ociCore.SecurityList) (ociCore.ListSecurityListsRequest, ociCore.ListSecurityListsResponse) {
    49  	if len(seclistDetails) == 0 {
    50  		return ociCore.ListSecurityListsRequest{}, ociCore.ListSecurityListsResponse{}
    51  	}
    52  
    53  	compartment := seclistDetails[0].CompartmentId
    54  	vcnId := seclistDetails[0].VcnId
    55  	request := ociCore.ListSecurityListsRequest{
    56  		CompartmentId: compartment,
    57  		VcnId:         vcnId,
    58  	}
    59  	response := ociCore.ListSecurityListsResponse{
    60  		Items: seclistDetails,
    61  	}
    62  
    63  	return request, response
    64  }
    65  
    66  func makeListInternetGatewaysRequestResponse(gwDetails []ociCore.InternetGateway) (ociCore.ListInternetGatewaysRequest, ociCore.ListInternetGatewaysResponse) {
    67  	if len(gwDetails) == 0 {
    68  		return ociCore.ListInternetGatewaysRequest{}, ociCore.ListInternetGatewaysResponse{}
    69  	}
    70  
    71  	compartment := gwDetails[0].CompartmentId
    72  	vcnId := gwDetails[0].VcnId
    73  	request := ociCore.ListInternetGatewaysRequest{
    74  		CompartmentId: compartment,
    75  		VcnId:         vcnId,
    76  	}
    77  	response := ociCore.ListInternetGatewaysResponse{
    78  		Items: gwDetails,
    79  	}
    80  	return request, response
    81  }
    82  
    83  func makeListRouteTableRequestResponse(routeDetails []ociCore.RouteTable) (ociCore.ListRouteTablesRequest, ociCore.ListRouteTablesResponse) {
    84  	if len(routeDetails) == 0 {
    85  		return ociCore.ListRouteTablesRequest{}, ociCore.ListRouteTablesResponse{}
    86  	}
    87  
    88  	compartment := routeDetails[0].CompartmentId
    89  	vcnId := routeDetails[0].VcnId
    90  
    91  	request := ociCore.ListRouteTablesRequest{
    92  		CompartmentId: compartment,
    93  		VcnId:         vcnId,
    94  	}
    95  	response := ociCore.ListRouteTablesResponse{
    96  		Items: routeDetails,
    97  	}
    98  	return request, response
    99  }
   100  
   101  func makeListInstancesRequestResponse(instances []ociCore.Instance) (ociCore.ListInstancesRequest, ociCore.ListInstancesResponse) {
   102  
   103  	if len(instances) == 0 {
   104  		return ociCore.ListInstancesRequest{}, ociCore.ListInstancesResponse{}
   105  	}
   106  
   107  	compartment := instances[0].CompartmentId
   108  
   109  	request := ociCore.ListInstancesRequest{
   110  		CompartmentId: compartment,
   111  	}
   112  
   113  	response := ociCore.ListInstancesResponse{
   114  		Items: instances,
   115  	}
   116  
   117  	return request, response
   118  }
   119  
   120  func makeListAvailabilityDomainsRequestResponse(azDetails []ociIdentity.AvailabilityDomain) (ociIdentity.ListAvailabilityDomainsRequest, ociIdentity.ListAvailabilityDomainsResponse) {
   121  	if len(azDetails) == 0 {
   122  		return ociIdentity.ListAvailabilityDomainsRequest{}, ociIdentity.ListAvailabilityDomainsResponse{}
   123  	}
   124  
   125  	compartment := azDetails[0].CompartmentId
   126  	request := ociIdentity.ListAvailabilityDomainsRequest{
   127  		CompartmentId: compartment,
   128  	}
   129  
   130  	response := ociIdentity.ListAvailabilityDomainsResponse{
   131  		Items: azDetails,
   132  	}
   133  	return request, response
   134  }
   135  
   136  func makeGetVnicRequestResponse(vnicDetails []ociCore.GetVnicResponse) ([]ociCore.GetVnicRequest, []ociCore.GetVnicResponse) {
   137  	requests := make([]ociCore.GetVnicRequest, len(vnicDetails))
   138  	responses := make([]ociCore.GetVnicResponse, len(vnicDetails))
   139  
   140  	for idx, val := range vnicDetails {
   141  		requests[idx] = ociCore.GetVnicRequest{
   142  			VnicId: val.Id,
   143  		}
   144  
   145  		responses[idx] = val
   146  	}
   147  
   148  	return requests, responses
   149  }
   150  
   151  func newFakeOCIInstance(Id, compartment string, state ociCore.InstanceLifecycleStateEnum) *ociCore.Instance {
   152  	return &ociCore.Instance{
   153  		AvailabilityDomain: makeStringPointer("fake-az"),
   154  		Id:                 &Id,
   155  		CompartmentId:      &compartment,
   156  		Region:             makeStringPointer("us-phoenix-1"),
   157  		Shape:              makeStringPointer("VM.Standard1.1"),
   158  		DisplayName:        makeStringPointer("fakeName"),
   159  		FreeformTags:       map[string]string{},
   160  		LifecycleState:     state,
   161  	}
   162  }
   163  
   164  func makeGetInstanceRequestResponse(instanceDetails ociCore.Instance) (ociCore.GetInstanceRequest, ociCore.GetInstanceResponse) {
   165  	request := ociCore.GetInstanceRequest{
   166  		InstanceId: instanceDetails.Id,
   167  	}
   168  
   169  	response := ociCore.GetInstanceResponse{
   170  		Instance: instanceDetails,
   171  	}
   172  
   173  	return request, response
   174  }
   175  
   176  func makeListVnicAttachmentsRequestResponse(vnicAttachDetails []ociCore.VnicAttachment) (ociCore.ListVnicAttachmentsRequest, ociCore.ListVnicAttachmentsResponse) {
   177  	if len(vnicAttachDetails) == 0 {
   178  		return ociCore.ListVnicAttachmentsRequest{}, ociCore.ListVnicAttachmentsResponse{}
   179  	}
   180  	compartment := vnicAttachDetails[0].CompartmentId
   181  	instanceID := vnicAttachDetails[0].InstanceId
   182  
   183  	request := ociCore.ListVnicAttachmentsRequest{
   184  		CompartmentId: compartment,
   185  		InstanceId:    instanceID,
   186  	}
   187  
   188  	response := ociCore.ListVnicAttachmentsResponse{
   189  		Items: vnicAttachDetails,
   190  	}
   191  	return request, response
   192  }
   193  
   194  func listShapesResponse() []ociCore.Shape {
   195  	return []ociCore.Shape{
   196  		{
   197  			Shape:                    makeStringPointer("VM.Standard1.1"),
   198  			ProcessorDescription:     makeStringPointer("2.0 GHz Intel® Xeon® Platinum 8167M (Skylake)"),
   199  			Ocpus:                    makeFloat32Pointer(1),
   200  			MemoryInGBs:              makeFloat32Pointer(7),
   201  			LocalDisks:               makeIntPointer(0),
   202  			LocalDisksTotalSizeInGBs: (*float32)(nil),
   203  			PlatformConfigOptions: &ociCore.ShapePlatformConfigOptions{
   204  				Type: "INTEL_VM",
   205  			},
   206  			IsBilledForStoppedInstance: makeBoolPointer(false),
   207  			BillingType:                "PAID",
   208  		},
   209  		{
   210  			Shape:                      makeStringPointer("VM.GPU.A10.1"),
   211  			ProcessorDescription:       makeStringPointer("2.6 GHz Intel® Xeon® Platinum 8358 (Ice Lake)"),
   212  			Ocpus:                      makeFloat32Pointer(15),
   213  			MemoryInGBs:                makeFloat32Pointer(240),
   214  			Gpus:                       makeIntPointer(1),
   215  			GpuDescription:             makeStringPointer("NVIDIA® A10"),
   216  			LocalDisks:                 makeIntPointer(0),
   217  			LocalDisksTotalSizeInGBs:   (*float32)(nil),
   218  			PlatformConfigOptions:      (*ociCore.ShapePlatformConfigOptions)(nil),
   219  			IsBilledForStoppedInstance: makeBoolPointer(false),
   220  			BillingType:                "PAID",
   221  		},
   222  		{
   223  			Shape:                      makeStringPointer("BM.Standard.A1.160"),
   224  			ProcessorDescription:       makeStringPointer("3.0 GHz Ampere® Altra™"),
   225  			Ocpus:                      makeFloat32Pointer(160),
   226  			MemoryInGBs:                makeFloat32Pointer(1024),
   227  			LocalDisks:                 makeIntPointer(0),
   228  			LocalDisksTotalSizeInGBs:   (*float32)(nil),
   229  			PlatformConfigOptions:      (*ociCore.ShapePlatformConfigOptions)(nil),
   230  			IsBilledForStoppedInstance: makeBoolPointer(false),
   231  			BillingType:                "PAID",
   232  		},
   233  		{
   234  			Shape:                makeStringPointer("VM.Standard.A1.Flex"),
   235  			ProcessorDescription: makeStringPointer("3.0 GHz Ampere® Altra™"),
   236  			OcpuOptions: &ociCore.ShapeOcpuOptions{
   237  				Max: makeFloat32Pointer(80),
   238  			},
   239  			MemoryOptions: &ociCore.ShapeMemoryOptions{
   240  				MaxInGBs: makeFloat32Pointer(512),
   241  			},
   242  			Ocpus:                      makeFloat32Pointer(1),
   243  			MemoryInGBs:                makeFloat32Pointer(6),
   244  			LocalDisks:                 makeIntPointer(0),
   245  			LocalDisksTotalSizeInGBs:   (*float32)(nil),
   246  			PlatformConfigOptions:      (*ociCore.ShapePlatformConfigOptions)(nil),
   247  			IsBilledForStoppedInstance: makeBoolPointer(false),
   248  			BillingType:                "LIMITED_FREE",
   249  		},
   250  		{
   251  			Shape:                makeStringPointer("VM.Standard3.Flex"),
   252  			ProcessorDescription: makeStringPointer("2.0 GHz Intel® Xeon® Platinum 8167M (Skylake)"),
   253  			OcpuOptions: &ociCore.ShapeOcpuOptions{
   254  				Max: makeFloat32Pointer(32),
   255  			},
   256  			MemoryOptions: &ociCore.ShapeMemoryOptions{
   257  				MaxInGBs: makeFloat32Pointer(512),
   258  			},
   259  			Ocpus:                      makeFloat32Pointer(1),
   260  			MemoryInGBs:                makeFloat32Pointer(6),
   261  			LocalDisks:                 makeIntPointer(0),
   262  			LocalDisksTotalSizeInGBs:   (*float32)(nil),
   263  			PlatformConfigOptions:      (*ociCore.ShapePlatformConfigOptions)(nil),
   264  			IsBilledForStoppedInstance: makeBoolPointer(false),
   265  			BillingType:                "LIMITED_FREE",
   266  		},
   267  	}
   268  }
   269  
   270  type commonSuite struct {
   271  	gitjujutesting.IsolationSuite
   272  
   273  	testInstanceID  string
   274  	testCompartment string
   275  	controllerUUID  string
   276  
   277  	ident   *ocitesting.MockIdentityClient
   278  	compute *ocitesting.MockComputeClient
   279  	netw    *ocitesting.MockNetworkingClient
   280  	fw      *ocitesting.MockFirewallClient
   281  	storage *ocitesting.MockStorageClient
   282  
   283  	env         *oci.Environ
   284  	provider    environs.EnvironProvider
   285  	spec        environscloudspec.CloudSpec
   286  	config      *config.Config
   287  	ociInstance *ociCore.Instance
   288  	tags        map[string]string
   289  	ctrlTags    map[string]string
   290  }
   291  
   292  func (s *commonSuite) SetUpTest(c *gc.C) {
   293  	s.IsolationSuite.SetUpTest(c)
   294  	oci.SetImageCache(&oci.ImageCache{})
   295  
   296  	s.controllerUUID = jujutesting.ControllerTag.Id()
   297  	s.testInstanceID = "ocid1.instance.oc1.phx.abyhqljt4bl4i76iforb7wczlc4qmmmrmzvngeyzi2n45bxsee7a11rukjla"
   298  	s.testCompartment = "ocid1.compartment.oc1..aaaaaaaaakr75vvb5yx4nkm7ag7ekvluap7afa2y4zprswuprcnehqecwqga"
   299  
   300  	s.provider = &oci.EnvironProvider{}
   301  	s.spec = fakeCloudSpec()
   302  
   303  	config := newConfig(c, jujutesting.Attrs{"compartment-id": s.testCompartment})
   304  	env, err := environs.Open(stdcontext.TODO(), s.provider, environs.OpenParams{
   305  		Cloud:  s.spec,
   306  		Config: config,
   307  	})
   308  	c.Assert(err, jc.ErrorIsNil)
   309  	c.Assert(env, gc.NotNil)
   310  
   311  	s.config = config
   312  	s.env = env.(*oci.Environ)
   313  	s.env.SetClock(&advancingClock)
   314  
   315  	s.ociInstance = newFakeOCIInstance(s.testInstanceID, s.testCompartment, ociCore.InstanceLifecycleStateRunning)
   316  	s.tags = map[string]string{
   317  		tags.JujuController: s.controllerUUID,
   318  		tags.JujuModel:      config.UUID(),
   319  	}
   320  	s.ctrlTags = map[string]string{
   321  		tags.JujuController:   s.controllerUUID,
   322  		tags.JujuModel:        s.config.UUID(),
   323  		tags.JujuIsController: "true",
   324  	}
   325  	s.ociInstance.FreeformTags = s.tags
   326  }
   327  
   328  func (e *commonSuite) setupListInstancesExpectations(instanceId string, state ociCore.InstanceLifecycleStateEnum, times int) {
   329  	listInstancesRequest, listInstancesResponse := makeListInstancesRequestResponse(
   330  		[]ociCore.Instance{
   331  			{
   332  				AvailabilityDomain: makeStringPointer("fakeZone1"),
   333  				CompartmentId:      &e.testCompartment,
   334  				Id:                 makeStringPointer(instanceId),
   335  				LifecycleState:     state,
   336  				Region:             makeStringPointer("us-phoenix-1"),
   337  				Shape:              makeStringPointer("VM.Standard1.1"),
   338  				DisplayName:        makeStringPointer("fakeName"),
   339  				FreeformTags:       e.tags,
   340  			},
   341  		},
   342  	)
   343  	expect := e.compute.EXPECT().ListInstances(
   344  		context.Background(), listInstancesRequest.CompartmentId).Return(
   345  		listInstancesResponse.Items, nil)
   346  	if times == 0 {
   347  		expect.AnyTimes()
   348  	} else {
   349  		expect.Times(times)
   350  	}
   351  }
   352  
   353  func (s *commonSuite) patchEnv(c *gc.C) *gomock.Controller {
   354  	ctrl := gomock.NewController(c)
   355  	s.compute = ocitesting.NewMockComputeClient(ctrl)
   356  	s.ident = ocitesting.NewMockIdentityClient(ctrl)
   357  	s.netw = ocitesting.NewMockNetworkingClient(ctrl)
   358  	s.fw = ocitesting.NewMockFirewallClient(ctrl)
   359  	s.storage = ocitesting.NewMockStorageClient(ctrl)
   360  
   361  	s.env.Compute = s.compute
   362  	s.env.Networking = s.netw
   363  	s.env.Firewall = s.fw
   364  	s.env.Storage = s.storage
   365  	s.env.Identity = s.ident
   366  
   367  	return ctrl
   368  }