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

Add project support for lxd_container and lxd_profile module #4479

Merged
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
minor_changes:
- lxd_container - adds ``project`` option to allow selecting project for LXD instance (https://github.com/ansible-collections/community.general/pull/4479).
- lxd_profile - adds ``project`` option to allow selecting project for LXD profile (https://github.com/ansible-collections/community.general/pull/4479).
75 changes: 60 additions & 15 deletions plugins/modules/cloud/lxd/lxd_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@
- Name of an instance.
type: str
required: true
project:
description:
- 'Project of an instance.
See U(https://github.com/lxc/lxd/blob/master/doc/projects.md).'
required: false
type: str
we10710aa marked this conversation as resolved.
Show resolved Hide resolved
version_added: 4.8.0
architecture:
description:
- 'The architecture for the instance (for example C(x86_64) or C(i686)).
Expand Down Expand Up @@ -248,6 +255,26 @@
wait_for_ipv4_addresses: true
timeout: 600

# An example for creating container in project other than default
- hosts: localhost
connection: local
tasks:
- name: Create a started container in project mytestproject
community.general.lxd_container:
name: mycontainer
project: mytestproject
ignore_volatile_options: true
state: started
source:
protocol: simplestreams
type: image
mode: pull
server: https://images.linuxcontainers.org
alias: ubuntu/20.04/cloud
profiles: ["default"]
wait_for_ipv4_addresses: true
timeout: 600

# An example for deleting a container
- hosts: localhost
connection: local
Expand Down Expand Up @@ -412,6 +439,7 @@ def __init__(self, module):
"""
self.module = module
self.name = self.module.params['name']
self.project = self.module.params['project']
self._build_config()

self.state = self.module.params['state']
Expand Down Expand Up @@ -468,16 +496,16 @@ def _build_config(self):
self.config[attr] = param_val

def _get_instance_json(self):
return self.client.do(
'GET', '{0}/{1}'.format(self.api_endpoint, self.name),
ok_error_codes=[404]
)
url = '{0}/{1}'.format(self.api_endpoint, self.name)
if self.project:
url = '{0}?{1}'.format(url, urlencode(dict(project=self.project)))
return self.client.do('GET', url, ok_error_codes=[404])

def _get_instance_state_json(self):
return self.client.do(
'GET', '{0}/{1}/state'.format(self.api_endpoint, self.name),
ok_error_codes=[404]
)
url = '{0}/{1}/state'.format(self.api_endpoint, self.name)
if self.project:
url = '{0}?{1}'.format(url, urlencode(dict(project=self.project)))
return self.client.do('GET', url, ok_error_codes=[404])

@staticmethod
def _instance_json_to_module_state(resp_json):
Expand All @@ -486,18 +514,26 @@ def _instance_json_to_module_state(resp_json):
return ANSIBLE_LXD_STATES[resp_json['metadata']['status']]

def _change_state(self, action, force_stop=False):
url = '{0}/{1}/state'.format(self.api_endpoint, self.name)
if self.project:
url = '{0}?{1}'.format(url, urlencode(dict(project=self.project)))
body_json = {'action': action, 'timeout': self.timeout}
if force_stop:
body_json['force'] = True
return self.client.do('PUT', '{0}/{1}/state'.format(self.api_endpoint, self.name), body_json=body_json)
return self.client.do('PUT', url, body_json=body_json)

def _create_instance(self):
url = self.api_endpoint
url_params = dict()
if self.target:
url_params['target'] = self.target
if self.project:
url_params['project'] = self.project
if url_params:
url = '{0}?{1}'.format(url, urlencode(url_params))
config = self.config.copy()
config['name'] = self.name
if self.target:
self.client.do('POST', '{0}?{1}'.format(self.api_endpoint, urlencode(dict(target=self.target))), config, wait_for_container=self.wait_for_container)
else:
self.client.do('POST', self.api_endpoint, config, wait_for_container=self.wait_for_container)
self.client.do('POST', url, config, wait_for_container=self.wait_for_container)
self.actions.append('create')

def _start_instance(self):
Expand All @@ -513,7 +549,10 @@ def _restart_instance(self):
self.actions.append('restart')

def _delete_instance(self):
self.client.do('DELETE', '{0}/{1}'.format(self.api_endpoint, self.name))
url = '{0}/{1}'.format(self.api_endpoint, self.name)
if self.project:
url = '{0}?{1}'.format(url, urlencode(dict(project=self.project)))
self.client.do('DELETE', url)
self.actions.append('delete')

def _freeze_instance(self):
Expand Down Expand Up @@ -666,7 +705,10 @@ def _apply_instance_configs(self):
if self._needs_to_change_instance_config('profiles'):
body_json['profiles'] = self.config['profiles']

self.client.do('PUT', '{0}/{1}'.format(self.api_endpoint, self.name), body_json=body_json)
url = '{0}/{1}'.format(self.api_endpoint, self.name)
if self.project:
url = '{0}?{1}'.format(url, urlencode(dict(project=self.project)))
self.client.do('PUT', url, body_json=body_json)
self.actions.append('apply_instance_configs')

def run(self):
Expand Down Expand Up @@ -715,6 +757,9 @@ def main():
type='str',
required=True
),
project=dict(
type='str',
),
architecture=dict(
type='str',
),
Expand Down
53 changes: 45 additions & 8 deletions plugins/modules/cloud/lxd/lxd_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@
- Name of a profile.
required: true
type: str
project:
description:
- 'Project of a profile.
See U(https://github.com/lxc/lxd/blob/master/doc/projects.md).'
type: str
required: false
we10710aa marked this conversation as resolved.
Show resolved Hide resolved
version_added: 4.8.0
description:
description:
- Description of the profile.
Expand Down Expand Up @@ -129,6 +136,19 @@
parent: br0
type: nic

# An example for creating a profile in project mytestproject
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that you have a "project" to that example. :)

- hosts: localhost
connection: local
tasks:
- name: Create a profile
community.general.lxd_profile:
name: testprofile
felixfontein marked this conversation as resolved.
Show resolved Hide resolved
project: mytestproject
state: present
config: {}
description: test profile in project mytestproject
devices: {}

# An example for creating a profile via http connection
- hosts: localhost
connection: local
Expand Down Expand Up @@ -208,6 +228,7 @@
import os
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.community.general.plugins.module_utils.lxd import LXDClient, LXDClientException
from ansible.module_utils.six.moves.urllib.parse import urlencode

# ANSIBLE_LXD_DEFAULT_URL is a default value of the lxd endpoint
ANSIBLE_LXD_DEFAULT_URL = 'unix:/var/lib/lxd/unix.socket'
Expand All @@ -232,6 +253,7 @@ def __init__(self, module):
"""
self.module = module
self.name = self.module.params['name']
self.project = self.module.params['project']
self._build_config()
self.state = self.module.params['state']
self.new_name = self.module.params.get('new_name', None)
Expand Down Expand Up @@ -272,10 +294,10 @@ def _build_config(self):
self.config[attr] = param_val

def _get_profile_json(self):
return self.client.do(
'GET', '/1.0/profiles/{0}'.format(self.name),
ok_error_codes=[404]
)
url = '/1.0/profiles/{0}'.format(self.name)
if self.project:
url = '{0}?{1}'.format(url, urlencode(dict(project=self.project)))
return self.client.do('GET', url, ok_error_codes=[404])

@staticmethod
def _profile_json_to_module_state(resp_json):
Expand Down Expand Up @@ -307,14 +329,20 @@ def _update_profile(self):
changed=False)

def _create_profile(self):
url = '/1.0/profiles'
if self.project:
url = '{0}?{1}'.format(url, urlencode(dict(project=self.project)))
config = self.config.copy()
config['name'] = self.name
self.client.do('POST', '/1.0/profiles', config)
self.client.do('POST', url, config)
self.actions.append('create')

def _rename_profile(self):
url = '/1.0/profiles/{0}'.format(self.name)
if self.project:
url = '{0}?{1}'.format(url, urlencode(dict(project=self.project)))
config = {'name': self.new_name}
self.client.do('POST', '/1.0/profiles/{0}'.format(self.name), config)
self.client.do('POST', url, config)
self.actions.append('rename')
self.name = self.new_name

Expand Down Expand Up @@ -421,11 +449,17 @@ def _apply_profile_configs(self):
config = self._generate_new_config(config)

# upload config to lxd
self.client.do('PUT', '/1.0/profiles/{0}'.format(self.name), config)
url = '/1.0/profiles/{0}'.format(self.name)
if self.project:
url = '{0}?{1}'.format(url, urlencode(dict(project=self.project)))
self.client.do('PUT', url, config)
self.actions.append('apply_profile_configs')

def _delete_profile(self):
self.client.do('DELETE', '/1.0/profiles/{0}'.format(self.name))
url = '/1.0/profiles/{0}'.format(self.name)
if self.project:
url = '{0}?{1}'.format(url, urlencode(dict(project=self.project)))
self.client.do('DELETE', url)
self.actions.append('delete')

def run(self):
Expand Down Expand Up @@ -469,6 +503,9 @@ def main():
type='str',
required=True
),
project=dict(
type='str',
),
new_name=dict(
type='str',
),
Expand Down