Skip to content

Commit

Permalink
[pre-commit.ci] auto fixes from pre-commit.com hooks
Browse files Browse the repository at this point in the history
for more information, see https://pre-commit.ci
  • Loading branch information
pre-commit-ci[bot] committed Jul 23, 2023
1 parent db3cbc0 commit 5ef69c3
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 107 deletions.
28 changes: 16 additions & 12 deletions docs/kubevirt.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ This example is using Ansible playbooks and it does not need any molecule
plugins to run. You can fully control which test requirements you need to be
installed.

## Prerequisites
## Prerequisites

The `create.yml` and `destroy.yml` Ansible playbooks require the Ansible collection `kubernetes.core`. For seamless communication with the Kubernetes API server, the collection uses the following environment variables:

- `K8S_AUTH_API_KEY`: This is the token from the service account used to authenticate with the Kubernetes cluster.

- `K8S_AUTH_HOST`: This points to the URL of the Kubernetes cluster's API.

- `K8S_AUTH_VERIFY_SSL`: If set to `false`, this disables the verification of SSL/TLS certificates, which might pose a security risk. It's mainly used for testing environments, particularly when dealing with self-signed certificates.
- `K8S_AUTH_VERIFY_SSL`: If set to `false`, this disables the verification of SSL/TLS certificates, which might pose a security risk. It's mainly used for testing environments, particularly when dealing with self-signed certificates.

Additionally, for the playbooks to work, the Kubernetes service account needs specific roles and role bindings to operate in a particular namespace. This ensures the playbook has sufficient privileges to execute commands on the Kubernetes resources. These roles include getting, listing, watching, creating, deleting, and editing virtual machines and services.

