Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

slcli autoscale create #1623

Merged
merged 7 commits into from
May 5, 2022
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 127 additions & 0 deletions SoftLayer/CLI/autoscale/create.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
"""Order/Create a scale group."""
# :license: MIT, see LICENSE for more details.

import click
from SoftLayer import utils

import SoftLayer
from SoftLayer.CLI import environment
from SoftLayer.CLI import exceptions
from SoftLayer.CLI import formatting
from SoftLayer.CLI import helpers
from SoftLayer.managers.autoscale import AutoScaleManager


@click.command()
@click.option('--name', required=True, prompt=True, help="Scale group's name.")
@click.option('--cooldown', required=True, prompt=True, type=click.INT,
help="The number of seconds this group will wait after lastActionDate before performing another action.")
@click.option('--min', 'minimum', required=True, prompt=True, type=click.INT, help="Set the minimum number of guests")
@click.option('--max', 'maximum', required=True, prompt=True, type=click.INT, help="Set the maximum number of guests")
@click.option('--regional', required=True, prompt=True, type=click.INT,
help="The identifier of the regional group this scaling group is assigned to.")
@click.option('--postinstall', '-i', help="Post-install script to download")
@click.option('--os', '-o', required=True, prompt=True, help="OS install code. Tip: you can specify <OS>_LATEST")
@click.option('--datacenter', '-d', required=True, prompt=True, help="Datacenter shortname")
@click.option('--hostname', '-H', required=True, prompt=True, help="Host portion of the FQDN")
@click.option('--domain', '-D', required=True, prompt=True, help="Domain portion of the FQDN")
@click.option('--cpu', required=True, prompt=True, type=click.INT,
help="Number of CPUs for new guests (existing not effected")
@click.option('--memory', required=True, prompt=True, type=click.INT,
help="RAM in MB or GB for new guests (existing not effected")
@click.option('--policy-relative', required=True, prompt=True,
help="The type of scale to perform(ABSOLUTE, PERCENT, RELATIVE).")
@click.option('--termination-policy',
help="The termination policy for the group(CLOSEST_TO_NEXT_CHARGE=1, NEWEST=2, OLDEST=3).")
@click.option('--policy-name', help="Collection of policies for this group. This can be empty.")
@click.option('--policy-amount', help="The number to scale by. This number has different meanings based on type.")
@click.option('--userdata', help="User defined metadata string")
@helpers.multi_option('--key', '-k', help="SSH keys to add to the root user")
@helpers.multi_option('--disk', required=True, prompt=True, help="Disk sizes")
@environment.pass_env
def cli(env, **args):
"""Order/Create a scale group."""
scale = AutoScaleManager(env.client)
network = SoftLayer.NetworkManager(env.client)

datacenter = network.get_datacenter(args.get('datacenter'))

ssh_keys = []
for key in args.get('key'):
resolver = SoftLayer.SshKeyManager(env.client).resolve_ids
key_id = helpers.resolve_id(resolver, key, 'SshKey')
ssh_keys.append(key_id)
scale_actions = [
{
"amount": args['policy_amount'],
"scaleType": args['policy_relative']
}
]
policy_template = {
'name': args['policy_name'],
'policies': scale_actions

}
policies = []

block = []
number_disk = 0
for guest_disk in args['disk']:
disks = {'diskImage': {'capacity': guest_disk}, 'device': number_disk}
block.append(disks)
number_disk += 1

virt_template = {
'localDiskFlag': False,
'domain': args['domain'],
'hostname': args['hostname'],
'sshKeys': ssh_keys,
'postInstallScriptUri': args.get('postinstall'),
'operatingSystemReferenceCode': args['os'],
'maxMemory': args.get('memory'),
'datacenter': {'id': datacenter[0]['id']},
'startCpus': args.get('cpu'),
'blockDevices': block,
'hourlyBillingFlag': True,
'privateNetworkOnlyFlag': False,
'networkComponents': [{'maxSpeed': 100}],
'typeId': 1,
'userData': [{
'value': args.get('userdata')
}],
'networkVlans': [],

}

order = {
'name': args['name'],
'cooldown': args['cooldown'],
'maximumMemberCount': args['maximum'],
'minimumMemberCount': args['minimum'],
'regionalGroupId': args['regional'],
'suspendedFlag': False,
'balancedTerminationFlag': False,
'virtualGuestMemberTemplate': virt_template,
'virtualGuestMemberCount': 0,
'policies': policies.append(utils.clean_dict(policy_template)),
'terminationPolicyId': args['termination_policy']
}

