diff --git a/CODEOWNERS b/CODEOWNERS index df487ef..86cacd4 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1,5 +1,2 @@ # Enter code owners here: -# https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners -# -# Example: -# * +* @wickdchromosome diff --git a/README.md b/README.md index 6eb8014..f039543 100644 --- a/README.md +++ b/README.md @@ -1,51 +1,53 @@ -# Ansible Role - potos\_template +# XDG autostart role -Role to use as template for new roles of Potos Linux Clients. +A role for Potos, used to configure scripts that should run for users as they log in. -[![Test](https://github.com/projectpotos/ansible-role-potos_template/actions/workflows/test.yml/badge.svg)](https://github.com/projectpotos/ansible-role-potos_template/actions/workflows/test.yml) +A key feature is to only run the script once. So the first time the user logs in, the script runs, then disables itself. -## Example Playbook +# A picture is worth a thousand words +![Role chart](role.png) -As this role is tested via Molecule one can use [that -playbook](./molecule/default/converge.yml) as a starting point: +This role is supposed to be imported into the specs repo, and configured in the specs repo's vars/ directory. -```yaml ---- +## Quickstart -- name: Converge - hosts: all - gather_facts: yes - tasks: - - name: run role - ansible.builtin.include_role: - name: 'ansible-role-potos_template' +If the role is only imported into the specs repo, but not configured with vars, it will deploy a script which sets the volume of the default sound sink to ~80% using pulseaudio. +To get started asap, import the role in the specs repo(files/templates/requirements.yml.j2): +``` +- name: xdgautostart + src: git+https://github.com/wickdChromosome/ansible-role-potos_xdgautostart.git + version: 'master' ``` -## Role Variables - -The default variables are defined in [defaults/main.yml](./defaults/main.yml): +Now do an ansible-pull. In var/log/potos/ansible.log, you should be able to see the pulseaudio script being deployed. -```yaml ---- +In `/usr/local/bin`, you should be able to see `pulseaudio-example.sh-wrapper.sh` and `pulseaudio-example.sh`. -# Example variable -potos_template_example_var: 'hello world!' +In `/etc/xdg/autostart` you will find pulseaudio-example.sh-wrapper.sh.desktop. -# List of items used for action xyz -potos_template_example_list: [] +After logout and login, if runonlyonce is set(by default it is for this example), you will find `~/.config/autostart/pulseaudio-example.sh-wrapper.sh.desktop` as well, where autorun is disabled for the user you are logged in under for this script. -``` +## If the script is already on the remote host +Existing script automation(maybe deployed by another role under /usr/local/bin) is also supported. +However, in that case the potos_xdgautostart list should refer to the script as $deployed_script + .j2 -Another option is to use `ansible-doc` to read the argument specification: +For example, if the script is under `/usr/local/bin/example.sh`, the script should be present in the list as `script: "example.sh.j2"`, even +if there is no existing .j2 template for the script. -```sh -ansible-doc --type role -r . main ansible-role-potos_template +## Vars +Here, after importing the role in the specs repo: +``` +- potos_xdgautostart: # List of scripts to autostart + - script: "test_1.sh.j2" # Name of script to run on user login(stored in files/potos_xdgautostart for specs repo) + runonlyonce: yes # For each user, run the script once and only once on first login + my_var_to_template: "1245" # If test_1.sh.j2 has $my_var_to_template, it can be templated as {{ item.my_var_to_template }} in test_1.sh.j2 + - script: "test_2.sh.j2" + runonlyonce: no # For each user, run the script on every login ``` ## Requirements - -N/A +The script specified to be deployed must exist either under templates/ as specified, or on the remote host already deployed. ## License diff --git a/defaults/main.yml b/defaults/main.yml index caf29c2..4e98e3b 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -1,7 +1,8 @@ --- -# Example variable -potos_template_example_var: 'hello world!' - -# List of items used for action xyz -potos_template_example_list: [] +# Int between 0 and 65536(0-100%), for setting +# PulseAudio default volume +potos_xdg_autostart: + - script: "pulseaudio_example.sh.j2" + runonlyonce: true + potos_pulseaudio_default_volume: 50000 diff --git a/files/disable_script.sh b/files/disable_script.sh new file mode 100644 index 0000000..ad6078d --- /dev/null +++ b/files/disable_script.sh @@ -0,0 +1,6 @@ +# Disable this script +script_name=$(basename "$0") +mkdir -p "$HOME/.config/autostart/" +cp "/etc/xdg/autostart/$script_name.desktop" "$HOME/.config/autostart/$script_name.desktop" +sed -i 's/X-GNOME-Autostart-enabled=true/X-GNOME-Autostart-enabled=false/g' "$HOME/.config/autostart/$script_name.desktop" +chmod +x "$HOME/.config/autostart/$script_name.sh.desktop" diff --git a/meta/argument_specs.yml b/meta/argument_specs.yml index a595d31..b79e96d 100644 --- a/meta/argument_specs.yml +++ b/meta/argument_specs.yml @@ -2,18 +2,12 @@ argument_specs: main: - short_description: Role to use as template for new roles of Potos Linux Clients. + short_description: Role to use to run scripts automatically on user login, either once or recurringly options: - potos_template_example_var: + potos_xdg_autostart: description: - - Example variable - type: str - required: no - default: 'hello world!' - potos_template_example_list: - description: - - List of items used for action xyz + - List of scripts for deployment type: list - elements: str - required: no + elements: dict + required: false default: [] diff --git a/meta/main.yml b/meta/main.yml index fd5f6bd..2ac2bba 100644 --- a/meta/main.yml +++ b/meta/main.yml @@ -2,9 +2,9 @@ galaxy_info: author: Project Potos - description: ole to use as template for new roles of Potos Linux Clients. + description: Role to use as a way to auto-execute on scripts on login company: Project Potos - role_name: potos_wallpaper + role_name: potos_xdgautostart namespace: projectpotos license: GPL-3.0-only min_ansible_version: '2.12' diff --git a/molecule/default/converge.yml b/molecule/default/converge.yml index 63d2a8e..c2b7232 100644 --- a/molecule/default/converge.yml +++ b/molecule/default/converge.yml @@ -2,8 +2,16 @@ - name: Converge hosts: all - gather_facts: yes + gather_facts: true + vars: + potos_xdg_autostart: + - script: "test_1.sh.j2" + runonlyonce: true + - script: "test_2.sh.j2" + runonlyonce: false + tasks: - - name: run role + + - name: Run role ansible.builtin.include_role: - name: 'ansible-role-potos_template' + name: 'ansible-role-potos_xdgautostart' diff --git a/molecule/default/potos_wallpaper/potos-wallpaper_test.png b/molecule/default/potos_wallpaper/potos-wallpaper_test.png deleted file mode 100644 index a9f687f..0000000 Binary files a/molecule/default/potos_wallpaper/potos-wallpaper_test.png and /dev/null differ diff --git a/molecule/default/potos_xdgautostart/usr/local/bin/test_1.sh.j2 b/molecule/default/potos_xdgautostart/usr/local/bin/test_1.sh.j2 new file mode 100644 index 0000000..bb3e0c7 --- /dev/null +++ b/molecule/default/potos_xdgautostart/usr/local/bin/test_1.sh.j2 @@ -0,0 +1,4 @@ +#!/bin/bash + +touch $HOME/"$0"_worked.txt + diff --git a/molecule/default/potos_xdgautostart/usr/local/bin/test_2.sh.j2 b/molecule/default/potos_xdgautostart/usr/local/bin/test_2.sh.j2 new file mode 100644 index 0000000..bb3e0c7 --- /dev/null +++ b/molecule/default/potos_xdgautostart/usr/local/bin/test_2.sh.j2 @@ -0,0 +1,4 @@ +#!/bin/bash + +touch $HOME/"$0"_worked.txt + diff --git a/molecule/default/prepare.yml b/molecule/default/prepare.yml index 1338b7a..171a50f 100644 --- a/molecule/default/prepare.yml +++ b/molecule/default/prepare.yml @@ -2,6 +2,9 @@ - name: Prepare hosts: all - gather_facts: yes + gather_facts: true - tasks: [] + tasks: + - name: Make directory for gnome autostart script(w/o installing gnome) + changed_when: false + ansible.builtin.command: 'mkdir -p /etc/xdg/autostart' # noqa: command-instead-of-module diff --git a/molecule/default/verify.yml b/molecule/default/verify.yml index e8ddfc1..344bd42 100644 --- a/molecule/default/verify.yml +++ b/molecule/default/verify.yml @@ -2,13 +2,65 @@ - name: Verify hosts: all - gather_facts: no - + gather_facts: false tasks: - - name: check if template has been applied + # test templates + - name: Check if template for script desktop file has been applied + ansible.builtin.stat: + path: "/etc/xdg/autostart/test_1.sh_wrapper.sh.desktop" + register: out + failed_when: + - not out.stat.exists + + - name: Check if template for script has been applied ansible.builtin.stat: - path: "/potos.example" + path: "/usr/local/bin/test_1.sh" register: out - changed_when: false failed_when: - not out.stat.exists + + - name: Check if template for wrapper script has been applied + ansible.builtin.stat: + path: "/usr/local/bin/test_1.sh_wrapper.sh" + register: out + failed_when: + - not out.stat.exists + + # test that the wrapper doesn't have disable lines when it shouldn't(if the script is set to run on every login) + - name: Check that the test case where runonlyonce is true does have the disable script + ansible.builtin.lineinfile: + path: "/usr/local/bin/test_1.sh_wrapper.sh" + line: "# BEGIN ANSIBLE MANAGED BLOCK" + state: present + register: out + failed_when: + - out.changed + + - name: Check that the test case where runonlyonce is false doesnt have the disable script + ansible.builtin.lineinfile: + path: "/usr/local/bin/test_2.sh_wrapper.sh" + line: "BEGIN ANSIBLE MANAGED BLOCK" + state: absent + register: out + failed_when: + - out.changed + + # test that the desktop file points to the correct wrapper script + - name: Test that the desktop file points to the correct wrapper script + ansible.builtin.lineinfile: + path: "/etc/xdg/autostart/test_2.sh_wrapper.sh.desktop" + line: "Exec=/usr/local/bin/test_2.sh_wrapper.sh" + state: present + register: out + failed_when: + - out.changed + + # test that the wrapper script points to the correct path for the main script it wraps + - name: Test that the wrapper script points to the correct path for the main script it wraps + ansible.builtin.lineinfile: + path: "/etc/xdg/autostart/test_2.sh_wrapper" + line: "/usr/local/bin/test_2.sh" + state: present + register: out + failed_when: + - out.changed diff --git a/requirements.txt b/requirements.txt index 5ed0084..7d70e70 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,7 +4,7 @@ ansible>=2.12 # Required for testing ## ansible/yaml lint -ansible-lint~=24.5.0 +ansible-lint~=24.2.2 yamllint~=1.35.1 ## molecule tests diff --git a/role.png b/role.png new file mode 100644 index 0000000..1a35aae Binary files /dev/null and b/role.png differ diff --git a/tasks/main.yml b/tasks/main.yml index 4a00de6..91c3753 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -1,9 +1,50 @@ --- -- name: Example task to deploy a template +# Loop over all script names, make an autostart desktopfile for each +- name: Copy over the desktop file to the new dir ansible.builtin.template: - src: 'potos.example.j2' - dest: '/potos.example' - owner: root - group: root - mode: '0755' + src: "potos_xdgautostart/etc/xdg/autostart/desktopfile.j2" + dest: "/etc/xdg/autostart/{{ item.script | replace('.j2','') }}_wrapper.sh.desktop" + force: true + mode: '0777' + loop: "{{ potos_xdg_autostart }}" + +# Copy over script file to global autostart dir +- name: Copy over the script file to the new dir + ansible.builtin.template: + src: "potos_xdgautostart/usr/local/bin/{{ item.script }}" + dest: "/usr/local/bin/{{ item.script | replace('.j2','') }}" + force: true + mode: '0777' + loop: "{{ potos_xdg_autostart }}" + failed_when: false + +# Check to make sure target script file is on the remote host, +# either because it was copied over or it was already there +- name: Make sure target script file is present + ansible.builtin.stat: + path: "/usr/local/bin/{{ item.script | replace('.j2','') }}" + register: file_stat + failed_when: not file_stat.stat.exists + loop: "{{ potos_xdg_autostart }}" + +# Create the script wrapper file to global autostart dir +- name: Copy over the script file wrapper to the new dir + ansible.builtin.lineinfile: + path: "/usr/local/bin/{{ item.script | replace('.j2','') }}_wrapper.sh" + line: "/usr/local/bin/{{ item.script | replace('.j2','') }}" + regexp: "^/usr/local/bin/{{ item.script | replace('.j2','') }}$" + state: present + backup: false + create: true + mode: '0777' + loop: "{{ potos_xdg_autostart }}" + +# Append disable script to each copied over script +- name: Add disable script to wrapper + ansible.builtin.blockinfile: + path: "/usr/local/bin/{{ item.script | replace('.j2','') }}_wrapper.sh" + block: "{{ lookup('file', 'files/disable_script.sh') }}" + state: present + loop: "{{ potos_xdg_autostart }}" + when: item.runonlyonce diff --git a/templates/potos.example.j2 b/templates/potos.example.j2 deleted file mode 100644 index acc5fe1..0000000 --- a/templates/potos.example.j2 +++ /dev/null @@ -1,3 +0,0 @@ -{{ ansible_managed }} - -Just a simple example template waiting to be deployed. diff --git a/templates/potos_xdgautostart/etc/xdg/autostart/desktopfile.j2 b/templates/potos_xdgautostart/etc/xdg/autostart/desktopfile.j2 new file mode 100644 index 0000000..4ad8149 --- /dev/null +++ b/templates/potos_xdgautostart/etc/xdg/autostart/desktopfile.j2 @@ -0,0 +1,8 @@ +{{ ansible_managed | comment }} +[Desktop Entry] +Type=Application +Name=Potos autostart script for {{ item.script | replace('.j2','') }} +Comment=Potos autostart script for {{ item.script | replace('.j2','') }} +Exec=/usr/local/bin/{{ item.script | replace('.j2','') }}_wrapper.sh +X-GNOME-AutoRestart=false +X-GNOME-Autostart-enabled=true diff --git a/templates/potos_xdgautostart/usr/local/bin/pulseaudio_example.sh.j2 b/templates/potos_xdgautostart/usr/local/bin/pulseaudio_example.sh.j2 new file mode 100644 index 0000000..3af847f --- /dev/null +++ b/templates/potos_xdgautostart/usr/local/bin/pulseaudio_example.sh.j2 @@ -0,0 +1,8 @@ +#!/bin/bash + +{{ ansible_managed | comment }} + +# Set default sink volume for user +potos_pulseaudio_defsink=$( pactl info | awk '/Default Sink:/ {print $3}' ) +pactl set-sink-mute $potos_pulseaudio_defsink 0 # Make sure its unmuted +pactl set-sink-volume $potos_pulseaudio_defsink "{{ item.potos_pulseaudio_default_volume }}" diff --git a/test_local.sh b/test_local.sh new file mode 100755 index 0000000..c63cb17 --- /dev/null +++ b/test_local.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +MOLECULE_DISTRO="ubuntu22" molecule test