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 }