diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 871c1b1..9452bf3 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.1.0 +current_version = 0.1.1 commit = True message = Bumps version to {new_version} tag = False diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a071a98..903f5fd 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -25,3 +25,20 @@ jobs: salt-os-version: ${{ matrix.os_version }} salt-state: ${{ matrix.salt_state }} salt-pillar-root: ${{ matrix.salt_pillar_root }} + + windows: + uses: plus3it/actions-workflows/.github/workflows/test-salt-windows.yml@ddd67e99878a285f728de398c1116151c2d7791a + strategy: + matrix: + os_version: + - windows-2019 + - windows-2022 + - windows-2025 + salt_state: + - flux-cli + salt_pillar_root: + - ./tests/pillar/test-flux-cli + with: + salt-os-version: ${{ matrix.os_version }} + salt-state: ${{ matrix.salt_state }} + salt-pillar-root: ${{ matrix.salt_pillar_root }} diff --git a/CHANGELOG.md b/CHANGELOG.md index d5d22bc..6d28227 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +### 0.1.1 + +**Released**: 2026.05.13 + +**Summary**: + +* Adds setup-capability for Windows-based onfiguration-targets (tested with Windows Server 2022) +* Adds Windows-related CI features to project +* Add conditional, VERY basic integration-steps for Podman and Docker + ### 0.1.0 **Released**: 2026.05.12 diff --git a/README.md b/README.md index b5a6a42..a5e9062 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,12 @@ A SaltStack formula designed to install and configure the [Flux](https://fluxcd. It is primarily expected that this formula will be run via [P3](https://www.plus3it.com/)'s "[watchmaker](https://watchmaker.readthedocs.io/en/stable/)" framework. -This formula is able to install the Flux CLI on both Linux[^1] and Windows Server[^2] operating environments. Intallation for internet-connected systems will come from the Flux CLI project's ["releases" page](https://github.com/fluxcd/flux2/releases). +This formula is able to install the Flux CLI on both Linux[^1] and Windows Server[^2] operating environments. Intallation for internet-connected systems may come from the Flux CLI project's ["releases" page](https://github.com/fluxcd/flux2/releases). If installing this way, the formula will install the latest-available version of the content. Alternately: + +* Sites whose installation-targets won't be able to reach the Flux CLI project's GitHub repository will need to self-host copies of the desired content. +* Sites that wish to use a specific version of the Flux CLI will need to target that content + +Targeting specific versions of the FluX CLI or local copies of the install-archives can be directed to do so by adding appropriate content to the formula's associated Pillar-data (see thish projct's [pillar.example](pillar.example) file for guidance). ## Available states diff --git a/flux-cli/config/clean.sls b/flux-cli/config/clean.sls index c06a14d..55bc866 100644 --- a/flux-cli/config/clean.sls +++ b/flux-cli/config/clean.sls @@ -3,7 +3,6 @@ {#- Get the `tplroot` from `tpldir` #} {%- set tplroot = tpldir.split('/')[0] %} -{%- set sls_service_clean = tplroot ~ '.service.clean' %} {%- from tplroot ~ "/map.jinja" import mapdata as flux_cli with context %} include: @@ -13,3 +12,5 @@ include: - flux-cli.config.win_clean {%- endif %} +Avoid being a null-router (config/clean): + test.nop: [] diff --git a/flux-cli/config/file.sls b/flux-cli/config/file.sls index ad68683..caeae91 100644 --- a/flux-cli/config/file.sls +++ b/flux-cli/config/file.sls @@ -15,4 +15,5 @@ include: - flux-cli.config.win_file {%- endif %} - +Avoid being a null-router (config/file): + test.nop: [] diff --git a/flux-cli/config/lin_clean.sls b/flux-cli/config/lin_clean.sls index 05c8d4c..bd9a0ec 100644 --- a/flux-cli/config/lin_clean.sls +++ b/flux-cli/config/lin_clean.sls @@ -12,10 +12,6 @@ Remove bash-completion file for Flux: file.absent: - name: '/etc/bash_completion.d/flux' -Remove kubeconfig directory for all users: - file.absent: - - name: '/etc/skel/.kube' - Remove shell-ENVs for Flux: file.absent: - name: '/etc/profile.d/flux_env.sh' diff --git a/flux-cli/config/lin_file.sls b/flux-cli/config/lin_file.sls index dc64a50..b9b4ad6 100644 --- a/flux-cli/config/lin_file.sls +++ b/flux-cli/config/lin_file.sls @@ -27,7 +27,7 @@ Ensure Docker Service for Flux/Kind: - name: 'docker' - enable: True - require: - - file: 'Enforce flux permissions and SELinux' + - sls: {{ sls_package_install }} - require_in: - file: 'Install user-env setup for Podman socket' {%- endif %} @@ -39,7 +39,7 @@ Ensure Podman Socket for Kind: - enable: True - comment: "Podman detected; enabling socket for Flux/Kind compatibility." - require: - - file: 'Enforce flux permissions and SELinux' + - sls: {{ sls_package_install }} - require_in: - file: 'Install user-env setup for Podman socket' {%- endif %} @@ -48,7 +48,7 @@ Ensure bash-completion package is present: pkg.installed: - name: bash-completion - require: - - file: 'Enforce flux permissions and SELinux' + - sls: {{ sls_package_install }} Ensure kubeconfig directory for all users: file.directory: diff --git a/flux-cli/config/win_clean.sls b/flux-cli/config/win_clean.sls new file mode 100644 index 0000000..87f55b1 --- /dev/null +++ b/flux-cli/config/win_clean.sls @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# vim: ft=sls + +{#- Get the `tplroot` from `tpldir` #} +{%- set tplroot = tpldir.split('/')[0] %} + +Remove Flux Autoload from Global Windows PowerShell Profile: + file.replace: + - name: 'C:\Windows\System32\WindowsPowerShell\v1.0\profile.ps1' + # (?ms) enables multiline matching so we can grab the whole block at once + - pattern: '(?ms)^# --- START FLUX CLI AUTOLOAD ---.*?# --- END FLUX CLI AUTOLOAD ---$' + - repl: '' + - ignore_if_missing: True + +Remove Flux Autoload from Global PowerShell 7 Profile: + file.replace: + - name: 'C:\Program Files\PowerShell\7\profile.ps1' + - pattern: '(?ms)^# --- START FLUX CLI AUTOLOAD ---.*?# --- END FLUX CLI AUTOLOAD ---$' + - repl: '' + - ignore_if_missing: True diff --git a/flux-cli/config/win_file.sls b/flux-cli/config/win_file.sls new file mode 100644 index 0000000..5f3a703 --- /dev/null +++ b/flux-cli/config/win_file.sls @@ -0,0 +1,95 @@ +# -*- coding: utf-8 -*- +# vim: ft=sls + +{#- Get the `tplroot` from `tpldir` #} +{%- set tplroot = tpldir.split('/')[0] %} +{%- set sls_package_install = tplroot ~ '.package.install' %} +{%- from tplroot ~ "/map.jinja" import mapdata as flux_cli with context %} +{%- from tplroot ~ "/libtofs.jinja" import files_switch with context %} +{%- set install_dir = 'C:\\Program Files\\FluxCLI\\' %} + + +include: + - {{ sls_package_install }} + +Ensure Default User kubeconfig directory exists: + file.directory: + - makedirs: True + - name: 'C:\Users\Default\.kube' + - require: + - sls: {{ sls_package_install }} + +Ensure Flux CLI Autocompletion in Global (default) Windows PowerShell Profile: + file.blockreplace: + - append_if_not_found: True + - content: | + if (Test-Path "{{ install_dir }}flux-completion.ps1") { + . "{{ install_dir }}flux-completion.ps1" + } + if (Test-Path "{{ install_dir }}flux-env.ps1") { + . "{{ install_dir }}flux-env.ps1" + } + - marker_end: '# --- END FLUX CLI AUTOLOAD ---' + - marker_start: '# --- START FLUX CLI AUTOLOAD ---' + - name: 'C:\Windows\System32\WindowsPowerShell\v1.0\profile.ps1' + - require: + - file: 'Ensure Global (default) Windows PowerShell Profile Exists' + - cmd: 'Generate Flux CLI PowerShell Autocompletion' + - file: 'Install user-env setup for Windows container runtimes' + +Ensure Flux CLI Autocompletion in Global PowerShell 7 Profile: + file.blockreplace: + - append_if_not_found: True + - content: | + if (Test-Path "{{ install_dir }}flux-completion.ps1") { + . "{{ install_dir }}flux-completion.ps1" + } + if (Test-Path "{{ install_dir }}flux-env.ps1") { + . "{{ install_dir }}flux-env.ps1" + } + - marker_end: '# --- END FLUX CLI AUTOLOAD ---' + - marker_start: '# --- START FLUX CLI AUTOLOAD ---' + - name: 'C:\Program Files\PowerShell\7\profile.ps1' + - onlyif: + - 'Test-Path "C:\Program Files\PowerShell\7"' + - shell: powershell + - require: + - file: 'Ensure Global PowerShell 7 Profile Exists' + - cmd: 'Generate Flux CLI PowerShell Autocompletion' + - file: 'Install user-env setup for Windows container runtimes' + +Ensure Global (default) Windows PowerShell Profile Exists: + file.managed: + - name: 'C:\Windows\System32\WindowsPowerShell\v1.0\profile.ps1' + - replace: False + +Ensure Global PowerShell 7 Profile Exists: + file.managed: + - name: 'C:\Program Files\PowerShell\7\profile.ps1' + - onlyif: + - 'Test-Path "C:\Program Files\PowerShell\7"' + - shell: powershell + - replace: False + +Generate Flux CLI PowerShell Autocompletion: + cmd.run: + - name: > + & "{{ install_dir }}flux.exe" completion powershell | + Out-File -FilePath "{{ install_dir }}flux-completion.ps1" + -Encoding UTF8 + - onchanges: + - archive: 'Extract flux CLI Archive' + - shell: powershell + +Install user-env setup for Windows container runtimes: + file.managed: + - name: '{{ install_dir }}flux-env.ps1' + - contents: | + # Ensure Flux and Kind can locate the correct container socket on Windows + if (Get-Command podman -ErrorAction SilentlyContinue) { + $env:DOCKER_HOST = "npipe:////./pipe/podman-machine-default" + } elseif (Get-Command docker -ErrorAction SilentlyContinue) { + $env:DOCKER_HOST = "npipe:////./pipe/docker_engine" + } + - require: + - sls: {{ sls_package_install }} diff --git a/flux-cli/files/default/example.tmpl.jinja b/flux-cli/files/default/example.tmpl.jinja deleted file mode 100644 index a181024..0000000 --- a/flux-cli/files/default/example.tmpl.jinja +++ /dev/null @@ -1,11 +0,0 @@ -######################################################################## -# File managed by Salt at <{{ source }}>. -# Your changes will be overwritten. -######################################################################## - -This is another example file from SaltStack template-formula. - -# This is here for testing purposes -{{ flux__cd | json }} - -winner of the merge: {{ flux__cd['winner'] }} diff --git a/flux-cli/package/clean.sls b/flux-cli/package/clean.sls index 46d02cb..3216007 100644 --- a/flux-cli/package/clean.sls +++ b/flux-cli/package/clean.sls @@ -14,3 +14,5 @@ include: - flux-cli.package.win_clean {%- endif %} +Avoid being a null-router (package/clean): + test.nop: [] diff --git a/flux-cli/package/install.sls b/flux-cli/package/install.sls index 6324664..fb87cf0 100644 --- a/flux-cli/package/install.sls +++ b/flux-cli/package/install.sls @@ -12,3 +12,5 @@ include: - flux-cli.package.win_install {%- endif %} +Avoid being a null-router (package/install): + test.nop: [] diff --git a/flux-cli/package/win_clean.sls b/flux-cli/package/win_clean.sls new file mode 100644 index 0000000..902ad79 --- /dev/null +++ b/flux-cli/package/win_clean.sls @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# vim: ft=sls + +{#- Get the `tplroot` from `tpldir` #} +{%- set tplroot = tpldir.split('/')[0] %} +{%- set sls_config_clean = tplroot ~ '.config.clean' %} +{%- set install_dir = 'C:\\Program Files\\FluxCLI\\' %} + +include: + - {{ sls_config_clean }} + +Ensure Flux CLI is removed from PATH: + win_path.absent: + - name: '{{ install_dir }}' + +Remove Flux CLI installation directory: + file.absent: + - name: '{{ install_dir }}' + - require: + - win_path: 'Ensure Flux CLI is removed from PATH' diff --git a/flux-cli/package/win_install.sls b/flux-cli/package/win_install.sls new file mode 100644 index 0000000..41a356c --- /dev/null +++ b/flux-cli/package/win_install.sls @@ -0,0 +1,81 @@ +# -*- coding: utf-8 -*- +# vim: ft=sls + +{#- Get the `tplroot` from `tpldir` #} +{%- set tplroot = tpldir.split('/')[0] %} +{%- from tplroot ~ "/map.jinja" import mapdata as flux_cli with context %} +{%- set target_arch = flux_cli.get('arch', 'amd64') %} +{%- set flux_archive = 'C:\\Windows\\TEMP\\flux_windows_' ~ target_arch ~ + '.zip' %} +{%- set install_dir = 'C:\\Program Files\\FluxCLI\\' %} + +{#- Determine the download URI #} +{%- set download_uri = flux_cli.pkg.download_uri %} +{%- set api_response = {} %} + +{%- if not download_uri %} + {%- set api_url = 'https://api.github.com/repos/fluxcd/flux2/releases/latest' %} + {%- set api_response = salt['http.query'](api_url, decode=True, decode_type='json') %} + + {%- if 'dict' in api_response and 'tag_name' in api_response['dict'] %} + {%- set latest_tag = api_response['dict']['tag_name'] %} + {%- set version_num = latest_tag | replace('v', '') %} + {%- set download_uri = 'https://github.com/fluxcd/flux2/releases/download/' + ~ latest_tag ~ '/flux_' ~ version_num ~ '_windows_' ~ target_arch ~ + '.zip' %} + {%- endif %} +{%- endif %} + + +{%- if not download_uri %} +Alert-and-exit Due to Missing URL: + test.fail_without_changes: + - name: 'Failed to construct download_uri. Please provide the URL manually in Pillar.' + - failhard: True +{%- elif flux_cli.pkg.download_uri %} +Download flux CLI Archive-File: + file.managed: + - name: '{{ flux_archive }}' + - onchanges_in: + - archive: 'Extract flux CLI Archive' + - skip_verify: True + - source: '{{ flux_cli.pkg.download_uri }}' +{%- else %} +Announce Fall-back: + test.show_notification: + - text: | + ------------------------------------------------------------------------ + No URL specified in Pillar. Attempting to download release-archive from: + + {{ download_uri }} + + ------------------------------------------------------------------------ + +Download flux CLI Archive-File: + cmd.run: + - name: 'curl -sSLf -o {{ flux_archive }} {{ download_uri }}' + - onchanges_in: + - archive: 'Extract flux CLI Archive' + - require: + - test: 'Announce Fall-back' + - unless: 'test -s {{ flux_archive }}' +{%- endif %} + +Extract flux CLI Archive: + archive.extracted: + - enforce_toplevel: False + - name: '{{ install_dir }}' + - overwrite: True + - source: '{{ flux_archive }}' + +Ensure Flux CLI is in PATH: + win_path.exists: + - name: '{{ install_dir }}' + - require: + - archive: 'Extract flux CLI Archive' + +Remove staged flux CLI Archive-File: + file.absent: + - name: '{{ flux_archive }}' + - require: + - archive: 'Extract flux CLI Archive' diff --git a/flux-cli/parameters/os_family/Windows.yaml b/flux-cli/parameters/os_family/Windows.yaml new file mode 100644 index 0000000..8e9ac65 --- /dev/null +++ b/flux-cli/parameters/os_family/Windows.yaml @@ -0,0 +1,17 @@ +# -*- coding: utf-8 -*- +# vim: ft=yaml +# +# Set values specific to: +# salt['config.get']('os_family') == RedHat. +# +# You just need to add the key:values for this `os_family` that differ +# from `defaults.yaml` + `.yaml`. +# +# If you do not need to provide defaults via the `os_family` config, +# you can remove this file or provide at least an empty dict, e.g. +# values: {} +--- +values: + pkg: + name: flux-cli-windows +... diff --git a/flux-cli/service/clean.sls b/flux-cli/service/clean.sls deleted file mode 100644 index aa120b5..0000000 --- a/flux-cli/service/clean.sls +++ /dev/null @@ -1,11 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: ft=sls - -{#- Get the `tplroot` from `tpldir` #} -{%- set tplroot = tpldir.split('/')[0] %} -{%- from tplroot ~ "/map.jinja" import mapdata as flux_cli with context %} - -flux-cli-service-clean-service-dead: - service.dead: - - name: {{ flux_cli.service.name }} - - enable: False diff --git a/flux-cli/service/init.sls b/flux-cli/service/init.sls deleted file mode 100644 index 6fe4d1a..0000000 --- a/flux-cli/service/init.sls +++ /dev/null @@ -1,5 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: ft=sls - -include: - - .running diff --git a/flux-cli/service/running.sls b/flux-cli/service/running.sls deleted file mode 100644 index e8882ce..0000000 --- a/flux-cli/service/running.sls +++ /dev/null @@ -1,17 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: ft=sls - -{#- Get the `tplroot` from `tpldir` #} -{%- set tplroot = tpldir.split('/')[0] %} -{%- set sls_config_file = tplroot ~ '.config.file' %} -{%- from tplroot ~ "/map.jinja" import mapdata as flux_cli with context %} - -include: - - {{ sls_config_file }} - -flux-cli-service-running-service-running: - service.running: - - name: {{ flux_cli.service.name }} - - enable: True - - watch: - - sls: {{ sls_config_file }} diff --git a/flux-cli/subcomponent/clean.sls b/flux-cli/subcomponent/clean.sls deleted file mode 100644 index 564769d..0000000 --- a/flux-cli/subcomponent/clean.sls +++ /dev/null @@ -1,5 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: ft=sls - -include: - - .config.clean diff --git a/flux-cli/subcomponent/config/clean.sls b/flux-cli/subcomponent/config/clean.sls deleted file mode 100644 index 5b820dc..0000000 --- a/flux-cli/subcomponent/config/clean.sls +++ /dev/null @@ -1,16 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: ft=sls - -{#- Get the `tplroot` from `tpldir` #} -{%- set tplroot = tpldir.split('/')[0] %} -{%- set sls_service_clean = tplroot ~ '.service.clean' %} -{%- from tplroot ~ "/map.jinja" import mapdata as flux_cli with context %} - -include: - - {{ sls_service_clean }} - -flux-cli-subcomponent-config-clean-file-absent: - file.absent: - - name: {{ flux_cli.subcomponent.config }} - - watch_in: - - sls: {{ sls_service_clean }} diff --git a/flux-cli/subcomponent/config/file.sls b/flux-cli/subcomponent/config/file.sls deleted file mode 100644 index 2dc3a9e..0000000 --- a/flux-cli/subcomponent/config/file.sls +++ /dev/null @@ -1,27 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: ft=sls - -{#- Get the `tplroot` from `tpldir` #} -{%- set tplroot = tpldir.split('/')[0] %} -{%- set sls_config_file = tplroot ~ '.config.file' %} -{%- from tplroot ~ "/map.jinja" import mapdata as flux_cli with context %} -{%- from tplroot ~ "/libtofs.jinja" import files_switch with context %} - -include: - - {{ sls_config_file }} - -flux-cli-subcomponent-config-file-file-managed: - file.managed: - - name: {{ flux_cli.subcomponent.config }} - - source: {{ files_switch(['subcomponent-example.tmpl'], - lookup='flux-cli-subcomponent-config-file-file-managed', - use_subpath=True - ) - }} - - mode: 644 - - user: root - - group: {{ flux_cli.rootgroup }} - - makedirs: True - - template: jinja - - require_in: - - sls: {{ sls_config_file }} diff --git a/flux-cli/subcomponent/config/files/default/subcomponent-example.tmpl b/flux-cli/subcomponent/config/files/default/subcomponent-example.tmpl deleted file mode 100644 index 522de00..0000000 --- a/flux-cli/subcomponent/config/files/default/subcomponent-example.tmpl +++ /dev/null @@ -1,6 +0,0 @@ -######################################################################## -# File managed by Salt at <{{ source }}>. -# Your changes will be overwritten. -######################################################################## - -This is a subcomponent example file from SaltStack template-formula. diff --git a/flux-cli/subcomponent/config/files/default/subcomponent-example.tmpl.jinja b/flux-cli/subcomponent/config/files/default/subcomponent-example.tmpl.jinja deleted file mode 100644 index cbfd51d..0000000 --- a/flux-cli/subcomponent/config/files/default/subcomponent-example.tmpl.jinja +++ /dev/null @@ -1,6 +0,0 @@ -######################################################################## -# File managed by Salt at <{{ source }}>. -# Your changes will be overwritten. -######################################################################## - -This is another subcomponent example file from SaltStack template-formula. diff --git a/flux-cli/subcomponent/config/init.sls b/flux-cli/subcomponent/config/init.sls deleted file mode 100644 index 465ddfe..0000000 --- a/flux-cli/subcomponent/config/init.sls +++ /dev/null @@ -1,5 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: ft=sls - -include: - - .file diff --git a/flux-cli/subcomponent/init.sls b/flux-cli/subcomponent/init.sls deleted file mode 100644 index 6003be1..0000000 --- a/flux-cli/subcomponent/init.sls +++ /dev/null @@ -1,5 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: ft=sls - -include: - - .config