add tags support for aws provider

Change-Id: Ib871bfda41192a74ee02b0b3d2e422fde21f2801
This commit is contained in:
Clément Mondion
2020-01-21 17:14:12 +01:00
parent b6f3f38479
commit 49482e157c
6 changed files with 62 additions and 4 deletions

View File

@@ -1597,10 +1597,15 @@ section of the configuration.
cloud-image: debian9 cloud-image: debian9
instance-type: t3.medium instance-type: t3.medium
key-name: zuul key-name: zuul
tags:
key1: value1
- name: debian9-large - name: debian9-large
cloud-image: debian9 cloud-image: debian9
instance-type: t3.large instance-type: t3.large
key-name: zuul key-name: zuul
tags:
key1: value1
key2: value2
.. attr:: name .. attr:: name
:required: :required:
@@ -1827,6 +1832,12 @@ section of the configuration.
Additional info about options in cloud-config: Additional info about options in cloud-config:
https://cloudinit.readthedocs.io/en/latest/topics/examples.html https://cloudinit.readthedocs.io/en/latest/topics/examples.html
.. attr:: tags
:type: dict
:default: None
A dictionary of tags to add to the EC2 instances
.. _`EBS volume type`: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSVolumeTypes.html .. _`EBS volume type`: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSVolumeTypes.html
.. _`AWS region`: https://docs.aws.amazon.com/general/latest/gr/rande.html .. _`AWS region`: https://docs.aws.amazon.com/general/latest/gr/rande.html
.. _`Boto configuration`: https://boto3.amazonaws.com/v1/documentation/api/latest/guide/configuration.html .. _`Boto configuration`: https://boto3.amazonaws.com/v1/documentation/api/latest/guide/configuration.html

View File

@@ -59,6 +59,7 @@ class ProviderLabel(ConfigValue):
self.userdata = None self.userdata = None
# The ProviderPool object that owns this label. # The ProviderPool object that owns this label.
self.pool = None self.pool = None
self.tags = None
def __eq__(self, other): def __eq__(self, other):
if isinstance(other, ProviderLabel): if isinstance(other, ProviderLabel):
@@ -71,7 +72,7 @@ class ProviderLabel(ConfigValue):
and other.volume_size == self.volume_size and other.volume_size == self.volume_size
and other.volume_type == self.volume_type and other.volume_type == self.volume_type
and other.userdata == self.userdata and other.userdata == self.userdata
) and other.tags == self.tags)
return False return False
def __repr__(self): def __repr__(self):
@@ -127,6 +128,12 @@ class ProviderPool(ConfigPool):
pl.volume_type = label.get('volume-type') pl.volume_type = label.get('volume-type')
pl.volume_size = label.get('volume-size') pl.volume_size = label.get('volume-size')
pl.userdata = label.get('userdata', None) pl.userdata = label.get('userdata', None)
pl.tags = [
{
"Key": k,
"Value": str(v)
} for k, v in label.get('tags', {}).items()
]
full_config.labels[label['name']].pools.append(self) full_config.labels[label['name']].pools.append(self)
def __eq__(self, other): def __eq__(self, other):
@@ -232,6 +239,7 @@ class AwsProviderConfig(ProviderConfig):
'volume-type': str, 'volume-type': str,
'volume-size': int, 'volume-size': int,
'userdata': str, 'userdata': str,
'tags': dict,
} }
pool = ConfigPool.getCommonSchemaDict() pool = ConfigPool.getCommonSchemaDict()

View File

