diff --git a/roles/config_drive/README.md b/roles/config_drive/README.md new file mode 100644 index 0000000000..ce7740203c --- /dev/null +++ b/roles/config_drive/README.md @@ -0,0 +1,60 @@ +# config_drive +Role to build a `NoCloud` config-drive ISO image. + +## Privilege escalation +Required to installed required packages. + +## Parameters +* `cifmw_config_drive_basedir`: (String) Base directory. Defaults to `{{ cifmw_basedir }}` which defaults to `~/ci-framework-data`. +* `cifmw_config_drive_workdir`: (String) Working directory. Defaults to: `{{ cifmw_config_drive_basedir }}/cifmw_config_drive` +* `cifmw_config_drive_instancedir`: (String) Per-instance working directory. Defaults to: `{{ cifmw_config_drive_workdir }}/{{ cifmw_config_drive_uuid }}` +* `cifmw_config_drive_iso_image`: (String) Path to built ISO image. Defaults to: `{{ cifmw_config_drive_workdir }}/{{ cifmw_config_drive_uuid }}.iso` +* `cifmw_config_drive_uuid`: (String) Instance UUID. Defaults to `uuid-test`. +* `cifmw_config_drive_name`: (String) Instance Name. Defaults to `test`. +* `cifmw_config_drive_hostname`: (String) Instance hostname. Defaults to `test.example.com`. +* `cifmw_config_drive_userdata`: (Dict) cloud-init user-data, in cloud-config-data format. Defaults to `none`. +* `cifmw_config_drive_networkconfig`: (Dict) cloud-init network-config. Defaults to `none`. + +## Examples + +``` +- name: Build config-drive image playbook + hosts: "{{ cifmw_target_host | default('localhost') }}" + tasks: + - name: Include config_drive role + vars: + cifmw_config_drive_uuid: de2f369a-1886-4a90-8e50-e419289e6850 + cifmw_config_drive_name: test01 + cifmw_config_drive_hostname: test01.example.com + cifmw_config_drive_userdata: + ssh_authorized_keys: + - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCg1LHRahLiT1NFv4l/XH + packages: + - git + - bind-utils + write_files: + - path: /root/test.file + owner: root:root + content: | + # Test file content + runcmd: + - [ 'sh', '-c', 'echo foo | tee -a /tmp/foo' ] + cifmw_config_drive_networkconfig: + network: + version: 2 + ethernets: + id0: + match: + macaddress: "aa:bb:cc:dd:ee:ff" + addresses: + - 192.168.0.101/24 + routes: + - to: 0.0.0.0/0 + via: 192.168.0.1 + on-link: true + nameservers: + addresses: + - 192.168.0.1 + ansible.builtin.include_role: + name: config_drive +``` diff --git a/roles/config_drive/defaults/main.yml b/roles/config_drive/defaults/main.yml new file mode 100644 index 0000000000..dd93b65e5c --- /dev/null +++ b/roles/config_drive/defaults/main.yml @@ -0,0 +1,32 @@ +--- +# Copyright Red Hat, Inc. +# All Rights Reserved. +# +# 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. + + +# All variables intended for modification should be placed in this file. +# All variables within this role should have a prefix of "cifmw_config_drive" +cifmw_config_drive_basedir: >- + {{ + cifmw_basedir | default(ansible_user_dir ~ '/ci-framework-data') + }} +cifmw_config_drive_workdir: "{{ cifmw_config_drive_basedir }}/cifmw_config_drive" + +cifmw_config_drive_uuid: uuid-test +cifmw_config_drive_instancedir: "{{ cifmw_config_drive_workdir }}/{{ cifmw_config_drive_uuid }}" +cifmw_config_drive_iso_image: "{{ cifmw_config_drive_workdir }}/{{ cifmw_config_drive_uuid }}.iso" +cifmw_config_drive_name: test +cifmw_config_drive_hostname: test.example.com +cifmw_config_drive_userdata: +cifmw_config_drive_networkconfig: diff --git a/roles/config_drive/meta/main.yml b/roles/config_drive/meta/main.yml new file mode 100644 index 0000000000..01a30c6389 --- /dev/null +++ b/roles/config_drive/meta/main.yml @@ -0,0 +1,41 @@ +--- +# Copyright Red Hat, Inc. +# All Rights Reserved. +# +# 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. + + +galaxy_info: + author: CI Framework + description: CI Framework Role -- config_drive + company: Red Hat + license: Apache-2.0 + min_ansible_version: 2.14 + namespace: cifmw + # + # Provide a list of supported platforms, and for each platform a list of versions. + # If you don't wish to enumerate all versions for a particular platform, use 'all'. + # To view available platforms and versions (or releases), visit: + # https://galaxy.ansible.com/api/v1/platforms/ + # + platforms: + - name: CentOS + versions: + - 9 + + galaxy_tags: + - cifmw + +# List your role dependencies here, one per line. Be sure to remove the '[]' above, +# if you add dependencies to this list. +dependencies: [] diff --git a/roles/config_drive/molecule/default/converge.yml b/roles/config_drive/molecule/default/converge.yml new file mode 100644 index 0000000000..cbb896b55c --- /dev/null +++ b/roles/config_drive/molecule/default/converge.yml @@ -0,0 +1,56 @@ +--- +# Copyright Red Hat, Inc. +# All Rights Reserved. +# +# 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. + + +- name: Converge + hosts: all + tasks: + - name: Include config_drive role + vars: + cifmw_config_drive_uuid: de2f369a-1886-4a90-8e50-e419289e6850 + cifmw_config_drive_name: test01 + cifmw_config_drive_hostname: test01.example.com + cifmw_config_drive_userdata: + ssh_authorized_keys: + - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCg1LHRahLiT1NFv4l/XH + packages: + - git + - bind-utils + write_files: + - path: /root/test.file + owner: root:root + content: |- + # Test file content + runcmd: + - ['sh', '-c', 'echo foo | tee -a /tmp/foo'] + cifmw_config_drive_networkconfig: + network: + version: 2 + ethernets: + id0: + match: + macaddress: "aa:bb:cc:dd:ee:ff" + addresses: + - 192.168.0.101/24 + routes: + - to: 0.0.0.0/0 + via: 192.168.0.1 + on-link: true + nameservers: + addresses: + - 192.168.0.1 + ansible.builtin.include_role: + name: config_drive diff --git a/roles/config_drive/molecule/default/molecule.yml b/roles/config_drive/molecule/default/molecule.yml new file mode 100644 index 0000000000..fda947cafe --- /dev/null +++ b/roles/config_drive/molecule/default/molecule.yml @@ -0,0 +1,11 @@ +--- +# Mainly used to override the defaults set in .config/molecule/ +# By default, it uses the "config_podman.yml" - in CI, it will use +# "config_local.yml". +log: true + +provisioner: + name: ansible + log: true + env: + ANSIBLE_STDOUT_CALLBACK: yaml diff --git a/roles/config_drive/molecule/default/prepare.yml b/roles/config_drive/molecule/default/prepare.yml new file mode 100644 index 0000000000..d3594acc41 --- /dev/null +++ b/roles/config_drive/molecule/default/prepare.yml @@ -0,0 +1,21 @@ +--- +# Copyright Red Hat, Inc. +# All Rights Reserved. +# +# 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. + + +- name: Prepare + hosts: all + roles: + - role: test_deps diff --git a/roles/config_drive/tasks/cleanup.yml b/roles/config_drive/tasks/cleanup.yml new file mode 100644 index 0000000000..39dbb7baa3 --- /dev/null +++ b/roles/config_drive/tasks/cleanup.yml @@ -0,0 +1,20 @@ +--- +# Copyright Red Hat, Inc. +# All Rights Reserved. +# +# 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. + +- name: Cleaning up config_drive working directory + ansible.builtin.file: + state: absent + path: "{{ cifmw_config_drive_workdir }}/" diff --git a/roles/config_drive/tasks/main.yml b/roles/config_drive/tasks/main.yml new file mode 100644 index 0000000000..af65b882a3 --- /dev/null +++ b/roles/config_drive/tasks/main.yml @@ -0,0 +1,73 @@ +--- +# Copyright Red Hat, Inc. +# All Rights Reserved. +# +# 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. + +- name: Ensure needed directories exist + ansible.builtin.file: + path: "{{ cifmw_config_drive_basedir }}/{{ item }}" + state: directory + mode: "0755" + loop: + - artifacts + - logs + +- name: Install required RPM packages + tags: + - packages + become: true + ansible.builtin.package: + name: + - genisoimage + - gzip + - coreutils + state: present + +- name: Crate config drive instance directory + ansible.builtin.file: + path: "{{ cifmw_config_drive_instancedir }}" + state: directory + mode: "0755" + +- name: Generate meta-data + ansible.builtin.template: + src: "meta-data.j2" + dest: "{{ cifmw_config_drive_instancedir }}/meta-data" + mode: '0644' + +- name: Generate user-data + ansible.builtin.template: + src: "user-data.j2" + dest: "{{ cifmw_config_drive_instancedir }}/user-data" + mode: '0644' + +- name: Generate network-data + when: + - "cifmw_config_drive_networkconfig is defined" + - "cifmw_config_drive_networkconfig is not none" + ansible.builtin.template: + src: "network-config.j2" + dest: "{{ cifmw_config_drive_instancedir }}/network-config" + mode: '0644' + +- name: Generate nocloud iso image + cifmw.general.ci_script: + chdir: "{{ cifmw_config_drive_instancedir }}" + output_dir: "{{ cifmw_config_drive_basedir }}/artifacts" + script: >- + genisoimage -output {{ cifmw_config_drive_iso_image }} -volid CIDATA -joliet \ + -rock user-data meta-data \ + {% if cifmw_config_drive_networkconfig is defined and cifmw_config_drive_networkconfig is not none -%} + network-config + {%- endif -%} diff --git a/roles/config_drive/templates/meta-data.j2 b/roles/config_drive/templates/meta-data.j2 new file mode 100644 index 0000000000..00ce3f2a07 --- /dev/null +++ b/roles/config_drive/templates/meta-data.j2 @@ -0,0 +1,3 @@ +--- +instance-id: {{ cifmw_config_drive_uuid }} +hostname: {{ cifmw_config_drive_hostname }} diff --git a/roles/config_drive/templates/network-config.j2 b/roles/config_drive/templates/network-config.j2 new file mode 100644 index 0000000000..4c96d4445e --- /dev/null +++ b/roles/config_drive/templates/network-config.j2 @@ -0,0 +1 @@ +{{ cifmw_config_drive_networkconfig | to_nice_yaml(indent=2, default_style="\"") }} diff --git a/roles/config_drive/templates/user-data.j2 b/roles/config_drive/templates/user-data.j2 new file mode 100644 index 0000000000..11b325515a --- /dev/null +++ b/roles/config_drive/templates/user-data.j2 @@ -0,0 +1,4 @@ +#cloud-config +{% if cifmw_config_drive_userdata is defined and cifmw_config_drive_userdata is not none -%} +{{ cifmw_config_drive_userdata | to_nice_yaml(indent=2, default_style="\"") }} +{% endif %} diff --git a/zuul.d/molecule.yaml b/zuul.d/molecule.yaml index c43ba41e37..2c92ea6a43 100644 --- a/zuul.d/molecule.yaml +++ b/zuul.d/molecule.yaml @@ -202,6 +202,17 @@ parent: cifmw-molecule-base vars: TEST_RUN: cifmw_test_role +- job: + files: + - ^common-requirements.txt + - ^test-requirements.txt + - ^roles/config_drive/(?!meta|README).* + - ^ci/playbooks/molecule.* + - ^.config/molecule/.* + name: cifmw-molecule-config_drive + parent: cifmw-molecule-base + vars: + TEST_RUN: config_drive - job: files: - ^common-requirements.txt diff --git a/zuul.d/projects.yaml b/zuul.d/projects.yaml index f780ae7a4e..64481f409c 100644 --- a/zuul.d/projects.yaml +++ b/zuul.d/projects.yaml @@ -29,6 +29,7 @@ - cifmw-molecule-cifmw_cephadm - cifmw-molecule-cifmw_create_admin - cifmw-molecule-cifmw_test_role + - cifmw-molecule-config_drive - cifmw-molecule-copy_container - cifmw-molecule-deploy_bmh - cifmw-molecule-devscripts