if not (env.skip_confirmations or formatting.confirm(
"This action will incur charges on your account. Continue?")):
raise exceptions.CLIAbort('Aborting scale group order.')

result = scale.create(order)

table = formatting.KeyValueTable(['name', 'value'])
table.align['name'] = 'r'
table.align['value'] = 'l'
table.add_row(['Id', result['id']])
table.add_row(['Created', result['createDate']])
table.add_row(['Name', result['name']])
table.add_row(['Virtual Guest Id', result['virtualGuestMembers'][0]['virtualGuest']['id']])
table.add_row(['Virtual Guest domain', result['virtualGuestMembers'][0]['virtualGuest']['domain']])
table.add_row(['Virtual Guest hostname', result['virtualGuestMembers'][0]['virtualGuest']['hostname']])
output = table

env.fout(output)
1 change: 1 addition & 0 deletions SoftLayer/CLI/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,7 @@

('autoscale', 'SoftLayer.CLI.autoscale'),
('autoscale:list', 'SoftLayer.CLI.autoscale.list:cli'),
('autoscale:create', 'SoftLayer.CLI.autoscale.create:cli'),
('autoscale:detail', 'SoftLayer.CLI.autoscale.detail:cli'),
('autoscale:scale', 'SoftLayer.CLI.autoscale.scale:cli'),
('autoscale:logs', 'SoftLayer.CLI.autoscale.logs:cli'),
Expand Down
76 changes: 76 additions & 0 deletions SoftLayer/fixtures/SoftLayer_Scale_Group.py
Original file line number Diff line number Diff line change
Expand Up @@ -456,3 +456,79 @@

editObject = True
forceDeleteObject = True

createObject = {
"accountId": 307608,
"cooldown": 3600,
"createDate": "2022-04-22T13:45:24-06:00",
"id": 5446140,
"lastActionDate": "2022-04-22T13:45:29-06:00",
"maximumMemberCount": 5,
"minimumMemberCount": 1,
"name": "test22042022",
"regionalGroupId": 4568,
"suspendedFlag": False,
"terminationPolicyId": 2,
"virtualGuestMemberTemplate": {
"accountId": 307608,
"domain": "test.com",
"hostname": "testvs",
"maxMemory": 2048,
"startCpus": 2,
"blockDevices": [
{
"diskImage": {
"capacity": 100,
}
}
],
"hourlyBillingFlag": True,
"localDiskFlag": True,
"networkComponents": [
{
"maxSpeed": 100,
}
],
"operatingSystemReferenceCode": "CENTOS_7_64",
"userData": [
{
"value": "the userData"
}
]
},
"virtualGuestMemberCount": 0,
"networkVlans": [],
"policies": [],
"status": {
"id": 1,
"keyName": "ACTIVE",
"name": "Active"
},
"virtualGuestAssets": [],
"virtualGuestMembers": [
{
"createDate": "2022-04-22T13:45:29-06:00",
"id": 123456,
"scaleGroupId": 5446140,
"virtualGuest": {
"createDate": "2022-04-22T13:45:28-06:00",
"deviceStatusId": 3,
"domain": "test.com",
"fullyQualifiedDomainName": "testvs-97e7.test.com",
"hostname": "testvs-97e7",
"id": 129911702,
"maxCpu": 2,
"maxCpuUnits": "CORE",
"maxMemory": 2048,
"startCpus": 2,
"statusId": 1001,
"typeId": 1,
"uuid": "46e55f99-b412-4287-95b5-b8182b2fc924",
"status": {
"keyName": "ACTIVE",
"name": "Active"
}
}
}
]
}
11 changes: 11 additions & 0 deletions SoftLayer/managers/autoscale.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,17 @@ def edit(self, identifier, template):
"""
return self.client.call('SoftLayer_Scale_Group', 'editObject', template, id=identifier)

def create(self, template):
"""Calls `SoftLayer_Scale_Group::createObject()`_

:param template: `SoftLayer_Scale_Group`_

.. _SoftLayer_Scale_Group::createObject():
https://sldn.softlayer.com/reference/services/SoftLayer_Scale_Group/createObject/
.. _SoftLayer_Scale_Group: https://sldn.softlayer.com/reference/datatypes/SoftLayer_Scale_Group/
"""
return self.client.call('SoftLayer_Scale_Group', 'createObject', template)

def delete(self, identifier):
"""Calls `SoftLayer_Scale_Group::forceDeleteObject()`_