@@ -73,7 +73,7 @@ class AwsProvider(Provider):
if instance.tags: if instance.tags:
for tag in instance.tags: for tag in instance.tags:
if (tag["Key"] == 'nodepool_provider' if (tag["Key"] == 'nodepool_provider'
and tag["Value"] == self.provider.name): and tag["Value"] == self.provider.name):
ours = True ours = True
break break
if not ours: if not ours:
@@ -170,7 +170,13 @@ class AwsProvider(Provider):
InstanceType=label.instance_type, InstanceType=label.instance_type,
NetworkInterfaces=[{ NetworkInterfaces=[{
'AssociatePublicIpAddress': label.pool.public_ip, 'AssociatePublicIpAddress': label.pool.public_ip,
'DeviceIndex': 0}]) 'DeviceIndex': 0}],
TagSpecifications=[{
'ResourceType': 'instance',
'Tags': [{"Key": "Name",
"Value": str(label.name)}] + label.tags
}]
)
if label.pool.security_group_id: if label.pool.security_group_id:
args['NetworkInterfaces'][0]['Groups'] = [ args['NetworkInterfaces'][0]['Groups'] = [

View File

@@ -12,6 +12,7 @@ labels:
- name: ubuntu1404-non-host-key-checking - name: ubuntu1404-non-host-key-checking
- name: ubuntu1404-private-ip - name: ubuntu1404-private-ip
- name: ubuntu1404-userdata - name: ubuntu1404-userdata
- name: ubuntu1404-with-tags
providers: providers:
- name: ec2-us-west-2 - name: ec2-us-west-2
@@ -94,3 +95,14 @@ providers:
cloud-image: ubuntu1404 cloud-image: ubuntu1404
instance-type: t3.medium instance-type: t3.medium
key-name: zuul key-name: zuul
- name: tags
max-servers: 1
subnet-id: null
security-group-id: null
labels:
- name: ubuntu1404-with-tags
cloud-image: ubuntu1404
instance-type: t3.medium
key-name: zuul
tags:
has-tags: true

View File

@@ -48,7 +48,8 @@ class TestDriverAws(tests.DBTestCase):
is_valid_config=True, is_valid_config=True,
host_key_checking=True, host_key_checking=True,
userdata=None, userdata=None,
public_ip=True): public_ip=True,
tags=False):
aws_id = 'AK000000000000000000' aws_id = 'AK000000000000000000'
aws_key = '0123456789abcdef0123456789abcdef0123456789abcdef' aws_key = '0123456789abcdef0123456789abcdef0123456789abcdef'
self.useFixture( self.useFixture(
@@ -85,6 +86,8 @@ class TestDriverAws(tests.DBTestCase):
raw_config['providers'][0]['pools'][1]['security-group-id'] = sg_id raw_config['providers'][0]['pools'][1]['security-group-id'] = sg_id
raw_config['providers'][0]['pools'][2]['subnet-id'] = subnet_id raw_config['providers'][0]['pools'][2]['subnet-id'] = subnet_id
raw_config['providers'][0]['pools'][2]['security-group-id'] = sg_id raw_config['providers'][0]['pools'][2]['security-group-id'] = sg_id
raw_config['providers'][0]['pools'][3]['subnet-id'] = subnet_id
raw_config['providers'][0]['pools'][3]['security-group-id'] = sg_id
with tempfile.NamedTemporaryFile() as tf: with tempfile.NamedTemporaryFile() as tf:
tf.write(yaml.safe_dump( tf.write(yaml.safe_dump(
@@ -152,6 +155,16 @@ class TestDriverAws(tests.DBTestCase):
userdata = base64.b64decode( userdata = base64.b64decode(
response['UserData']['Value']).decode() response['UserData']['Value']).decode()
self.assertEqual('fake-user-data', userdata) self.assertEqual('fake-user-data', userdata)
if tags:
instance = ec2_resource.Instance(node.external_id)
tag_list = instance.tags
self.assertIn({"Key": "has-tags", "Value": "true"},
tag_list)
self.assertIn({
"Key": "Name",
"Value": "ubuntu1404-with-tags"
}, tag_list)
# A new request will be paused and for lack of quota # A new request will be paused and for lack of quota
# until this one is deleted # until this one is deleted
@@ -210,3 +223,7 @@ class TestDriverAws(tests.DBTestCase):
def test_ec2_machine_private_ip(self): def test_ec2_machine_private_ip(self):
self._test_ec2_machine('ubuntu1404-private-ip', self._test_ec2_machine('ubuntu1404-private-ip',
public_ip=False) public_ip=False)
def test_ec2_machine_tags(self):
self._test_ec2_machine('ubuntu1404-with-tags',
tags=True)

View File

@@ -0,0 +1,4 @@
---
features:
- |
Add optional tags on ec2 instances and use cloud-image label as Name.