diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fc4b306f0..eebfa5191 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -145,21 +145,6 @@ jobs: - windows-2019: - name: Windows 2019 - if: github.event_name == 'push' || needs.collect-changed-files.outputs.run-tests == 'true' - uses: ./.github/workflows/test-windows.yml - needs: - - lint - - generate-actions-workflow - with: - distro-slug: windows-2019 - display-name: Windows 2019 - timeout: 20 - runs-on: windows-2019 - instances: '["stable-3006", "stable-3006-8", "stable-3007", "stable-3007-1", "latest"]' - - windows-2022: name: Windows 2022 if: github.event_name == 'push' || needs.collect-changed-files.outputs.run-tests == 'true' @@ -218,20 +203,6 @@ jobs: instances: '["stable-3006", "onedir-3006", "stable-3006-8", "stable-3007", "onedir-3007", "stable-3007-1", "latest", "default"]' - arch: - name: Arch - if: github.event_name == 'push' || needs.collect-changed-files.outputs.run-tests == 'true' - uses: ./.github/workflows/test-linux.yml - needs: - - lint - - generate-actions-workflow - with: - distro-slug: arch - display-name: Arch - timeout: 20 - instances: '["git-master", "latest", "default"]' - - centos-stream9: name: CentOS Stream 9 if: github.event_name == 'push' || needs.collect-changed-files.outputs.run-tests == 'true' @@ -302,34 +273,6 @@ jobs: instances: '["stable-3007", "onedir-3007", "stable-3007-1", "git-master", "latest", "default"]' - gentoo: - name: Gentoo - if: github.event_name == 'push' - uses: ./.github/workflows/test-linux.yml - needs: - - lint - - generate-actions-workflow - with: - distro-slug: gentoo - display-name: Gentoo - timeout: 90 - instances: '["git-master"]' - - - gentoo-systemd: - name: Gentoo (systemd) - if: github.event_name == 'push' - uses: ./.github/workflows/test-linux.yml - needs: - - lint - - generate-actions-workflow - with: - distro-slug: gentoo-systemd - display-name: Gentoo (systemd) - timeout: 90 - instances: '["git-master"]' - - opensuse-15: name: Opensuse 15 if: github.event_name == 'push' || needs.collect-changed-files.outputs.run-tests == 'true' @@ -480,19 +423,15 @@ jobs: - generate-actions-workflow - macos-12 - macos-13 - - windows-2019 - windows-2022 - almalinux-8 - almalinux-9 - amazon-2 - - arch - centos-stream9 - debian-11 - debian-12 - fedora-39 - fedora-40 - - gentoo - - gentoo-systemd - opensuse-15 - oraclelinux-8 - oraclelinux-9 diff --git a/.github/workflows/templates/generate.py b/.github/workflows/templates/generate.py index 0fb618158..537d1da5e 100755 --- a/.github/workflows/templates/generate.py +++ b/.github/workflows/templates/generate.py @@ -6,20 +6,15 @@ os.chdir(os.path.abspath(os.path.dirname(__file__))) -## "amazon-2023", -## "opensuse-tumbleweed", LINUX_DISTROS = [ "almalinux-8", "almalinux-9", "amazon-2", - "arch", "centos-stream9", "debian-11", "debian-12", "fedora-39", "fedora-40", - "gentoo", - "gentoo-systemd", "opensuse-15", "oraclelinux-8", "oraclelinux-9", @@ -31,8 +26,8 @@ "ubuntu-2204", "ubuntu-2404", ] + WINDOWS = [ - "windows-2019", "windows-2022", ] @@ -41,14 +36,10 @@ "macos-13", ] - -## "amazon-2023", -## "opensuse-tumbleweed", STABLE_DISTROS = [ "almalinux-8", "almalinux-9", "amazon-2", - "arch", "centos-stream9", "debian-11", "debian-12", @@ -66,7 +57,6 @@ "ubuntu-2404", ] -## "amazon-2023", ONEDIR_DISTROS = [ "almalinux-8", "almalinux-9", @@ -99,40 +89,27 @@ "ubuntu-2404", ] -## "opensuse-tumbleweed", BLACKLIST_3006 = [ - "arch", "debian-12", "fedora-40", - "gentoo", - "gentoo-systemd", "opensuse-15", "ubuntu-2404", ] -## "opensuse-tumbleweed", BLACKLIST_3007 = [ - "arch", "fedora-39", - "gentoo", - "gentoo-systemd", "opensuse-15", "photon-4", "photon-5", ] -## "amazon-2023", -## "opensuse-tumbleweed", BLACKLIST_GIT_3006 = [ "almalinux-9", "amazon-2", - "arch", "centos-stream9", "debian-11", "debian-12", "fedora-40", - "gentoo", - "gentoo-systemd", "opensuse-15", "oraclelinux-9", "photon-4", @@ -143,19 +120,14 @@ "ubuntu-2404", ] -## "amazon-2023", -## "opensuse-tumbleweed", BLACKLIST_GIT_3007 = [ "almalinux-9", "amazon-2", - "arch", "centos-stream9", "debian-11", "debian-12", "fedora-39", "fedora-40", - "gentoo", - "gentoo-systemd", "opensuse-15", "oraclelinux-9", "photon-4", @@ -234,25 +206,17 @@ "rockylinux-8", ] -LATEST_PKG_BLACKLIST = [ - "gentoo", - "gentoo-systemd", -] +LATEST_PKG_BLACKLIST = [] -## "amazon-2023": "Amazon 2023", -## "opensuse-tumbleweed": "Opensuse Tumbleweed", DISTRO_DISPLAY_NAMES = { "almalinux-8": "AlmaLinux 8", "almalinux-9": "AlmaLinux 9", "amazon-2": "Amazon 2", - "arch": "Arch", "centos-stream9": "CentOS Stream 9", "debian-11": "Debian 11", "debian-12": "Debian 12", "fedora-39": "Fedora 39", "fedora-40": "Fedora 40", - "gentoo": "Gentoo", - "gentoo-systemd": "Gentoo (systemd)", "opensuse-15": "Opensuse 15", "oraclelinux-8": "Oracle Linux 8", "oraclelinux-9": "Oracle Linux 9", @@ -265,19 +229,12 @@ "ubuntu-2404": "Ubuntu 24.04", "macos-12": "macOS 12", "macos-13": "macOS 13", - "windows-2019": "Windows 2019", "windows-2022": "Windows 2022", } TIMEOUT_DEFAULT = 20 -TIMEOUT_OVERRIDES = { - "gentoo": 90, - "gentoo-systemd": 90, -} -VERSION_ONLY_OVERRIDES = [ - "gentoo", - "gentoo-systemd", -] +TIMEOUT_OVERRIDES = {} +VERSION_ONLY_OVERRIDES = [] TEMPLATE = """ {distro}: diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml index 4bc98f4d4..e4d4dde34 100644 --- a/.github/workflows/test-windows.yml +++ b/.github/workflows/test-windows.yml @@ -41,7 +41,6 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Set up Python 3.10 uses: actions/setup-python@v5 with: @@ -49,20 +48,23 @@ jobs: - name: Install Pytest run: | - pip install -U pytest + pip install -r tests\requirements.txt - - name: Bootstrap Salt + - name: Get Version run: | - . ./bootstrap-salt.ps1 -RunService $false + # We need to get the version here and make it an environment variable + # It is used to install via bootstrap and in the test + # The version is in the instance name + $instance = "${{ matrix.instance }}" + $version = $instance -split "-",2 + if ( $version.Count -gt 1 ) { + $version = $version[1].Replace("-", ".") + } + Write-Output "SaltVersion=$version" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - - name: Set Environment Variables + - name: Bootstrap Salt run: | - $env:Path = "$env:Path;C:\Program Files\Salt Project\Salt" - $env:Instance = ${{ matrix.instance }} - Write-Output "Path:" - Write-Output $env:Path - Write-Output "Environment Variables" - Get-ChildItem Env: + . .\bootstrap-salt.ps1 -RunService $false -Version $env:SaltVersion - name: Test Bootstrap run: | diff --git a/.gitignore b/.gitignore index f1af41c03..f21787dbe 100644 --- a/.gitignore +++ b/.gitignore @@ -8,9 +8,3 @@ venv # Pycharm .idea - -# test-kitchen -.kitchen.local.yml -kitchen.local.yml -.kitchen/ -.bundle/ diff --git a/Gemfile b/Gemfile deleted file mode 100644 index a70a9da93..000000000 --- a/Gemfile +++ /dev/null @@ -1,11 +0,0 @@ -# frozen_string_literal: true - -source "https://rubygems.org" - -gem 'test-kitchen', '>= 3.2.2' -gem 'kitchen-salt', '>= 0.7.2' -gem 'kitchen-docker', :git => 'https://github.com/test-kitchen/kitchen-docker.git', :branch => 'main' - -group :vagrant do - gem 'kitchen-vagrant' -end diff --git a/Vagrantfile b/Vagrantfile deleted file mode 100644 index 4a8a57f57..000000000 --- a/Vagrantfile +++ /dev/null @@ -1,119 +0,0 @@ -# -*- mode: ruby -*- -# vi: set ft=ruby : - -# Vagrantfile API/syntax version. Don't touch unless you know what you're doing! -VAGRANTFILE_API_VERSION = "2" - -Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| - # All Vagrant configuration is done here. The most common configuration - # options are documented and commented below. For a complete reference, - # please see the online documentation at vagrantup.com. - - # Every Vagrant virtual environment requires a box to build off of. - config.vm.box = "ubuntu/focal64" - - # The url from where the 'config.vm.box' box will be fetched if it - # doesn't already exist on the user's system. - # config.vm.box_url = "http://domain.com/path/to/above.box" - - # Create a forwarded port mapping which allows access to a specific port - # within the machine from a port on the host machine. In the example below, - # accessing "localhost:8080" will access port 80 on the guest machine. - # config.vm.network :forwarded_port, guest: 80, host: 8080 - - # Create a private network, which allows host-only access to the machine - # using a specific IP. - # config.vm.network :private_network, ip: "192.168.33.10" - - # Create a public network, which generally matched to bridged network. - # Bridged networks make the machine appear as another physical device on - # your network. - # config.vm.network :public_network - - # If true, then any SSH connections made will enable agent forwarding. - # Default value: false - # config.ssh.forward_agent = true - - # Share an additional folder to the guest VM. The first argument is - # the path on the host to the actual folder. The second argument is - # the path on the guest to mount the folder. And the optional third - # argument is a set of non-required options. - config.vm.synced_folder ".", "/salt_bootstrap" - - config.vm.provision "shell", path: "bootstrap-salt.sh" - # Provider-specific configuration so you can fine-tune various - # backing providers for Vagrant. These expose provider-specific options. - # Example for VirtualBox: - # - # config.vm.provider :virtualbox do |vb| - # # Don't boot with headless mode - # vb.gui = true - # - # # Use VBoxManage to customize the VM. For example to change memory: - # vb.customize ["modifyvm", :id, "--memory", "1024"] - # end - # - # View the documentation for the provider you're using for more - # information on available options. - - # Enable provisioning with Puppet stand alone. Puppet manifests - # are contained in a directory path relative to this Vagrantfile. - # You will need to create the manifests directory and a manifest in - # the file precise64.pp in the manifests_path directory. - # - # An example Puppet manifest to provision the message of the day: - # - # # group { "puppet": - # # ensure => "present", - # # } - # # - # # File { owner => 0, group => 0, mode => 0644 } - # # - # # file { '/etc/motd': - # # content => "Welcome to your Vagrant-built virtual machine! - # # Managed by Puppet.\n" - # # } - # - # config.vm.provision :puppet do |puppet| - # puppet.manifests_path = "manifests" - # puppet.manifest_file = "site.pp" - # end - - # Enable provisioning with chef solo, specifying a cookbooks path, roles - # path, and data_bags path (all relative to this Vagrantfile), and adding - # some recipes and/or roles. - # - # config.vm.provision :chef_solo do |chef| - # chef.cookbooks_path = "../my-recipes/cookbooks" - # chef.roles_path = "../my-recipes/roles" - # chef.data_bags_path = "../my-recipes/data_bags" - # chef.add_recipe "mysql" - # chef.add_role "web" - # - # # You may also specify custom JSON attributes: - # chef.json = { :mysql_password => "foo" } - # end - - # Enable provisioning with chef server, specifying the chef server URL, - # and the path to the validation key (relative to this Vagrantfile). - # - # The Opscode Platform uses HTTPS. Substitute your organization for - # ORGNAME in the URL and validation key. - # - # If you have your own Chef Server, use the appropriate URL, which may be - # HTTP instead of HTTPS depending on your configuration. Also change the - # validation key to validation.pem. - # - # config.vm.provision :chef_client do |chef| - # chef.chef_server_url = "https://api.opscode.com/organizations/ORGNAME" - # chef.validation_key_path = "ORGNAME-validator.pem" - # end - # - # If you're using the Opscode platform, your validator client is - # ORGNAME-validator, replacing ORGNAME with your organization name. - # - # If you have your own Chef Server, the default validation client name is - # chef-validator, unless you changed the configuration. - # - # chef.validation_client_name = "ORGNAME-validator" -end diff --git a/bootstrap-salt.ps1 b/bootstrap-salt.ps1 index eccbb3526..fc862ab7f 100644 --- a/bootstrap-salt.ps1 +++ b/bootstrap-salt.ps1 @@ -18,7 +18,7 @@ Specifies a particular version of the installer. .EXAMPLE - ./bootstrap-salt.ps1 -RunService false + ./bootstrap-salt.ps1 -RunService $false Specifies the salt-minion service to stop and be set to manual. Useful for testing locally from the command line with the --local switch @@ -28,7 +28,7 @@ installer values of host name for the minion id and "salt" for the master. .EXAMPLE - ./bootstrap-salt.ps1 -Minion minion-box -Master master-box -Version 3006.7 -RunService false + ./bootstrap-salt.ps1 -Minion minion-box -Master master-box -Version 3006.7 -RunService $false Specifies all the optional parameters in no particular order. .NOTES @@ -56,12 +56,11 @@ param( [String]$Version = "latest", [Parameter(Mandatory=$false, ValueFromPipeline=$True)] - [ValidateSet("true","false")] [Alias("s")] - # Boolean flag to start or stop the minion service. True will start the - # minion service. False will stop the minion service and set it to "manual". + # Boolean flag to start or stop the minion service. $true will start the + # minion service. $false will stop the minion service and set it to "manual". # The installer starts it by default. - [String]$RunService = "true", + [Bool]$RunService = $true, [Parameter(Mandatory=$false, ValueFromPipeline=$True)] [Alias("m")] @@ -76,12 +75,11 @@ param( [Parameter(Mandatory=$false, ValueFromPipeline=$True)] [Alias("r")] - # URL to the windows packages. Will look for a file named repo.json at the - # root of the URL. This file is used to determine the name and location of - # the installer in the repo. If repo.json is not found, it will look for the - # file under the minor directory. - # Default is "https://repo.saltproject.io/salt/py3/windows" - [String]$RepoUrl = "https://repo.saltproject.io/salt/py3/windows", + # URL to the windows packages. Will look for the installer at the root of + # the URL/Version. Place a folder for each version of Salt in this directory + # and place the installer binary for each version in its folder. + # Default is "https://packages.broadcom.com/artifactory/saltproject-generic/windows/" + [String]$RepoUrl = "https://packages.broadcom.com/artifactory/saltproject-generic/windows/", [Parameter(Mandatory=$false, ValueFromPipeline=$True)] [Alias("c")] @@ -301,16 +299,29 @@ if (!(Get-IsAdministrator)) { } #=============================================================================== -# Change RepoUrl for older versions +# Check for older versions #=============================================================================== -$defaultUrl = "https://repo.saltproject.io/salt/py3/windows" -$oldRepoUrl = "https://repo.saltproject.io/windows" $majorVersion = Get-MajorVersion -Version $Version -if ( [Uri]($RepoUrl).AbsoluteUri -eq $defaultUrl ) { - # No customURL passed, let's check for a pre 3006 version - if ($majorVersion -lt "3006") { - # This is an older version, use the old URL - $RepoUrl = $oldRepoUrl +if ($majorVersion -lt "3006") { + # This is an older version, use the old URL + Write-Host "Versions older than 3006 are not available" -ForegroundColor Red + exit 1 +} + +#=============================================================================== +# Declare variables +#=============================================================================== +$ConfDir = "$RootDir\conf" +$PkiDir = "$ConfDir\pki\minion" +$RootDir = "$env:ProgramData\Salt Project\Salt" +$DfltUrl = "https://packages.broadcom.com/artifactory/saltproject-generic/windows/" +$ApiUrl = "https://packages.broadcom.com/artifactory/api/storage/saltproject-generic/windows" + +# Check for existing installation where RootDir is stored in the registry +$SaltRegKey = "HKLM:\SOFTWARE\Salt Project\Salt" +if (Test-Path -Path $SaltRegKey) { + if ($null -ne (Get-ItemProperty $SaltRegKey).root_dir) { + $RootDir = (Get-ItemProperty $SaltRegKey).root_dir } } @@ -325,48 +336,24 @@ Write-Verbose "runservice: $RunService" Write-Verbose "master: $Master" Write-Verbose "minion: $Minion" Write-Verbose "repourl: $RepoUrl" +Write-Verbose "apiurl: $ApiUrl" +Write-Verbose "ConfDir: $ConfDir" +Write-Verbose "RootDir: $RootDir" -if ($RunService.ToLower() -eq "true") { +if ($RunService) { Write-Verbose "Windows service will be set to run" [bool]$RunService = $True -} elseif ($RunService.ToLower() -eq "false") { +} else { Write-Verbose "Windows service will be stopped and set to manual" [bool]$RunService = $False -} else { - # Param passed in wasn't clear so defaulting to true. - Write-Verbose "Windows service defaulting to run automatically" - [bool]$RunService = $True } #=============================================================================== -# Ensure Directories are present, copy Vagrant Configs if found +# Copy Vagrant Files to their proper location. #=============================================================================== $ConfiguredAnything = $False -# Detect older version of Salt to determing default RootDir -if ($majorVersion -lt 3004) { - $RootDir = "$env:SystemDrive`:\salt" -} else { - $RootDir = "$env:ProgramData\Salt Project\Salt" -} - -# Check for existing installation where RootDir is stored in the registry -$SaltRegKey = "HKLM:\SOFTWARE\Salt Project\Salt" -if (Test-Path -Path $SaltRegKey) { - if ($null -ne (Get-ItemProperty $SaltRegKey).root_dir) { - $RootDir = (Get-ItemProperty $SaltRegKey).root_dir - } -} - -$ConfDir = "$RootDir\conf" -$PkiDir = "$ConfDir\pki\minion" -Write-Verbose "ConfDir: $ConfDir" - -#=============================================================================== -# Copy Vagrant Files to their proper location. -#=============================================================================== - # Vagrant files will be placed in C:\tmp # Check if minion keys have been uploaded, copy to correct location if (Test-Path C:\tmp\minion.pem) { @@ -413,146 +400,83 @@ if ([IntPtr]::Size -eq 4) { } #=============================================================================== -# Get file name to download +# Getting version information from the repo #=============================================================================== -$saltFileName = "" -$saltVersion = "" -$saltSha512= "" -$saltFileUrl = "" -# Look for a repo.json file -try { - Write-Verbose "Looking for $RepoUrl/repo.json" - $response = Invoke-WebRequest "$RepoUrl/repo.json" ` - -DisableKeepAlive ` - -UseBasicParsing ` - -Method Head - if ( $response.StatusCode -eq "200" ) { - Write-Verbose "Found $RepoUrl/repo.json" - # This URL contains a repo.json file, let's use it - $use_repo_json = $true - } else { - Write-Verbose "Did not find $RepoUrl/repo.json" - # No repo.json file found at the default location - $use_repo_json = $false +if ( $RepoUrl -eq $DfltUrl ) { + Write-Verbose "Getting version information from Artifactory" + $response = Invoke-WebRequest $ApiUrl -UseBasicParsing + # Convert the output to a powershell object + $psobj = $response.ToString() | ConvertFrom-Json + + # Filter the object for folders + $filtered = $psobj.children | Where-Object -Property folder -EQ $true + + # Get each uri and add it to the list of versions + $available_versions = [System.Collections.ArrayList]@() + $filtered | Select-Object -Property uri | ForEach-Object { + $available_versions.Add($_.uri.Trim("/")) | Out-Null } -} catch { - Write-Verbose "There was an error looking up $RepoUrl/repo.json" - Write-Verbose "ERROR: $_" - $use_repo_json = $false -} -if ( $use_repo_json ) { - # We will use the json file to get the name of the installer - $enc = [System.Text.Encoding]::UTF8 - try { - Write-Verbose "Downloading $RepoUrl/repo.json" - $response = Invoke-WebRequest -Uri "$RepoUrl/repo.json" -UseBasicParsing - if ($response.Content.GetType().Name -eq "Byte[]") { - $psobj = $enc.GetString($response.Content) | ConvertFrom-Json - } else { - $psobj = $response.Content | ConvertFrom-Json - } - $hash = Convert-PSObjectToHashtable $psobj - } catch { - Write-Verbose "repo.json not found at: $RepoUrl" - Write-Host "ERROR: $_" - $hash = @{} + + # Create a versions table, similar to repo.json + # This will have the latest version available, the latest version available for + # each major version, and every version available. This makes the version + # lookup logic easier. You can view the contents of the versions table by + # passing the -Verbose command + $latest = $available_versions | Select-Object -Last 1 + $versions_table = [ordered]@{"latest"=$latest} + + $available_versions | ForEach-Object { + $versions_table[$(Get-MajorVersion $_)] = $_ + $versions_table[$_.ToLower()] = $_.ToLower() } - $searchVersion = $Version.ToLower() - if ( $hash.Contains($searchVersion)) { - Write-Verbose "Found $searchVersion in $RepoUrl/repo.json" - foreach ($item in $hash.($searchVersion).Keys) { - if ( $item.ToLower().EndsWith(".exe") ) { - if ( $item.ToLower().Contains($arch.ToLower()) ) { - $saltFileName = $hash.($searchVersion).($item).name - $saltVersion = $hash.($searchVersion).($item).version - $saltSha512 = $hash.($searchVersion).($item).SHA512 - } - } - } + Write-Verbose "Available versions:" + $available_versions | ForEach-Object { + Write-Verbose "- $_" + } + Write-Verbose "Versions Table:" + $versions_table | Sort-Object Name | Out-String | Write-Verbose + + #=============================================================================== + # Validate passed version + #=============================================================================== + if ( $versions_table.Contains($Version.ToLower()) ) { + $Version = $versions_table[$Version.ToLower()] } else { - try { - Write-Verbose "Searching for $searchVersion in $RepoUrl/minor/repo.json" - $response = Invoke-WebRequest -Uri "$RepoUrl/minor/repo.json" -UseBasicParsing - if ($response.Content.GetType().Name -eq "Byte[]") { - $psobj = $enc.GetString($response.Content) | ConvertFrom-Json - } else { - $psobj = $response.Content | ConvertFrom-Json - } - $hash = Convert-PSObjectToHashtable $psobj - } catch { - Write-Verbose "repo.json not found at: $RepoUrl/minor/repo.json" - Write-Verbose "ERROR: $_" - $hash = @{} - } - if ( $hash.Contains($searchVersion)) { - Write-Verbose "Found $searchVersion in $RepoUrl/minor/repo.json" - foreach ($item in $hash.($searchVersion).Keys) { - if ( $item.ToLower().EndsWith(".exe") ) { - if ( $item.ToLower().Contains($arch.ToLower()) ) { - $saltFileName = $hash.($searchVersion).($item).name - $saltVersion = $hash.($searchVersion).($item).version - $saltSha512 = $hash.($searchVersion).($item).SHA512 - } - } - } - } else { - Write-Verbose "Version not found in $RepoUrl/minor/repo.json" - } + Write-Host "Version $Version is not available" -ForegroundColor Red + Write-Host "Available versions are:" -ForegroundColor Yellow + $available_versions | ForEach-Object { Write-Host "- $_" -ForegroundColor Yellow } + exit 1 } -} -if ( $saltFileName -and $saltVersion -and $saltSha512 ) { - Write-Verbose "Found Name, Version, and Sha" -} else { - # We will guess the name of the installer - Write-Verbose "Failed to get Name, Version, and Sha from repo.json" - Write-Verbose "We'll try to find the file in standard paths" + #=============================================================================== + # Get file url and sha256 + #=============================================================================== $saltFileName = "Salt-Minion-$Version-Py3-$arch-Setup.exe" - $saltVersion = $Version -} - -Write-Verbose "Creating list of urls using the following:" -Write-Verbose "RepoUrl: $RepoUrl" -Write-Verbose "Version: $saltVersion" -Write-Verbose "File Name: $saltFileName" -$urls = $(@($RepoUrl, $saltVersion, $saltFileName) -join "/"), - $(@($RepoUrl, "minor", $saltVersion, $saltFileName) -join "/"), - $(@($RepoUrl, $saltFileName) -join "/"), - $(@($oldRepoUrl, $saltFileName) -join "/") + $response = Invoke-WebRequest "$ApiUrl/$Version/$saltFileName" -UseBasicParsing + $psobj = $response.ToString() | ConvertFrom-Json + $saltFileUrl = $psobj.downloadUri + $saltSha256 = $psobj.checksums.sha256 -$saltFileUrl = $null - -foreach ($url in $urls) { - try { - Write-Verbose "Looking for installer at: $url" - $response = Invoke-WebRequest "$url" ` - -DisableKeepAlive ` - -UseBasicParsing ` - -Method Head - if ( $response.StatusCode -eq "200" ) { - Write-Verbose "Found installer" - # This URL contains a repo.json file, let's use it - $saltFileUrl = $url - break - } else { - Write-Verbose "Installer not found: $url" - } - } catch { - Write-Verbose "ERROR: $url" - } -} - -if ( !$saltFileUrl ) { - Write-Host "Could not find an installer:" - Write-Verbose "Here are the urls searched:" - foreach ($url in $urls) { - Write-Verbose $url + if ( $saltFileName -and $saltVersion -and $saltSha256) { + Write-Verbose "Found Name, Version, and Sha" + } else { + # We will guess the name of the installer + Write-Verbose "Failed to get Name, Version, and Sha from Artifactory API" + Write-Verbose "We'll try to find the file in standard paths" + $saltFileName = "Salt-Minion-$Version-Py3-$arch-Setup.exe" + $saltVersion = $Version } - exit 1 +} else { + # If we're using a custom RepoUrl, we're going to assum that the binary is + # in the reoot of the RepoUrl/Version. We will not check the sha on custom + # repos + $saltFileName = "Salt-Minion-$Version-Py3-$arch-Setup.exe" + $saltFileUrl = "$RepoUrl/$Version/$saltFileName" + $saltVersion = $Version + $saltSha256 = "" } - #=============================================================================== # Download minion setup file #=============================================================================== @@ -561,6 +485,7 @@ Write-Host " Bootstrapping Salt Minion" -ForegroundColor Green Write-Host " - version: $Version" Write-Host " - file name: $saltFileName" Write-Host " - file url: $saltFileUrl" +Write-Host " - file hash: $saltSha256" Write-Host " - master: $Master" Write-Host " - minion id: $Minion" Write-Host " - start service: $RunService" @@ -573,22 +498,23 @@ Write-Verbose "" Write-Verbose "Salt File URL: $saltFileUrl" Write-Verbose "Local File: $localFile" -$webclient = New-Object System.Net.WebClient -$webclient.DownloadFile($saltFileUrl, $localFile) +if ( Test-Path -Path $localFile ) {Remove-Item -Path $localFile -Force} +Invoke-WebRequest -Uri $saltFileUrl -OutFile $localFile if ( Test-Path -Path $localFile ) { Write-Host "Success" -ForegroundColor Green } else { Write-Host "Failed" -ForegroundColor Red + exit 1 } -if ( $saltSha512 ) { - $localSha512 = (Get-FileHash -Path $localFile -Algorithm SHA512).Hash +if ( $saltSha256 ) { + $localSha256 = (Get-FileHash -Path $localFile -Algorithm SHA256).Hash Write-Host "Comparing Hash: " -NoNewline Write-Verbose "" - Write-Verbose "Local Hash: $localSha512" - Write-Verbose "Remote Hash: $saltSha512" - if ( $localSha512 -eq $saltSha512 ) { + Write-Verbose "Local Hash: $localSha256" + Write-Verbose "Remote Hash: $saltSha256" + if ( $localSha256 -eq $saltSha256 ) { Write-Host "Success" -ForegroundColor Green } else { Write-Host "Failed" -ForegroundColor Red @@ -626,7 +552,7 @@ $process | Wait-Process -Timeout 300 -ErrorAction SilentlyContinue $process.Refresh() if ( !$process.HasExited ) { - Write-Host "Timedout" -ForegroundColor Yellow + Write-Host "Installer Timeout" -ForegroundColor Yellow Write-Host "Killing hung installer: " -NoNewline $process | Stop-Process $process.Refresh() @@ -636,8 +562,6 @@ if ( !$process.HasExited ) { Write-Host "Failed" -ForegroundColor Red exit 1 } - - Write-Host "Checking installed service: " -NoNewline } # Wait for salt-minion service to be registered to verify successful @@ -658,7 +582,7 @@ while ( ! $service ) { # probably went wrong and user intervention is required - report # failure. Write-Host "Failed" -ForegroundColor Red - Write-Host "Timed out waiting for the salt-minion service to be installed" + Write-Host "Timeout waiting for the salt-minion service to be installed" exit 1 } } @@ -676,27 +600,31 @@ if( $RunService ) { # We'll try for 2 minutes, sometimes the minion takes that long to start as # it compiles python code for the first time $max_tries = 60 - while ( $service.Status -ne "Running" ) { - if ( $service.Status -eq "Stopped" ) { - Start-Service -Name "salt-minion" -ErrorAction SilentlyContinue - } - Start-Sleep -Seconds 2 - Write-Verbose "Checking the service status" - $service.Refresh() - if ( $service.Status -eq "Running" ) { - Write-Host "Success" -ForegroundColor Green - } else { - if ( $tries -le $max_tries ) { - $tries += 1 + if ( $service.Status -ne "Running" ) { + while ( $service.Status -ne "Running" ) { + if ( $service.Status -eq "Stopped" ) { + Start-Service -Name "salt-minion" -ErrorAction SilentlyContinue + } + Start-Sleep -Seconds 2 + Write-Verbose "Checking the service status" + $service.Refresh() + if ( $service.Status -eq "Running" ) { + Write-Host "Success" -ForegroundColor Green } else { - # If the salt-minion service is still not running, something - # probably went wrong and user intervention is required - report - # failure. - Write-Host "Failed" -ForegroundColor Red - Write-Host "Timed out waiting for the salt-minion service to start" - exit 1 + if ( $tries -le $max_tries ) { + $tries += 1 + } else { + # If the salt-minion service is still not running, something + # probably went wrong and user intervention is required - report + # failure. + Write-Host "Failed" -ForegroundColor Red + Write-Host "Timed out waiting for the salt-minion service to start" + exit 1 + } } } + } else { + Write-Host "Success" -ForegroundColor Green } } else { # Set the service to manual start diff --git a/kitchen.macos.yml b/kitchen.macos.yml deleted file mode 100644 index 616a489e0..000000000 --- a/kitchen.macos.yml +++ /dev/null @@ -1,42 +0,0 @@ ---- -driver: - name: exec - -provisioner: - sudo: true - salt_bootstrap_options: -MP stable %s - init_environment: | - echo 'auto_accept: true' > /tmp/auto-accept-keys.conf - sudo mkdir -p /etc/salt/master.d - sudo mv /tmp/auto-accept-keys.conf /etc/salt/master.d/auto-accept-keys.conf - brew install coreutils - sh -c 't=$(gshuf -i 1-15 -n 1); echo Sleeping $t seconds; sleep $t' - -platforms: - - name: macos-12 - - name: macos-13 - -suites: - - name: stable-3006 - provisioner: - salt_version: 3006 - salt_call_command: /opt/salt/salt-call - - name: stable-3006-8 - provisioner: - salt_version: 3006.8 - salt_call_command: /opt/salt/salt-call - - name: stable-3007 - provisioner: - salt_version: 3007 - salt_call_command: /opt/salt/salt-call - - name: stable-3007-1 - provisioner: - salt_version: 3007.1 - salt_call_command: /opt/salt/salt-call - - name: latest - provisioner: - salt_version: latest - salt_call_command: /opt/salt/salt-call - -verifier: - command: pytest --cache-clear -v -s -ra --log-cli-level=debug -k "not test_ping" tests/integration/ diff --git a/kitchen.windows.yml b/kitchen.windows.yml deleted file mode 100644 index a2b88e2e3..000000000 --- a/kitchen.windows.yml +++ /dev/null @@ -1,42 +0,0 @@ ---- -driver: - name: proxy - host: localhost - reset_command: "exit 0" - port: 5985 - username: kitchen - password: Password1 - -provisioner: - salt_bootstrap_url: D:/a/salt-bootstrap/salt-bootstrap/bootstrap-salt.ps1 - salt_bootstrap_options: -Version %s -Verbose - init_environment: '' - -platforms: - - name: windows-2022 - - name: windows-2019 - -suites: - - name: stable-3006 - provisioner: - salt_version: 3006 - salt_call_command: c:\Program Files\Salt Project\Salt\salt-call.exe - - name: stable-3006-8 - provisioner: - salt_version: 3006.8 - salt_call_command: c:\Program Files\Salt Project\Salt\salt-call.exe - - name: stable-3007 - provisioner: - salt_version: 3007 - salt_call_command: c:\Program Files\Salt Project\Salt\salt-call.exe - - name: stable-3007-1 - provisioner: - salt_version: 3007.1 - salt_call_command: c:\Program Files\Salt Project\Salt\salt-call.exe - - name: latest - provisioner: - salt_version: latest - salt_call_command: c:\Program Files\Salt Project\Salt\salt-call.exe - -verifier: - command: pytest --cache-clear -v -s -ra --log-cli-level=debug -k "not test_ping" tests/integration/ diff --git a/kitchen.yml b/kitchen.yml deleted file mode 100644 index 62cc73808..000000000 --- a/kitchen.yml +++ /dev/null @@ -1,296 +0,0 @@ ---- -driver: - name: docker - use_sudo: false - hostname: salt - privileged: true - username: root - cap_add: - - sys_admin - disable_upstart: false - use_internal_docker_network: false - run_command: /usr/lib/systemd/systemd - -provisioner: - name: salt_solo - salt_install: bootstrap - salt_bootstrap_url: bootstrap-salt.sh - salt_bootstrap_options: -MPfq git %s - install_after_init_environment: true - log_level: info - sudo: false - require_chef: false - formula: tests - run_salt_call: false - init_environment: | - echo 'auto_accept: true' > /tmp/auto-accept-keys.conf - mkdir -p /etc/salt/master.d - mv /tmp/auto-accept-keys.conf /etc/salt/master.d/auto-accept-keys.conf - sh -c 't=$(shuf -i 1-15 -n 1); echo Sleeping $t seconds; sleep $t' - - -## - name: amazon-2023 -## driver: -## image: amazonlinux:2023 -## provision_command: -## - yum -y install --allowerasing procps-ng curl -## - echo "PubkeyAcceptedAlgorithms +ssh-rsa" | tee -a /etc/ssh/sshd_config - -## - name: opensuse-tumbleweed -## driver: -## image: opensuse/tumbleweed:latest -## provision_command: -## - *opensuse_provision_command_01 -## - *opensuse_provision_command_02 -## - *opensuse_provision_command_03 -## - echo "PubkeyAcceptedAlgorithms +ssh-rsa" | tee -a /etc/ssh/sshd_config - -platforms: - - name: almalinux-9 - driver: - provision_command: - - dnf -y install crypto-policies-scripts procps-ng - - update-crypto-policies --set DEFAULT:SHA1 - - echo "PubkeyAcceptedAlgorithms +ssh-rsa" | tee -a /etc/ssh/sshd_config - - name: almalinux-8 - - name: amazon-2 - driver: - image: amazonlinux:2 - platform: rhel - provision_command: - - yum -y install procps-ng - - name: arch - driver: - image: archlinux/archlinux - provision_command: - - pacman -Syu --noconfirm --needed systemd grep awk procps which - - systemctl enable sshd - - echo "PubkeyAcceptedAlgorithms +ssh-rsa" | tee -a /etc/ssh/sshd_config - - name: centos-stream9 - driver: - platform: centosstream - image: quay.io/centos/centos:stream9 - provision_command: - - dnf -y install crypto-policies-scripts procps-ng - - update-crypto-policies --set DEFAULT:SHA1 - - echo "PubkeyAcceptedAlgorithms +ssh-rsa" | tee -a /etc/ssh/sshd_config - - name: debian-11 - driver: - image: debian:bullseye - run_command: /lib/systemd/systemd - - name: debian-12 - driver: - image: debian:bookworm - run_command: /lib/systemd/systemd - provision_command: - - echo "PubkeyAcceptedAlgorithms +ssh-rsa" | tee -a /etc/ssh/sshd_config - - name: fedora-39 - driver: - provision_command: &fedora_provision_command - - dnf -y install procps-ng crypto-policies-scripts - - update-crypto-policies --set LEGACY - - name: fedora-40 - driver: - provision_command: *fedora_provision_command - - name: gentoo - driver: - image: gentoo/stage3:latest - run_command: /sbin/init - provision_command: - - rc-update add sshd default - - echo "PubkeyAcceptedAlgorithms +ssh-rsa" | tee -a /etc/ssh/sshd_config - - name: gentoo-systemd - driver: - image: gentoo/stage3:systemd - run_command: /lib/systemd/systemd - provision_command: - - systemctl enable sshd.service - - echo "PubkeyAcceptedAlgorithms +ssh-rsa" | tee -a /etc/ssh/sshd_config - - name: opensuse-15 - driver: - image: opensuse/leap:15.4 - provision_command: - - &opensuse_provision_command_01 zypper --non-interactive install --auto-agree-with-licenses dbus-1 - - &opensuse_provision_command_02 zypper --non-interactive install --auto-agree-with-licenses sudo openssh which curl systemd - - &opensuse_provision_command_03 systemctl enable sshd.service - - name: rockylinux-9 - driver: - platform: centosstream - run_command: /usr/lib/systemd/systemd - provision_command: - - dnf -y install crypto-policies-scripts procps-ng - - update-crypto-policies --set DEFAULT:SHA1 - - echo "PubkeyAcceptedAlgorithms +ssh-rsa" | tee -a /etc/ssh/sshd_config - - name: oraclelinux-9 - driver: - run_command: /usr/lib/systemd/systemd - provision_command: - - dnf -y install crypto-policies-scripts procps-ng - - update-crypto-policies --set DEFAULT:SHA1 - - echo "PubkeyAcceptedAlgorithms +ssh-rsa" | tee -a /etc/ssh/sshd_config - - name: rockylinux-8 - - name: oraclelinux-8 - - name: ubuntu-24.04 - driver: - run_command: /lib/systemd/systemd - provision_command: - - echo "PubkeyAcceptedAlgorithms +ssh-rsa" | tee -a /etc/ssh/sshd_config - - name: ubuntu-22.04 - driver: - run_command: /lib/systemd/systemd - provision_command: - - echo "PubkeyAcceptedAlgorithms +ssh-rsa" | tee -a /etc/ssh/sshd_config - - name: ubuntu-20.04 - driver: - run_command: /lib/systemd/systemd - - name: photon-4 - driver: - image: photon:4.0 - provision_command: - - tdnf -y install rpm procps-ng coreutils gawk systemd - - echo "PubkeyAcceptedKeyTypes +ssh-rsa" | tee -a /etc/ssh/sshd_config - - sed -ie 's/PermitRootLogin no/PermitRootLogin yes/' /etc/ssh/sshd_config - - systemctl enable sshd.service - - name: photon-5 - driver: - image: photon:5.0 - provision_command: - - tdnf -y install rpm procps-ng coreutils gawk systemd - - echo "PubkeyAcceptedKeyTypes +ssh-rsa" | tee -a /etc/ssh/sshd_config - - sed -ie 's/PermitRootLogin no/PermitRootLogin yes/' /etc/ssh/sshd_config - - systemctl enable sshd.service - -suites: - - name: git-3006 - provisioner: - salt_version: v3006 - salt_bootstrap_options: -x python3 -MPfq git %s - excludes: - - opensuse-15 - - opensuse-tumbleweed - - debian-11 - - debian-12 - - arch - - gentoo - - gentoo-systemd - - name: git-3006x - provisioner: - salt_version: 3006.x - salt_bootstrap_options: -x python3 -MPfq git %s - excludes: - - opensuse-15 - - opensuse-tumbleweed - - debian-11 - - debian-12 - - arch - - gentoo - - gentoo-systemd - - name: git-3007 - provisioner: - salt_version: v3007 - salt_bootstrap_options: -x python3 -MPfq git %s - excludes: - - opensuse-15 - - opensuse-tumbleweed - - debian-11 - - arch - - gentoo - - gentoo-systemd - - name: git-3007x - provisioner: - salt_version: 3007.x - salt_bootstrap_options: -x python3 -MPfq git %s - excludes: - - opensuse-15 - - opensuse-tumbleweed - - debian-11 - - arch - - gentoo - - gentoo-systemd - - name: stable-3006 - provisioner: - salt_version: 3006 - salt_bootstrap_options: -x python3 -MP stable %s - excludes: - - opensuse-15 - - opensuse-tumbleweed - - arch - - name: stable-3006-8 - provisioner: - salt_version: 3006.8 - salt_bootstrap_options: -x python3 -MP stable %s - excludes: - - opensuse-15 - - opensuse-tumbleweed - - arch - - name: stable-3007 - provisioner: - salt_version: 3007 - salt_bootstrap_options: -x python3 -MP stable %s - excludes: - - opensuse-15 - - opensuse-tumbleweed - - arch - - name: stable-3007-1 - provisioner: - salt_version: 3007.1 - salt_bootstrap_options: -x python3 -MP stable %s - excludes: - - opensuse-15 - - opensuse-tumbleweed - - arch - - name: git-master - provisioner: - salt_version: master - salt_bootstrap_options: -x python3 -MPfq -D git %s - - - name: latest - provisioner: - salt_version: latest - salt_bootstrap_options: -MP stable %s - - - name: default - provisioner: - salt_version: latest - salt_bootstrap_options: -MP - - - name: onedir-nightly - provisioner: - salt_version: nightly - salt_bootstrap_options: -MP onedir %s - - - name: onedir-latest - provisioner: - salt_version: latest - salt_bootstrap_options: -MP onedir %s - - - name: onedir-3006 - provisioner: - salt_version: 3006 - salt_bootstrap_options: -MP onedir %s - - - name: onedir-3007 - provisioner: - salt_version: 3007 - salt_bootstrap_options: -MP onedir %s - - - name: onedir-rc-3008-0rc1 - provisioner: - salt_version: 3008.0rc1 - salt_bootstrap_options: -R staging.repo.saltproject.io -MP onedir_rc %s - excludes: - - arch - - gentoo - - opensuse-15 - - opensuse-tumbleweed - - ubuntu-2004 - - ubuntu-2204 - - - name: quickstart - provisioner: - salt_bootstrap_options: -Q - -verifier: - name: shell - remote_exec: false - command: pytest --cache-clear -v -s -ra --log-cli-level=info tests/integration/ diff --git a/tests/conftest.py b/tests/conftest.py index 74ded3b2d..154b257c0 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,9 +1,12 @@ -import logging +import json import os import pytest +import requests -log = logging.getLogger(__name__) +API_URL = ( + "https://packages.broadcom.com/artifactory/api/storage/saltproject-generic/windows" +) @pytest.fixture(scope="session") @@ -13,21 +16,26 @@ def target_python_version(): @pytest.fixture(scope="session") def target_salt_version(): - bootstrap_types = ("git", "stable", "onedir", "onedir_rc") - # filter out any bootstrap types and then join - target_salt = ".".join( - [ - item - for item in os.environ.get("KITCHEN_SUITE", "").split("-") - if item not in bootstrap_types - ] - ) - - # target_salt = os.environ["KITCHEN_SUITE"].split("-", 1)[-1].replace("-", ".") + target_salt = os.environ.get("SaltVersion", "") + + html_response = requests.get(API_URL) + content = json.loads(html_response.text) + folders = content["children"] + versions = {} + for folder in folders: + if folder["folder"]: + version = folder["uri"].strip("/") + versions[version] = version + # We're trying to get the latest major version and latest overall + maj_version = version.split(".")[0] + versions[maj_version] = version + versions["latest"] = version if target_salt.startswith("v"): target_salt = target_salt[1:] + if target_salt not in versions: + pytest.skip(f"Invalid testing version: {target_salt}") if target_salt in ("default", "latest", "master", "nightly"): pytest.skip("Don't have a specific salt version to test against") - return target_salt + return versions[target_salt] diff --git a/tests/integration/__init__.py b/tests/integration/__init__.py deleted file mode 100644 index 40a96afc6..000000000 --- a/tests/integration/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/tests/integration/test_installation.py b/tests/integration/test_installation.py index 8d0b41467..f8427b675 100644 --- a/tests/integration/test_installation.py +++ b/tests/integration/test_installation.py @@ -1,12 +1,11 @@ import json import logging +import os import platform import subprocess import pytest -## from Demos.win32cred_demo import target - log = logging.getLogger(__name__) @@ -26,19 +25,17 @@ def run_salt_call(cmd): """ cmd.append("--out=json") result = subprocess.run(cmd, capture_output=True, text=True) - if result.stdout: - json_data = json.loads(result.stdout) - return json_data["local"] - return None + json_data = json.loads(result.stdout) + return json_data["local"] -def test_ping(): +def test_ping(path): cmd = ["salt-call", "--local", "test.ping"] result = run_salt_call(cmd) assert result == True -def test_target_python_version(target_python_version): +def test_target_python_version(path, target_python_version): cmd = ["salt-call", "--local", "grains.item", "pythonversion", "--timeout=120"] result = run_salt_call(cmd) # Returns: {'pythonversion': [3, 10, 11, 'final', 0]} @@ -46,8 +43,10 @@ def test_target_python_version(target_python_version): assert py_maj_ver == target_python_version -def test_target_salt_version(target_salt_version): +def test_target_salt_version(path, target_salt_version): + if not target_salt_version: + pytest.skip(f"No target version specified") cmd = ["salt-call", "--local", "grains.item", "saltversion", "--timeout=120"] result = run_salt_call(cmd) # Returns: {'saltversion': '3006.9+217.g53cfa53040'} - assert result["saltversion"] == target_salt_version + assert result["saltversion"] == target_salt_version \ No newline at end of file diff --git a/tests/requirements.txt b/tests/requirements.txt index e079f8a60..547de5c5b 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1 +1,2 @@ pytest +requests