Expand Down
10 changes: 10 additions & 0 deletions SoftLayer/managers/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -839,3 +839,13 @@ def route(self, subnet_id, type_serv, target):
"""
return self.client.call('SoftLayer_Network_Subnet', 'route',
type_serv, target, id=subnet_id, )

def get_datacenter(self, _filter=None, datacenter=None):
"""Calls SoftLayer_Location::getDatacenters()

returns datacenter list.
"""
if datacenter:
_filter = {"name": {"operation": datacenter}}

return self.client.call('SoftLayer_Location', 'getDatacenters', filter=_filter, limit=1)
5 changes: 5 additions & 0 deletions SoftLayer/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -427,3 +427,8 @@ def format_comment(comment, max_line_length=60):

comment_length = len(word) + 1
return formatted_comment


def clean_dict(dictionary):
"""Removes any `None` entires from the dictionary"""
return {k: v for k, v in dictionary.items() if v}
4 changes: 4 additions & 0 deletions docs/cli/autoscale.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,9 @@ For making changes to the triggers or the autoscale group itself, see the `Autos
:prog: autoscale delete
:show-nested:

.. click:: SoftLayer.CLI.autoscale.create:cli
:prog: autoscale create
:show-nested:


.. _Autoscale Portal: https://cloud.ibm.com/classic/autoscale
24 changes: 23 additions & 1 deletion tests/CLI/modules/autoscale_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def test_autoscale_edit_userdata(self, manager):
@mock.patch('SoftLayer.managers.autoscale.AutoScaleManager.edit')
def test_autoscale_edit_userfile(self, manager):
# On windows, python cannot edit a NamedTemporaryFile.
if(sys.platform.startswith("win")):
if (sys.platform.startswith("win")):
self.skipTest("Test doesn't work in Windows")
group = fixtures.SoftLayer_Scale_Group.getObject
template = {
Expand All @@ -90,6 +90,28 @@ def test_autoscale_edit_userfile(self, manager):
self.assert_no_fail(result)
manager.assert_called_with('12345', template)

@mock.patch('SoftLayer.CLI.formatting.confirm')
def test_autoscale_create(self, confirm_mock):
confirm_mock.return_value = True
result = self.run_command(['autoscale', 'create',
'--name=test',
'--cooldown=3600',
'--min=1',
'--max=3',
'-o=CENTOS_7_64',
'--datacenter=ams01',
'--termination-policy=2',
'-H=testvs',
'-D=test.com',
'--cpu=2',
'--memory=1024',
'--policy-relative=absolute',
'--policy-amount=3',
'--regional=102',
'--disk=25'])
self.assert_no_fail(result)
self.assertEqual(result.exit_code, 0)

def test_autoscale_delete(self):
result = self.run_command(['autoscale', 'delete', '12345'])
self.assert_no_fail(result)
51 changes: 51 additions & 0 deletions tests/managers/autoscale_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,57 @@ def test_edit_object(self):
args=(template,),
identifier=12345)

def test_create_object(self):
template = {
'name': 'test',
'cooldown': 3600,
'maximumMemberCount': 5,
'minimumMemberCount': 1,
'regionalGroupId': 4568,
'suspendedFlag': False,
'balancedTerminationFlag': False,
'virtualGuestMemberTemplate': {
'domain': 'test.com',
'hostname': 'testvs',
'operatingSystemReferenceCode': 'CENTOS_7_64',
'maxMemory': 2048,
'datacenter': {
'id': 265592
},
'startCpus': 2,
'blockDevices': [
{
'diskImage': {
'capacity': '100'
},
'device': 0
}
],
'hourlyBillingFlag': True,
'networkComponents': [
{
'maxSpeed': 100
}
],
'localDiskFlag': True,
'typeId': 1,
'userData': [
{
'value': 'the userData'
}
]
},
'virtualGuestMemberCount': 0,

'terminationPolicyId': '2',
}

self.autoscale.create(template)
self.assert_called_with(
'SoftLayer_Scale_Group',
'createObject',
args=(template,))

def test_delete_object(self):
self.autoscale.delete(12345)
self.assert_called_with('SoftLayer_Scale_Group', 'forceDeleteObject')
4 changes: 4 additions & 0 deletions tests/managers/network_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -633,3 +633,7 @@ def test_get_all_pods(self):
def test_route(self):
self.network.route('SoftLayer_Hardware_Server', 123456, 100)
self.assert_called_with('SoftLayer_Network_Subnet', 'route')

def test_get_all_datacenter(self):
self.network.get_datacenter()
self.assert_called_with('SoftLayer_Location', 'getDatacenters')