Expand All @@ -34,34 +34,37 @@ metadata:
namespace: <Kubernetes VM Namespace>
name: <Molecule Kubernetes Role>
rules:
- apiGroups: ["kubevirt.io"]
resources: ["virtualmachines"]
verbs: ["get", "list", "watch", "create", "delete", "patch", "edit"]
- apiGroups: [""]
resources: ["services"]
verbs: ["get", "list", "watch", "create", "delete", "patch", "edit"]
- apiGroups: ["kubevirt.io"]
resources: ["virtualmachines"]
verbs: ["get", "list", "watch", "create", "delete", "patch", "edit"]
- apiGroups: [""]
resources: ["services"]
verbs: ["get", "list", "watch", "create", "delete", "patch", "edit"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: <Molecule Kubernetes Rolebinding>
namespace: <Kubernetes VM Namespace>
subjects:
- kind: ServiceAccount
name: <Molecule Kubernetes Serviceaccount>
namespace: <Kubernetes VM Namespace>
- kind: ServiceAccount
name: <Molecule Kubernetes Serviceaccount>
namespace: <Kubernetes VM Namespace>
roleRef:
kind: Role
name: <Molecule Kubernetes Role>
apiGroup: rbac.authorization.k8s.io
```
You will need to substitute the following placeholders:
- `<Molecule Kubernetes Serviceaccount>`: This refers to the name of the Kubernetes Serviceaccount that the molecule test utilizes to create the KubeVirt VM.
- `<Kubernetes VM Namespace>`: This denotes the name of the Kubernetes namespace where the VMs will be instantiated.
- `<Molecule Kubernetes Role>`: This is the name of the Kubernetes role which encapsulates the necessary permissions for the molecule test to function.
- `<Molecule Kubernetes Rolebinding>`: This represents the name of the Kubernetes rolebinding that associates the role `<Molecule Kubernetes Role>` with the serviceaccount `<Molecule Kubernetes Serviceaccount>`.

## Considerations

- This example employs ephemeral VMs, which enhance the speed of VM creation and cleanup. However, it's important to note that any data in the system will not be retained if the VM is rebooted.
- You don't need to worry about setting up SSH keys. The `create.yml` Ansible playbook takes care of configuring a temporary SSH key.

Expand All @@ -72,6 +75,7 @@ You will need to substitute the following placeholders:
```

Please, replace the following parameters:

- `<Kubernetes VM Namespace>`: This should be replaced with the namespace in Kubernetes where you intend to create the KubeVirt VMs.
- `<Kubernetes Node FQDN>`: Change this to the fully qualified domain name (FQDN) of the Kubernetes node that Ansible will attempt to SSH into via the Service NodePort.

Expand Down Expand Up @@ -103,4 +107,4 @@ Please, replace the following parameters:

```yaml title="destroy.yml"
{!../molecule/kubevirt/destroy.yml!}
```
```
64 changes: 32 additions & 32 deletions molecule/kubevirt/create.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,31 @@
connection: local
gather_facts: false
vars:
temporary_ssh_key_size: 2048 # Variable for the size of the SSH key
temporary_ssh_key_size: 2048 # Variable for the size of the SSH key
tasks:
- name: Set default SSH key path # Sets the path of the SSH key
- name: Set default SSH key path # Sets the path of the SSH key
set_fact:
tempoary_ssh_key_path: "{{ molecule_ephemeral_directory }}/identity_file"

- name: Generate SSH key pair # Generates a new SSH key pair
- name: Generate SSH key pair # Generates a new SSH key pair
community.crypto.openssh_keypair:
path: "{{ tempoary_ssh_key_path }}"
size: "{{ temporary_ssh_key_size }}"
register: temporary_ssh_keypair # Stores the output of this task in a variable
register: temporary_ssh_keypair # Stores the output of this task in a variable

- name: Set SSH public key # Sets the SSH public key from the key pair
set_fact:
- name: Set SSH public key # Sets the SSH public key from the key pair
set_fact:
temporary_ssh_public_key: "{{ temporary_ssh_keypair.public_key }}"

- name: Create VM in KubeVirt # Calls another file to create the VM in KubeVirt
- name: Create VM in KubeVirt # Calls another file to create the VM in KubeVirt
include_tasks: tasks/create_vm.yml
loop: "{{ molecule_yml.platforms }}" # Loops over all platforms defined in molecule_yml
loop: "{{ molecule_yml.platforms }}" # Loops over all platforms defined in molecule_yml
loop_control:
loop_var: vm # Sets the variable for the current item in the loop
loop_var: vm # Sets the variable for the current item in the loop

- name: Create Nodeport service if ssh_type is set to NodePort # Conditional block, executes if vm.ssh_service.type is NodePort
- name: Create Nodeport service if ssh_type is set to NodePort # Conditional block, executes if vm.ssh_service.type is NodePort
block:
- name: Create ssh NodePort Kubernetes Services # Creates a new NodePort service in Kubernetes
- name: Create ssh NodePort Kubernetes Services # Creates a new NodePort service in Kubernetes
kubernetes.core.k8s:
state: present
definition:
Expand All @@ -44,53 +44,53 @@
selector:
kubevirt.io/domain: "{{ vm.name }}"
type: NodePort
loop: "{{ molecule_yml.platforms }}" # Loops over all platforms defined in molecule_yml
loop: "{{ molecule_yml.platforms }}" # Loops over all platforms defined in molecule_yml
loop_control:
loop_var: vm # Sets the variable for the current item in the loop
loop_var: vm # Sets the variable for the current item in the loop

- name: Retrieve Service Info # Retrieves information about the service
- name: Retrieve Service Info # Retrieves information about the service
kubernetes.core.k8s_info:
api_version: v1
kind: Service
name: "{{ vm.name }}"
namespace: "{{ vm.namespace }}"
loop: "{{ molecule_yml.platforms }}" # Loops over all platforms defined in molecule_yml
loop: "{{ molecule_yml.platforms }}" # Loops over all platforms defined in molecule_yml
loop_control:
loop_var: vm # Sets the variable for the current item in the loop
register: node_port_services # Stores the output of this task in a variable
when: "vm.ssh_service.type == 'NodePort'" # The block is executed when this condition is met
loop_var: vm # Sets the variable for the current item in the loop
register: node_port_services # Stores the output of this task in a variable
when: "vm.ssh_service.type == 'NodePort'" # The block is executed when this condition is met

- name: Create VM dictionary # Calls another file to create a dictionary with information about the VM
- name: Create VM dictionary # Calls another file to create a dictionary with information about the VM
include_tasks: tasks/create_vm_dictionary.yml
loop: "{{ molecule_yml.platforms }}" # Loops over all platforms defined in molecule_yml
loop: "{{ molecule_yml.platforms }}" # Loops over all platforms defined in molecule_yml
loop_control:
loop_var: vm # Sets the variable for the current item in the loop
loop_var: vm # Sets the variable for the current item in the loop

- name: Create ansible inventory from dictionary # Creates an Ansible inventory file from the dictionary
- name: Create ansible inventory from dictionary # Creates an Ansible inventory file from the dictionary
vars:
molecule_inventory:
all:
children:
molecule:
hosts: "{{ molecule_systems }}"
hosts: "{{ molecule_systems }}"
ansible.builtin.copy:
content: "{{ molecule_inventory | to_nice_yaml }}"
dest: "{{ molecule_ephemeral_directory }}/inventory/molecule_inventory.yml"
mode: 0600 # Sets the permissions of the file to -rw-------
mode: 0600 # Sets the permissions of the file to -rw-------

- name: Refresh inventory # Refreshes the inventory
- name: Refresh inventory # Refreshes the inventory
ansible.builtin.meta: refresh_inventory

- name: Assert molecule group exists # Checks if the 'molecule' group exists in the inventory
- name: Assert molecule group exists # Checks if the 'molecule' group exists in the inventory
ansible.builtin.assert:
that: "'molecule' in groups"
fail_msg: "Molecule group was not found in inventory groups: {{ groups }}"
run_once: true # Ensures this task is only run once, not on every host in 'hosts'
run_once: true # Ensures this task is only run once, not on every host in 'hosts'

- name: Validate that inventory was refreshed # New playbook to validate the inventory
hosts: molecule # Runs on hosts in the 'molecule' group
gather_facts: false # Disables fact gathering
- name: Validate that inventory was refreshed # New playbook to validate the inventory
hosts: molecule # Runs on hosts in the 'molecule' group
gather_facts: false # Disables fact gathering
tasks:
- name: Wait for the host to be reachable # Waits for the host to become reachable
- name: Wait for the host to be reachable # Waits for the host to become reachable
ansible.builtin.wait_for_connection:
timeout: 120 # Waits for up to 120 seconds
timeout: 120 # Waits for up to 120 seconds
2 changes: 1 addition & 1 deletion molecule/kubevirt/destroy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@
namespace: "{{ vm.namespace }}"
loop: "{{ molecule_yml.platforms }}"
loop_control:
loop_var: vm
loop_var: vm
2 changes: 1 addition & 1 deletion molecule/kubevirt/molecule.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,4 @@ scenario:
- idempotence
- side_effect
- verify
- destroy
- destroy
104 changes: 52 additions & 52 deletions molecule/kubevirt/tasks/create_vm.yml
Original file line number Diff line number Diff line change
@@ -1,59 +1,59 @@
---
- name: Create VM in KubeVirt
kubernetes.core.k8s: # Uses the k8s module from the kubernetes.core Ansible collection
state: present # Ensures the VM exists. If it doesn't, it will be created.
kubernetes.core.k8s: # Uses the k8s module from the kubernetes.core Ansible collection
state: present # Ensures the VM exists. If it doesn't, it will be created.
definition:
apiVersion: kubevirt.io/v1 # KubeVirt's API version
kind: VirtualMachine # The type of Kubernetes resource to create
apiVersion: kubevirt.io/v1 # KubeVirt's API version
kind: VirtualMachine # The type of Kubernetes resource to create
metadata:
labels:
kubevirt.io/domain: "{{ vm.name }}" # Labels for the VM
name: "{{ vm.name }}" # Name of the VM
kubevirt.io/domain: "{{ vm.name }}" # Labels for the VM
name: "{{ vm.name }}" # Name of the VM
namespace: "{{ vm.namespace }}" # Namespace where the VM will be created
spec:
running: true # Starts the VM after creation
template:
metadata:
labels:
kubevirt.io/domain: "{{ vm.name }}" # Labels for the VM's template
spec:
domain:
devices:
disks:
- disk:
bus: virtio # Type of disk bus
name: containerdisk # Name of the container disk
- disk:
bus: virtio # Type of disk bus
name: cloudinitdisk # Name of the cloud-init disk
- name: emptydisk # Name of the empty disk
disk:
bus: virtio # Type of disk bus
resources:
requests:
memory: "{{ vm.memory | default('1Gi') }}" # Amount of memory requested for the VM
volumes:
- name: emptydisk
emptyDisk:
capacity: "{{ vm.capacity | default('2Gi') }}" # Capacity of the empty ephemeral disk
- containerDisk:
image: "{{ vm.image }}" # The image used for the container disk
name: containerdisk
- cloudInitNoCloud: # Cloud-init configuration
userData: | # User-data script
#cloud-config
preserve_hostname: true
hostname: "{{ vm.name }}" # Sets the hostname
fqdn: "{{ vm.name }}" # Fully Qualified Domain Name
prefer_fqdn_over_hostname: true
users:
- default
- name: {{ vm.ansible_user }}
lock_passwd: true # Locks the password
ssh_authorized_keys:
- "{{ temporary_ssh_public_key }}" # SSH public key
runcmd:
- [ sh, -c, "hostnamectl set-hostname {{ vm.name }}" ] # Sets the hostname
- [ sudo, yum, install, -y, qemu-guest-agent ] # Installs qemu-guest-agent
- [ sudo, systemctl, start, qemu-guest-agent ] # Starts qemu-guest-agent
name: cloudinitdisk
running: true # Starts the VM after creation
template:
metadata:
labels:
kubevirt.io/domain: "{{ vm.name }}" # Labels for the VM's template
spec:
domain:
devices:
disks:
- disk:
bus: virtio # Type of disk bus
name: containerdisk # Name of the container disk
- disk:
bus: virtio # Type of disk bus
name: cloudinitdisk # Name of the cloud-init disk
- name: emptydisk # Name of the empty disk
disk:
bus: virtio # Type of disk bus
resources:
requests:
memory: "{{ vm.memory | default('1Gi') }}" # Amount of memory requested for the VM
volumes:
- name: emptydisk
emptyDisk:
capacity: "{{ vm.capacity | default('2Gi') }}" # Capacity of the empty ephemeral disk
- containerDisk:
image: "{{ vm.image }}" # The image used for the container disk
name: containerdisk
- cloudInitNoCloud: # Cloud-init configuration
userData: | # User-data script
#cloud-config
preserve_hostname: true
hostname: "{{ vm.name }}" # Sets the hostname
fqdn: "{{ vm.name }}" # Fully Qualified Domain Name
prefer_fqdn_over_hostname: true
users:
- default
- name: {{ vm.ansible_user }}
lock_passwd: true # Locks the password
ssh_authorized_keys:
- "{{ temporary_ssh_public_key }}" # SSH public key
runcmd:
- [ sh, -c, "hostnamectl set-hostname {{ vm.name }}" ] # Sets the hostname
- [ sudo, yum, install, -y, qemu-guest-agent ] # Installs qemu-guest-agent
- [ sudo, systemctl, start, qemu-guest-agent ] # Starts qemu-guest-agent
name: cloudinitdisk
18 changes: 9 additions & 9 deletions molecule/kubevirt/tasks/create_vm_dictionary.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,25 @@
- name: Create VM dictionary
vars:
# This variable block is setting the `ssh_service_address` variable.
# It first checks if the service type of the SSH service is 'NodePort'.
# It first checks if the service type of the SSH service is 'NodePort'.
# If it is, it retrieves the 'nodePort' from the services results.
ssh_service_address: >-
{%- set svc_type = vm.ssh_service.type | default(None) -%}
{%- if svc_type == 'NodePort' -%}
{%- set svc_type = vm.ssh_service.type | default(None) -%}
{%- if svc_type == 'NodePort' -%}
{{(node_port_services.results | selectattr('vm.name','==',vm.name) | first)['resources'][0]['spec']['ports'][0]['nodePort'] }}
{%- endif -%}
set_fact:
set_fact:
# Here, the task is updating the `molecule_systems` dictionary with new VM information.
# If `molecule_systems` doesn't exist, it is created as an empty dictionary.
# Then it is combined with a new dictionary for the current VM, containing ansible connection details.
molecule_systems: >-
{{
{{
molecule_systems | default({}) | combine({
vm.name: {
'ansible_user': 'cloud-user',
'ansible_host': vm.ssh_service.nodeport_host,
'ansible_ssh_port': ssh_service_address,
'ansible_user': 'cloud-user',
'ansible_host': vm.ssh_service.nodeport_host,
'ansible_ssh_port': ssh_service_address,
'ansible_ssh_private_key_file': tempoary_ssh_key_path
}
})
})
}}

0 comments on commit 5ef69c3

Please sign in to comment.