From 49fc85dfed0fbc0c3e35f20a45f22f2353810e99 Mon Sep 17 00:00:00 2001 From: Imran Iqbal Date: Fri, 26 Mar 2021 11:15:12 +0000 Subject: [PATCH 1/4] ci: enable Vagrant-based testing using GitHub Actions * Semi-automated using https://github.com/myii/ssf-formula/pull/304 --- .github/workflows/kitchen.vagrant.yml | 33 +++++++++ .github/workflows/kitchen.windows.yml | 101 ++++++++++++++++++++++++++ Gemfile | 4 + Gemfile.lock | 3 + kitchen.vagrant.yml | 35 +++++++++ kitchen.windows.yml | 18 +++++ kitchen.yml | 20 +++++ test/integration/windows/README.md | 50 +++++++++++++ test/integration/windows/inspec.yml | 13 ++++ 9 files changed, 277 insertions(+) create mode 100644 .github/workflows/kitchen.vagrant.yml create mode 100644 .github/workflows/kitchen.windows.yml create mode 100644 kitchen.vagrant.yml create mode 100644 kitchen.windows.yml create mode 100644 test/integration/windows/README.md create mode 100644 test/integration/windows/inspec.yml diff --git a/.github/workflows/kitchen.vagrant.yml b/.github/workflows/kitchen.vagrant.yml new file mode 100644 index 0000000..8b59ac9 --- /dev/null +++ b/.github/workflows/kitchen.vagrant.yml @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +# vim: ft=yaml +--- +name: 'Kitchen Vagrant (Windows)' +'on': ['push', 'pull_request'] + +env: + KITCHEN_LOCAL_YAML: 'kitchen.vagrant.yml' + +jobs: + test: + runs-on: 'macos-10.15' + strategy: + fail-fast: false + matrix: + instance: + - windows-windows-81-latest-py3 + steps: + - name: 'Check out code' + uses: 'actions/checkout@v2' + - name: 'Set up Bundler cache' + uses: 'actions/cache@v1' + with: + path: 'vendor/bundle' + key: "${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}" + restore-keys: "${{ runner.os }}-gems-" + - name: 'Run Bundler' + run: | + ruby --version + bundle config path vendor/bundle + bundle install --jobs 4 --retry 3 + - name: 'Run Test Kitchen' + run: 'bundle exec kitchen verify ${{ matrix.instance }}' diff --git a/.github/workflows/kitchen.windows.yml b/.github/workflows/kitchen.windows.yml new file mode 100644 index 0000000..d33fac3 --- /dev/null +++ b/.github/workflows/kitchen.windows.yml @@ -0,0 +1,101 @@ +# -*- coding: utf-8 -*- +# vim: ft=yaml +--- +name: 'Kitchen (Windows)' +'on': ['push', 'pull_request'] + +env: + machine_user: kitchen + machine_pass: Pass@word1 + machine_port: 5985 + KITCHEN_LOCAL_YAML: 'kitchen.windows.yml' + +jobs: + test-2019: + runs-on: 'windows-2019' + strategy: + fail-fast: false + matrix: + instance: + - windows-windows-2019-latest-py3 + steps: + - name: 'Check out code' + uses: 'actions/checkout@v2' + - name: 'Install Chef' + uses: 'actionshub/chef-install@1.1.0' + with: + project: 'chef' + version: '16.10.8' + - name: 'Add Chef bindir to PATH' + uses: 'myci-actions/export-env-var-powershell@1' + with: + name: 'PATH' + value: "C:\\opscode\\chef\\bin;\ + C:\\opscode\\chef\\embedded\\bin;$env:PATH" + - name: 'Set up Bundler cache' + uses: 'actions/cache@v1' + with: + path: 'vendor/bundle' + key: "${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}" + restore-keys: "${{ runner.os }}-gems-" + - name: 'Set up test user' + run: | + $password = ConvertTo-SecureString $env:machine_pass -AsPlainText -Force + New-LocalUser $env:machine_user -Password $password + Add-LocalGroupMember -Group "Administrators" -Member $env:machine_user + - name: 'Set up WinRM' + run: > + Set-WSManQuickConfig -Force; + Set-WSManInstance -ResourceURI winrm/config/service + -ValueSet @{AllowUnencrypted="true"} + - name: 'Run Bundler' + run: | + ruby --version + bundle config path vendor/bundle + bundle install --jobs 4 --retry 3 + - name: 'Run Test Kitchen' + run: 'bundle exec kitchen verify ${{ matrix.instance }}' + test-2016: + runs-on: 'windows-2016' + strategy: + fail-fast: false + matrix: + instance: + - windows-windows-2016-latest-py3 + steps: + - name: 'Check out code' + uses: 'actions/checkout@v2' + - name: 'Install Chef' + uses: 'actionshub/chef-install@1.1.0' + with: + project: 'chef' + version: '16.10.8' + - name: 'Add Chef bindir to PATH' + uses: 'myci-actions/export-env-var-powershell@1' + with: + name: 'PATH' + value: "C:\\opscode\\chef\\bin;\ + C:\\opscode\\chef\\embedded\\bin;$env:PATH" + - name: 'Set up Bundler cache' + uses: 'actions/cache@v1' + with: + path: 'vendor/bundle' + key: "${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}" + restore-keys: "${{ runner.os }}-gems-" + - name: 'Set up test user' + run: | + $password = ConvertTo-SecureString $env:machine_pass -AsPlainText -Force + New-LocalUser $env:machine_user -Password $password + Add-LocalGroupMember -Group "Administrators" -Member $env:machine_user + - name: 'Set up WinRM' + run: > + Set-WSManQuickConfig -Force; + Set-WSManInstance -ResourceURI winrm/config/service + -ValueSet @{AllowUnencrypted="true"} + - name: 'Run Bundler' + run: | + ruby --version + bundle config path vendor/bundle + bundle install --jobs 4 --retry 3 + - name: 'Run Test Kitchen' + run: 'bundle exec kitchen verify ${{ matrix.instance }}' diff --git a/Gemfile b/Gemfile index c08ad6c..8be107e 100644 --- a/Gemfile +++ b/Gemfile @@ -12,3 +12,7 @@ gem 'kitchen-docker', git: 'https://gitlab.com/saltstack-formulas/infrastructure # rubocop:enable Layout/LineLength gem 'kitchen-inspec', '>= 2.2.1' gem 'kitchen-salt', '>= 0.6.3' + +group :vagrant do + gem 'kitchen-vagrant' +end diff --git a/Gemfile.lock b/Gemfile.lock index d7cbc3b..ef26d96 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -292,6 +292,8 @@ GEM kitchen-salt (0.6.3) hashie (>= 3.5) test-kitchen (>= 1.4) + kitchen-vagrant (1.7.0) + test-kitchen (>= 1.4, < 3) libyajl2 (1.2.0) license-acceptance (1.0.19) pastel (~> 0.7) @@ -525,6 +527,7 @@ DEPENDENCIES kitchen-docker! kitchen-inspec (>= 2.2.1) kitchen-salt (>= 0.6.3) + kitchen-vagrant BUNDLED WITH 2.1.2 diff --git a/kitchen.vagrant.yml b/kitchen.vagrant.yml new file mode 100644 index 0000000..9fedbd8 --- /dev/null +++ b/kitchen.vagrant.yml @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +# vim: ft=yaml +--- +driver: + name: vagrant + cache_directory: false + customize: + usbxhci: 'off' + gui: false + linked_clone: true + ssh: + shell: /bin/sh + +platforms: + - name: windows-81-latest-py3 + driver: + box: techneg/win81x64-pro-salt + cache_directory: "/omnibus/cache" + customize: {} + ssh: {} + provisioner: + salt_install: none + # yamllint disable rule:line-length + init_environment: | + # Workaround to allow `kitchen converge` to be used multiple times + # without having to `kitchen destroy` first: remove state files cached by + # Salt during the previous `converge` (if present) + rm -recurse ` + C:\Users\vagrant\AppData\Local\Temp\kitchen\var\cache\salt\minion\files\base ` + -ErrorAction SilentlyContinue + exit 0 + # yamllint enable rule:line-length + +provisioner: + salt_install: bootstrap diff --git a/kitchen.windows.yml b/kitchen.windows.yml new file mode 100644 index 0000000..c02a8d6 --- /dev/null +++ b/kitchen.windows.yml @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# vim: ft=yaml +--- +driver: + name: proxy + host: localhost + reset_command: "exit 0" + port: 5985 + username: kitchen + password: Pass@word1 + +platforms: + - name: windows-2019-latest-py3 + - name: windows-2016-latest-py3 + +provisioner: + salt_install: bootstrap + salt_bootstrap_options: -pythonVersion 3 diff --git a/kitchen.yml b/kitchen.yml index b4bfae6..e7184d2 100644 --- a/kitchen.yml +++ b/kitchen.yml @@ -609,3 +609,23 @@ suites: verifier: inspec_tests: - path: test/integration/default + - name: windows + includes: + - windows-81-latest-py3 + - windows-2019-latest-py3 + - windows-2016-latest-py3 + provisioner: + state_top: + base: + '*': + - packages.chocolatey + pillars: + top.sls: + base: + '*': + - packages + pillars_from_files: + packages.sls: test/salt/pillar/windows.sls + verifier: + inspec_tests: + - path: test/integration/windows diff --git a/test/integration/windows/README.md b/test/integration/windows/README.md new file mode 100644 index 0000000..397930c --- /dev/null +++ b/test/integration/windows/README.md @@ -0,0 +1,50 @@ +# InSpec Profile: `windows` + +This shows the implementation of the `windows` InSpec [profile](https://github.com/inspec/inspec/blob/master/docs/profiles.md). + +## Verify a profile + +InSpec ships with built-in features to verify a profile structure. + +```bash +$ inspec check windows +Summary +------- +Location: windows +Profile: profile +Controls: 4 +Timestamp: 2019-06-24T23:09:01+00:00 +Valid: true + +Errors +------ + +Warnings +-------- +``` + +## Execute a profile + +To run all **supported** controls on a local machine use `inspec exec /path/to/profile`. + +```bash +$ inspec exec windows +.. + +Finished in 0.0025 seconds (files took 0.12449 seconds to load) +8 examples, 0 failures +``` + +## Execute a specific control from a profile + +To run one control from the profile use `inspec exec /path/to/profile --controls name`. + +```bash +$ inspec exec windows --controls package +. + +Finished in 0.0025 seconds (files took 0.12449 seconds to load) +1 examples, 0 failures +``` + +See an [example control here](https://github.com/inspec/inspec/blob/master/examples/profile/controls/example.rb). diff --git a/test/integration/windows/inspec.yml b/test/integration/windows/inspec.yml new file mode 100644 index 0000000..1f1a195 --- /dev/null +++ b/test/integration/windows/inspec.yml @@ -0,0 +1,13 @@ +# -*- coding: utf-8 -*- +# vim: ft=yaml +--- +name: windows +title: packages formula +maintainer: SaltStack Formulas +license: Apache-2.0 +summary: Verify that the packages formula is setup and configured correctly (on Windows) +depends: + - name: share + path: test/integration/share +supports: + - platform: windows From e7bbefa9f336f19cd7e673d49f6316291557b1e9 Mon Sep 17 00:00:00 2001 From: Imran Iqbal Date: Sat, 8 Aug 2020 16:37:44 +0100 Subject: [PATCH 2/4] ci(windows): test using GitHub Actions --- pillar.example | 6 ++--- .../integration/windows/controls/pkgs_spec.rb | 26 +++++++++++++++++++ test/salt/pillar/windows.sls | 19 ++++++++++++++ 3 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 test/integration/windows/controls/pkgs_spec.rb create mode 100644 test/salt/pillar/windows.sls diff --git a/pillar.example b/pillar.example index ca927d7..3a00266 100644 --- a/pillar.example +++ b/pillar.example @@ -64,14 +64,14 @@ packages: chocolatey: wanted: - firefox: - install_args: "l=fr-FR" + Firefox: + package_args: "/l:en-GB" packagename: version: '12.04' source: 'mychocolatey/source' force: true unwanted: - - googlechrome + - GoogleChrome snaps: wanted: diff --git a/test/integration/windows/controls/pkgs_spec.rb b/test/integration/windows/controls/pkgs_spec.rb new file mode 100644 index 0000000..984393a --- /dev/null +++ b/test/integration/windows/controls/pkgs_spec.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +pkgs_wanted = %w[Firefox jq notepadplusplus] +pkgs_unwanted = %w[GoogleChrome hg] + +### WANTED +control 'Wanted packages' do + title 'should be installed' + + pkgs_wanted.each do |p| + describe chocolatey_package(p) do + it { should be_installed } + end + end +end + +### UNWANTED +control 'Unwanted packages' do + title 'should be uninstalled' + + pkgs_unwanted.each do |p| + describe chocolatey_package(p) do + it { should_not be_installed } + end + end +end diff --git a/test/salt/pillar/windows.sls b/test/salt/pillar/windows.sls new file mode 100644 index 0000000..ae8149d --- /dev/null +++ b/test/salt/pillar/windows.sls @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# vim: ft=yaml +--- +packages: + chocolatey: + required: + pkgs: [] + wanted: + Firefox: + package_args: "/l:en-GB" + jq: + version: '1.5' + # `1.6` already installed on the pre-salted image + force: true + notepadplusplus: + version: '7.8.8' + unwanted: + - GoogleChrome + - hg From f7a6fcf707bb451a687bfbdbf33b74cace158254 Mon Sep 17 00:00:00 2001 From: Imran Iqbal Date: Fri, 26 Mar 2021 11:29:53 +0000 Subject: [PATCH 3/4] test(pkgs_spec): fix `rubocop` violations (`--enable-pending-cops`) ``` Offenses: test/integration/default/controls/pkgs_spec.rb:27:5: W: [Corrected] Lint/SymbolConversion: Unnecessary symbol conversion; use iotop: instead. 'iotop': '' ^^^^^^^ test/integration/default/controls/pkgs_spec.rb:33:5: W: [Corrected] Lint/SymbolConversion: Unnecessary symbol conversion; use alien: instead. 'alien': '8.95-8.fc29', ^^^^^^^ test/integration/default/controls/pkgs_spec.rb:34:5: W: [Corrected] Lint/SymbolConversion: Unnecessary symbol conversion; use iotop: instead. 'iotop': '0.6-18.fc29' ^^^^^^^ test/integration/default/controls/pkgs_spec.rb:46:5: W: [Corrected] Lint/SymbolConversion: Unnecessary symbol conversion; use alien: instead. 'alien': '8.95', ^^^^^^^ test/integration/default/controls/pkgs_spec.rb:48:5: W: [Corrected] Lint/SymbolConversion: Unnecessary symbol conversion; use iotop: instead. 'iotop': '0.6-' ^^^^^^^ ``` --- test/integration/default/controls/pkgs_spec.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/integration/default/controls/pkgs_spec.rb b/test/integration/default/controls/pkgs_spec.rb index 34ff634..44b7241 100644 --- a/test/integration/default/controls/pkgs_spec.rb +++ b/test/integration/default/controls/pkgs_spec.rb @@ -24,14 +24,14 @@ held_packages = { # We use this test for held packages in a list, # with no version (current version). - 'iotop': '' + iotop: '' } lock_file = '/etc/yum/pluginconf.d/versionlock.list' when 'fedora' platform_packages = ['python3-dnf-plugin-versionlock'] held_packages = { - 'alien': '8.95-8.fc29', - 'iotop': '0.6-18.fc29' + alien: '8.95-8.fc29', + iotop: '0.6-18.fc29' } lock_file = '/etc/dnf/plugins/versionlock.list' # Adding empty Suse entries, to get tests passing @@ -43,9 +43,9 @@ when 'debian' platform_packages = %w[] held_packages = { - 'alien': '8.95', + alien: '8.95', # To match also ubuntu16's - 'iotop': '0.6-' + iotop: '0.6-' } lock_file = '/var/lib/dpkg/status' when 'linux' From d734d434c9e0a428cb484438e421c253e591b0d7 Mon Sep 17 00:00:00 2001 From: Imran Iqbal Date: Fri, 26 Mar 2021 14:34:03 +0000 Subject: [PATCH 4/4] docs(readme): add `Testing with Vagrant` section --- docs/README.rst | 64 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/docs/README.rst b/docs/README.rst index 5734265..163ae69 100644 --- a/docs/README.rst +++ b/docs/README.rst @@ -271,7 +271,7 @@ e.g. ``debian-9-2019-2-py3``. ``bin/kitchen converge`` ^^^^^^^^^^^^^^^^^^^^^^^^ -Creates the docker instance and runs the ``packages`` main state, ready for testing. +Creates the docker instance and runs the ``packages`` main states, ready for testing. ``bin/kitchen verify`` ^^^^^^^^^^^^^^^^^^^^^^ @@ -292,3 +292,65 @@ Runs all of the stages above in one go: i.e. ``destroy`` + ``converge`` + ``veri ^^^^^^^^^^^^^^^^^^^^^ Gives you SSH access to the instance for manual testing. + +Testing with Vagrant +-------------------- + +Windows/FreeBSD/OpenBSD testing is done with ``kitchen-salt``. + +Requirements +^^^^^^^^^^^^ + +* Ruby +* Virtualbox +* Vagrant + +Setup +^^^^^ + +.. code-block:: bash + + $ gem install bundler + $ bundle install --with=vagrant + $ bin/kitchen test [platform] + +Where ``[platform]`` is the platform name defined in ``kitchen.vagrant.yml``, +e.g. ``windows-81-latest-py3``. + +Note +^^^^ + +When testing using Vagrant you must set the environment variable ``KITCHEN_LOCAL_YAML`` to ``kitchen.vagrant.yml``. For example: + +.. code-block:: bash + + $ KITCHEN_LOCAL_YAML=kitchen.vagrant.yml bin/kitchen test # Alternatively, + $ export KITCHEN_LOCAL_YAML=kitchen.vagrant.yml + $ bin/kitchen test + +Then run the following commands as needed. + +``bin/kitchen converge`` +^^^^^^^^^^^^^^^^^^^^^^^^ + +Creates the Vagrant instance and runs the ``packages`` main states, ready for testing. + +``bin/kitchen verify`` +^^^^^^^^^^^^^^^^^^^^^^ + +Runs the ``inspec`` tests on the actual instance. + +``bin/kitchen destroy`` +^^^^^^^^^^^^^^^^^^^^^^^ + +Removes the Vagrant instance. + +``bin/kitchen test`` +^^^^^^^^^^^^^^^^^^^^ + +Runs all of the stages above in one go: i.e. ``destroy`` + ``converge`` + ``verify`` + ``destroy``. + +``bin/kitchen login`` +^^^^^^^^^^^^^^^^^^^^^ + +Gives you RDP/SSH access to the instance for manual testing.