716 lines
25 KiB
Python
716 lines
25 KiB
Python
# Copyright (C) 2021 Acme Gating, 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.
|
|
|
|
import json
|
|
import time
|
|
import re
|
|
import urllib
|
|
import uuid
|
|
|
|
import fixtures
|
|
|
|
import responses
|
|
|
|
|
|
class CRUDManager:
|
|
name = ''
|
|
list_name = None
|
|
|
|
def __init__(self, cloud):
|
|
self.cloud = cloud
|
|
self.items = []
|
|
self.requests = []
|
|
|
|
def list(self, request):
|
|
listname = self.list_name or self.name
|
|
resp = {
|
|
"limit": 50,
|
|
"first": {
|
|
"href": ("https://us-south.iaas.cloud.ibm.com/v1/"
|
|
f"{self.name}?limit=50")
|
|
},
|
|
"total_count": len(self.items),
|
|
listname: self.items,
|
|
}
|
|
return (200, {}, json.dumps(resp))
|
|
|
|
def get(self, request):
|
|
url = urllib.parse.urlparse(request.path_url)
|
|
uid = url.path.split('/')[-1]
|
|
item = self.lookup(id=uid)
|
|
if item:
|
|
return (200, {}, json.dumps(item))
|
|
else:
|
|
return (404, {}, json.dumps({
|
|
'message': 'Item not found',
|
|
}))
|
|
|
|
def lookup(self, **kw):
|
|
for item in self.items:
|
|
for k, v in kw.items():
|
|
if item[k] == v:
|
|
return item
|
|
|
|
|
|
class ResourceGroupsCRUD(CRUDManager):
|
|
name = "resources"
|
|
|
|
def make(self, name):
|
|
uid = str(uuid.uuid4().hex)
|
|
uid2 = str(uuid.uuid4().hex)
|
|
data = {
|
|
"id": uid,
|
|
"crn": ("crn:v1:bluemix:public:resource-controller::a/"
|
|
f"{self.cloud.account_id}::resource-group:{uid}"),
|
|
"account_id": self.cloud.account_id,
|
|
"name": name,
|
|
"state": "ACTIVE",
|
|
"default": False,
|
|
"enable_reclamation": False,
|
|
"quota_id": uid2,
|
|
"quota_url": f"/v2/quota_definitions/{uid2}",
|
|
"payment_methods_url": (f"/v2/resource_groups/{uid}"
|
|
"/payment_methods"),
|
|
"resource_linkages": [],
|
|
"teams_url": f"/v2/resource_groups/{uid}/teams",
|
|
"created_at": "2021-12-01T20:41:25.202Z",
|
|
"updated_at": "2021-12-01T20:41:25.202Z"
|
|
}
|
|
return data
|
|
|
|
def post(self, request):
|
|
data = json.loads(request.body)
|
|
obj = self.make(data['name'])
|
|
self.items.append(obj)
|
|
return (200, {}, json.dumps(obj))
|
|
|
|
|
|
class ResourceInstancesCRUD(CRUDManager):
|
|
name = "resource_instances"
|
|
list_name = "resources"
|
|
|
|
def make(self, name, kind, resource_group):
|
|
uid = str(uuid.uuid4().hex)
|
|
uid2 = str(uuid.uuid4().hex)
|
|
uid3 = str(uuid.uuid4().hex)
|
|
data = {
|
|
"id": (f"crn:v1:bluemix:public:{kind}:global:"
|
|
f"a/{self.cloud.account_id}:{uid}::"),
|
|
"guid": uid,
|
|
"url": f"/v2/resource_instances/{uid}",
|
|
"created_at": "2021-12-11T01:01:19.588831392Z",
|
|
"updated_at": "2021-12-11T01:01:21.814042061Z",
|
|
"deleted_at": None,
|
|
"created_by": "IBMid-something",
|
|
"updated_by": "",
|
|
"deleted_by": "",
|
|
"scheduled_reclaim_at": None,
|
|
"restored_at": None,
|
|
"scheduled_reclaim_by": "",
|
|
"restored_by": "",
|
|
"name": name,
|
|
"region_id": "global",
|
|
"account_id": f"{self.cloud.account_id}",
|
|
"reseller_channel_id": "",
|
|
"resource_plan_id": uid2,
|
|
"resource_group_id": resource_group['id'],
|
|
"resource_group_crn": resource_group['crn'],
|
|
"target_crn": (f"crn:v1:bluemix:public:globalcatalog::::"
|
|
f"deployment:{uid2}%3Aglobal"),
|
|
"allow_cleanup": False,
|
|
"crn": (f"crn:v1:bluemix:public:{kind}:global:"
|
|
f"a/{self.cloud.account_id}:{uid}::"),
|
|
"state": "active",
|
|
"type": "service_instance",
|
|
"resource_id": uid3,
|
|
"dashboard_url": "https://cloud.ibm.com/something/",
|
|
"last_operation": {
|
|
"type": "create",
|
|
"state": "succeeded",
|
|
"async": False,
|
|
"description": "Completed create instance operation"
|
|
},
|
|
"resource_aliases_url": (
|
|
f"/v2/resource_instances/{uid}/resource_aliases"),
|
|
"resource_bindings_url": (
|
|
f"/v2/resource_instances/{uid}/resource_bindings"),
|
|
"resource_keys_url": f"/v2/resource_instances/{uid}/resource_keys",
|
|
"plan_history": [
|
|
{
|
|
"resource_plan_id": uid2,
|
|
"start_date": "2021-12-11T01:01:19.588831392Z",
|
|
"requestor_id": "IBMid-something"
|
|
}
|
|
],
|
|
"migrated": False,
|
|
"controlled_by": "",
|
|
"locked": False,
|
|
}
|
|
return data
|
|
|
|
|
|
class ProfilesCRUD(CRUDManager):
|
|
name = "profiles"
|
|
|
|
def make(self, name, cpu, ram):
|
|
data = {
|
|
'bandwidth': {'type': 'fixed', 'value': 4000},
|
|
'disks': [],
|
|
'family': 'compute',
|
|
'href': ('https://us-south.iaas.cloud.ibm.com/v1/instance/'
|
|
f'profiles/{name}'),
|
|
'memory': {'type': 'fixed', 'value': ram},
|
|
'name': 'cx2-2x4',
|
|
'os_architecture': {
|
|
'default': 'amd64', 'type': 'enum', 'values': ['amd64']
|
|
},
|
|
'port_speed': {'type': 'fixed', 'value': 16000},
|
|
'total_volume_bandwidth': {
|
|
'default': 1000, 'max': 3500, 'min': 500,
|
|
'step': 1, 'type': 'range'
|
|
},
|
|
'vcpu_architecture': {'type': 'fixed', 'value': 'amd64'},
|
|
'vcpu_count': {'type': 'fixed', 'value': cpu}
|
|
}
|
|
return data
|
|
|
|
|
|
class VpcsCRUD(CRUDManager):
|
|
name = "vpcs"
|
|
|
|
def make(self, name, resource_group):
|
|
uid = str(uuid.uuid4())
|
|
net_acl = str(uuid.uuid4())
|
|
routing_table = str(uuid.uuid4())
|
|
security_group = str(uuid.uuid4())
|
|
data = {
|
|
"id": uid,
|
|
"crn": ("crn:v1:bluemix:public:is:us-south:"
|
|
f"a/{self.cloud.account_id}::vpc:{uid}"),
|
|
"href": f"https://us-south.iaas.cloud.ibm.com/v1/vpcs/{uid}",
|
|
"name": name,
|
|
"resource_type": "vpc",
|
|
"status": "available",
|
|
"classic_access": False,
|
|
"created_at": "2021-12-09T17:11:13Z",
|
|
"default_network_acl": {
|
|
"id": net_acl,
|
|
"crn": ("crn:v1:bluemix:public:is:us-south:"
|
|
f"a/{self.cloud.account_id}::network-acl:{net_acl}"),
|
|
"href": ("https://us-south.iaas.cloud.ibm.com/v1/network_acls/"
|
|
f"{net_acl}"),
|
|
"name": net_acl,
|
|
},
|
|
"default_routing_table": {
|
|
"id": routing_table,
|
|
"href": ("https://us-south.iaas.cloud.ibm.com/v1/vpcs/"
|
|
f"{uid}/routing_tables/{routing_table}"),
|
|
"name": routing_table,
|
|
"resource_type": "routing_table"
|
|
},
|
|
"default_security_group": {
|
|
"id": security_group,
|
|
"crn": ("crn:v1:bluemix:public:is:us-south:"
|
|
f"a/{self.cloud.account_id}::"
|
|
f"security-group:{security_group}"),
|
|
"href": ("https://us-south.iaas.cloud.ibm.com/v1/"
|
|
f"security_groups/{security_group}"),
|
|
"name": security_group,
|
|
},
|
|
"resource_group": {
|
|
"id": resource_group['id'],
|
|
"href": ("https://us-south.iaas.cloud.ibm.com/v1/"
|
|
f"resource_groups/{resource_group['id']}"),
|
|
"name": resource_group['name']
|
|
},
|
|
"cse_source_ips": [
|
|
{
|
|
"ip": {"address": "10.16.234.155"},
|
|
"zone": {
|
|
"name": "us-south-1",
|
|
"href": ("https://us-south.iaas.cloud.ibm.com/v1/"
|
|
"regions/us-south/zones/us-south-1")
|
|
}
|
|
},
|
|
{
|
|
"ip": {"address": "10.16.246.112"},
|
|
"zone": {
|
|
"name": "us-south-2",
|
|
"href": ("https://us-south.iaas.cloud.ibm.com/v1/"
|
|
"regions/us-south/zones/us-south-2")
|
|
}
|
|
},
|
|
{
|
|
"ip": {"address": "10.16.250.50"},
|
|
"zone": {
|
|
"name": "us-south-3",
|
|
"href": ("https://us-south.iaas.cloud.ibm.com/v1/"
|
|
"regions/us-south/zones/us-south-3")
|
|
}
|
|
}
|
|
]
|
|
}
|
|
return data
|
|
|
|
|
|
class SubnetsCRUD(CRUDManager):
|
|
name = "subnets"
|
|
|
|
def make(self, name, vpc):
|
|
uid = str(uuid.uuid4())
|
|
data = {
|
|
"id": uid,
|
|
"crn": ("crn:v1:bluemix:public:is:us-south-1:"
|
|
f"a/{self.cloud.account_id}::subnet:{uid}"),
|
|
"href": f"https://us-south.iaas.cloud.ibm.com/v1/subnets/{uid}",
|
|
"name": name,
|
|
"resource_type": "subnet",
|
|
"available_ipv4_address_count": 250,
|
|
"ipv4_cidr_block": "10.240.0.0/24",
|
|
"ip_version": "ipv4",
|
|
"zone": {
|
|
"name": "us-south-1",
|
|
"href": ("https://us-south.iaas.cloud.ibm.com/v1/"
|
|
"regions/us-south/zones/us-south-1")
|
|
},
|
|
"vpc": {
|
|
"id": vpc['id'],
|
|
"crn": ("crn:v1:bluemix:public:is:us-south:"
|
|
f"a/{self.cloud.account_id}::vpc:{vpc['id']}"),
|
|
"href": ("https://us-south.iaas.cloud.ibm.com/v1/"
|
|
f"vpcs/{vpc['id']}"),
|
|
"name": vpc['name'],
|
|
"resource_type": "vpc"
|
|
},
|
|
"status": "available",
|
|
"total_ipv4_address_count": 256,
|
|
"created_at": "2021-12-09T17:11:18Z",
|
|
"network_acl": vpc['default_network_acl'],
|
|
"resource_group": vpc['resource_group'],
|
|
"routing_table": vpc['default_routing_table'],
|
|
}
|
|
return data
|
|
|
|
|
|
class KeysCRUD(CRUDManager):
|
|
name = "keys"
|
|
|
|
def make(self, name, vpc):
|
|
uid = str(uuid.uuid4())
|
|
data = {
|
|
"created_at": "2021-12-09T17:14:53Z",
|
|
"crn": ("crn:v1:bluemix:public:is:us-south:"
|
|
f"a/{self.cloud.account_id}::key:{uid}"),
|
|
"fingerprint": "SHA256:something",
|
|
"href": f"https://us-south.iaas.cloud.ibm.com/v1/keys/{uid}",
|
|
"id": uid,
|
|
"length": 2048,
|
|
"name": name,
|
|
"public_key": "ssh-rsa something\n",
|
|
"resource_group": vpc['resource_group'],
|
|
"type": "rsa"
|
|
}
|
|
return data
|
|
|
|
|
|
class FloatingIPsCRUD(CRUDManager):
|
|
name = "floating_ips"
|
|
|
|
def addTarget(self, fip, instance):
|
|
if 'target' in fip:
|
|
raise Exception("FIP already has target")
|
|
fip['target'] = {
|
|
"href": instance['primary_network_interface']['href'],
|
|
"id": instance['primary_network_interface']['id'],
|
|
"name": instance['primary_network_interface']['name'],
|
|
"primary_ipv4_address": instance['primary_network_interface'
|
|
]['primary_ipv4_address'],
|
|
"resource_type": "network_interface"
|
|
}
|
|
|
|
def removeTarget(self, fip):
|
|
del fip['target']
|
|
|
|
def make(self, name, resource_group):
|
|
uid = str(uuid.uuid4())
|
|
addr = 'fake'
|
|
data = {
|
|
"address": addr,
|
|
"created_at": "2021-12-11T00:07:08Z",
|
|
"crn": ("crn:v1:bluemix:public:is:us-south-1:"
|
|
f"a/{self.cloud.account_id}::floating-ip:{uid}"),
|
|
"href": ("https://us-south.iaas.cloud.ibm.com/"
|
|
f"v1/floating_ips/{uid}"),
|
|
"id": uid,
|
|
"name": name,
|
|
"resource_group": {
|
|
"id": resource_group['id'],
|
|
"href": ("https://us-south.iaas.cloud.ibm.com/v1/"
|
|
f"resource_groups/{resource_group['id']}"),
|
|
"name": resource_group['name']
|
|
},
|
|
"status": "available",
|
|
"zone": {
|
|
"href": ("https://us-south.iaas.cloud.ibm.com/v1/"
|
|
"regions/us-south/zones/us-south-1"),
|
|
"name": "us-south-1"
|
|
}
|
|
}
|
|
return data
|
|
|
|
def post(self, request):
|
|
data = json.loads(request.body)
|
|
resource_group = self.cloud.crud['resources'].lookup(
|
|
id=data['resource_group']['id'])
|
|
zone = data['zone']['name']
|
|
# Make sure this argument is supplied
|
|
if zone != 'us-south-1':
|
|
raise Exception("Unsupported zone")
|
|
obj = self.make(data['name'], resource_group)
|
|
self.items.append(obj)
|
|
return (200, {}, json.dumps(obj))
|
|
|
|
def delete(self, request):
|
|
url = urllib.parse.urlparse(request.path_url)
|
|
uid = url.path.split('/')[-1]
|
|
instance = self.lookup(id=uid)
|
|
if instance:
|
|
self.items.remove(instance)
|
|
else:
|
|
return (404, {}, json.dumps({
|
|
'message': 'Floating IP not found',
|
|
}))
|
|
|
|
return self.list(request)
|
|
|
|
|
|
class InstancesCRUD(CRUDManager):
|
|
name = "instances"
|
|
|
|
def make(self, name, vpc, profile, image):
|
|
uid = str(uuid.uuid4())
|
|
boot_volume_id = str(uuid.uuid4())
|
|
boot_volume_attachment_id = str(uuid.uuid4())
|
|
nic_id = str(uuid.uuid4())
|
|
subnet = self.cloud.crud['subnets'].lookup(name='sn-nodepool')
|
|
|
|
nic = {
|
|
"href": ("https://us-south.iaas.cloud.ibm.com/v1/instances/"
|
|
f"{uid}/network_interfaces/{nic_id}"),
|
|
"id": nic_id,
|
|
"name": "eth0",
|
|
"primary_ipv4_address": f"10.240.0.{len(self.items) + 1}",
|
|
"resource_type": "network_interface",
|
|
"subnet": {
|
|
"crn": subnet['crn'],
|
|
"href": subnet['href'],
|
|
"id": subnet['id'],
|
|
"name": subnet['name'],
|
|
"resource_type": "subnet"
|
|
}
|
|
}
|
|
boot_volume_attachment = {
|
|
"device": {"id": f"{boot_volume_attachment_id}-25fcc"},
|
|
"href": ("https://us-south.iaas.cloud.ibm.com/v1/instances/"
|
|
f"{uid}/volume_attachments/{boot_volume_attachment_id}"),
|
|
"id": boot_volume_attachment_id,
|
|
"name": boot_volume_attachment_id,
|
|
"volume": {
|
|
"crn": ("crn:v1:bluemix:public:is:us-south-1:"
|
|
f"a/{self.cloud.account_id}::volume:{boot_volume_id}"),
|
|
"href": ("https://us-south.iaas.cloud.ibm.com/v1/volumes/"
|
|
f"{boot_volume_id}"),
|
|
"id": boot_volume_id,
|
|
"name": f"{name}-boot-1639181087000"
|
|
}
|
|
}
|
|
|
|
data = {
|
|
"bandwidth": 4000,
|
|
"boot_volume_attachment": boot_volume_attachment,
|
|
"created_at": "2021-12-11T00:05:16Z",
|
|
"crn": ("crn:v1:bluemix:public:is:us-south-1:"
|
|
f"a/{self.cloud.account_id}::instance:{uid}"),
|
|
"disks": [],
|
|
"href": f"https://us-south.iaas.cloud.ibm.com/v1/instances/{uid}",
|
|
"id": uid,
|
|
"image": {
|
|
"crn": image['crn'],
|
|
"href": image['href'],
|
|
"id": image['id'],
|
|
"name": image['name'],
|
|
},
|
|
"memory": 4,
|
|
"name": name,
|
|
"network_interfaces": [nic],
|
|
"primary_network_interface": nic,
|
|
"profile": {
|
|
"href": profile['href'],
|
|
"name": profile['name'],
|
|
},
|
|
"resource_group": vpc['resource_group'],
|
|
"resource_type": "instance",
|
|
"startable": True,
|
|
"status": "pending",
|
|
"status_reasons": [],
|
|
"total_network_bandwidth": 3000,
|
|
"total_volume_bandwidth": 1000,
|
|
"vcpu": {
|
|
"architecture": "amd64",
|
|
"count": 2
|
|
},
|
|
"volume_attachments": [boot_volume_attachment],
|
|
"vpc": {
|
|
"crn": vpc['crn'],
|
|
"href": vpc['href'],
|
|
"id": vpc['id'],
|
|
"name": vpc['name'],
|
|
"resource_type": "vpc"
|
|
},
|
|
"zone": {
|
|
"href": ("https://us-south.iaas.cloud.ibm.com/v1/"
|
|
"regions/us-south/zones/us-south-1"),
|
|
"name": "us-south-1"
|
|
}
|
|
}
|
|
return data
|
|
|
|
def post(self, request):
|
|
data = json.loads(request.body)
|
|
vpc = self.cloud.crud['vpcs'].lookup(id=data['vpc']['id'])
|
|
profile = self.cloud.crud['profiles'].lookup(
|
|
name=data['profile']['name'])
|
|
image = self.cloud.crud['images'].lookup(id=data['image']['id'])
|
|
obj = self.make(data['name'], vpc, profile, image)
|
|
self.items.append(obj)
|
|
ret = json.dumps(obj)
|
|
# Finish provisioning after return
|
|
obj['status'] = 'running'
|
|
return (200, {}, ret)
|
|
|
|
def delete(self, request):
|
|
url = urllib.parse.urlparse(request.path_url)
|
|
uid = url.path.split('/')[-1]
|
|
instance = self.lookup(id=uid)
|
|
if instance:
|
|
self.items.remove(instance)
|
|
else:
|
|
return (404, {}, json.dumps({
|
|
'message': 'Instance not found',
|
|
}))
|
|
|
|
return self.list(request)
|
|
|
|
|
|
class ImagesCRUD(CRUDManager):
|
|
name = "images"
|
|
|
|
def make(self, name, operating_system, owner_type, resource_group=None):
|
|
uid = str(uuid.uuid4())
|
|
if resource_group:
|
|
rg = {
|
|
"id": resource_group['id'],
|
|
"href": ("https://us-south.iaas.cloud.ibm.com/v1/"
|
|
f"resource_groups/{resource_group['id']}"),
|
|
}
|
|
else:
|
|
rgid = str(uuid.uuid4())
|
|
rg = {
|
|
"id": rgid,
|
|
"href": ("https://resource-controller.cloud.ibm.com/"
|
|
f"v1/resource_groups/{rgid}")
|
|
}
|
|
|
|
data = {
|
|
"id": uid,
|
|
"crn": ("crn:v1:bluemix:public:is:us-south:"
|
|
f"a/something::image:{uid}"),
|
|
"href": f"https://us-south.iaas.cloud.ibm.com/v1/images/{uid}",
|
|
"name": name,
|
|
"minimum_provisioned_size": 100,
|
|
"resource_group": rg,
|
|
"created_at": "2020-01-11T01:01:01Z",
|
|
"file": {
|
|
"checksums": {"sha256": "something"},
|
|
"size": 2
|
|
},
|
|
"operating_system": operating_system,
|
|
"status": "available",
|
|
"visibility": "public",
|
|
"encryption": "none",
|
|
"status_reasons": [],
|
|
"owner_type": owner_type,
|
|
}
|
|
return data
|
|
|
|
def post(self, request):
|
|
data = json.loads(request.body)
|
|
resource_group = self.cloud.crud['resources'].lookup(
|
|
id=data['resource_group']['id'])
|
|
os = self.cloud.operating_systems[data['operating_system']['name']]
|
|
obj = self.make(data['name'], os, 'user', resource_group)
|
|
self.items.append(obj)
|
|
return (200, {}, json.dumps(obj))
|
|
|
|
def delete(self, request):
|
|
url = urllib.parse.urlparse(request.path_url)
|
|
uid = url.path.split('/')[-1]
|
|
instance = self.lookup(id=uid)
|
|
if instance:
|
|
self.items.remove(instance)
|
|
else:
|
|
return (404, {}, json.dumps({
|
|
'message': 'Image not found',
|
|
}))
|
|
|
|
return self.list(request)
|
|
|
|
|
|
class FakeIBMVPCFixture(fixtures.Fixture):
|
|
operating_systems = {
|
|
'debian-9-amd64': {
|
|
"href": ("https://us-south.iaas.cloud.ibm.com/v1/"
|
|
"operating_systems/debian-9-amd64"),
|
|
"name": "debian-9-amd64",
|
|
"architecture": "amd64",
|
|
"display_name": ("Debian GNU/Linux 9.x Stretch/Stable - "
|
|
"Minimal Install (amd64)"),
|
|
"family": "Debian GNU/Linux",
|
|
"vendor": "Debian",
|
|
"version": "9.x Stretch/Stable - Minimal Install",
|
|
"dedicated_host_only": False
|
|
},
|
|
}
|
|
|
|
def _setUp(self):
|
|
self.crud = {}
|
|
self.responses = responses.RequestsMock()
|
|
self.responses.start()
|
|
self.account_id = str(uuid.uuid4())
|
|
|
|
self._setup_crud(
|
|
'https://resource-controller.cloud.ibm.com/v2/resource_groups',
|
|
ResourceGroupsCRUD)
|
|
p = self.crud['resources']
|
|
p.items.append(p.make('Default'))
|
|
|
|
self._setup_crud(
|
|
r'https://resource-controller.cloud.ibm.com/v2/'
|
|
r'resource_instances\?name=(.*?)&type=(.*?)',
|
|
ResourceInstancesCRUD)
|
|
p = self.crud['resource_instances']
|
|
p.items.append(p.make(
|
|
"Cloud Object Storage-r6", "cloud-object-storage",
|
|
self.crud['resources'].lookup(name='Default')))
|
|
|
|
self._setup_crud(
|
|
'https://us-south.iaas.cloud.ibm.com/v1/vpcs',
|
|
VpcsCRUD)
|
|
p = self.crud['vpcs']
|
|
p.items.append(p.make(
|
|
'nodepool', self.crud['resources'].lookup(name='Default')))
|
|
|
|
self._setup_crud(
|
|
'https://us-south.iaas.cloud.ibm.com/v1/subnets',
|
|
SubnetsCRUD)
|
|
p = self.crud['subnets']
|
|
p.items.append(p.make(
|
|
'sn-nodepool', self.crud['vpcs'].lookup(name='nodepool')))
|
|
|
|
self._setup_crud(
|
|
'https://us-south.iaas.cloud.ibm.com/v1/keys',
|
|
KeysCRUD)
|
|
p = self.crud['keys']
|
|
p.items.append(p.make(
|
|
'testuser', self.crud['vpcs'].lookup(name='nodepool')))
|
|
|
|
self._setup_crud(
|
|
'https://us-south.iaas.cloud.ibm.com/v1/instance/profiles',
|
|
ProfilesCRUD)
|
|
p = self.crud['profiles']
|
|
p.items.append(p.make('cx2-2x4', 2, 4))
|
|
|
|
self._setup_crud(
|
|
'https://us-south.iaas.cloud.ibm.com/v1/floating_ips',
|
|
FloatingIPsCRUD)
|
|
|
|
self._setup_crud(
|
|
'https://us-south.iaas.cloud.ibm.com/v1/instances',
|
|
InstancesCRUD)
|
|
|
|
self._setup_crud(
|
|
'https://us-south.iaas.cloud.ibm.com/v1/images',
|
|
ImagesCRUD)
|
|
p = self.crud['images']
|
|
p.items.append(p.make('ibm-debian-9-13-minimal-amd64-4',
|
|
self.operating_systems['debian-9-amd64'],
|
|
'provider'))
|
|
|
|
self.attach_fip_re = re.compile(
|
|
r'https://us-south.iaas.cloud.ibm.com/v1/instances/(.*?)'
|
|
r'/network_interfaces/(.*?)'
|
|
r'/floating_ips/(.*?)'
|
|
r'\?version=(.+?)&generation=(\d+)')
|
|
self.responses.add_callback(
|
|
responses.PUT,
|
|
self.attach_fip_re,
|
|
callback=self._attach_floating_ip,
|
|
content_type='application/json')
|
|
|
|
self.responses.add(
|
|
responses.POST,
|
|
'https://iam.cloud.ibm.com/identity/token',
|
|
json={
|
|
'token_type': 'Bearer',
|
|
'access_token': 'secret_token',
|
|
'expires_in': 600,
|
|
'expiration': time.time() + 600,
|
|
})
|
|
|
|
self.addCleanup(self.responses.stop)
|
|
self.addCleanup(self.responses.reset)
|
|
|
|
def _setup_crud(self, url, manager):
|
|
self.crud[manager.name] = manager(self)
|
|
list_re = re.compile(
|
|
'^' + url + r'(\?version=(.+?)&generation=(\d+))?$')
|
|
crud_re = re.compile(
|
|
'^' + url + r'/(.+?)(\?version=(.+?)&generation=(\d+))?$')
|
|
self.responses.add_callback(
|
|
responses.GET, list_re, callback=self.crud[manager.name].list,
|
|
content_type='application/json')
|
|
self.responses.add_callback(
|
|
responses.GET, crud_re, callback=self.crud[manager.name].get,
|
|
content_type='application/json')
|
|
if hasattr(self.crud[manager.name], 'post'):
|
|
self.responses.add_callback(
|
|
responses.POST, list_re, callback=self.crud[manager.name].post,
|
|
content_type='application/json')
|
|
if hasattr(self.crud[manager.name], 'delete'):
|
|
self.responses.add_callback(
|
|
responses.DELETE, crud_re,
|
|
callback=self.crud[manager.name].delete,
|
|
content_type='application/json')
|
|
|
|
def _attach_floating_ip(self, request):
|
|
m = self.attach_fip_re.match(request.url)
|
|
instance_id, nic_id, fip_id, version, generation = m.groups()
|
|
fip = self.crud['floating_ips'].lookup(id=fip_id)
|
|
instance = self.crud['instances'].lookup(id=instance_id)
|
|
if nic_id != instance['primary_network_interface']['id']:
|
|
raise Exception("Unsupported nic id")
|
|
self.crud['floating_ips'].addTarget(fip, instance)
|
|
return (200, {}, json.dumps(fip))
|