diff --git a/.coveralls.yml b/.coveralls.yml new file mode 100644 index 0000000..cf27a37 --- /dev/null +++ b/.coveralls.yml @@ -0,0 +1 @@ +service_name: travis-pro diff --git a/.dockerignore b/.dockerignore index eaf3712..6174523 100644 --- a/.dockerignore +++ b/.dockerignore @@ -3,7 +3,10 @@ **/*.md **/*example **/Dockerfile* +Gemfile.lock +Rakefile coverage +spec examples scripts vendor diff --git a/.github/PULL_REQUEST_TEMPLATE b/.github/PULL_REQUEST_TEMPLATE index 5b0d10e..0259cfe 100644 --- a/.github/PULL_REQUEST_TEMPLATE +++ b/.github/PULL_REQUEST_TEMPLATE @@ -15,3 +15,8 @@ FIXME - [ ] Tests - [ ] Documentation +## Reviewers + +@puppetlabs/dio +@highb +@briancain diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 90d6dfd..c8f8016 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -3,17 +3,6 @@ updates: - package-ecosystem: bundler directory: "/" schedule: - interval: weekly - open-pull-requests-limit: 10 - -- package-ecosystem: docker - directory: "/" - schedule: - interval: weekly - open-pull-requests-limit: 10 - -- package-ecosystem: github-actions - directory: "/" - schedule: - interval: weekly + interval: daily + time: "13:00" open-pull-requests-limit: 10 diff --git a/.github/workflows/auto_release_prep.yml b/.github/workflows/auto_release_prep.yml deleted file mode 100644 index 19380e9..0000000 --- a/.github/workflows/auto_release_prep.yml +++ /dev/null @@ -1,12 +0,0 @@ -name: Automated release prep - -on: - workflow_dispatch: - -jobs: - auto_release_prep: - uses: puppetlabs/release-engineering-repo-standards/.github/workflows/auto_release_prep.yml@v1 - secrets: inherit - with: - project-type: ruby - version-file-path: lib/vmfloaty/version.rb diff --git a/.github/workflows/dependabot_merge.yml b/.github/workflows/dependabot_merge.yml deleted file mode 100644 index 75b9cea..0000000 --- a/.github/workflows/dependabot_merge.yml +++ /dev/null @@ -1,8 +0,0 @@ -name: Dependabot auto-merge - -on: pull_request - -jobs: - dependabot_merge: - uses: puppetlabs/release-engineering-repo-standards/.github/workflows/dependabot_merge.yml@v1 - secrets: inherit diff --git a/.github/workflows/ensure_label.yml b/.github/workflows/ensure_label.yml deleted file mode 100644 index 50a5fa8..0000000 --- a/.github/workflows/ensure_label.yml +++ /dev/null @@ -1,8 +0,0 @@ -name: Ensure label - -on: pull_request - -jobs: - ensure_label: - uses: puppetlabs/release-engineering-repo-standards/.github/workflows/ensure_label.yml@v1 - secrets: inherit diff --git a/.github/workflows/gempush.yml b/.github/workflows/gempush.yml new file mode 100644 index 0000000..0d8a445 --- /dev/null +++ b/.github/workflows/gempush.yml @@ -0,0 +1,29 @@ +name: Ruby Gem + +on: + push: + tags: + - 'v*.*.*' + +jobs: + build: + name: Build + Publish + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up Ruby 2.6 + uses: actions/setup-ruby@v1 + with: + version: 2.6.x + + - name: Publish to RubyGems + run: | + mkdir -p $HOME/.gem + touch $HOME/.gem/credentials + chmod 0600 $HOME/.gem/credentials + printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials + gem build *.gemspec + gem push *.gem + env: + GEM_HOST_API_KEY: ${{secrets.RUBYGEMS_AUTH_TOKEN}} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index d79ed5f..0000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,118 +0,0 @@ -name: Tag Release & Push Gem & Docker - -on: workflow_dispatch - -permissions: - contents: write - issues: read - pull-requests: read - packages: write - -jobs: - release: - name: Validate Docs, Tag, and Docker Push - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - ref: ${{ github.ref }} - clean: true - fetch-depth: 0 - - - name: Get New Version - id: nv - run: | - version=$(grep VERSION lib/vmfloaty/version.rb |rev |cut -d "'" -f2 |rev) - echo "version=$version" >> $GITHUB_OUTPUT - echo "Found version $version from lib/vmfloaty/version.rb" - - - name: Get Current Version - uses: actions/github-script@v7 - id: cv - with: - script: | - const { data: response } = await github.rest.repos.getLatestRelease({ - owner: context.repo.owner, - repo: context.repo.repo, - }) - console.log(`The latest release is ${response.tag_name}`) - return response.tag_name - result-encoding: string - - - name: Generate Changelog - uses: docker://githubchangeloggenerator/github-changelog-generator:1.16.2 - with: - args: >- - --future-release ${{ steps.nv.outputs.version }} - env: - CHANGELOG_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Validate Changelog - run : | - set -e - if output=$(git status --porcelain) && [ ! -z "$output" ]; then - echo "Here is the current git status:" - git status - echo - echo "The following changes were detected:" - git --no-pager diff - echo "Uncommitted PRs found in the changelog. Please submit a release prep PR of changes after running './release-prep ${{ steps.nv.outputs.version }}'" - exit 1 - fi - - - name: Generate Release Notes - uses: docker://githubchangeloggenerator/github-changelog-generator:1.16.2 - with: - args: >- - --since-tag ${{ steps.cv.outputs.result }} - --future-release ${{ steps.nv.outputs.version }} - --output release-notes.md - env: - CHANGELOG_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Tag Release - uses: ncipollo/release-action@v1 - with: - tag: ${{ steps.nv.outputs.version }} - token: ${{ secrets.GITHUB_TOKEN }} - bodyfile: release-notes.md - draft: false - prerelease: false - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Login to GitHub Container Registry - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Build and push - uses: docker/build-push-action@v5 - with: - push: true - tags: | - ghcr.io/${{ github.repository }}:${{ steps.nv.outputs.version }} - ghcr.io/${{ github.repository }}:latest - - - name: Set up Ruby 3.2 - uses: actions/setup-ruby@v1 - with: - version: 3.2.x - - - name: Build gem - run: gem build *.gemspec - - - name: Publish gem - run: | - mkdir -p $HOME/.gem - touch $HOME/.gem/credentials - chmod 0600 $HOME/.gem/credentials - printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials - gem push *.gem - env: - GEM_HOST_API_KEY: ${{secrets.RUBYGEMS_AUTH_TOKEN}} diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml deleted file mode 100644 index ba273f5..0000000 --- a/.github/workflows/security.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: Security -on: - workflow_dispatch: - push: - branches: - - main - -jobs: - scan: - name: Mend Scanning - runs-on: ubuntu-latest - steps: - - name: checkout repo content - uses: actions/checkout@v4 - with: - fetch-depth: 1 - - name: setup ruby - uses: ruby/setup-ruby@v1 - with: - ruby-version: 2.7 - # setup a package lock if one doesn't exist, otherwise do nothing - - name: check lock - run: '[ -f "Gemfile.lock" ] && echo "package lock file exists, skipping" || bundle lock' - # install java - - uses: actions/setup-java@v4 - with: - distribution: 'temurin' # See 'Supported distributions' for available options - java-version: '17' - # download mend - - name: download_mend - run: curl -o wss-unified-agent.jar https://unified-agent.s3.amazonaws.com/wss-unified-agent.jar - - name: run mend - run: java -jar wss-unified-agent.jar - env: - WS_APIKEY: ${{ secrets.MEND_API_KEY }} - WS_WSS_URL: https://saas-eu.whitesourcesoftware.com/agent - WS_USERKEY: ${{ secrets.MEND_TOKEN }} - WS_PRODUCTNAME: RE - WS_PROJECTNAME: ${{ github.event.repository.name }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml deleted file mode 100644 index 8562713..0000000 --- a/.github/workflows/test.yml +++ /dev/null @@ -1,54 +0,0 @@ -# This workflow uses actions that are not certified by GitHub. -# They are provided by a third-party and are governed by -# separate terms of service, privacy policy, and support -# documentation. -# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake -# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby - -name: Test - -on: - pull_request: - branches: - - main - -jobs: - spec: - runs-on: ubuntu-latest - strategy: - matrix: - ruby-version: - - '2.7' - - '3.0' - - '3.1' - - '3.2' - - steps: - - uses: actions/checkout@v4 - - name: Set up Ruby - # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby, - # change this to (see https://github.com/ruby/setup-ruby#versioning): - # uses: ruby/setup-ruby@v1 - uses: ruby/setup-ruby@v1 - with: - ruby-version: ${{ matrix.ruby-version }} - bundler-cache: true # runs 'bundle install' and caches installed gems automatically - - name: Run tests - run: bundle exec rake spec - - name: Coveralls - uses: coverallsapp/github-action@v2 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - flag-name: run-${{ matrix.ruby-version }} - parallel: true - - finish: - needs: spec - if: ${{ always() }} - runs-on: ubuntu-latest - steps: - - name: Coveralls Finished - uses: coverallsapp/github-action@v2 - with: - github-token: ${{ secrets.github_token }} - parallel-finished: true diff --git a/.github_changelog_generator b/.github_changelog_generator deleted file mode 100644 index 02a0c7c..0000000 --- a/.github_changelog_generator +++ /dev/null @@ -1,3 +0,0 @@ -project=vmfloaty -user=puppetlabs -exclude_labels=maintenance diff --git a/.gitignore b/.gitignore index 76a21bc..5102fb1 100644 --- a/.gitignore +++ b/.gitignore @@ -25,10 +25,9 @@ build/ /vendor/ /lib/bundler/man/ -.dccache - # for a library or gem, you might want to ignore these files since the code is # intended to run in multiple environments; otherwise, check them in: +Gemfile.lock .ruby-version .ruby-gemset diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..770839e --- /dev/null +++ b/.travis.yml @@ -0,0 +1,7 @@ +language: ruby +dist: xenial +os: + - linux +rvm: + - 2.6.5 +script: bundle exec rake spec diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index ff7c73f..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,340 +0,0 @@ -# Changelog - -## [1.8.1](https://github.com/puppetlabs/vmfloaty/tree/1.8.1) (2023-08-07) - -[Full Changelog](https://github.com/puppetlabs/vmfloaty/compare/1.8.0...1.8.1) - -**Fixed bugs:** - -- status and summary broken for pooler service after v3 [\#185](https://github.com/puppetlabs/vmfloaty/issues/185) -- \(RE-15687\) Use relative path for pooler status and summary [\#186](https://github.com/puppetlabs/vmfloaty/pull/186) ([yachub](https://github.com/yachub)) - -**Merged pull requests:** - -- Bump rubocop from 1.54.2 to 1.55.1 [\#183](https://github.com/puppetlabs/vmfloaty/pull/183) ([dependabot[bot]](https://github.com/apps/dependabot)) -- Bump rubocop from 1.52.0 to 1.54.2 [\#182](https://github.com/puppetlabs/vmfloaty/pull/182) ([dependabot[bot]](https://github.com/apps/dependabot)) -- Bump rubocop from 1.51.0 to 1.52.0 [\#177](https://github.com/puppetlabs/vmfloaty/pull/177) ([dependabot[bot]](https://github.com/apps/dependabot)) -- Bump rubocop from 1.50.2 to 1.51.0 [\#176](https://github.com/puppetlabs/vmfloaty/pull/176) ([dependabot[bot]](https://github.com/apps/dependabot)) -- Bump rubocop from 1.49.0 to 1.50.2 [\#174](https://github.com/puppetlabs/vmfloaty/pull/174) ([dependabot[bot]](https://github.com/apps/dependabot)) -- Bump rubocop from 1.48.1 to 1.49.0 [\#173](https://github.com/puppetlabs/vmfloaty/pull/173) ([dependabot[bot]](https://github.com/apps/dependabot)) -- Update simplecov requirement from ~\> 0.21.2 to ~\> 0.22.0 [\#167](https://github.com/puppetlabs/vmfloaty/pull/167) ([dependabot[bot]](https://github.com/apps/dependabot)) -- Update rspec requirement from ~\> 3.11.0 to ~\> 3.12.0 [\#166](https://github.com/puppetlabs/vmfloaty/pull/166) ([dependabot[bot]](https://github.com/apps/dependabot)) - -## [1.8.0](https://github.com/puppetlabs/vmfloaty/tree/1.8.0) (2023-03-21) - -[Full Changelog](https://github.com/puppetlabs/vmfloaty/compare/1.7.0...1.8.0) - -**Implemented enhancements:** - -- Docker, Actions, and Docs Updates [\#170](https://github.com/puppetlabs/vmfloaty/pull/170) ([yachub](https://github.com/yachub)) - -**Fixed bugs:** - -- Fix `floaty list --active` for vmpooler api v2 [\#169](https://github.com/puppetlabs/vmfloaty/pull/169) ([yachub](https://github.com/yachub)) - -**Merged pull requests:** - -- \(RE-15111\) Migrate Synk to Mend [\#168](https://github.com/puppetlabs/vmfloaty/pull/168) ([yachub](https://github.com/yachub)) -- \(RE-14811\) Move codeowners from DIO to RE [\#165](https://github.com/puppetlabs/vmfloaty/pull/165) ([yachub](https://github.com/yachub)) -- Add Snyk action and Move to RE org [\#164](https://github.com/puppetlabs/vmfloaty/pull/164) ([yachub](https://github.com/yachub)) -- Add release-engineering to codeowners [\#163](https://github.com/puppetlabs/vmfloaty/pull/163) ([yachub](https://github.com/yachub)) - -## [1.7.0](https://github.com/puppetlabs/vmfloaty/tree/1.7.0) (2022-04-05) - -[Full Changelog](https://github.com/puppetlabs/vmfloaty/compare/v1.6.0...1.7.0) - -**Implemented enhancements:** - -- \(maint\) Add Ruby 3.1 to test matrix + dockerfile and drop EOL Ruby 2.6 [\#159](https://github.com/puppetlabs/vmfloaty/pull/159) ([yachub](https://github.com/yachub)) -- \(DIO-3101\) Add VMPooler API v2 Support [\#158](https://github.com/puppetlabs/vmfloaty/pull/158) ([yachub](https://github.com/yachub)) - -**Fixed bugs:** - -- \(maint\) Remove colorize usage from `floaty status` [\#160](https://github.com/puppetlabs/vmfloaty/pull/160) ([yachub](https://github.com/yachub)) - -**Merged pull requests:** - -- v1.7.0 release prep [\#162](https://github.com/puppetlabs/vmfloaty/pull/162) ([yachub](https://github.com/yachub)) -- \(maint\) removing previous maintainers [\#157](https://github.com/puppetlabs/vmfloaty/pull/157) ([binford2k](https://github.com/binford2k)) -- Update rspec requirement from ~\> 3.10.0 to ~\> 3.11.0 [\#155](https://github.com/puppetlabs/vmfloaty/pull/155) ([dependabot[bot]](https://github.com/apps/dependabot)) -- Docs on contributing and releasing [\#152](https://github.com/puppetlabs/vmfloaty/pull/152) ([genebean](https://github.com/genebean)) - -## [v1.6.0](https://github.com/puppetlabs/vmfloaty/tree/v1.6.0) (2022-02-16) - -[Full Changelog](https://github.com/puppetlabs/vmfloaty/compare/v1.5.0...v1.6.0) - -**Merged pull requests:** - -- \(DIO-2700\) Vmfloaty should not use the Colorize gem [\#156](https://github.com/puppetlabs/vmfloaty/pull/156) ([sbeaulie](https://github.com/sbeaulie)) -- \(maint\) Fix up nspooler list active bug [\#154](https://github.com/puppetlabs/vmfloaty/pull/154) ([cthorn42](https://github.com/cthorn42)) -- Minor cleanup to the readme [\#151](https://github.com/puppetlabs/vmfloaty/pull/151) ([genebean](https://github.com/genebean)) -- Release prep for 1.5.0 [\#150](https://github.com/puppetlabs/vmfloaty/pull/150) ([genebean](https://github.com/genebean)) - -## [v1.5.0](https://github.com/puppetlabs/vmfloaty/tree/v1.5.0) (2021-10-12) - -[Full Changelog](https://github.com/puppetlabs/vmfloaty/compare/v1.4.0...v1.5.0) - -**Merged pull requests:** - -- DIO 2412- Ondemand and Priority flag added to SSH command [\#149](https://github.com/puppetlabs/vmfloaty/pull/149) ([tanisha-payne](https://github.com/tanisha-payne)) -- \(DIO-2135\) Update docker FROM image to ruby 3.0.2 [\#148](https://github.com/puppetlabs/vmfloaty/pull/148) ([sbeaulie](https://github.com/sbeaulie)) -- Migrate CI to GitHub Actions [\#147](https://github.com/puppetlabs/vmfloaty/pull/147) ([genebean](https://github.com/genebean)) -- v1.4.0 release prep [\#146](https://github.com/puppetlabs/vmfloaty/pull/146) ([genebean](https://github.com/genebean)) - -## [v1.4.0](https://github.com/puppetlabs/vmfloaty/tree/v1.4.0) (2021-07-16) - -[Full Changelog](https://github.com/puppetlabs/vmfloaty/compare/v1.3.0...v1.4.0) - -**Merged pull requests:** - -- \(maint\) Use latest Faraday/webmock, update specs [\#145](https://github.com/puppetlabs/vmfloaty/pull/145) ([nmburgan](https://github.com/nmburgan)) -- Update commander requirement from \>= 4.4.3, \< 4.6.0 to \>= 4.4.3, \< 4.7.0 [\#140](https://github.com/puppetlabs/vmfloaty/pull/140) ([dependabot[bot]](https://github.com/apps/dependabot)) -- Release prep for v1.3.0 [\#137](https://github.com/puppetlabs/vmfloaty/pull/137) ([sbeaulie](https://github.com/sbeaulie)) -- Run the rubocop auto\_correct [\#135](https://github.com/puppetlabs/vmfloaty/pull/135) ([sbeaulie](https://github.com/sbeaulie)) - -## [v1.3.0](https://github.com/puppetlabs/vmfloaty/tree/v1.3.0) (2021-03-03) - -[Full Changelog](https://github.com/puppetlabs/vmfloaty/compare/v1.2.0...v1.3.0) - -**Merged pull requests:** - -- \(DIO-1522\) Show the VM state \(running, destroyed\) and colorize in red… [\#134](https://github.com/puppetlabs/vmfloaty/pull/134) ([sbeaulie](https://github.com/sbeaulie)) -- Release prep for 1.2.0 [\#132](https://github.com/puppetlabs/vmfloaty/pull/132) ([genebean](https://github.com/genebean)) -- Update rubocop requirement from ~\> 0.52 to ~\> 1.6 [\#124](https://github.com/puppetlabs/vmfloaty/pull/124) ([dependabot[bot]](https://github.com/apps/dependabot)) - -## [v1.2.0](https://github.com/puppetlabs/vmfloaty/tree/v1.2.0) (2021-02-11) - -[Full Changelog](https://github.com/puppetlabs/vmfloaty/compare/v1.1.1...v1.2.0) - -**Merged pull requests:** - -- \(DIO-908\) Floaty can now report the status of ABS requests [\#131](https://github.com/puppetlabs/vmfloaty/pull/131) ([sbeaulie](https://github.com/sbeaulie)) -- Update rspec requirement from ~\> 3.9.0 to ~\> 3.10.0 [\#116](https://github.com/puppetlabs/vmfloaty/pull/116) ([dependabot[bot]](https://github.com/apps/dependabot)) - -## [v1.1.1](https://github.com/puppetlabs/vmfloaty/tree/v1.1.1) (2020-10-16) - -[Full Changelog](https://github.com/puppetlabs/vmfloaty/compare/v1.1.0...v1.1.1) - -**Merged pull requests:** - -- V1.1.1 [\#112](https://github.com/puppetlabs/vmfloaty/pull/112) ([sbeaulie](https://github.com/sbeaulie)) - -## [v1.1.0](https://github.com/puppetlabs/vmfloaty/tree/v1.1.0) (2020-10-09) - -[Full Changelog](https://github.com/puppetlabs/vmfloaty/compare/v1.0.0...v1.1.0) - -**Merged pull requests:** - -- \(maint\) Add more uniqueness to jobid and useful termination message [\#107](https://github.com/puppetlabs/vmfloaty/pull/107) ([sbeaulie](https://github.com/sbeaulie)) -- \(maint\) Fix bug with detecting ABS service [\#106](https://github.com/puppetlabs/vmfloaty/pull/106) ([sbeaulie](https://github.com/sbeaulie)) -- \(maint\) Don't require config file for list --active [\#105](https://github.com/puppetlabs/vmfloaty/pull/105) ([sbeaulie](https://github.com/sbeaulie)) -- \(maint\) Don't require configuration file for get [\#104](https://github.com/puppetlabs/vmfloaty/pull/104) ([nwolfe](https://github.com/nwolfe)) -- \(maint\) Add vmpooler\_fallback to the get service check [\#103](https://github.com/puppetlabs/vmfloaty/pull/103) ([cthorn42](https://github.com/cthorn42)) -- Update completion scripts for `service` subcommands [\#102](https://github.com/puppetlabs/vmfloaty/pull/102) ([scotje](https://github.com/scotje)) -- Bump to version 1.0.0 [\#100](https://github.com/puppetlabs/vmfloaty/pull/100) ([genebean](https://github.com/genebean)) - -## [v1.0.0](https://github.com/puppetlabs/vmfloaty/tree/v1.0.0) (2020-09-22) - -[Full Changelog](https://github.com/puppetlabs/vmfloaty/compare/0.11.1...v1.0.0) - -**Merged pull requests:** - -- \(maint\) Fix for ABS PR\#306 that includes json responses [\#99](https://github.com/puppetlabs/vmfloaty/pull/99) ([sbeaulie](https://github.com/sbeaulie)) -- \(maint\) Support any vmpooler for ABS via vmpooler\_fallback [\#98](https://github.com/puppetlabs/vmfloaty/pull/98) ([sbeaulie](https://github.com/sbeaulie)) -- \(DIO-991\) Add service command [\#97](https://github.com/puppetlabs/vmfloaty/pull/97) ([genebean](https://github.com/genebean)) -- \( DIO-911\) Include job\_id in ABS --json output [\#96](https://github.com/puppetlabs/vmfloaty/pull/96) ([sbeaulie](https://github.com/sbeaulie)) -- ABS enables fallback to vmpooler for some scenarios [\#94](https://github.com/puppetlabs/vmfloaty/pull/94) ([sbeaulie](https://github.com/sbeaulie)) -- WIP \(DIO-911\) Include job\_id in ABS --json output [\#92](https://github.com/puppetlabs/vmfloaty/pull/92) ([nwolfe](https://github.com/nwolfe)) -- \(maint\) Remove warning about missing configuration file [\#91](https://github.com/puppetlabs/vmfloaty/pull/91) ([nwolfe](https://github.com/nwolfe)) -- Add tab completion script for zsh and fix bash completion for ABS services [\#90](https://github.com/puppetlabs/vmfloaty/pull/90) ([scotje](https://github.com/scotje)) - -## [0.11.1](https://github.com/puppetlabs/vmfloaty/tree/0.11.1) (2020-08-20) - -[Full Changelog](https://github.com/puppetlabs/vmfloaty/compare/0.10.0...0.11.1) - -**Merged pull requests:** - -- Update version for 0.11.1 release [\#89](https://github.com/puppetlabs/vmfloaty/pull/89) ([mattkirby](https://github.com/mattkirby)) -- \(maint\) Fix using ABS service without a .vmfloaty.yml file [\#88](https://github.com/puppetlabs/vmfloaty/pull/88) ([cthorn42](https://github.com/cthorn42)) -- Fix the argument list for nonstandardpooler [\#87](https://github.com/puppetlabs/vmfloaty/pull/87) ([jarretlavallee](https://github.com/jarretlavallee)) -- Json output for delete/list + better ABS error handling [\#86](https://github.com/puppetlabs/vmfloaty/pull/86) ([mcdonaldseanp](https://github.com/mcdonaldseanp)) -- Bump version for 0.11.0 release [\#85](https://github.com/puppetlabs/vmfloaty/pull/85) ([mattkirby](https://github.com/mattkirby)) -- Print all non-success output to STDERR [\#84](https://github.com/puppetlabs/vmfloaty/pull/84) ([austb](https://github.com/austb)) -- Update travis.yml [\#83](https://github.com/puppetlabs/vmfloaty/pull/83) ([rooneyshuman](https://github.com/rooneyshuman)) -- Bump version to 0.10.0 for release [\#82](https://github.com/puppetlabs/vmfloaty/pull/82) ([mattkirby](https://github.com/mattkirby)) - -## [0.10.0](https://github.com/puppetlabs/vmfloaty/tree/0.10.0) (2020-08-04) - -[Full Changelog](https://github.com/puppetlabs/vmfloaty/compare/v0.9.2-retag-for-gh-actions-for-real...0.10.0) - -**Merged pull requests:** - -- Update Dependabot config file [\#78](https://github.com/puppetlabs/vmfloaty/pull/78) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview)) -- Update rspec requirement from ~\> 3.5.0 to ~\> 3.9.0 [\#75](https://github.com/puppetlabs/vmfloaty/pull/75) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview)) -- Update commander requirement from ~\> 4.4.3 to \>= 4.4.3, \< 4.6.0 [\#73](https://github.com/puppetlabs/vmfloaty/pull/73) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview)) -- Fix formatting of CODEOWNERS [\#71](https://github.com/puppetlabs/vmfloaty/pull/71) ([genebean](https://github.com/genebean)) -- Add Dependabot and Coveralls [\#70](https://github.com/puppetlabs/vmfloaty/pull/70) ([genebean](https://github.com/genebean)) -- Update docs [\#69](https://github.com/puppetlabs/vmfloaty/pull/69) ([genebean](https://github.com/genebean)) -- Remove old maintainer note [\#68](https://github.com/puppetlabs/vmfloaty/pull/68) ([briancain](https://github.com/briancain)) -- Add support for vmpooler on demand provisioning [\#67](https://github.com/puppetlabs/vmfloaty/pull/67) ([mattkirby](https://github.com/mattkirby)) - -## [v0.9.2-retag-for-gh-actions-for-real](https://github.com/puppetlabs/vmfloaty/tree/v0.9.2-retag-for-gh-actions-for-real) (2020-02-05) - -[Full Changelog](https://github.com/puppetlabs/vmfloaty/compare/v0.9.2...v0.9.2-retag-for-gh-actions-for-real) - -**Merged pull requests:** - -- Update gempush action to remove GPR publish [\#66](https://github.com/puppetlabs/vmfloaty/pull/66) ([highb](https://github.com/highb)) - -## [v0.9.2](https://github.com/puppetlabs/vmfloaty/tree/v0.9.2) (2020-02-05) - -[Full Changelog](https://github.com/puppetlabs/vmfloaty/compare/v0.9.2-retag-for-gh-actions...v0.9.2) - -## [v0.9.2-retag-for-gh-actions](https://github.com/puppetlabs/vmfloaty/tree/v0.9.2-retag-for-gh-actions) (2020-02-05) - -[Full Changelog](https://github.com/puppetlabs/vmfloaty/compare/v0.9.0...v0.9.2-retag-for-gh-actions) - -**Merged pull requests:** - -- Bump version.rb to 0.9.2 for release [\#65](https://github.com/puppetlabs/vmfloaty/pull/65) ([highb](https://github.com/highb)) -- Create gempush.yml Github Action [\#64](https://github.com/puppetlabs/vmfloaty/pull/64) ([highb](https://github.com/highb)) -- Bump faraday dependency for Ruby 2.7 compatibility [\#62](https://github.com/puppetlabs/vmfloaty/pull/62) ([nicklewis](https://github.com/nicklewis)) -- SSH Command respects ABS now and tests should fail if the API changes… [\#61](https://github.com/puppetlabs/vmfloaty/pull/61) ([mikkergimenez](https://github.com/mikkergimenez)) -- \(QENG-7604\) Add support for Job IDs to ABS delete [\#60](https://github.com/puppetlabs/vmfloaty/pull/60) ([highb](https://github.com/highb)) -- Bump version.rb to 0.9.1 [\#59](https://github.com/puppetlabs/vmfloaty/pull/59) ([highb](https://github.com/highb)) -- Fix error with delete command for vmpooler and nspooler [\#58](https://github.com/puppetlabs/vmfloaty/pull/58) ([mikkergimenez](https://github.com/mikkergimenez)) - -## [v0.9.0](https://github.com/puppetlabs/vmfloaty/tree/v0.9.0) (2019-12-17) - -[Full Changelog](https://github.com/puppetlabs/vmfloaty/compare/v0.8.2...v0.9.0) - -**Implemented enhancements:** - -- Add abs vm get [\#53](https://github.com/puppetlabs/vmfloaty/pull/53) ([mikkergimenez](https://github.com/mikkergimenez)) - -**Fixed bugs:** - -- vmfloaty reports an error on latest API version output [\#48](https://github.com/puppetlabs/vmfloaty/issues/48) - -**Merged pull requests:** - -- ABS will sometimes return null values in the /status/queue endpoint [\#57](https://github.com/puppetlabs/vmfloaty/pull/57) ([mikkergimenez](https://github.com/mikkergimenez)) -- Minor version bump to 0.9.0 [\#56](https://github.com/puppetlabs/vmfloaty/pull/56) ([highb](https://github.com/highb)) -- Update pooler provider to throw an exception if the API returns non-OK [\#55](https://github.com/puppetlabs/vmfloaty/pull/55) ([highb](https://github.com/highb)) -- Update Faraday to 0.15, remove unnecessary headers [\#54](https://github.com/puppetlabs/vmfloaty/pull/54) ([highb](https://github.com/highb)) -- change urls in docs to use example.net/.com [\#50](https://github.com/puppetlabs/vmfloaty/pull/50) ([steveax](https://github.com/steveax)) -- Rubocop cleanup [\#49](https://github.com/puppetlabs/vmfloaty/pull/49) ([rodjek](https://github.com/rodjek)) - -## [v0.8.2](https://github.com/puppetlabs/vmfloaty/tree/v0.8.2) (2018-01-05) - -[Full Changelog](https://github.com/puppetlabs/vmfloaty/compare/v0.8.1...v0.8.2) - -**Merged pull requests:** - -- 🎂🎂🎂 Add --json option for `floaty get` [\#47](https://github.com/puppetlabs/vmfloaty/pull/47) ([nicklewis](https://github.com/nicklewis)) - -## [v0.8.1](https://github.com/puppetlabs/vmfloaty/tree/v0.8.1) (2017-10-24) - -[Full Changelog](https://github.com/puppetlabs/vmfloaty/compare/v0.8.0...v0.8.1) - -**Merged pull requests:** - -- Bump commander version to clear up deprecation warnings [\#46](https://github.com/puppetlabs/vmfloaty/pull/46) ([highb](https://github.com/highb)) - -## [v0.8.0](https://github.com/puppetlabs/vmfloaty/tree/v0.8.0) (2017-10-13) - -[Full Changelog](https://github.com/puppetlabs/vmfloaty/compare/v0.7.9...v0.8.0) - -**Closed issues:** - -- don't automatically call system pager for help screens [\#20](https://github.com/puppetlabs/vmfloaty/issues/20) - -**Merged pull requests:** - -- Add configuration for multiple pooler services and integration with nspooler [\#45](https://github.com/puppetlabs/vmfloaty/pull/45) ([caseywilliams](https://github.com/caseywilliams)) - -## [v0.7.9](https://github.com/puppetlabs/vmfloaty/tree/v0.7.9) (2017-07-31) - -[Full Changelog](https://github.com/puppetlabs/vmfloaty/compare/v0.7.8...v0.7.9) - -**Closed issues:** - -- Handle when vmfloaty cannot reach vmpooler [\#39](https://github.com/puppetlabs/vmfloaty/issues/39) - -**Merged pull requests:** - -- Add basic bash completion script and framework for others [\#44](https://github.com/puppetlabs/vmfloaty/pull/44) ([scotje](https://github.com/scotje)) -- Developersdevelopersdevelopers [\#43](https://github.com/puppetlabs/vmfloaty/pull/43) ([mckern](https://github.com/mckern)) - -## [v0.7.8](https://github.com/puppetlabs/vmfloaty/tree/v0.7.8) (2016-12-20) - -[Full Changelog](https://github.com/puppetlabs/vmfloaty/compare/v0.7.7...v0.7.8) - -## [v0.7.7](https://github.com/puppetlabs/vmfloaty/tree/v0.7.7) (2016-12-14) - -[Full Changelog](https://github.com/puppetlabs/vmfloaty/compare/v0.7.6...v0.7.7) - -## [v0.7.6](https://github.com/puppetlabs/vmfloaty/tree/v0.7.6) (2016-12-09) - -[Full Changelog](https://github.com/puppetlabs/vmfloaty/compare/v0.7.5...v0.7.6) - -**Closed issues:** - -- Improve the help text for floaty commands [\#41](https://github.com/puppetlabs/vmfloaty/issues/41) -- Require force flag for pool requests larger than 5? [\#40](https://github.com/puppetlabs/vmfloaty/issues/40) - -## [v0.7.5](https://github.com/puppetlabs/vmfloaty/tree/v0.7.5) (2016-12-06) - -[Full Changelog](https://github.com/puppetlabs/vmfloaty/compare/1f86113243eb2e898b21c29892c05477e3487d2d...v0.7.5) - -**Implemented enhancements:** - -- Improve how to specify number of vms in get request [\#8](https://github.com/puppetlabs/vmfloaty/issues/8) -- Improve output from commands [\#3](https://github.com/puppetlabs/vmfloaty/issues/3) - -**Fixed bugs:** - -- floaty snapshot fails to authenticate [\#4](https://github.com/puppetlabs/vmfloaty/issues/4) - -**Closed issues:** - -- floaty snapshot should warn users about how long it takes to get snapshot [\#37](https://github.com/puppetlabs/vmfloaty/issues/37) -- floaty modify should allow to make changes on more than one machine [\#36](https://github.com/puppetlabs/vmfloaty/issues/36) -- Pooler.modify raises exception if Token is nil [\#34](https://github.com/puppetlabs/vmfloaty/issues/34) -- Improve error handling in Pooler and Auth classes [\#33](https://github.com/puppetlabs/vmfloaty/issues/33) -- Handle vmpooler responses when token is invalid in Pooler class [\#32](https://github.com/puppetlabs/vmfloaty/issues/32) -- Misuse of 'floaty revert ...' seems to create a new snapshot [\#31](https://github.com/puppetlabs/vmfloaty/issues/31) -- Test [\#30](https://github.com/puppetlabs/vmfloaty/issues/30) -- Don't system exit in Auth class [\#29](https://github.com/puppetlabs/vmfloaty/issues/29) -- Add flag to auto-ssh into a newly created \(single\) VM [\#28](https://github.com/puppetlabs/vmfloaty/issues/28) -- Handle vmpooler URL key that doesn't have 'https' [\#27](https://github.com/puppetlabs/vmfloaty/issues/27) -- Abstract vmfloaty cli related errors to command class rather than pooler class [\#26](https://github.com/puppetlabs/vmfloaty/issues/26) -- Don't puts results in `delete` method in Pooler library [\#25](https://github.com/puppetlabs/vmfloaty/issues/25) -- Improve `get` output [\#24](https://github.com/puppetlabs/vmfloaty/issues/24) -- specs don't work [\#22](https://github.com/puppetlabs/vmfloaty/issues/22) -- Add ability to get additional disk space for a running vm [\#19](https://github.com/puppetlabs/vmfloaty/issues/19) -- Have a force option for `delete --all` [\#17](https://github.com/puppetlabs/vmfloaty/issues/17) -- Stop printing json response in library methods [\#14](https://github.com/puppetlabs/vmfloaty/issues/14) -- Stop system exiting in library methods [\#13](https://github.com/puppetlabs/vmfloaty/issues/13) -- List active vms for a given token [\#12](https://github.com/puppetlabs/vmfloaty/issues/12) -- Provide a way to clean up vms obtained by a token [\#11](https://github.com/puppetlabs/vmfloaty/issues/11) -- Allow spaces when passing in vms for commands [\#10](https://github.com/puppetlabs/vmfloaty/issues/10) -- Write Tests for Pooler class [\#9](https://github.com/puppetlabs/vmfloaty/issues/9) -- Document all valid config file keys [\#7](https://github.com/puppetlabs/vmfloaty/issues/7) -- Write up simple "introduction" to using the tool [\#6](https://github.com/puppetlabs/vmfloaty/issues/6) -- Document how to use Pooler class for ruby scripts [\#5](https://github.com/puppetlabs/vmfloaty/issues/5) -- Convert vmfloaty to use latest pooler API [\#1](https://github.com/puppetlabs/vmfloaty/issues/1) - -**Merged pull requests:** - -- Show the status of pools with `floaty status` [\#38](https://github.com/puppetlabs/vmfloaty/pull/38) ([nicklewis](https://github.com/nicklewis)) -- Show tag values in `list --active` [\#23](https://github.com/puppetlabs/vmfloaty/pull/23) ([justinstoller](https://github.com/justinstoller)) -- \(\#19\) Update vmfloaty to expect /api/v1 in URL for disk endpoint [\#21](https://github.com/puppetlabs/vmfloaty/pull/21) ([briancain](https://github.com/briancain)) -- \(\#17\) Add a force option for delete --all [\#18](https://github.com/puppetlabs/vmfloaty/pull/18) ([briancain](https://github.com/briancain)) -- \(\#12\) List active vms for a given token [\#16](https://github.com/puppetlabs/vmfloaty/pull/16) ([briancain](https://github.com/briancain)) -- Cleanup vmfloaty library and command processor [\#15](https://github.com/puppetlabs/vmfloaty/pull/15) ([briancain](https://github.com/briancain)) -- \(\#1\) Update with commander [\#2](https://github.com/puppetlabs/vmfloaty/pull/2) ([briancain](https://github.com/briancain)) - - - -\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)* diff --git a/CODEOWNERS b/CODEOWNERS index e8dffe5..321cebf 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1,3 +1,3 @@ # Set the default code owners -* @puppetlabs/release-engineering +* @puppetlabs/dio @briancain @highb diff --git a/Dockerfile b/Dockerfile index 5c8fd0e..c564fa8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,23 +1,6 @@ -FROM ruby:3.3.5-slim-bullseye +FROM ruby:2.7 -LABEL org.opencontainers.image.authors="@puppetlabs/release-engineering" -LABEL org.opencontainers.image.title="vmfloaty" -LABEL org.opencontainers.image.source=https://github.com/puppetlabs/vmfloaty -LABEL org.opencontainers.image.description="A CLI helper tool for VMPooler" +COPY ./ ./ -RUN apt-get update -qq && apt-get install -y build-essential less make openssh-client - -RUN groupadd --gid 1000 floatygroup \ - && useradd --uid 1000 --gid 1000 -m floatyuser - -USER floatyuser - -WORKDIR /home/floatyuser/app -COPY --chown=floatyuser:floatygroup . . - -RUN gem install bundler \ - && bundle install \ - && gem build vmfloaty.gemspec \ - && gem install vmfloaty*.gem - -ENTRYPOINT [ "floaty" ] +RUN apt-get update && apt-get install -y less +RUN gem install bundler && bundle install && gem build vmfloaty.gemspec && gem install vmfloaty*.gem diff --git a/Gemfile b/Gemfile index 7f70b2e..b8bcc0f 100644 --- a/Gemfile +++ b/Gemfile @@ -4,15 +4,13 @@ source 'https://rubygems.org' gemspec -gem 'rake', require: false +gem 'rake', :require => false group :test do - gem 'simplecov', '~> 0.22.0' - gem 'simplecov-html', '~> 0.13.1' - gem 'simplecov-lcov', '~> 0.8.0' + gem 'coveralls', '~> 0.8.23' gem 'pry' gem 'rb-readline' - gem 'rspec', '~> 3.13.0' - gem 'rubocop', '~> 1.66' - gem 'webmock', '~> 3.23' + gem 'rspec', '~> 3.9.0' + gem 'rubocop', '~> 0.52' + gem 'webmock', '1.21.0' end diff --git a/Gemfile.lock b/Gemfile.lock deleted file mode 100644 index 7d27ddd..0000000 --- a/Gemfile.lock +++ /dev/null @@ -1,125 +0,0 @@ -PATH - remote: . - specs: - vmfloaty (1.8.1) - commander (>= 4.4.3, < 4.7.0) - faraday (~> 1.5, >= 1.5.1) - -GEM - remote: https://rubygems.org/ - specs: - addressable (2.8.6) - public_suffix (>= 2.0.2, < 6.0) - ast (2.4.2) - bigdecimal (3.1.8) - coderay (1.1.3) - commander (4.6.0) - highline (~> 2.0.0) - crack (1.0.0) - bigdecimal - rexml - diff-lcs (1.5.1) - docile (1.4.0) - faraday (1.10.3) - faraday-em_http (~> 1.0) - faraday-em_synchrony (~> 1.0) - faraday-excon (~> 1.1) - faraday-httpclient (~> 1.0) - faraday-multipart (~> 1.0) - faraday-net_http (~> 1.0) - faraday-net_http_persistent (~> 1.0) - faraday-patron (~> 1.0) - faraday-rack (~> 1.0) - faraday-retry (~> 1.0) - ruby2_keywords (>= 0.0.4) - faraday-em_http (1.0.0) - faraday-em_synchrony (1.0.0) - faraday-excon (1.1.0) - faraday-httpclient (1.0.1) - faraday-multipart (1.0.4) - multipart-post (~> 2) - faraday-net_http (1.0.1) - faraday-net_http_persistent (1.2.0) - faraday-patron (1.0.0) - faraday-rack (1.0.0) - faraday-retry (1.0.3) - hashdiff (1.1.0) - highline (2.0.3) - json (2.7.2) - language_server-protocol (3.17.0.3) - method_source (1.0.0) - multipart-post (2.3.0) - parallel (1.26.3) - parser (3.3.5.0) - ast (~> 2.4.1) - racc - pry (0.14.2) - coderay (~> 1.1) - method_source (~> 1.0) - public_suffix (5.0.5) - racc (1.8.1) - rainbow (3.1.1) - rake (13.2.1) - rb-readline (0.5.5) - regexp_parser (2.9.2) - rexml (3.3.6) - strscan - rspec (3.13.0) - rspec-core (~> 3.13.0) - rspec-expectations (~> 3.13.0) - rspec-mocks (~> 3.13.0) - rspec-core (3.13.0) - rspec-support (~> 3.13.0) - rspec-expectations (3.13.0) - diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.13.0) - rspec-mocks (3.13.0) - diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.13.0) - rspec-support (3.13.0) - rubocop (1.66.1) - json (~> 2.3) - language_server-protocol (>= 3.17.0) - parallel (~> 1.10) - parser (>= 3.3.0.2) - rainbow (>= 2.2.2, < 4.0) - regexp_parser (>= 2.4, < 3.0) - rubocop-ast (>= 1.32.2, < 2.0) - ruby-progressbar (~> 1.7) - unicode-display_width (>= 2.4.0, < 3.0) - rubocop-ast (1.32.3) - parser (>= 3.3.1.0) - ruby-progressbar (1.13.0) - ruby2_keywords (0.0.5) - simplecov (0.22.0) - docile (~> 1.1) - simplecov-html (~> 0.11) - simplecov_json_formatter (~> 0.1) - simplecov-html (0.13.1) - simplecov-lcov (0.8.0) - simplecov_json_formatter (0.1.4) - strscan (3.1.0) - unicode-display_width (2.5.0) - webmock (3.23.1) - addressable (>= 2.8.0) - crack (>= 0.3.2) - hashdiff (>= 0.4.0, < 2.0.0) - -PLATFORMS - aarch64-linux - x86_64-linux - -DEPENDENCIES - pry - rake - rb-readline - rspec (~> 3.13.0) - rubocop (~> 1.66) - simplecov (~> 0.22.0) - simplecov-html (~> 0.13.1) - simplecov-lcov (~> 0.8.0) - vmfloaty! - webmock (~> 3.23) - -BUNDLED WITH - 2.4.8 diff --git a/README.md b/README.md index dfc22f9..54e246e 100644 --- a/README.md +++ b/README.md @@ -1,48 +1,36 @@ # vmfloaty [![Gem Version](https://badge.fury.io/rb/vmfloaty.svg)](https://badge.fury.io/rb/vmfloaty) -[![Test](https://github.com/puppetlabs/vmfloaty/actions/workflows/test.yml/badge.svg)](https://github.com/puppetlabs/vmfloaty/actions/workflows/test.yml) +[![Build Status](https://travis-ci.com/puppetlabs/vmfloaty.svg?branch=master)](https://travis-ci.com/puppetlabs/vmfloaty) +[![Coverage Status](https://coveralls.io/repos/github/puppetlabs/vmfloaty/badge.svg?branch=master)](https://coveralls.io/github/puppetlabs/vmfloaty?branch=master) +[![Dependabot Status](https://api.dependabot.com/badges/status?host=github&repo=puppetlabs/vmfloaty)](https://dependabot.com) -A CLI helper tool for [Puppet's VMPooler](https://github.com/puppetlabs/vmpooler) to help you stay afloat. +A CLI helper tool for [Puppet's vmpooler](https://github.com/puppetlabs/vmpooler) to help you stay afloat. ![float image](float.jpg) -- [vmfloaty](#vmfloaty) - - [Install](#install) - - [Ruby](#ruby) - - [Docker](#docker) - - [Usage](#usage) - - [Example workflow](#example-workflow) - - [vmfloaty dotfile](#vmfloaty-dotfile) - - [Basic configuration](#basic-configuration) - - [Using multiple services](#using-multiple-services) - - [Using backends besides VMPooler](#using-backends-besides-vmpooler) - - [Valid config keys](#valid-config-keys) - - [Tab Completion](#tab-completion) - - [VMPooler API](#vmpooler-api) - - [Using the Pooler class](#using-the-pooler-class) - - [Example Projects](#example-projects) - - [Contributing](#contributing) - - [Code Reviews](#code-reviews) - - [Releasing](#releasing) - - [Special thanks](#special-thanks) +- [Install](#install) +- [Usage](#usage) + - [Example workflow](#example-workflow) + - [vmfloaty dotfile](#vmfloaty-dotfile) + - [Basic configuration](#basic-configuration) + - [Using multiple services](#using-multiple-services) + - [Using backends besides VMPooler](#using-backends-besides-vmpooler) + - [Valid config keys](#valid-config-keys) + - [Tab Completion](#tab-completion) +- [vmpooler API](#vmpooler-api) +- [Using the Pooler class](#using-the-pooler-class) + - [Example Projects](#example-projects) +- [Special thanks](#special-thanks) ## Install -### Ruby - Grab the latest from ruby gems... ```bash gem install vmfloaty ``` -### Docker - -Run the docker image: - -`docker run -it --rm -v ~/.vmfloaty.yml:/home/floatyuser/.vmfloaty.yml ghcr.io/puppetlabs/vmfloaty --help` - ## Usage ```plain @@ -53,7 +41,7 @@ $ floaty --help DESCRIPTION: - A CLI helper tool for Puppet's VMPooler to help you stay afloat + A CLI helper tool for Puppet's vmpooler to help you stay afloat COMMANDS: @@ -163,13 +151,13 @@ There is also tab completion for zsh: source $(floaty completion --shell zsh) ``` -## VMPooler API +## vmpooler API -This cli tool uses the [VMPooler API](https://github.com/puppetlabs/vmpooler/blob/master/API.md). +This cli tool uses the [vmpooler API](https://github.com/puppetlabs/vmpooler/blob/master/API.md). ## Using the Pooler class -vmfloaty providers a `Pooler` class that gives users the ability to make requests to VMPooler without having to write their own requests. It also provides an `Auth` class for managing VMPooler tokens within your application. +vmfloaty providers a `Pooler` class that gives users the ability to make requests to vmpooler without having to write their own requests. It also provides an `Auth` class for managing vmpooler tokens within your application. ### Example Projects @@ -178,23 +166,6 @@ vmfloaty providers a `Pooler` class that gives users the ability to make request - [Brian Cain: vagrant-vmpooler](https://github.com/briancain/vagrant-vmpooler) - Use Vagrant to manage your vmpooler instances -## Contributing - -PR's are welcome! We always love to see how others think this tool can be made better. - -### Code Reviews - -Please wait for multiple code owners to sign off on any notable change. - -## Releasing - -Follow these steps to publish a new GitHub release, build and push the gem to , and build and push a Docker Image to GitHub Container Registry: - -1. Bump the "VERSION" in `lib/vmfloaty/version.rb` appropriately based on changes in `CHANGELOG.md` since the last release. -2. Run `./release-prep` to update `Gemfile.lock` and `CHANGELOG.md`. -3. Commit and push changes to a new branch, then open a pull request against `main` and be sure to add the "maintenance" label. -4. After the pull request is approved and merged, then navigate to --> Run workflow --> select "main" branch --> Run workflow. This will publish a GitHub release, build and push the gem to RubyGems, and build and push a Docker Image to GitHub Container Registry. - ## Special thanks Special thanks to [Brian Cain](https://github.com/briancain) as he is the original author of vmfloaty! Vast amounts of this code exist thanks to his efforts. diff --git a/Rakefile b/Rakefile index cdd6c8f..bde93cf 100644 --- a/Rakefile +++ b/Rakefile @@ -28,4 +28,4 @@ RuboCop::RakeTask.new(:rubocop) do |task| end # Default task is to run the unit tests -task default: :spec +task :default => :spec diff --git a/lib/vmfloaty.rb b/lib/vmfloaty.rb index 3c6bbec..7d015f3 100644 --- a/lib/vmfloaty.rb +++ b/lib/vmfloaty.rb @@ -2,6 +2,7 @@ require 'rubygems' require 'commander' +require 'colorize' require 'json' require 'pp' require 'uri' @@ -19,8 +20,7 @@ class Vmfloaty def run # rubocop:disable Metrics/AbcSize program :version, Vmfloaty::VERSION - program :description, - "A CLI helper tool for Puppet's vmpooler to help you stay afloat.\n\nConfiguration may be placed in a ~/.vmfloaty.yml file." + program :description, "A CLI helper tool for Puppet's vmpooler to help you stay afloat.\n\nConfiguration may be placed in a ~/.vmfloaty.yml file." config = Conf.read_config @@ -39,11 +39,8 @@ class Vmfloaty c.option '--force', 'Forces vmfloaty to get requested vms' c.option '--json', 'Prints retrieved vms in JSON format' c.option '--ondemand', 'Requested vms are provisioned upon receival of the request, tracked by a request ID' - c.option '--continue STRING', String, 'resume polling ABS for job_id, for use when the cli was interrupted' - c.option '--loglevel STRING', String, 'the log level to use (debug, info, error)' c.action do |args, options| verbose = options.verbose || config['verbose'] - FloatyLogger.setlevel = options.loglevel if options.loglevel service = Service.new(options, config) use_token = !options.notoken force = options.force @@ -55,11 +52,6 @@ class Vmfloaty os_types = Utils.generate_os_hash(args) - if os_types.empty? - FloatyLogger.error 'No operating systems provided to obtain. See `floaty get --help` for more information on how to get VMs.' - exit 1 - end - max_pool_request = 5 large_pool_requests = os_types.select { |_, v| v > max_pool_request } if !large_pool_requests.empty? && !force @@ -68,7 +60,12 @@ class Vmfloaty exit 1 end - response = service.retrieve(verbose, os_types, use_token, options.ondemand, options.continue) + if os_types.empty? + FloatyLogger.error 'No operating systems provided to obtain. See `floaty get --help` for more information on how to get VMs.' + exit 1 + end + + response = service.retrieve(verbose, os_types, use_token, options.ondemand) request_id = response['request_id'] if options.ondemand response = service.wait_for_request(verbose, request_id) if options.ondemand @@ -95,22 +92,20 @@ class Vmfloaty c.option '--token STRING', String, 'Token for pooler service' c.option '--url STRING', String, 'URL of pooler service' c.option '--user STRING', String, 'User to authenticate with' - c.option '--loglevel STRING', String, 'the log level to use (debug, info, error)' c.action do |args, options| verbose = options.verbose || config['verbose'] - FloatyLogger.setlevel = options.loglevel if options.loglevel service = Service.new(options, config) filter = args[0] if options.active # list active vms - running_vms = if service.type == 'ABS' - # this is actually job_ids - service.list_active_job_ids(verbose, service.url, service.user) - else - service.list_active(verbose) - end + if service.type == "ABS" + # this is actually job_ids + running_vms = service.list_active_job_ids(verbose, service.url, service.user) + else + running_vms = service.list_active(verbose) + end host = URI.parse(service.url).host if running_vms.empty? if options.json @@ -118,15 +113,17 @@ class Vmfloaty else FloatyLogger.info "You have no running VMs on #{host}" end - elsif options.json - puts Utils.get_host_data(verbose, service, running_vms).to_json - elsif options.hostnameonly - Utils.get_host_data(verbose, service, running_vms).each do |hostname, host_data| - Utils.print_fqdn_for_host(service, hostname, host_data) - end else - puts "Your VMs on #{host}:" - Utils.pretty_print_hosts(verbose, service, running_vms) + if options.json + puts Utils.get_host_data(verbose, service, running_vms).to_json + elsif options.hostnameonly + Utils.get_host_data(verbose, service, running_vms).each do |hostname, host_data| + Utils.print_fqdn_for_host(service, hostname, host_data) + end + else + puts "Your VMs on #{host}:" + Utils.pretty_print_hosts(verbose, service, running_vms) + end end else # list available vms from pooler @@ -158,8 +155,7 @@ class Vmfloaty c.syntax = 'floaty modify hostname [options]' c.summary = 'Modify a VM\'s tags, time to live, disk space, or reservation reason' c.description = 'This command makes modifications to the virtual machines state in the pooler service. You can either append tags to the vm, increase how long it stays active for, or increase the amount of disk space.' - c.example 'Modifies myhost1 to have a TTL of 12 hours and adds a custom tag', - 'floaty modify myhost1 --lifetime 12 --url https://myurl --token mytokenstring --tags \'{"tag":"myvalue"}\'' + c.example 'Modifies myhost1 to have a TTL of 12 hours and adds a custom tag', 'floaty modify myhost1 --lifetime 12 --url https://myurl --token mytokenstring --tags \'{"tag":"myvalue"}\'' c.option '--verbose', 'Enables verbose output' c.option '--service STRING', String, 'Configured pooler service name' c.option '--url STRING', String, 'URL of pooler service' @@ -180,18 +176,18 @@ class Vmfloaty exit 1 end running_vms = - if modify_all - service.list_active(verbose) - else - hostname.split(',') - end + if modify_all + service.list_active(verbose) + else + hostname.split(',') + end tags = options.tags ? JSON.parse(options.tags) : nil modify_hash = { - lifetime: options.lifetime, - disk: options.disk, - tags: tags, - reason: options.reason + :lifetime => options.lifetime, + :disk => options.disk, + :tags => tags, + :reason => options.reason, } modify_hash.delete_if { |_, value| value.nil? } @@ -199,10 +195,12 @@ class Vmfloaty ok = true modified_hash = {} running_vms.each do |vm| - modified_hash[vm] = service.modify(verbose, vm, modify_hash) - rescue ModifyError => e - FloatyLogger.error e - ok = false + begin + modified_hash[vm] = service.modify(verbose, vm, modify_hash) + rescue ModifyError => e + FloatyLogger.error e + ok = false + end end if ok if modify_all @@ -231,11 +229,8 @@ class Vmfloaty c.option '--token STRING', String, 'Token for pooler service' c.option '--url STRING', String, 'URL of pooler service' c.option '--user STRING', String, 'User to authenticate with' - c.option '--loglevel STRING', String, 'the log level to use (debug, info, error)' c.action do |args, options| verbose = options.verbose || config['verbose'] - FloatyLogger.setlevel = options.loglevel if options.loglevel - service = Service.new(options, config) hostnames = args[0] delete_all = options.all @@ -245,17 +240,17 @@ class Vmfloaty successes = [] if delete_all - running_vms = if service.type == 'ABS' - # this is actually job_ids - service.list_active_job_ids(verbose, service.url, service.user) - else - service.list_active(verbose) - end + if service.type == "ABS" + # this is actually job_ids + running_vms = service.list_active_job_ids(verbose, service.url, service.user) + else + running_vms = service.list_active(verbose) + end if running_vms.empty? if options.json puts {}.to_json else - FloatyLogger.info 'You have no running VMs.' + FloatyLogger.info "You have no running VMs." end else confirmed = true @@ -319,8 +314,7 @@ class Vmfloaty c.syntax = 'floaty snapshot hostname [options]' c.summary = 'Takes a snapshot of a given vm' c.description = 'Will request a snapshot be taken of the given hostname in the pooler service. This command is known to take a while depending on how much load is on the pooler service.' - c.example 'Takes a snapshot for a given host', - 'floaty snapshot myvm.example.com --url http://vmpooler.example.com --token a9znth9dn01t416hrguu56ze37t790bl' + c.example 'Takes a snapshot for a given host', 'floaty snapshot myvm.example.com --url http://vmpooler.example.com --token a9znth9dn01t416hrguu56ze37t790bl' c.option '--verbose', 'Enables verbose output' c.option '--service STRING', String, 'Configured pooler service name' c.option '--url STRING', String, 'URL of pooler service' @@ -346,8 +340,7 @@ class Vmfloaty c.syntax = 'floaty revert hostname snapshot [options]' c.summary = 'Reverts a vm to a specified snapshot' c.description = 'Given a snapshot SHA, vmfloaty will request a revert to the pooler service to go back to a previous snapshot.' - c.example 'Reverts to a snapshot for a given host', - 'floaty revert myvm.example.com n4eb4kdtp7rwv4x158366vd9jhac8btq --url http://vmpooler.example.com --token a9znth9dn01t416hrguu56ze37t790bl' + c.example 'Reverts to a snapshot for a given host', 'floaty revert myvm.example.com n4eb4kdtp7rwv4x158366vd9jhac8btq --url http://vmpooler.example.com --token a9znth9dn01t416hrguu56ze37t790bl' c.option '--verbose', 'Enables verbose output' c.option '--service STRING', String, 'Configured pooler service name' c.option '--url STRING', String, 'URL of pooler service' @@ -359,9 +352,7 @@ class Vmfloaty hostname = args[0] snapshot_sha = args[1] || options.snapshot - if args[1] && options.snapshot - FloatyLogger.info "Two snapshot arguments were given....using snapshot #{snapshot_sha}" - end + FloatyLogger.info "Two snapshot arguments were given....using snapshot #{snapshot_sha}" if args[1] && options.snapshot begin revert_req = service.revert(verbose, hostname, snapshot_sha) @@ -383,10 +374,8 @@ class Vmfloaty c.option '--service STRING', String, 'Configured pooler service name' c.option '--url STRING', String, 'URL of pooler service' c.option '--json', 'Prints status in JSON format' - c.option '--loglevel STRING', String, 'the log level to use (debug, info, error)' c.action do |_, options| verbose = options.verbose || config['verbose'] - FloatyLogger.setlevel = options.loglevel if options.loglevel service = Service.new(options, config) if options.json pp service.status(verbose) @@ -468,8 +457,6 @@ class Vmfloaty c.option '--user STRING', String, 'User to authenticate with' c.option '--token STRING', String, 'Token for pooler service' c.option '--notoken', 'Makes a request without a token' - c.option '--priority STRING', 'Priority for supported backends(ABS) (High(1), Medium(2), Low(3))' - c.option '--ondemand', 'Requested vms are provisioned upon receival of the request, tracked by a request ID' c.action do |args, options| verbose = options.verbose || config['verbose'] service = Service.new(options, config) @@ -484,7 +471,7 @@ class Vmfloaty FloatyLogger.info "Can't ssh to multiple hosts; Using #{host_os} only..." if args.length > 1 - service.ssh(verbose, host_os, use_token, options.ondemand) + service.ssh(verbose, host_os, use_token) exit 0 end end @@ -522,7 +509,7 @@ class Vmfloaty c.example 'Print a list of the valid service types', 'floaty service types' c.example 'Print a sample config file with multiple services', 'floaty service examples' c.example 'list vms from the service named "nspooler-prod"', 'floaty list --service nspooler-prod' - c.action do |args, _options| + c.action do |args, options| action = args.first example_config = Utils.strip_heredoc(<<-CONFIG) diff --git a/lib/vmfloaty/abs.rb b/lib/vmfloaty/abs.rb index e6769e0..873a0e0 100644 --- a/lib/vmfloaty/abs.rb +++ b/lib/vmfloaty/abs.rb @@ -53,10 +53,10 @@ class ABS def self.list_active(verbose, url, _token, user) hosts = [] get_active_requests(verbose, url, user).each do |req_hash| - next unless req_hash.key?('allocated_resources') - - req_hash['allocated_resources'].each do |onehost| - hosts.push(onehost['hostname']) + if req_hash.key?('allocated_resources') + req_hash['allocated_resources'].each do |onehost| + hosts.push(onehost['hostname']) + end end end @@ -116,7 +116,7 @@ class ABS ret_status = {} hosts.each do |host| ret_status[host] = { - 'ok' => false + 'ok' => false, } end @@ -132,7 +132,7 @@ class ABS if hosts.include? vm_name['hostname'] if all_job_resources_accounted_for(req_hash['allocated_resources'], hosts) ret_status[vm_name['hostname']] = { - 'ok' => true + 'ok' => true, } jobs_to_delete.push(req_hash) else @@ -147,7 +147,7 @@ class ABS jobs_to_delete.each do |job| req_obj = { 'job_id' => job['request']['job']['id'], - 'hosts' => job['allocated_resources'] + 'hosts' => job['allocated_resources'], } FloatyLogger.info "Deleting #{req_obj}" if verbose @@ -172,11 +172,11 @@ class ABS res_body = JSON.parse(res.body) if res_body.key?('vmpooler_platforms') os_list << '*** VMPOOLER Pools ***' - os_list += if res_body['vmpooler_platforms'].is_a?(String) - JSON.parse(res_body['vmpooler_platforms']) # legacy ABS had another JSON string always-be-scheduling/pull/306 - else - res_body['vmpooler_platforms'] - end + if res_body['vmpooler_platforms'].is_a?(String) + os_list += JSON.parse(res_body['vmpooler_platforms']) # legacy ABS had another JSON string always-be-scheduling/pull/306 + else + os_list += res_body['vmpooler_platforms'] + end end end @@ -200,11 +200,11 @@ class ABS if res_body.key?('nspooler_platforms') os_list << '' os_list << '*** NSPOOLER Pools ***' - os_list += if res_body['nspooler_platforms'].is_a?(String) - JSON.parse(res_body['nspooler_platforms']) # legacy ABS had another JSON string always-be-scheduling/pull/306 - else - res_body['nspooler_platforms'] - end + if res_body['nspooler_platforms'].is_a?(String) + os_list += JSON.parse(res_body['nspooler_platforms']) # legacy ABS had another JSON string always-be-scheduling/pull/306 + else + os_list += res_body['nspooler_platforms'] + end end end @@ -214,11 +214,11 @@ class ABS if res_body.key?('aws_platforms') os_list << '' os_list << '*** AWS Pools ***' - os_list += if res_body['aws_platforms'].is_a?(String) - JSON.parse(res_body['aws_platforms']) # legacy ABS had another JSON string always-be-scheduling/pull/306 - else - res_body['aws_platforms'] - end + if res_body['aws_platforms'].is_a?(String) + os_list += JSON.parse(res_body['aws_platforms']) # legacy ABS had another JSON string always-be-scheduling/pull/306 + else + os_list += res_body['aws_platforms'] + end end end @@ -228,7 +228,7 @@ class ABS end # Retrieve an OS from ABS. - def self.retrieve(verbose, os_types, token, url, user, config, _ondemand = nil, continue = nil) + def self.retrieve(verbose, os_types, token, url, user, config, _ondemand = nil) # # Contents of post must be like: # @@ -248,20 +248,15 @@ class ABS conn = Http.get_conn(verbose, supported_abs_url(url)) conn.headers['X-AUTH-TOKEN'] = token if token - saved_job_id = if continue.nil? - "#{user}-#{DateTime.now.strftime('%Q')}" - else - continue - end - + saved_job_id = user + "-" + DateTime.now.strftime('%Q') req_obj = { - resources: os_types, - job: { - id: saved_job_id, - tags: { - user: user - } - } + :resources => os_types, + :job => { + :id => saved_job_id, + :tags => { + :user => user, + }, + }, } if config['vmpooler_fallback'] # optional and not available as cli flag @@ -271,12 +266,11 @@ class ABS end if config['priority'] - req_obj[:priority] = case config['priority'] - when 'high' + req_obj[:priority] = if config['priority'] == 'high' 1 - when 'medium' + elsif config['priority'] == 'medium' 2 - when 'low' + elsif config['priority'] == 'low' 3 else config['priority'].to_i @@ -287,26 +281,26 @@ class ABS # os_string = os_type.map { |os, num| Array(os) * num }.flatten.join('+') # raise MissingParamError, 'No operating systems provided to obtain.' if os_string.empty? - FloatyLogger.info "Requesting VMs with job_id: #{saved_job_id} Will retry for up to an hour." + FloatyLogger.info "Requesting VMs with job_id: #{saved_job_id}. Will retry for up to an hour." res = conn.post 'request', req_obj.to_json retries = 360 - status = validate_queue_status_response(res.status, res.body, 'Initial request', verbose) + validate_queue_status_response(res.status, res.body, "Initial request", verbose) begin (1..retries).each do |i| - res_body = check_queue(conn, saved_job_id, req_obj, verbose) - return translated(res_body, saved_job_id) if res_body.is_a?(Array) # when we get a response with hostnames + queue_place, res_body = check_queue(conn, saved_job_id, req_obj, verbose) + return translated(res_body, saved_job_id) if res_body sleep_seconds = 10 if i >= 10 sleep_seconds = i if i < 10 - FloatyLogger.info "Waiting #{sleep_seconds}s (x#{i}) #{res_body.strip}" + FloatyLogger.info "Waiting #{sleep_seconds} seconds to check if ABS request has been filled. Queue Position: #{queue_place}... (x#{i})" sleep(sleep_seconds) end rescue SystemExit, Interrupt - FloatyLogger.info "\n\nFloaty interrupted, you can resume polling with\n1) `floaty get [same arguments] and adding the flag --continue #{saved_job_id}` or query the state of the queue via\n2) `floaty query #{saved_job_id}` or delete it via\n3) `floaty delete #{saved_job_id}`" + FloatyLogger.info "\n\nFloaty interrupted, you can query the state of your request via\n1) `floaty query #{saved_job_id}` or delete it via\n2) `floaty delete #{saved_job_id}`" exit 1 end nil @@ -316,10 +310,10 @@ class ABS # We should fix the ABS API to be more like the vmpooler or nspooler api, but for now # def self.translated(res_body, job_id) - vmpooler_formatted_body = { 'job_id' => job_id } + vmpooler_formatted_body = {'job_id' => job_id} res_body.each do |host| - if vmpooler_formatted_body[host['type']] && vmpooler_formatted_body[host['type']]['hostname'].instance_of?(Array) + if vmpooler_formatted_body[host['type']] && vmpooler_formatted_body[host['type']]['hostname'].class == Array vmpooler_formatted_body[host['type']]['hostname'] << host['hostname'] else vmpooler_formatted_body[host['type']] = { 'hostname' => [host['hostname']] } @@ -330,14 +324,23 @@ class ABS vmpooler_formatted_body end - def self.check_queue(conn, _job_id, req_obj, verbose) + def self.check_queue(conn, job_id, req_obj, verbose) + queue_info_res = conn.get "status/queue/info/#{job_id}" + if valid_json?(queue_info_res.body) + queue_info = JSON.parse(queue_info_res.body) + else + FloatyLogger.warn "Could not parse the status/queue/info/#{job_id}" + return [nil, nil] + end + res = conn.post 'request', req_obj.to_json - status = validate_queue_status_response(res.status, res.body, 'Check queue request', verbose) + validate_queue_status_response(res.status, res.body, "Check queue request", verbose) + unless res.body.empty? || !valid_json?(res.body) res_body = JSON.parse(res.body) - return res_body + return queue_info['queue_place'], res_body end - res.body + [queue_info['queue_place'], nil] end def self.snapshot(_verbose, _url, _hostname, _token) @@ -352,7 +355,7 @@ class ABS res.body == 'OK' end - def self.summary(_verbose, _url) + def self.summary(verbose, url) raise NoMethodError, 'summary is not defined for ABS' end @@ -404,17 +407,17 @@ class ABS def self.valid_json?(json) JSON.parse(json) - true + return true rescue TypeError, JSON::ParserError => e - false + return false end # when missing, adds the required api/v2 in the url def self.supported_abs_url(url) - expected_ending = 'api/v2' - unless url.include?(expected_ending) + expected_ending = "api/v2" + if !url.include?(expected_ending) # add a slash if missing - expected_ending = "/#{expected_ending}" if url[-1] != '/' + expected_ending = "/#{expected_ending}" if url[-1] != "/" url = "#{url}#{expected_ending}" end url diff --git a/lib/vmfloaty/http.rb b/lib/vmfloaty/http.rb index c1f03f6..b1984b8 100644 --- a/lib/vmfloaty/http.rb +++ b/lib/vmfloaty/http.rb @@ -21,11 +21,13 @@ class Http url = "https://#{url}" unless url?(url) - Faraday.new(url: url, ssl: { verify: false }) do |faraday| + conn = Faraday.new(:url => url, :ssl => { :verify => false }) do |faraday| faraday.request :url_encoded faraday.response :logger if verbose faraday.adapter Faraday.default_adapter end + + conn end def self.get_conn_with_auth(verbose, url, user, password) @@ -35,11 +37,13 @@ class Http url = "https://#{url}" unless url?(url) - Faraday.new(url: url, ssl: { verify: false }) do |faraday| + conn = Faraday.new(:url => url, :ssl => { :verify => false }) do |faraday| faraday.request :url_encoded faraday.request :basic_auth, user, password faraday.response :logger if verbose faraday.adapter Faraday.default_adapter end + + conn end end diff --git a/lib/vmfloaty/logger.rb b/lib/vmfloaty/logger.rb index bdc2bb4..d669d78 100644 --- a/lib/vmfloaty/logger.rb +++ b/lib/vmfloaty/logger.rb @@ -1,5 +1,3 @@ -# frozen_string_literal: true - require 'logger' class FloatyLogger < ::Logger @@ -19,25 +17,11 @@ class FloatyLogger < ::Logger FloatyLogger.logger.error msg end - def self.setlevel=(level) - level = level.downcase - case level - when 'debug' - logger.level = ::Logger::DEBUG - when 'info' - logger.level = ::Logger::INFO - when 'error' - logger.level = ::Logger::ERROR - else - error('set loglevel to debug, info or error') - end - end - def initialize - super($stderr) + super(STDERR) self.level = ::Logger::INFO - self.formatter = proc do |_severity, _datetime, _progname, msg| - "#{msg}\n" + self.formatter = proc do |severity, datetime, progname, msg| + "#{msg}\n" end end end diff --git a/lib/vmfloaty/nonstandard_pooler.rb b/lib/vmfloaty/nonstandard_pooler.rb index eb6c6a7..5d755a9 100644 --- a/lib/vmfloaty/nonstandard_pooler.rb +++ b/lib/vmfloaty/nonstandard_pooler.rb @@ -22,7 +22,7 @@ class NonstandardPooler status['reserved_hosts'] || [] end - def self.retrieve(verbose, os_type, token, url, _user, _options, _ondemand = nil, _continue = nil) + def self.retrieve(verbose, os_type, token, url, _user, _options, ondemand = nil) conn = Http.get_conn(verbose, url) conn.headers['X-AUTH-TOKEN'] = token if token @@ -46,8 +46,7 @@ class NonstandardPooler raise TokenError, 'Token provided was nil; Request cannot be made to modify VM' if token.nil? modify_hash.each do |key, _value| - raise ModifyError, "Configured service type does not support modification of #{key}" unless %i[reason - reserved_for_reason].include? key + raise ModifyError, "Configured service type does not support modification of #{key}" unless %i[reason reserved_for_reason].include? key end if modify_hash[:reason] diff --git a/lib/vmfloaty/pooler.rb b/lib/vmfloaty/pooler.rb index 9d47407..fb811cf 100644 --- a/lib/vmfloaty/pooler.rb +++ b/lib/vmfloaty/pooler.rb @@ -12,11 +12,13 @@ class Pooler response = conn.get 'vm' response_body = JSON.parse(response.body) - if os_filter - response_body.select { |i| i[/#{os_filter}/] } - else - response_body - end + hosts = if os_filter + response_body.select { |i| i[/#{os_filter}/] } + else + response_body + end + + hosts end def self.list_active(verbose, url, token, _user) @@ -26,7 +28,7 @@ class Pooler vms end - def self.retrieve(verbose, os_type, token, url, _user, _options, ondemand = nil, _continue = nil) + def self.retrieve(verbose, os_type, token, url, _user, _options, ondemand = nil) # NOTE: # Developers can use `Utils.generate_os_hash` to # generate the os_type param. @@ -48,10 +50,7 @@ class Pooler elsif response.status == 403 raise "HTTP #{response.status}: Failed to obtain VMs from the pooler at #{url}/vm/#{os_string}. Request exceeds the configured per pool maximum. #{res_body}" else - unless ondemand - raise "HTTP #{response.status}: Failed to obtain VMs from the pooler at #{url}/vm/#{os_string}. #{res_body}" - end - + raise "HTTP #{response.status}: Failed to obtain VMs from the pooler at #{url}/vm/#{os_string}. #{res_body}" unless ondemand raise "HTTP #{response.status}: Failed to obtain VMs from the pooler at #{url}/ondemandvm/#{os_string}. #{res_body}" end end @@ -64,7 +63,7 @@ class Pooler FloatyLogger.info "waiting for request #{request_id} to be fulfilled" sleep 5 end - FloatyLogger.info 'The request has been fulfilled' + FloatyLogger.info "The request has been fulfilled" check_ondemandvm(verbose, request_id, url) end @@ -85,9 +84,8 @@ class Pooler def self.modify(verbose, url, hostname, token, modify_hash) raise TokenError, 'Token provided was nil. Request cannot be made to modify vm' if token.nil? - modify_hash.each_key do |key| - raise ModifyError, "Configured service type does not support modification of #{key}." unless %i[tags lifetime - disk].include? key + modify_hash.keys.each do |key| + raise ModifyError, "Configured service type does not support modification of #{key}." unless %i[tags lifetime disk].include? key end conn = Http.get_conn(verbose, url) @@ -122,7 +120,8 @@ class Pooler response = conn.post "vm/#{hostname}/disk/#{disk}" - JSON.parse(response.body) + res_body = JSON.parse(response.body) + res_body end def self.delete(verbose, url, hosts, token, _user) @@ -146,22 +145,26 @@ class Pooler def self.status(verbose, url) conn = Http.get_conn(verbose, url) - response = conn.get 'status' - JSON.parse(response.body) + response = conn.get '/status' + res_body = JSON.parse(response.body) + res_body end def self.summary(verbose, url) conn = Http.get_conn(verbose, url) - response = conn.get 'summary' - JSON.parse(response.body) + response = conn.get '/summary' + res_body = JSON.parse(response.body) + res_body end def self.query(verbose, url, hostname) conn = Http.get_conn(verbose, url) response = conn.get "vm/#{hostname}" - JSON.parse(response.body) + res_body = JSON.parse(response.body) + + res_body end def self.snapshot(verbose, url, hostname, token) @@ -171,7 +174,8 @@ class Pooler conn.headers['X-AUTH-TOKEN'] = token response = conn.post "vm/#{hostname}/snapshot" - JSON.parse(response.body) + res_body = JSON.parse(response.body) + res_body end def self.revert(verbose, url, hostname, token, snapshot_sha) @@ -183,6 +187,7 @@ class Pooler raise "Snapshot SHA provided was nil, could not revert #{hostname}" if snapshot_sha.nil? response = conn.post "vm/#{hostname}/snapshot/#{snapshot_sha}" - JSON.parse(response.body) + res_body = JSON.parse(response.body) + res_body end end diff --git a/lib/vmfloaty/service.rb b/lib/vmfloaty/service.rb index a9e59ba..ee41648 100644 --- a/lib/vmfloaty/service.rb +++ b/lib/vmfloaty/service.rb @@ -39,7 +39,7 @@ class Service def user unless @config['user'] FloatyLogger.info "Enter your #{@config['url']} service username:" - @config['user'] = $stdin.gets.chomp + @config['user'] = STDIN.gets.chomp end @config['user'] end @@ -77,17 +77,17 @@ class Service @service_object.list_active verbose, url, token, user end - def retrieve(verbose, os_types, use_token = true, ondemand = nil, continue = nil) + def retrieve(verbose, os_types, use_token = true, ondemand = nil) FloatyLogger.info 'Requesting a vm without a token...' unless use_token token_value = use_token ? token : nil - @service_object.retrieve verbose, os_types, token_value, url, user, @config, ondemand, continue + @service_object.retrieve verbose, os_types, token_value, url, user, @config, ondemand end def wait_for_request(verbose, requestid) @service_object.wait_for_request verbose, requestid, url end - def ssh(verbose, host_os, use_token = true, ondemand = nil) + def ssh(verbose, host_os, use_token = true) token_value = nil if use_token begin @@ -97,7 +97,7 @@ class Service FloatyLogger.info 'Could not get token... requesting vm without a token anyway...' end end - Ssh.ssh(verbose, self, host_os, token_value, ondemand) + Ssh.ssh(verbose, self, host_os, token_value) end def query(verbose, hostname) @@ -140,8 +140,8 @@ class Service # some methods do not exist for ABS, and if possible should target the Pooler service def maybe_use_vmpooler if @service_object == ABS # this is not an instance - unless silent - FloatyLogger.info 'The service in use is ABS, but the requested method should run against vmpooler directly, using fallback_vmpooler config from ~/.vmfloaty.yml' + if !self.silent + FloatyLogger.info "The service in use is ABS, but the requested method should run against vmpooler directly, using fallback_vmpooler config from ~/.vmfloaty.yml" self.silent = true end diff --git a/lib/vmfloaty/ssh.rb b/lib/vmfloaty/ssh.rb index 582adea..f100b8b 100644 --- a/lib/vmfloaty/ssh.rb +++ b/lib/vmfloaty/ssh.rb @@ -14,45 +14,27 @@ class Ssh nil end - def self.command_string(verbose, service, host_os, use_token, ondemand = nil) + def self.command_string(verbose, service, host_os, use_token) ssh_path = which('ssh') raise 'Could not determine path to ssh' unless ssh_path - os_types = Utils.generate_os_hash([host_os]) + + os_types = {} os_types[host_os] = 1 - response = service.retrieve(verbose, os_types, use_token, ondemand) + response = service.retrieve(verbose, os_types, use_token) raise "Could not get vm from #{service.type}:\n #{response}" unless response['ok'] user = /win/.match?(host_os) ? 'Administrator' : 'root' - if ondemand - requestid = response['request_id'] - service.wait_for_request(verbose, requestid) - hosts = service.check_ondemandvm(verbose, requestid, service.url) - if hosts['domain'].nil? - hostname = hosts[host_os]['hostname'] - hostname = hosts[host_os]['hostname'][0] if hosts[host_os]['hostname'].is_a?(Array) - else - # Provides backwards compatibility with VMPooler API v1 - hostname = "#{hosts[host_os]['hostname']}.#{hosts['domain']}" - hostname = "#{hosts[host_os]['hostname'][0]}.#{hosts['domain']}" if hosts[host_os]['hostname'].is_a?(Array) - end - else - if response['domain'].nil? - hostname = response[host_os]['hostname'] - hostname = response[host_os]['hostname'][0] if response[host_os]['hostname'].is_a?(Array) - else - # Provides backwards compatibility with VMPooler API v1 - hostname = "#{response[host_os]['hostname']}.#{response['domain']}" - hostname = "#{response[host_os]['hostname'][0]}.#{response['domain']}" if response[host_os]['hostname'].is_a?(Array) - end - end + hostname = response[host_os]['hostname'] + hostname = response[host_os]['hostname'][0] if response[host_os]['hostname'].is_a?(Array) + hostname = "#{hostname}.#{response['domain']}" unless hostname.end_with?('puppetlabs.net') "#{ssh_path} #{user}@#{hostname}" end - def self.ssh(verbose, service, host_os, use_token, ondemand) - cmd = command_string(verbose, service, host_os, use_token, ondemand) + def self.ssh(verbose, service, host_os, use_token) + cmd = command_string(verbose, service, host_os, use_token) # TODO: Should this respect more ssh settings? Can it be configured # by users ssh config and does this respect those settings? Kernel.exec(cmd) diff --git a/lib/vmfloaty/utils.rb b/lib/vmfloaty/utils.rb index b393acf..e3408f3 100644 --- a/lib/vmfloaty/utils.rb +++ b/lib/vmfloaty/utils.rb @@ -9,7 +9,7 @@ class Utils # TODO: Takes the json response body from an HTTP GET # request and "pretty prints" it def self.standardize_hostnames(response_body) - # vmpooler api v1 response body example when `floaty get` arguments are `ubuntu-1610-x86_64=2 centos-7-x86_64`: + # vmpooler response body example when `floaty get` arguments are `ubuntu-1610-x86_64=2 centos-7-x86_64`: # { # "ok": true, # "domain": "delivery.mycompany.net", @@ -21,17 +21,6 @@ class Utils # } # } - # vmpooler api v2 response body example when `floaty get` arguments are `ubuntu-1610-x86_64=2 centos-7-x86_64`: - # { - # "ok": true, - # "ubuntu-1610-x86_64": { - # "hostname": ["gdoy8q3nckuob0i.pooler.example.com", "ctnktsd0u11p9tm.pooler.example.com"] - # }, - # "centos-7-x86_64": { - # "hostname": "dlgietfmgeegry2.pooler.example.com" - # } - # } - # nonstandard pooler response body example when `floaty get` arguments are `solaris-11-sparc=2 ubuntu-16.04-power8`: # { # "ok": true, @@ -50,10 +39,7 @@ class Utils # "engine"=>"vmpooler" # } - unless response_body.delete('ok') - raise ArgumentError, - "Bad GET response passed to format_hosts: #{response_body.to_json}" - end + raise ArgumentError, "Bad GET response passed to format_hosts: #{response_body.to_json}" unless response_body.delete('ok') # vmpooler reports the domain separately from the hostname domain = response_body.delete('domain') @@ -64,7 +50,7 @@ class Utils abs_job_id = response_body.delete('job_id') result['job_id'] = abs_job_id unless abs_job_id.nil? - filtered_response_body = response_body.reject { |key, _| %w[request_id ready].include?(key) } + filtered_response_body = response_body.reject { |key, _| key == 'request_id' || key == 'ready' } filtered_response_body.each do |os, value| hostnames = Array(value['hostname']) hostnames.map! { |host| "#{host}.#{domain}" } if domain @@ -109,11 +95,7 @@ class Utils puts abs_hostnames.join("\n") when 'Pooler' - if host_data['domain'].nil? - puts hostname - else - puts "#{hostname}.#{host_data['domain']}" - end + puts "#{hostname}.#{host_data['domain']}" when 'NonstandardPooler' puts host_data['fqdn'] else @@ -124,7 +106,7 @@ class Utils def self.pretty_print_hosts(verbose, service, hostnames = [], print_to_stderr = false, indent = 0) output_target = print_to_stderr ? $stderr : $stdout - fetched_data = get_host_data(verbose, service, hostnames) + fetched_data = self.get_host_data(verbose, service, hostnames) fetched_data.each do |hostname, host_data| case service.type when 'ABS' @@ -134,14 +116,13 @@ class Utils output_target.puts "- [JobID:#{host_data['request']['job']['id']}] <#{host_data['state']}>" host_data['allocated_resources'].each do |allocated_resources, _i| - if (allocated_resources['engine'] == 'vmpooler' || allocated_resources['engine'] == 'ondemand') && service.config['vmpooler_fallback'] + if allocated_resources['engine'] == "vmpooler" && service.config["vmpooler_fallback"] vmpooler_service = service.clone vmpooler_service.silent = true vmpooler_service.maybe_use_vmpooler - pretty_print_hosts(verbose, vmpooler_service, allocated_resources['hostname'].split('.')[0], - print_to_stderr, indent + 2) + self.pretty_print_hosts(verbose, vmpooler_service, allocated_resources['hostname'].split('.')[0], print_to_stderr, indent+2) else - # TODO: we could add more specific metadata for the other services, nspooler and aws + #TODO we could add more specific metadata for the other services, nspooler and aws output_target.puts " - #{allocated_resources['hostname']} (#{allocated_resources['type']})" end end @@ -149,24 +130,12 @@ class Utils tag_pairs = [] tag_pairs = host_data['tags'].map { |key, value| "#{key}: #{value}" } unless host_data['tags'].nil? duration = "#{host_data['running']}/#{host_data['lifetime']} hours" - metadata = [host_data['state'], host_data['template'], duration, *tag_pairs] - # For backwards compatibility with vmpooler api v1 - message = - if host_data['domain'] - "- #{hostname}.#{host_data['domain']} (#{metadata.join(', ')})".gsub(/^/, ' ' * indent) - else - "- #{host_data['fqdn']} (#{metadata.join(', ')})".gsub(/^/, ' ' * indent) - end - - if host_data['state'] && host_data['state'] == 'destroyed' - output_target.puts "- DESTROYED #{hostname}.#{host_data['domain']}".gsub(/^/, ' ' * indent) - else - output_target.puts message - end + metadata = [host_data['template'], duration, *tag_pairs] + output_target.puts "- #{hostname}.#{host_data['domain']} (#{metadata.join(', ')})".gsub(/^/, ' ' * indent) when 'NonstandardPooler' line = "- #{host_data['fqdn']} (#{host_data['os_triple']}" line += ", #{host_data['hours_left_on_reservation']}h remaining" - line += ", reason: #{host_data['reserved_for_reason']}" unless host_data['reserved_for_reason'].nil? || host_data['reserved_for_reason'].empty? + line += ", reason: #{host_data['reserved_for_reason']}" unless host_data['reserved_for_reason'].empty? line += ')' output_target.puts line else @@ -179,26 +148,30 @@ class Utils result = {} hostnames = [hostnames] unless hostnames.is_a? Array hostnames.each do |hostname| - response = service.query(verbose, hostname) - host_data = response[hostname] - if block_given? - yield host_data result - else - case service.type - when 'ABS' - # For ABS, 'hostname' variable is the jobID - result[hostname] = host_data if host_data['state'] == 'allocated' || host_data['state'] == 'filled' - when 'Pooler' - result[hostname] = host_data - when 'NonstandardPooler' - result[hostname] = host_data + begin + response = service.query(verbose, hostname) + host_data = response[hostname] + if block_given? + yield host_data result else - raise "Invalid service type #{service.type}" + case service.type + when 'ABS' + # For ABS, 'hostname' variable is the jobID + if host_data['state'] == 'allocated' || host_data['state'] == 'filled' + result[hostname] = host_data + end + when 'Pooler' + result[hostname] = host_data + when 'NonstandardPooler' + result[hostname] = host_data + else + raise "Invalid service type #{service.type}" + end end + rescue StandardError => e + FloatyLogger.error("Something went wrong while trying to gather information on #{hostname}:") + FloatyLogger.error(e) end - rescue StandardError => e - FloatyLogger.error("Something went wrong while trying to gather information on #{hostname}:") - FloatyLogger.error(e) end result end @@ -214,16 +187,18 @@ class Utils width = pools.keys.map(&:length).max pools.each do |name, pool| - max = pool['max'] - ready = pool['ready'] - pending = pool['pending'] - missing = max - ready - pending - char = 'o' - puts "#{name.ljust(width)} #{(char * ready)}#{(char * pending)}#{(char * missing)}" - rescue StandardError => e - FloatyLogger.error "#{name.ljust(width)} #{e}" + begin + max = pool['max'] + ready = pool['ready'] + pending = pool['pending'] + missing = max - ready - pending + char = 'o' + puts "#{name.ljust(width)} #{(char * ready).green}#{(char * pending).yellow}#{(char * missing).red}" + rescue StandardError => e + FloatyLogger.error "#{name.ljust(width)} #{e.red}" + end end - puts message + puts message.colorize(status_response['status']['ok'] ? :default : :red) when 'NonstandardPooler' pools = status_response pools.delete 'ok' @@ -231,18 +206,20 @@ class Utils width = pools.keys.map(&:length).max pools.each do |name, pool| - max = pool['total_hosts'] - ready = pool['available_hosts'] - pending = pool['pending'] || 0 # not available for nspooler - missing = max - ready - pending - char = 'o' - puts "#{name.ljust(width)} #{(char * ready)}#{(char * pending)}#{(char * missing)}" - rescue StandardError => e - FloatyLogger.error "#{name.ljust(width)} #{e}" + begin + max = pool['total_hosts'] + ready = pool['available_hosts'] + pending = pool['pending'] || 0 # not available for nspooler + missing = max - ready - pending + char = 'o' + puts "#{name.ljust(width)} #{(char * ready).green}#{(char * pending).yellow}#{(char * missing).red}" + rescue StandardError => e + FloatyLogger.error "#{name.ljust(width)} #{e.red}" + end end when 'ABS' FloatyLogger.error 'ABS Not OK' unless status_response - puts 'ABS is OK' if status_response + puts 'ABS is OK'.green if status_response else raise "Invalid service type #{service.type}" end @@ -274,11 +251,11 @@ class Utils def self.get_service_config(config, options) # The top-level url, user, and token values in the config file are treated as defaults service_config = { - 'url' => config['url'], - 'user' => config['user'], + 'url' => config['url'], + 'user' => config['user'], 'token' => config['token'], 'vmpooler_fallback' => config['vmpooler_fallback'], - 'type' => config['type'] || 'vmpooler' + 'type' => config['type'] || 'vmpooler', } if config['services'] @@ -289,10 +266,7 @@ class Utils service_config.merge! values else # If the user provided a service name at the command line, use that service if posible, or fail - unless config['services'][options.service] - raise ArgumentError, - "Could not find a configured service named '#{options.service}' in ~/.vmfloaty.yml" - end + raise ArgumentError, "Could not find a configured service named '#{options.service}' in ~/.vmfloaty.yml" unless config['services'][options.service] # If the service is configured but some values are missing, use the top-level defaults to fill them in service_config.merge! config['services'][options.service] @@ -316,22 +290,22 @@ class Utils config = Conf.read_config # The top-level url, user, and token values in the config file are treated as defaults service_config = { - 'url' => config['url'], - 'user' => config['user'], - 'token' => config['token'], - 'type' => 'vmpooler' + 'url' => config['url'], + 'user' => config['user'], + 'token' => config['token'], + 'type' => 'vmpooler', } # at a minimum, the url needs to be configured if config['services'] && config['services'][vmpooler_fallback] && config['services'][vmpooler_fallback]['url'] # If the service is configured but some values are missing, use the top-level defaults to fill them in service_config.merge! config['services'][vmpooler_fallback] - elsif vmpooler_fallback.nil? - raise ArgumentError, - "The abs service should have a key named 'vmpooler_fallback' in ~/.vmfloaty.yml with a value that points to a vmpooler service name use this format:\nservices:\n myabs:\n url: 'http://abs.com'\n user: 'superman'\n token: 'kryptonite'\n vmpooler_fallback: 'myvmpooler'\n myvmpooler:\n url: 'http://vmpooler.com'\n user: 'superman'\n token: 'kryptonite'" else - raise ArgumentError, - "Could not find a configured service named '#{vmpooler_fallback}' in ~/.vmfloaty.yml use this format:\nservices:\n #{vmpooler_fallback}:\n url: 'http://vmpooler.com'\n user: 'superman'\n token: 'kryptonite'" + if vmpooler_fallback.nil? + raise ArgumentError, "The abs service should have a key named 'vmpooler_fallback' in ~/.vmfloaty.yml with a value that points to a vmpooler service name use this format:\nservices:\n myabs:\n url: 'http://abs.com'\n user: 'superman'\n token: 'kryptonite'\n vmpooler_fallback: 'myvmpooler'\n myvmpooler:\n url: 'http://vmpooler.com'\n user: 'superman'\n token: 'kryptonite'" + else + raise ArgumentError, "Could not find a configured service named '#{vmpooler_fallback}' in ~/.vmfloaty.yml use this format:\nservices:\n #{vmpooler_fallback}:\n url: 'http://vmpooler.com'\n user: 'superman'\n token: 'kryptonite'" + end end service_config diff --git a/lib/vmfloaty/version.rb b/lib/vmfloaty/version.rb index aab63a3..c991fab 100644 --- a/lib/vmfloaty/version.rb +++ b/lib/vmfloaty/version.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true class Vmfloaty - VERSION = '1.8.1' + VERSION = '1.1.1' end + diff --git a/release-prep b/release-prep deleted file mode 100755 index 82ee104..0000000 --- a/release-prep +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash - -# bundle install -docker run -t --rm \ - -v $(pwd):/app \ - $(grep ^FROM ./Dockerfile |cut -d ' ' -f2) \ - /bin/bash -c 'apt-get update -qq && apt-get install -y --no-install-recommends build-essential make openssh-client && cd /app && gem install bundler && bundle install --jobs 3; echo "LOCK_FILE_UPDATE_EXIT_CODE=$?"' - -# Update Changelog -docker run -t --rm -e CHANGELOG_GITHUB_TOKEN -v $(pwd):/usr/local/src/your-app \ - githubchangeloggenerator/github-changelog-generator:1.16.2 \ - github_changelog_generator --future-release $(grep VERSION lib/vmfloaty/version.rb |rev |cut -d "'" -f2 |rev) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 1ed7ef7..e23a554 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,21 +1,12 @@ # frozen_string_literal: true require 'simplecov' -require 'simplecov-lcov' -require 'base64' - -SimpleCov::Formatter::LcovFormatter.config do |c| - c.report_with_single_file = true - c.single_report_path = 'coverage/lcov.info' -end - -SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new( - [ - SimpleCov::Formatter::HTMLFormatter, - SimpleCov::Formatter::LcovFormatter - ] -) +require 'coveralls' +SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new([ + SimpleCov::Formatter::HTMLFormatter, + Coveralls::SimpleCov::Formatter +]) SimpleCov.start do add_filter %r{^/spec/} end @@ -35,19 +26,3 @@ RSpec.configure do |config| config.tty = true config.formatter = :documentation end - -def get_headers(username: nil, password: nil, token: nil, content_type: nil, content_length: nil) - headers = { - 'Accept' => '*/*', - 'Accept-Encoding' => /gzip/, - 'User-Agent' => /Faraday/, - } - if username && password - auth = Base64.encode64("#{username}:#{password}").chomp - headers['Authorization'] = "Basic #{auth}" - end - headers['X-Auth-Token'] = token if token - headers['Content-Type'] = content_type if content_type - headers['Content-Length'] = content_length.to_s if content_length - headers -end \ No newline at end of file diff --git a/spec/vmfloaty/abs/auth_spec.rb b/spec/vmfloaty/abs/auth_spec.rb index ca1aec2..555d6c5 100644 --- a/spec/vmfloaty/abs/auth_spec.rb +++ b/spec/vmfloaty/abs/auth_spec.rb @@ -3,11 +3,7 @@ require 'spec_helper' require_relative '../../../lib/vmfloaty/auth' -user = 'first.last' -pass = 'password' - describe Pooler do - before :each do @abs_url = 'https://abs.example.com/api/v2' end @@ -19,20 +15,18 @@ describe Pooler do end it 'returns a token from abs' do - stub_request(:post, 'https://abs.example.com/api/v2/token') - .with(headers: get_headers(username: user, password: pass, content_length: 0)) - .to_return(status: 200, body: @get_token_response, headers: {}) + stub_request(:post, 'https://first.last:password@abs.example.com/api/v2/token') + .to_return(:status => 200, :body => @get_token_response, :headers => {}) - token = Auth.get_token(false, @abs_url, user, pass) + token = Auth.get_token(false, @abs_url, 'first.last', 'password') expect(token).to eq @token end it 'raises a token error if something goes wrong' do - stub_request(:post, 'https://abs.example.com/api/v2/token') - .with(headers: get_headers(username: user, password: pass, content_length: 0)) - .to_return(status: 500, body: '{"ok":false}', headers: {}) + stub_request(:post, 'https://first.last:password@abs.example.com/api/v2/token') + .to_return(:status => 500, :body => '{"ok":false}', :headers => {}) - expect { Auth.get_token(false, @abs_url, user, pass) }.to raise_error(TokenError) + expect { Auth.get_token(false, @abs_url, 'first.last', 'password') }.to raise_error(TokenError) end end @@ -43,24 +37,21 @@ describe Pooler do end it 'deletes the specified token' do - stub_request(:delete, 'https://abs.example.com/api/v2/token/utpg2i2xswor6h8ttjhu3d47z53yy47y') - .with(headers: get_headers(username: user, password: pass)) - .to_return(status: 200, body: @delete_token_response, headers: {}) + stub_request(:delete, 'https://first.last:password@abs.example.com/api/v2/token/utpg2i2xswor6h8ttjhu3d47z53yy47y') + .to_return(:status => 200, :body => @delete_token_response, :headers => {}) - expect(Auth.delete_token(false, @abs_url, user, pass, - @token)).to eq JSON.parse(@delete_token_response) + expect(Auth.delete_token(false, @abs_url, 'first.last', 'password', @token)).to eq JSON.parse(@delete_token_response) end it 'raises a token error if something goes wrong' do - stub_request(:delete, 'https://abs.example.com/api/v2/token/utpg2i2xswor6h8ttjhu3d47z53yy47y') - .with(headers: get_headers(username: user, password: pass)) - .to_return(status: 500, body: '{"ok":false}', headers: {}) + stub_request(:delete, 'https://first.last:password@abs.example.com/api/v2/token/utpg2i2xswor6h8ttjhu3d47z53yy47y') + .to_return(:status => 500, :body => '{"ok":false}', :headers => {}) - expect { Auth.delete_token(false, @abs_url, user, pass, @token) }.to raise_error(TokenError) + expect { Auth.delete_token(false, @abs_url, 'first.last', 'password', @token) }.to raise_error(TokenError) end it 'raises a token error if no token provided' do - expect { Auth.delete_token(false, @abs_url, user, pass, nil) }.to raise_error(TokenError) + expect { Auth.delete_token(false, @abs_url, 'first.last', 'password', nil) }.to raise_error(TokenError) end end @@ -72,16 +63,16 @@ describe Pooler do it 'checks the status of a token' do stub_request(:get, "#{@abs_url}/token/utpg2i2xswor6h8ttjhu3d47z53yy47y") - .with(headers: get_headers) - .to_return(status: 200, body: @token_status_response, headers: {}) + .with(:headers => { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3' }) + .to_return(:status => 200, :body => @token_status_response, :headers => {}) expect(Auth.token_status(false, @abs_url, @token)).to eq JSON.parse(@token_status_response) end it 'raises a token error if something goes wrong' do stub_request(:get, "#{@abs_url}/token/utpg2i2xswor6h8ttjhu3d47z53yy47y") - .with(headers: get_headers) - .to_return(status: 500, body: '{"ok":false}', headers: {}) + .with(:headers => { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3' }) + .to_return(:status => 500, :body => '{"ok":false}', :headers => {}) expect { Auth.token_status(false, @abs_url, @token) }.to raise_error(TokenError) end diff --git a/spec/vmfloaty/abs_spec.rb b/spec/vmfloaty/abs_spec.rb index 4a66c5c..d6eabfc 100644 --- a/spec/vmfloaty/abs_spec.rb +++ b/spec/vmfloaty/abs_spec.rb @@ -11,12 +11,12 @@ describe ABS do describe '#list' do it 'skips empty platforms and lists aws' do - stub_request(:get, 'http://foo/api/v2/status/platforms/vmpooler') - .to_return(status: 200, body: '', headers: {}) - stub_request(:get, 'http://foo/api/v2/status/platforms/ondemand_vmpooler') - .to_return(status: 200, body: '', headers: {}) - stub_request(:get, 'http://foo/api/v2/status/platforms/nspooler') - .to_return(status: 200, body: '', headers: {}) + stub_request(:get, "http://foo/api/v2/status/platforms/vmpooler"). + to_return(:status => 200, :body => "", :headers => {}) + stub_request(:get, "http://foo/api/v2/status/platforms/ondemand_vmpooler"). + to_return(:status => 200, :body => "", :headers => {}) + stub_request(:get, "http://foo/api/v2/status/platforms/nspooler"). + to_return(:status => 200, :body => "", :headers => {}) body = '{ "aws_platforms": [ "amazon-6-x86_64", @@ -26,55 +26,50 @@ describe ABS do "redhat-8-arm64" ] }' - stub_request(:get, 'http://foo/api/v2/status/platforms/aws') - .to_return(status: 200, body: body, headers: {}) + stub_request(:get, "http://foo/api/v2/status/platforms/aws"). + to_return(:status => 200, :body => body, :headers => {}) - results = ABS.list(false, 'http://foo') - expect(results).to include('amazon-6-x86_64', 'amazon-7-x86_64', 'amazon-7-arm64', 'centos-7-x86-64-west', - 'redhat-8-arm64') + results = ABS.list(false, "http://foo") + + expect(results).to include("amazon-6-x86_64", "amazon-7-x86_64", "amazon-7-arm64", "centos-7-x86-64-west", "redhat-8-arm64") end it 'legacy JSON string, prior to PR 306' do - stub_request(:get, 'http://foo/api/v2/status/platforms/vmpooler') - .to_return(status: 200, body: '', headers: {}) - stub_request(:get, 'http://foo/api/v2/status/platforms/ondemand_vmpooler') - .to_return(status: 200, body: '', headers: {}) - stub_request(:get, 'http://foo/api/v2/status/platforms/nspooler') - .to_return(status: 200, body: '', headers: {}) + stub_request(:get, "http://foo/api/v2/status/platforms/vmpooler"). + to_return(:status => 200, :body => "", :headers => {}) + stub_request(:get, "http://foo/api/v2/status/platforms/ondemand_vmpooler"). + to_return(:status => 200, :body => "", :headers => {}) + stub_request(:get, "http://foo/api/v2/status/platforms/nspooler"). + to_return(:status => 200, :body => "", :headers => {}) body = '{ "aws_platforms": "[\"amazon-6-x86_64\",\"amazon-7-x86_64\",\"amazon-7-arm64\",\"centos-7-x86-64-west\",\"redhat-8-arm64\"]" }' - stub_request(:get, 'http://foo/api/v2/status/platforms/aws') - .to_return(status: 200, body: body, headers: {}) + stub_request(:get, "http://foo/api/v2/status/platforms/aws"). + to_return(:status => 200, :body => body, :headers => {}) - results = ABS.list(false, 'http://foo') + results = ABS.list(false, "http://foo") - expect(results).to include('amazon-6-x86_64', 'amazon-7-x86_64', 'amazon-7-arm64', 'centos-7-x86-64-west', - 'redhat-8-arm64') + expect(results).to include("amazon-6-x86_64", "amazon-7-x86_64", "amazon-7-arm64", "centos-7-x86-64-west", "redhat-8-arm64") end end describe '#format' do it 'returns an hash formatted like a vmpooler return, plus the job_id' do - job_id = 'generated_by_floaty_12345' + job_id = "generated_by_floaty_12345" abs_formatted_response = [ - { 'hostname' => 'aaaaaaaaaaaaaaa.delivery.puppetlabs.net', 'type' => 'centos-7.2-x86_64', - 'engine' => 'vmpooler' }, - { 'hostname' => 'aaaaaaaaaaaaaab.delivery.puppetlabs.net', 'type' => 'centos-7.2-x86_64', - 'engine' => 'vmpooler' }, - { 'hostname' => 'aaaaaaaaaaaaaac.delivery.puppetlabs.net', 'type' => 'ubuntu-7.2-x86_64', - 'engine' => 'vmpooler' } + { 'hostname' => 'aaaaaaaaaaaaaaa.delivery.puppetlabs.net', 'type' => 'centos-7.2-x86_64', 'engine' => 'vmpooler' }, + { 'hostname' => 'aaaaaaaaaaaaaab.delivery.puppetlabs.net', 'type' => 'centos-7.2-x86_64', 'engine' => 'vmpooler' }, + { 'hostname' => 'aaaaaaaaaaaaaac.delivery.puppetlabs.net', 'type' => 'ubuntu-7.2-x86_64', 'engine' => 'vmpooler' }, ] vmpooler_formatted_response = ABS.translated(abs_formatted_response, job_id) vmpooler_formatted_compare = { 'centos-7.2-x86_64' => {}, - 'ubuntu-7.2-x86_64' => {} + 'ubuntu-7.2-x86_64' => {}, } - vmpooler_formatted_compare['centos-7.2-x86_64']['hostname'] = - ['aaaaaaaaaaaaaaa.delivery.puppetlabs.net', 'aaaaaaaaaaaaaab.delivery.puppetlabs.net'] + vmpooler_formatted_compare['centos-7.2-x86_64']['hostname'] = ['aaaaaaaaaaaaaaa.delivery.puppetlabs.net', 'aaaaaaaaaaaaaab.delivery.puppetlabs.net'] vmpooler_formatted_compare['ubuntu-7.2-x86_64']['hostname'] = ['aaaaaaaaaaaaaac.delivery.puppetlabs.net'] vmpooler_formatted_compare['ok'] = true @@ -91,22 +86,22 @@ describe ABS do hosts = ['host1'] allocated_resources = [ { - 'hostname' => 'host1' + 'hostname' => 'host1', }, { - 'hostname' => 'host2' - } + 'hostname' => 'host2', + }, ] expect(ABS.all_job_resources_accounted_for(allocated_resources, hosts)).to eq(false) - hosts = %w[host1 host2] + hosts = ['host1', 'host2'] allocated_resources = [ { - 'hostname' => 'host1' + 'hostname' => 'host1', }, { - 'hostname' => 'host2' - } + 'hostname' => 'host2', + }, ] expect(ABS.all_job_resources_accounted_for(allocated_resources, hosts)).to eq(true) end @@ -131,16 +126,16 @@ describe ABS do it 'will skip a line with a null value returned from abs' do stub_request(:get, 'https://abs.example.com/api/v2/status/queue') - .to_return(status: 200, body: @active_requests_response, headers: {}) + .to_return(:status => 200, :body => @active_requests_response, :headers => {}) ret = ABS.get_active_requests(false, @abs_url, @test_user) expect(ret[0]).to include( 'allocated_resources' => [{ 'hostname' => 'take-this.delivery.puppetlabs.net', - 'type' => 'win-2012r2-x86_64', - 'engine' => 'vmpooler' - }] + 'type' => 'win-2012r2-x86_64', + 'engine' => 'vmpooler', + }], ) end end @@ -152,11 +147,7 @@ describe ABS do [ { "state":"allocated", "last_processed":"2020-01-17 22:29:13 +0000", "allocated_resources":[{"hostname":"craggy-chord.delivery.puppetlabs.net", "type":"centos-7-x86_64", "engine":"vmpooler"}, {"hostname":"visible-revival.delivery.puppetlabs.net", "type":"centos-7-x86_64", "engine":"vmpooler"}], "audit_log":{"2020-01-17 22:28:45 +0000":"Allocated craggy-chord.delivery.puppetlabs.net, visible-revival.delivery.puppetlabs.net for job 1579300120799"}, "request":{"resources":{"centos-7-x86_64":2}, "job":{"id":"1579300120799", "tags":{"user":"test-user"}, "user":"test-user", "time-received":1579300120}, "priority":3}} ]' - @return_request = { - "job_id" => "1579300120799", - "hosts" => [{"hostname"=>"craggy-chord.delivery.puppetlabs.net","type"=>"centos-7-x86_64","engine"=>"vmpooler"}, - {"hostname"=>"visible-revival.delivery.puppetlabs.net","type"=>"centos-7-x86_64","engine"=>"vmpooler"}] - } + @return_request = { '{"job_id":"1579300120799","hosts":{"hostname":"craggy-chord.delivery.puppetlabs.net","type":"centos-7-x86_64","engine":"vmpooler"},{"hostname":"visible-revival.delivery.puppetlabs.net","type":"centos-7-x86_64","engine":"vmpooler"}}'=>true } # rubocop:enable Layout/LineLength @token = 'utpg2i2xswor6h8ttjhu3d47z53yy47y' @test_user = 'test-user' @@ -166,15 +157,15 @@ describe ABS do it 'will delete the whole job' do stub_request(:get, 'https://abs.example.com/api/v2/status/queue') - .to_return(status: 200, body: @active_requests_response, headers: {}) + .to_return(:status => 200, :body => @active_requests_response, :headers => {}) stub_request(:post, 'https://abs.example.com/api/v2/return') - .with(headers: get_headers(content_type: 'application/x-www-form-urlencoded', token: @token), body: @return_request.to_json) - .to_return(status: 200, body: 'OK', headers: {}) + .with(:body => @return_request) + .to_return(:status => 200, :body => 'OK', :headers => {}) ret = ABS.delete(false, @abs_url, @hosts, @token, @test_user) expect(ret).to include( - 'craggy-chord.delivery.puppetlabs.net' => { 'ok' => true }, 'visible-revival.delivery.puppetlabs.net' => { 'ok' => true } + 'craggy-chord.delivery.puppetlabs.net' => { 'ok'=>true }, 'visible-revival.delivery.puppetlabs.net' => { 'ok'=>true }, ) end end diff --git a/spec/vmfloaty/auth_spec.rb b/spec/vmfloaty/auth_spec.rb index 6ce4b77..65cadc4 100644 --- a/spec/vmfloaty/auth_spec.rb +++ b/spec/vmfloaty/auth_spec.rb @@ -3,9 +3,6 @@ require 'spec_helper' require_relative '../../lib/vmfloaty/auth' -user = 'first.last' -pass = 'password' - describe Pooler do before :each do @vmpooler_url = 'https://vmpooler.example.com' @@ -18,20 +15,18 @@ describe Pooler do end it 'returns a token from vmpooler' do - stub_request(:post, 'https://vmpooler.example.com/token') - .with(headers: get_headers(username: user, password: pass, content_length: 0)) - .to_return(status: 200, body: @get_token_response, headers: {}) + stub_request(:post, 'https://first.last:password@vmpooler.example.com/token') + .to_return(:status => 200, :body => @get_token_response, :headers => {}) - token = Auth.get_token(false, @vmpooler_url, user, pass) + token = Auth.get_token(false, @vmpooler_url, 'first.last', 'password') expect(token).to eq @token end it 'raises a token error if something goes wrong' do - stub_request(:post, 'https://vmpooler.example.com/token') - .with(headers: get_headers(username: user, password: pass, content_length: 0)) - .to_return(status: 500, body: '{"ok":false}', headers: {}) + stub_request(:post, 'https://first.last:password@vmpooler.example.com/token') + .to_return(:status => 500, :body => '{"ok":false}', :headers => {}) - expect { Auth.get_token(false, @vmpooler_url, user, pass) }.to raise_error(TokenError) + expect { Auth.get_token(false, @vmpooler_url, 'first.last', 'password') }.to raise_error(TokenError) end end @@ -42,18 +37,15 @@ describe Pooler do end it 'deletes the specified token' do - stub_request(:delete, 'https://vmpooler.example.com/token/utpg2i2xswor6h8ttjhu3d47z53yy47y') - .with(headers: get_headers(username: user, password: pass)) - .to_return(status: 200, body: @delete_token_response, headers: {}) + stub_request(:delete, 'https://first.last:password@vmpooler.example.com/token/utpg2i2xswor6h8ttjhu3d47z53yy47y') + .to_return(:status => 200, :body => @delete_token_response, :headers => {}) - expect(Auth.delete_token(false, @vmpooler_url, user, pass, - @token)).to eq JSON.parse(@delete_token_response) + expect(Auth.delete_token(false, @vmpooler_url, 'first.last', 'password', @token)).to eq JSON.parse(@delete_token_response) end it 'raises a token error if something goes wrong' do - stub_request(:delete, 'https://vmpooler.example.com/token/utpg2i2xswor6h8ttjhu3d47z53yy47y') - .with(headers: get_headers(username: user, password: pass)) - .to_return(status: 500, body: '{"ok":false}', headers: {}) + stub_request(:delete, 'https://first.last:password@vmpooler.example.com/token/utpg2i2xswor6h8ttjhu3d47z53yy47y') + .to_return(:status => 500, :body => '{"ok":false}', :headers => {}) expect { Auth.delete_token(false, @vmpooler_url, 'first.last', 'password', @token) }.to raise_error(TokenError) end @@ -71,16 +63,14 @@ describe Pooler do it 'checks the status of a token' do stub_request(:get, "#{@vmpooler_url}/token/utpg2i2xswor6h8ttjhu3d47z53yy47y") - .with(headers: get_headers) - .to_return(status: 200, body: @token_status_response, headers: {}) + .to_return(:status => 200, :body => @token_status_response, :headers => {}) expect(Auth.token_status(false, @vmpooler_url, @token)).to eq JSON.parse(@token_status_response) end it 'raises a token error if something goes wrong' do stub_request(:get, "#{@vmpooler_url}/token/utpg2i2xswor6h8ttjhu3d47z53yy47y") - .with(headers: get_headers) - .to_return(status: 500, body: '{"ok":false}', headers: {}) + .to_return(:status => 500, :body => '{"ok":false}', :headers => {}) expect { Auth.token_status(false, @vmpooler_url, @token) }.to raise_error(TokenError) end diff --git a/spec/vmfloaty/nonstandard_pooler_spec.rb b/spec/vmfloaty/nonstandard_pooler_spec.rb index 1f86dd2..8bcfe3c 100644 --- a/spec/vmfloaty/nonstandard_pooler_spec.rb +++ b/spec/vmfloaty/nonstandard_pooler_spec.rb @@ -8,7 +8,9 @@ require 'vmfloaty/nonstandard_pooler' describe NonstandardPooler do before :each do @nspooler_url = 'https://nspooler.example.com' - @auth_token_headers = get_headers(token: 'token-value') + @auth_token_headers = { + 'X-Auth-Token' => 'token-value', + } end describe '#list' do @@ -34,7 +36,7 @@ describe NonstandardPooler do it 'returns an array with operating systems from the pooler' do stub_request(:get, "#{@nspooler_url}/status") - .to_return(status: 200, body: @status_response_body, headers: {}) + .to_return(:status => 200, :body => @status_response_body, :headers => {}) list = NonstandardPooler.list(false, @nspooler_url, nil) expect(list).to be_an_instance_of Array @@ -42,7 +44,7 @@ describe NonstandardPooler do it 'filters operating systems based on the filter param' do stub_request(:get, "#{@nspooler_url}/status") - .to_return(status: 200, body: @status_response_body, headers: {}) + .to_return(:status => 200, :body => @status_response_body, :headers => {}) list = NonstandardPooler.list(false, @nspooler_url, 'aix') expect(list).to be_an_instance_of Array @@ -51,7 +53,7 @@ describe NonstandardPooler do it 'returns nothing if the filter does not match' do stub_request(:get, "#{@nspooler_url}/status") - .to_return(status: 199, body: @status_response_body, headers: {}) + .to_return(:status => 199, :body => @status_response_body, :headers => {}) list = NonstandardPooler.list(false, @nspooler_url, 'windows') expect(list).to be_an_instance_of Array @@ -87,7 +89,7 @@ describe NonstandardPooler do .and_return(JSON.parse(@token_status_body_active)) list = NonstandardPooler.list_active(false, @nspooler_url, 'token-value', 'user') - expect(list).to eql %w[sol10-9 sol10-11] + expect(list).to eql ['sol10-9', 'sol10-11'] end end @@ -119,19 +121,17 @@ describe NonstandardPooler do it 'raises an AuthError if the token is invalid' do stub_request(:post, "#{@nspooler_url}/host/solaris-11-sparc") - .with(headers: get_headers(token: 'token-value')) - .to_return(status: 401, body: '{"ok":false,"reason": "token: token-value does not exist"}', headers: {}) + .with(:headers => @auth_token_headers) + .to_return(:status => 401, :body => '{"ok":false,"reason": "token: token-value does not exist"}', :headers => {}) vm_hash = { 'solaris-11-sparc' => 1 } - expect do - NonstandardPooler.retrieve(false, vm_hash, 'token-value', @nspooler_url, 'first.last', {}) - end.to raise_error(AuthError) + expect { NonstandardPooler.retrieve(false, vm_hash, 'token-value', @nspooler_url, 'first.last', {}) }.to raise_error(AuthError) end it 'retrieves a single vm with a token' do stub_request(:post, "#{@nspooler_url}/host/solaris-11-sparc") - .with(headers: @auth_token_headers) - .to_return(status: 200, body: @retrieve_response_body_single, headers: {}) + .with(:headers => @auth_token_headers) + .to_return(:status => 200, :body => @retrieve_response_body_single, :headers => {}) vm_hash = { 'solaris-11-sparc' => 1 } vm_req = NonstandardPooler.retrieve(false, vm_hash, 'token-value', @nspooler_url, 'first.last', {}) @@ -142,16 +142,15 @@ describe NonstandardPooler do it 'retrieves a multiple vms with a token' do stub_request(:post, "#{@nspooler_url}/host/aix-7.1-power+solaris-10-sparc+solaris-10-sparc") - .with(headers: @auth_token_headers) - .to_return(status: 200, body: @retrieve_response_body_many, headers: {}) + .with(:headers => @auth_token_headers) + .to_return(:status => 200, :body => @retrieve_response_body_many, :headers => {}) vm_hash = { 'aix-7.1-power' => 1, 'solaris-10-sparc' => 2 } vm_req = NonstandardPooler.retrieve(false, vm_hash, 'token-value', @nspooler_url, 'first.last', {}) expect(vm_req).to be_an_instance_of Hash expect(vm_req['ok']).to equal true expect(vm_req['solaris-10-sparc']['hostname']).to be_an_instance_of Array - expect(vm_req['solaris-10-sparc']['hostname']).to eq ['sol10-9.delivery.puppetlabs.net', - 'sol10-10.delivery.puppetlabs.net'] + expect(vm_req['solaris-10-sparc']['hostname']).to eq ['sol10-9.delivery.puppetlabs.net', 'sol10-10.delivery.puppetlabs.net'] expect(vm_req['aix-7.1-power']['hostname']).to eq 'pe-aix-71-ci-acceptance.delivery.puppetlabs.net' end end @@ -163,22 +162,22 @@ describe NonstandardPooler do it 'raises an error if the user tries to modify an unsupported attribute' do stub_request(:put, 'https://nspooler.example.com/host/myfakehost') - .with(body: { '{}' => true }, - headers: @auth_token_headers) - .to_return(status: 200, body: '', headers: {}) - details = { lifetime: 12 } + .with(:body => { '{}' => true }, + :headers => @auth_token_headers) + .to_return(:status => 200, :body => '', :headers => {}) + details = { :lifetime => 12 } expect { NonstandardPooler.modify(false, @nspooler_url, 'myfakehost', 'token-value', details) } .to raise_error(ModifyError) end it 'modifies the reason of a vm' do - modify_request_body = { '{"reserved_for_reason":"testing"}' => nil } + modify_request_body = { '{"reserved_for_reason":"testing"}' => true } stub_request(:put, "#{@nspooler_url}/host/myfakehost") - .with(body: modify_request_body, - headers: @auth_token_headers) - .to_return(status: 200, body: '{"ok": true}', headers: {}) + .with(:body => modify_request_body, + :headers => @auth_token_headers) + .to_return(:status => 200, :body => '{"ok": true}', :headers => {}) - modify_hash = { reason: 'testing' } + modify_hash = { :reason => 'testing' } modify_req = NonstandardPooler.modify(false, @nspooler_url, 'myfakehost', 'token-value', modify_hash) expect(modify_req['ok']).to be true end @@ -209,7 +208,7 @@ describe NonstandardPooler do it 'prints the status' do stub_request(:get, "#{@nspooler_url}/status") - .to_return(status: 200, body: @status_response_body, headers: {}) + .to_return(:status => 200, :body => @status_response_body, :headers => {}) status = NonstandardPooler.status(false, @nspooler_url) expect(status).to be_an_instance_of Hash @@ -232,7 +231,7 @@ describe NonstandardPooler do it 'prints the summary' do stub_request(:get, "#{@nspooler_url}/summary") - .to_return(status: 200, body: @status_response_body, headers: {}) + .to_return(:status => 200, :body => @status_response_body, :headers => {}) summary = NonstandardPooler.summary(false, @nspooler_url) expect(summary).to be_an_instance_of Hash @@ -257,7 +256,7 @@ describe NonstandardPooler do it 'makes a query about a vm' do stub_request(:get, "#{@nspooler_url}/host/sol10-11") - .to_return(status: 200, body: @query_response_body, headers: {}) + .to_return(:status => 200, :body => @query_response_body, :headers => {}) query_req = NonstandardPooler.query(false, @nspooler_url, 'sol10-11') expect(query_req).to be_an_instance_of Hash @@ -272,8 +271,8 @@ describe NonstandardPooler do it 'deletes a single existing vm' do stub_request(:delete, "#{@nspooler_url}/host/sol11-7") - .with(headers: @auth_token_headers) - .to_return(status: 200, body: @delete_response_success, headers: {}) + .with(:headers => @auth_token_headers) + .to_return(:status => 200, :body => @delete_response_success, :headers => {}) request = NonstandardPooler.delete(false, @nspooler_url, 'sol11-7', 'token-value', nil) expect(request['sol11-7']['ok']).to be true @@ -281,8 +280,8 @@ describe NonstandardPooler do it 'does not delete a nonexistant vm' do stub_request(:delete, "#{@nspooler_url}/host/fakehost") - .with(headers: @auth_token_headers) - .to_return(status: 401, body: @delete_response_failure, headers: {}) + .with(:headers => @auth_token_headers) + .to_return(:status => 401, :body => @delete_response_failure, :headers => {}) request = NonstandardPooler.delete(false, @nspooler_url, 'fakehost', 'token-value', nil) expect(request['fakehost']['ok']).to be false diff --git a/spec/vmfloaty/pooler_spec.rb b/spec/vmfloaty/pooler_spec.rb index e9cebdd..7d83c79 100644 --- a/spec/vmfloaty/pooler_spec.rb +++ b/spec/vmfloaty/pooler_spec.rb @@ -15,7 +15,7 @@ describe Pooler do it 'returns a hash with operating systems from the pooler' do stub_request(:get, "#{@vmpooler_url}/vm") - .to_return(status: 200, body: @list_response_body, headers: {}) + .to_return(:status => 200, :body => @list_response_body, :headers => {}) list = Pooler.list(false, @vmpooler_url, nil) expect(list).to be_an_instance_of Array @@ -23,7 +23,7 @@ describe Pooler do it 'filters operating systems based on the filter param' do stub_request(:get, "#{@vmpooler_url}/vm") - .to_return(status: 200, body: @list_response_body, headers: {}) + .to_return(:status => 200, :body => @list_response_body, :headers => {}) list = Pooler.list(false, @vmpooler_url, 'deb') expect(list).to be_an_instance_of Array @@ -32,7 +32,7 @@ describe Pooler do it 'returns nothing if the filter does not match' do stub_request(:get, "#{@vmpooler_url}/vm") - .to_return(status: 200, body: @list_response_body, headers: {}) + .to_return(:status => 200, :body => @list_response_body, :headers => {}) list = Pooler.list(false, @vmpooler_url, 'windows') expect(list).to be_an_instance_of Array @@ -48,8 +48,8 @@ describe Pooler do it 'raises an AuthError if the token is invalid' do stub_request(:post, "#{@vmpooler_url}/vm/debian-7-i386") - .with(headers: { 'X-Auth-Token' => 'mytokenfile' }) - .to_return(status: 401, body: '{"ok":false}', headers: {}) + .with(:headers => { 'X-Auth-Token' => 'mytokenfile' }) + .to_return(:status => 401, :body => '{"ok":false}', :headers => {}) vm_hash = {} vm_hash['debian-7-i386'] = 1 @@ -58,8 +58,8 @@ describe Pooler do it 'retrieves a single vm with a token' do stub_request(:post, "#{@vmpooler_url}/vm/debian-7-i386") - .with(headers: { 'X-Auth-Token' => 'mytokenfile' }) - .to_return(status: 200, body: @retrieve_response_body_single, headers: {}) + .with(:headers => { 'X-Auth-Token' => 'mytokenfile' }) + .to_return(:status => 200, :body => @retrieve_response_body_single, :headers => {}) vm_hash = {} vm_hash['debian-7-i386'] = 1 @@ -71,8 +71,8 @@ describe Pooler do it 'retrieves a multiple vms with a token' do stub_request(:post, "#{@vmpooler_url}/vm/debian-7-i386+debian-7-i386+centos-7-x86_64") - .with(headers: { 'X-Auth-Token' => 'mytokenfile' }) - .to_return(status: 200, body: @retrieve_response_body_double, headers: {}) + .with(:headers => { 'X-Auth-Token' => 'mytokenfile' }) + .to_return(:status => 200, :body => @retrieve_response_body_double, :headers => {}) vm_hash = {} vm_hash['debian-7-i386'] = 2 @@ -89,11 +89,11 @@ describe Pooler do let(:ondemand_response) { '{"ok":true,"request_id":"1234"}' } it 'retreives the vm with a token' do stub_request(:post, "#{@vmpooler_url}/ondemandvm/debian-7-i386") - .with(headers: { 'X-Auth-Token' => 'mytokenfile' }) - .to_return(status: 200, body: ondemand_response, headers: {}) + .with(:headers => { 'X-Auth-Token' => 'mytokenfile' }) + .to_return(:status => 200, :body => ondemand_response, :headers => {}) stub_request(:get, "#{@vmpooler_url}/ondemandvm/1234") - .to_return(status: 200, body: @retrieve_response_body_single, headers: {}) + .to_return(:status => 200, :body => @retrieve_response_body_single, :headers => {}) vm_hash = {} vm_hash['debian-7-i386'] = 1 @@ -117,11 +117,11 @@ describe Pooler do end it 'modifies the TTL of a vm' do - modify_hash = { lifetime: 12 } + modify_hash = { :lifetime => 12 } stub_request(:put, "#{@vmpooler_url}/vm/fq6qlpjlsskycq6") - .with(body: { '{"lifetime":12}' => nil }, - headers: get_headers(content_type: 'application/x-www-form-urlencoded', token: 'mytokenfile')) - .to_return(status: 200, body: @modify_response_body_success, headers: {}) + .with(:body => { '{"lifetime":12}' => true }, + :headers => { 'Content-Type' => 'application/x-www-form-urlencoded', 'X-Auth-Token' => 'mytokenfile' }) + .to_return(:status => 200, :body => @modify_response_body_success, :headers => {}) modify_req = Pooler.modify(false, @vmpooler_url, 'fq6qlpjlsskycq6', 'mytokenfile', modify_hash) expect(modify_req['ok']).to be true @@ -136,8 +136,8 @@ describe Pooler do it 'deletes a specified vm' do stub_request(:delete, "#{@vmpooler_url}/vm/fq6qlpjlsskycq6") - .with(headers: { 'X-Auth-Token' => 'mytokenfile' }) - .to_return(status: 200, body: @delete_response_body_success, headers: {}) + .with(:headers => { 'X-Auth-Token' => 'mytokenfile' }) + .to_return(:status => 200, :body => @delete_response_body_success, :headers => {}) expect(Pooler.delete(false, @vmpooler_url, ['fq6qlpjlsskycq6'], 'mytokenfile', nil)).to eq @delete_response end @@ -155,7 +155,7 @@ describe Pooler do it 'prints the status' do stub_request(:get, "#{@vmpooler_url}/status") - .to_return(status: 200, body: @status_response_body, headers: {}) + .to_return(:status => 200, :body => @status_response_body, :headers => {}) status = Pooler.status(false, @vmpooler_url) expect(status).to be_an_instance_of Hash @@ -178,7 +178,7 @@ describe Pooler do it 'makes a query about a vm' do stub_request(:get, "#{@vmpooler_url}/vm/fq6qlpjlsskycq6") - .to_return(status: 200, body: @query_response_body, headers: {}) + .to_return(:status => 200, :body => @query_response_body, :headers => {}) query_req = Pooler.query(false, @vmpooler_url, 'fq6qlpjlsskycq6') expect(query_req).to be_an_instance_of Hash @@ -192,8 +192,8 @@ describe Pooler do it 'makes a snapshot for a single vm' do stub_request(:post, "#{@vmpooler_url}/vm/fq6qlpjlsskycq6/snapshot") - .with(headers: { 'X-Auth-Token' => 'mytokenfile' }) - .to_return(status: 200, body: @snapshot_response_body, headers: {}) + .with(:headers => { 'X-Auth-Token' => 'mytokenfile' }) + .to_return(:status => 200, :body => @snapshot_response_body, :headers => {}) snapshot_req = Pooler.snapshot(false, @vmpooler_url, 'fq6qlpjlsskycq6', 'mytokenfile') expect(snapshot_req['ok']).to be true @@ -207,18 +207,15 @@ describe Pooler do it 'makes a request to revert a vm from a snapshot' do stub_request(:post, "#{@vmpooler_url}/vm/fq6qlpjlsskycq6/snapshot/dAfewKNfaweLKNve") - .with(headers: { 'X-Auth-Token' => 'mytokenfile' }) - .to_return(status: 200, body: @revert_response_body, headers: {}) + .with(:headers => { 'X-Auth-Token' => 'mytokenfile' }) + .to_return(:status => 200, :body => @revert_response_body, :headers => {}) revert_req = Pooler.revert(false, @vmpooler_url, 'fq6qlpjlsskycq6', 'mytokenfile', 'dAfewKNfaweLKNve') expect(revert_req['ok']).to be true end it "doesn't make a request to revert a vm if snapshot is not provided" do - expect do - Pooler.revert(false, @vmpooler_url, 'fq6qlpjlsskycq6', 'mytokenfile', - nil) - end.to raise_error(RuntimeError, 'Snapshot SHA provided was nil, could not revert fq6qlpjlsskycq6') + expect { Pooler.revert(false, @vmpooler_url, 'fq6qlpjlsskycq6', 'mytokenfile', nil) }.to raise_error(RuntimeError, 'Snapshot SHA provided was nil, could not revert fq6qlpjlsskycq6') end it 'raises a TokenError if no token was provided' do @@ -234,7 +231,7 @@ describe Pooler do it 'makes a request to extend disk space of a vm' do stub_request(:post, "#{@vmpooler_url}/vm/fq6qlpjlsskycq6/disk/12") - .with(headers: { 'X-Auth-Token' => 'mytokenfile' }).to_return(status: 200, body: @disk_response_body_success, headers: {}) + .with(:headers => { 'X-Auth-Token' => 'mytokenfile' }). to_return(:status => 200, :body => @disk_response_body_success, :headers => {}) disk_req = Pooler.disk(false, @vmpooler_url, 'fq6qlpjlsskycq6', 'mytokenfile', 12) expect(disk_req['ok']).to be true diff --git a/spec/vmfloaty/service_spec.rb b/spec/vmfloaty/service_spec.rb index 70c7199..13426b3 100644 --- a/spec/vmfloaty/service_spec.rb +++ b/spec/vmfloaty/service_spec.rb @@ -16,7 +16,7 @@ describe Service do it 'prompts the user for their password and retrieves a token' do config = { 'user' => 'first.last', 'url' => 'http://default.url' } service = Service.new(MockOptions.new, config) - allow($stdout).to receive(:puts).with('Enter your http://default.url service password:') + allow(STDOUT).to receive(:puts).with('Enter your http://default.url service password:') allow(Commander::UI).to(receive(:password) .with('Enter your http://default.url service password:', '*') .and_return('hunter2')) @@ -29,9 +29,9 @@ describe Service do it 'prompts the user for their username and password if the username is unknown' do config = { 'url' => 'http://default.url' } service = Service.new(MockOptions.new({}), config) - allow($stdout).to receive(:puts).with 'Enter your http://default.url service username:' - allow($stdout).to receive(:puts).with "\n" - allow($stdin).to receive(:gets).and_return('first.last') + allow(STDOUT).to receive(:puts).with 'Enter your http://default.url service username:' + allow(STDOUT).to receive(:puts).with "\n" + allow(STDIN).to receive(:gets).and_return('first.last') allow(Commander::UI).to(receive(:password) .with('Enter your http://default.url service password:', '*') .and_return('hunter2')) @@ -59,16 +59,16 @@ describe Service do it 'reports the status of a token' do config = { 'user' => 'first.last', - 'url' => 'http://default.url' + 'url' => 'http://default.url', } options = MockOptions.new('token' => 'token-value') service = Service.new(options, config) status = { - 'ok' => true, - 'user' => config['user'], - 'created' => '2017-09-22 02:04:18 +0000', - 'last_accessed' => '2017-09-22 02:04:28 +0000', - 'reserved_hosts' => [] + 'ok' => true, + 'user' => config['user'], + 'created' => '2017-09-22 02:04:18 +0000', + 'last_accessed' => '2017-09-22 02:04:28 +0000', + 'reserved_hosts' => [], } allow(Auth).to(receive(:token_status) .with(nil, config['url'], 'token-value') diff --git a/spec/vmfloaty/ssh_spec.rb b/spec/vmfloaty/ssh_spec.rb index ec5fd4e..c780a88 100644 --- a/spec/vmfloaty/ssh_spec.rb +++ b/spec/vmfloaty/ssh_spec.rb @@ -4,35 +4,24 @@ require 'spec_helper' require 'vmfloaty/ssh' class ServiceStub - def retrieve(_verbose, os_types, _use_token, ondemand) + def retrieve(_verbose, os_types, _use_token) if os_types.keys[0] == 'abs_host_string' return { os_types.keys[0] => { 'hostname' => ['abs-hostname.delivery.puppetlabs.net'] }, - 'ok' => true - } - - elsif os_types.keys[0] == 'vmpooler_api_v2_host_string' - return { - os_types.keys[0] => { 'hostname' => ['vmpooler-v2-hostname.delivery.puppetlabs.net'] }, - 'ok' => true - } - - else - return { - os_types.keys[0] => { 'hostname' => 'vmpooler-v1-hostname' }, - 'domain' => 'delivery.puppetlabs.net', - 'ok' => true + 'ok' => true, } end + + { + os_types.keys[0] => { 'hostname' => 'vmpooler-hostname' }, + 'domain' => 'delivery.puppetlabs.net', + 'ok' => true, + } end def type return 'abs' if os_types == 'abs_host_string' - return 'vmpooler' if os_types == 'vmpooler_api_v1_host_string' || os_types == 'vmpooler_api_v2_host_string' - end - - def wait_for_request(verbose, requestid) - return true + return 'vmpooler' if os_types == 'vmpooler_host_string' end end @@ -40,73 +29,21 @@ describe Ssh do before :each do end - context "for pooled requests" do - it 'gets a hostname string for abs' do - verbose = false - service = ServiceStub.new - host_os = 'abs_host_string' - use_token = false - cmd = Ssh.command_string(verbose, service, host_os, use_token) - expect(cmd).to match(/ssh root@abs-hostname.delivery.puppetlabs.net/) - end - - it 'gets a hostname string for vmpooler api v1' do - verbose = true - service = ServiceStub.new - host_os = 'vmpooler_api_v1_host_string' - use_token = false - cmd = Ssh.command_string(verbose, service, host_os, use_token) - expect(cmd).to match(/ssh root@vmpooler-v1-hostname.delivery.puppetlabs.net/) - end - - it 'gets a hostname string for vmpooler api v2' do - verbose = false - service = ServiceStub.new - host_os = 'vmpooler_api_v2_host_string' - use_token = false - cmd = Ssh.command_string(verbose, service, host_os, use_token) - expect(cmd).to match(/ssh root@vmpooler-v2-hostname.delivery.puppetlabs.net/) - end + it 'gets a hostname string for abs' do + verbose = false + service = ServiceStub.new + host_os = 'abs_host_string' + use_token = false + cmd = Ssh.command_string(verbose, service, host_os, use_token) + expect(cmd).to match(/ssh root@abs-hostname.delivery.puppetlabs.net/) end - context "for ondemand requests" do - let(:service) { ServiceStub.new } - let(:url) { 'http://pooler.example.com' } - - it 'gets a hostname string for abs' do - verbose = false - host_os = 'abs_host_string' - use_token = false - ondemand = true - response = {'abs_host_string' => { 'hostname' => ['abs-hostname.delivery.puppetlabs.net']}} - allow(service).to receive(:url) - allow(service).to receive(:check_ondemandvm).and_return(response) - cmd = Ssh.command_string(verbose, service, host_os, use_token, ondemand) - expect(cmd).to match(/ssh root@abs-hostname.delivery.puppetlabs.net/) - end - - it 'gets a hostname string for abs' do - verbose = false - host_os = 'vmpooler_api_v1_host_string' - use_token = false - ondemand = true - response = {'vmpooler_api_v1_host_string' => { 'hostname' => ['vmpooler_api_v1_host_string.delivery.puppetlabs.net']}} - allow(service).to receive(:url) - allow(service).to receive(:check_ondemandvm).and_return(response) - cmd = Ssh.command_string(verbose, service, host_os, use_token, ondemand) - expect(cmd).to match(/ssh root@vmpooler_api_v1_host_string.delivery.puppetlabs.net/) - end - - it 'gets a hostname string for abs' do - verbose = false - host_os = 'vmpooler_api_v2_host_string' - use_token = false - ondemand = true - response = {'vmpooler_api_v2_host_string' => { 'hostname' => ['vmpooler_api_v2_host_string.delivery.puppetlabs.net']}} - allow(service).to receive(:url) - allow(service).to receive(:check_ondemandvm).and_return(response) - cmd = Ssh.command_string(verbose, service, host_os, use_token, ondemand) - expect(cmd).to match(/ssh root@vmpooler_api_v2_host_string.delivery.puppetlabs.net/) - end + it 'gets a hostname string for vmpooler' do + verbose = false + service = ServiceStub.new + host_os = 'vmpooler_host_string' + use_token = false + cmd = Ssh.command_string(verbose, service, host_os, use_token) + expect(cmd).to match(/ssh root@vmpooler-hostname.delivery.puppetlabs.net/) end end diff --git a/spec/vmfloaty/utils_spec.rb b/spec/vmfloaty/utils_spec.rb index 37d2537..a90d3b1 100644 --- a/spec/vmfloaty/utils_spec.rb +++ b/spec/vmfloaty/utils_spec.rb @@ -13,7 +13,7 @@ end describe Utils do describe '#standardize_hostnames' do before :each do - @vmpooler_api_v1_response_body = '{ + @vmpooler_response_body = '{ "ok": true, "domain": "delivery.mycompany.net", "ubuntu-1610-x86_64": { @@ -23,15 +23,6 @@ describe Utils do "hostname": "dlgietfmgeegry2" } }' - @vmpooler_api_v2_response_body = '{ - "ok": true, - "ubuntu-1610-x86_64": { - "hostname": ["gdoy8q3nckuob0i.delivery.mycompany.net", "ctnktsd0u11p9tm.delivery.mycompany.net"] - }, - "centos-7-x86_64": { - "hostname": "dlgietfmgeegry2.delivery.mycompany.net" - } - }' @nonstandard_response_body = '{ "ok": true, "solaris-10-sparc": { @@ -43,23 +34,15 @@ describe Utils do }' end - it 'formats a result from vmpooler v1 api into a hash of os to hostnames' do - result = Utils.standardize_hostnames(JSON.parse(@vmpooler_api_v1_response_body)) - expect(result).to eq('centos-7-x86_64' => ['dlgietfmgeegry2.delivery.mycompany.net'], - 'ubuntu-1610-x86_64' => ['gdoy8q3nckuob0i.delivery.mycompany.net', - 'ctnktsd0u11p9tm.delivery.mycompany.net']) - end - - it 'formats a result from vmpooler v2 api into a hash of os to hostnames' do - result = Utils.standardize_hostnames(JSON.parse(@vmpooler_api_v2_response_body)) - expect(result).to eq('centos-7-x86_64' => ['dlgietfmgeegry2.delivery.mycompany.net'], - 'ubuntu-1610-x86_64' => ['gdoy8q3nckuob0i.delivery.mycompany.net', - 'ctnktsd0u11p9tm.delivery.mycompany.net']) + it 'formats a result from vmpooler into a hash of os to hostnames' do + result = Utils.standardize_hostnames(JSON.parse(@vmpooler_response_body)) + expect(result).to eq('centos-7-x86_64' => ['dlgietfmgeegry2.delivery.mycompany.net'], + 'ubuntu-1610-x86_64' => ['gdoy8q3nckuob0i.delivery.mycompany.net', 'ctnktsd0u11p9tm.delivery.mycompany.net']) end it 'formats a result from the nonstandard pooler into a hash of os to hostnames' do result = Utils.standardize_hostnames(JSON.parse(@nonstandard_response_body)) - expect(result).to eq('solaris-10-sparc' => ['sol10-10.delivery.mycompany.net', 'sol10-11.delivery.mycompany.net'], + expect(result).to eq('solaris-10-sparc' => ['sol10-10.delivery.mycompany.net', 'sol10-11.delivery.mycompany.net'], 'ubuntu-16.04-power8' => ['power8-ubuntu16.04-6.delivery.mycompany.net']) end end @@ -67,12 +50,12 @@ describe Utils do describe '#format_host_output' do before :each do @vmpooler_results = { - 'centos-7-x86_64' => ['dlgietfmgeegry2.delivery.mycompany.net'], - 'ubuntu-1610-x86_64' => ['gdoy8q3nckuob0i.delivery.mycompany.net', 'ctnktsd0u11p9tm.delivery.mycompany.net'] + 'centos-7-x86_64' => ['dlgietfmgeegry2.delivery.mycompany.net'], + 'ubuntu-1610-x86_64' => ['gdoy8q3nckuob0i.delivery.mycompany.net', 'ctnktsd0u11p9tm.delivery.mycompany.net'], } @nonstandard_results = { - 'solaris-10-sparc' => ['sol10-10.delivery.mycompany.net', 'sol10-11.delivery.mycompany.net'], - 'ubuntu-16.04-power8' => ['power8-ubuntu16.04-6.delivery.mycompany.net'] + 'solaris-10-sparc' => ['sol10-10.delivery.mycompany.net', 'sol10-11.delivery.mycompany.net'], + 'ubuntu-16.04-power8' => ['power8-ubuntu16.04-6.delivery.mycompany.net'], } @vmpooler_output = <<~OUT.chomp - dlgietfmgeegry2.delivery.mycompany.net (centos-7-x86_64) @@ -115,23 +98,23 @@ describe Utils do describe '#get_service_config' do before :each do @default_config = { - 'url' => 'http://default.url', - 'user' => 'first.last.default', - 'token' => 'default-token' + 'url' => 'http://default.url', + 'user' => 'first.last.default', + 'token' => 'default-token', } @services_config = { 'services' => { 'vm' => { - 'url' => 'http://vmpooler.url', - 'user' => 'first.last.vmpooler', - 'token' => 'vmpooler-token' + 'url' => 'http://vmpooler.url', + 'user' => 'first.last.vmpooler', + 'token' => 'vmpooler-token', }, 'ns' => { - 'url' => 'http://nspooler.url', - 'user' => 'first.last.nspooler', - 'token' => 'nspooler-token' - } - } + 'url' => 'http://nspooler.url', + 'user' => 'first.last.nspooler', + 'token' => 'nspooler-token', + }, + }, } end @@ -143,26 +126,26 @@ describe Utils do it 'allows selection by configured service key' do config = @default_config.merge @services_config - options = MockOptions.new(service: 'ns') + options = MockOptions.new(:service => 'ns') expect(Utils.get_service_config(config, options)).to include @services_config['services']['ns'] end it 'uses top-level service config values as defaults when configured service values are missing' do config = @default_config.merge @services_config config['services']['vm'].delete 'url' - options = MockOptions.new(service: 'vm') + options = MockOptions.new(:service => 'vm') expect(Utils.get_service_config(config, options)['url']).to eq 'http://default.url' end it "raises an error if passed a service name that hasn't been configured" do config = @default_config.merge @services_config - options = MockOptions.new(service: 'none') + options = MockOptions.new(:service => 'none') expect { Utils.get_service_config(config, options) }.to raise_error ArgumentError end it 'prioritizes values passed as command line options over configuration options' do config = @default_config - options = MockOptions.new(url: 'http://alternate.url', token: 'alternate-token') + options = MockOptions.new(:url => 'http://alternate.url', :token => 'alternate-token') expected = config.merge('url' => 'http://alternate.url', 'token' => 'alternate-token') expect(Utils.get_service_config(config, options)).to include expected end @@ -199,15 +182,15 @@ describe Utils do { 'template' => 'ubuntu-1604-x86_64', 'lifetime' => 12, - 'running' => 9.66, - 'state' => 'running', - 'ip' => '127.0.0.1', - 'domain' => domain + 'running' => 9.66, + 'state' => 'running', + 'ip' => '127.0.0.1', + 'domain' => domain, } end it 'outputs fqdn for host' do - expect($stdout).to receive(:puts).with(fqdn) + expect(STDOUT).to receive(:puts).with(fqdn) subject end @@ -218,17 +201,17 @@ describe Utils do let(:hostname) { 'sol11-9.delivery.mycompany.net' } let(:host_data) do { - 'fqdn' => hostname, - 'os_triple' => 'solaris-11-sparc', - 'reserved_by_user' => 'first.last', - 'reserved_for_reason' => '', - 'hours_left_on_reservation' => 35.89 + 'fqdn' => hostname, + 'os_triple' => 'solaris-11-sparc', + 'reserved_by_user' => 'first.last', + 'reserved_for_reason' => '', + 'hours_left_on_reservation' => 35.89, } end let(:fqdn) { hostname } # for nspooler these are the same it 'outputs fqdn for host' do - expect($stdout).to receive(:puts).with(fqdn) + expect(STDOUT).to receive(:puts).with(fqdn) subject end @@ -248,19 +231,19 @@ describe Utils do { 'hostname' => fqdn, 'type' => template, - 'enging' => 'vmpooler' - } + 'enging' => 'vmpooler', + }, ], 'request' => { 'job' => { - 'id' => hostname + 'id' => hostname, } - } + }, } end it 'outputs fqdn for host' do - expect($stdout).to receive(:puts).with(fqdn) + expect(STDOUT).to receive(:puts).with(fqdn) subject end @@ -280,73 +263,7 @@ describe Utils do subject { Utils.pretty_print_hosts(verbose, service, hostname, print_to_stderr) } - describe 'with vmpooler api v2 service' do - let(:service) { Service.new(MockOptions.new, 'url' => url) } - - let(:hostname) { 'mcpy42eqjxli9g2' } - let(:fqdn) { [hostname, 'delivery.puppetlabs.net'].join('.') } - - let(:response_body) do - { - hostname => { - 'template' => 'ubuntu-1604-x86_64', - 'lifetime' => 12, - 'running' => 9.66, - 'state' => 'running', - 'ip' => '127.0.0.1', - 'fqdn' => fqdn - } - } - end - - let(:default_output) { "- #{fqdn} (running, ubuntu-1604-x86_64, 9.66/12 hours)" } - - it 'prints output with host fqdn, template and duration info' do - expect($stdout).to receive(:puts).with(default_output) - - subject - end - - context 'when tags are supplied' do - let(:hostname) { 'aiydvzpg23r415q' } - let(:response_body) do - { - hostname => { - 'template' => 'redhat-7-x86_64', - 'lifetime' => 48, - 'running' => 7.67, - 'state' => 'running', - 'tags' => { - 'user' => 'bob', - 'role' => 'agent' - }, - 'ip' => '127.0.0.1', - 'fqdn' => fqdn - } - } - end - - it 'prints output with host fqdn, template, duration info, and tags' do - output = "- #{fqdn} (running, redhat-7-x86_64, 7.67/48 hours, user: bob, role: agent)" - - expect($stdout).to receive(:puts).with(output) - - subject - end - end - - context 'when print_to_stderr option is true' do - let(:print_to_stderr) { true } - - it 'outputs to stderr instead of stdout' do - expect($stderr).to receive(:puts).with(default_output) - - subject - end - end - end - - describe 'with vmpooler api v1 service' do + describe 'with vmpooler service' do let(:service) { Service.new(MockOptions.new, 'url' => url) } let(:hostname) { 'mcpy42eqjxli9g2' } @@ -358,18 +275,18 @@ describe Utils do hostname => { 'template' => 'ubuntu-1604-x86_64', 'lifetime' => 12, - 'running' => 9.66, - 'state' => 'running', - 'ip' => '127.0.0.1', - 'domain' => domain + 'running' => 9.66, + 'state' => 'running', + 'ip' => '127.0.0.1', + 'domain' => domain, } } end - let(:default_output) { "- #{fqdn} (running, ubuntu-1604-x86_64, 9.66/12 hours)" } + let(:default_output) { "- #{fqdn} (ubuntu-1604-x86_64, 9.66/12 hours)" } it 'prints output with host fqdn, template and duration info' do - expect($stdout).to receive(:puts).with(default_output) + expect(STDOUT).to receive(:puts).with(default_output) subject end @@ -381,22 +298,22 @@ describe Utils do hostname => { 'template' => 'redhat-7-x86_64', 'lifetime' => 48, - 'running' => 7.67, - 'state' => 'running', - 'tags' => { + 'running' => 7.67, + 'state' => 'running', + 'tags' => { 'user' => 'bob', - 'role' => 'agent' + 'role' => 'agent', }, - 'ip' => '127.0.0.1', - 'domain' => domain + 'ip' => '127.0.0.1', + 'domain' => domain, } } end it 'prints output with host fqdn, template, duration info, and tags' do - output = "- #{fqdn} (running, redhat-7-x86_64, 7.67/48 hours, user: bob, role: agent)" + output = "- #{fqdn} (redhat-7-x86_64, 7.67/48 hours, user: bob, role: agent)" - expect($stdout).to receive(:puts).with(output) + expect(STDOUT).to receive(:puts).with(output) subject end @@ -406,7 +323,7 @@ describe Utils do let(:print_to_stderr) { true } it 'outputs to stderr instead of stdout' do - expect($stderr).to receive(:puts).with(default_output) + expect(STDERR).to receive(:puts).with(default_output) subject end @@ -420,11 +337,11 @@ describe Utils do let(:response_body) do { hostname => { - 'fqdn' => hostname, - 'os_triple' => 'solaris-11-sparc', - 'reserved_by_user' => 'first.last', - 'reserved_for_reason' => '', - 'hours_left_on_reservation' => 35.89 + 'fqdn' => hostname, + 'os_triple' => 'solaris-11-sparc', + 'reserved_by_user' => 'first.last', + 'reserved_for_reason' => '', + 'hours_left_on_reservation' => 35.89, } } end @@ -432,7 +349,7 @@ describe Utils do let(:default_output) { "- #{hostname} (solaris-11-sparc, 35.89h remaining)" } it 'prints output with host, template, and time remaining' do - expect($stdout).to receive(:puts).with(default_output) + expect(STDOUT).to receive(:puts).with(default_output) subject end @@ -441,11 +358,11 @@ describe Utils do let(:response_body) do { hostname => { - 'fqdn' => hostname, - 'os_triple' => 'solaris-11-sparc', - 'reserved_by_user' => 'first.last', - 'reserved_for_reason' => 'testing', - 'hours_left_on_reservation' => 35.89 + 'fqdn' => hostname, + 'os_triple' => 'solaris-11-sparc', + 'reserved_by_user' => 'first.last', + 'reserved_for_reason' => 'testing', + 'hours_left_on_reservation' => 35.89, } } end @@ -453,7 +370,7 @@ describe Utils do it 'prints output with host, template, time remaining, and reason' do output = '- sol11-9.delivery.mycompany.net (solaris-11-sparc, 35.89h remaining, reason: testing)' - expect($stdout).to receive(:puts).with(output) + expect(STDOUT).to receive(:puts).with(output) subject end @@ -463,7 +380,7 @@ describe Utils do let(:print_to_stderr) { true } it 'outputs to stderr instead of stdout' do - expect($stderr).to receive(:puts).with(default_output) + expect(STDERR).to receive(:puts).with(default_output) subject end @@ -475,7 +392,7 @@ describe Utils do let(:hostname) { '1597952189390' } let(:fqdn) { 'example-noun.delivery.mycompany.net' } - let(:fqdn_hostname) { 'example-noun' } + let(:fqdn_hostname) {'example-noun'} let(:template) { 'ubuntu-1604-x86_64' } # This seems to be the miminal stub response from ABS for the current output @@ -487,14 +404,14 @@ describe Utils do { 'hostname' => fqdn, 'type' => template, - 'engine' => 'vmpooler' - } + 'engine' => 'vmpooler', + }, ], 'request' => { 'job' => { - 'id' => hostname + 'id' => hostname, } - } + }, } } end @@ -503,58 +420,47 @@ describe Utils do let(:domain) { 'delivery.mycompany.net' } let(:response_body_vmpooler) do { - fqdn_hostname => { - 'template' => template, - 'lifetime' => 48, - 'running' => 7.67, - 'state' => 'running', - 'tags' => { - 'user' => 'bob', - 'role' => 'agent' - }, - 'ip' => '127.0.0.1', - 'domain' => domain - } + fqdn_hostname => { + 'template' => template, + 'lifetime' => 48, + 'running' => 7.67, + 'state' => 'running', + 'tags' => { + 'user' => 'bob', + 'role' => 'agent', + }, + 'ip' => '127.0.0.1', + 'domain' => domain, + } } end before(:each) do allow(Utils).to receive(:get_vmpooler_service_config).and_return({ - 'url' => 'http://vmpooler.example.com', - 'token' => 'krypto-knight' - }) + 'url' => 'http://vmpooler.example.com', + 'token' => 'krypto-knight' + }) allow(service).to receive(:query) - .with(anything, fqdn_hostname) - .and_return(response_body_vmpooler) + .with(anything, fqdn_hostname) + .and_return(response_body_vmpooler) end let(:default_output_first_line) { "- [JobID:#{hostname}] " } let(:default_output_second_line) { " - #{fqdn} (#{template})" } it 'prints output with job id, host, and template' do - expect($stdout).to receive(:puts).with(default_output_first_line) - expect($stdout).to receive(:puts).with(default_output_second_line) + expect(STDOUT).to receive(:puts).with(default_output_first_line) + expect(STDOUT).to receive(:puts).with(default_output_second_line) subject end it 'prints more information when vmpooler_fallback is set output with job id, host, template, lifetime, user and role' do - fallback = { 'vmpooler_fallback' => 'vmpooler' } + fallback = {'vmpooler_fallback' => 'vmpooler'} service.config.merge! fallback - default_output_second_line = " - #{fqdn} (running, #{template}, 7.67/48 hours, user: bob, role: agent)" - expect($stdout).to receive(:puts).with(default_output_first_line) - expect($stdout).to receive(:puts).with(default_output_second_line) - - subject - end - - it 'prints DESTROYED and hostname when destroyed' do - fallback = { 'vmpooler_fallback' => 'vmpooler' } - service.config.merge! fallback - response_body_vmpooler[fqdn_hostname]['state'] = 'destroyed' - default_output_second_line = " - DESTROYED #{fqdn}" - expect($stdout).to receive(:puts).with(default_output_first_line) - expect($stdout).to receive(:puts).with(default_output_second_line) + default_output_second_line=" - #{fqdn} (#{template}, 7.67/48 hours, user: bob, role: agent)" + expect(STDOUT).to receive(:puts).with(default_output_first_line) + expect(STDOUT).to receive(:puts).with(default_output_second_line) subject end @@ -563,8 +469,8 @@ describe Utils do let(:print_to_stderr) { true } it 'outputs to stderr instead of stdout' do - expect($stderr).to receive(:puts).with(default_output_first_line) - expect($stderr).to receive(:puts).with(default_output_second_line) + expect(STDERR).to receive(:puts).with(default_output_first_line) + expect(STDERR).to receive(:puts).with(default_output_second_line) subject end @@ -577,34 +483,34 @@ describe Utils do let(:hostname) { '1597952189390' } let(:fqdn) { 'this-noun.delivery.mycompany.net' } let(:fqdn_ns) { 'that-noun.delivery.mycompany.net' } - let(:fqdn_hostname) { 'this-noun' } - let(:fqdn_ns_hostname) { 'that-noun' } + let(:fqdn_hostname) {'this-noun'} + let(:fqdn_ns_hostname) {'that-noun'} let(:template) { 'ubuntu-1604-x86_64' } let(:template_ns) { 'solaris-10-sparc' } # This seems to be the miminal stub response from ABS for the current output let(:response_body) do { - hostname => { - 'state' => 'allocated', - 'allocated_resources' => [ - { - 'hostname' => fqdn, - 'type' => template, - 'engine' => 'vmpooler' - }, - { - 'hostname' => fqdn_ns, - 'type' => template_ns, - 'engine' => 'nspooler' - } - ], - 'request' => { - 'job' => { - 'id' => hostname - } + hostname => { + 'state' => 'allocated', + 'allocated_resources' => [ + { + 'hostname' => fqdn, + 'type' => template, + 'engine' => 'vmpooler', + }, + { + 'hostname' => fqdn_ns, + 'type' => template_ns, + 'engine' => 'nspooler', + }, + ], + 'request' => { + 'job' => { + 'id' => hostname, + } + }, } - } } end @@ -612,29 +518,29 @@ describe Utils do let(:domain) { 'delivery.mycompany.net' } let(:response_body_vmpooler) do { - fqdn_hostname => { - 'template' => template, - 'lifetime' => 48, - 'running' => 7.67, - 'state' => 'running', - 'tags' => { - 'user' => 'bob', - 'role' => 'agent' - }, - 'ip' => '127.0.0.1', - 'domain' => domain - } + fqdn_hostname => { + 'template' => template, + 'lifetime' => 48, + 'running' => 7.67, + 'state' => 'running', + 'tags' => { + 'user' => 'bob', + 'role' => 'agent', + }, + 'ip' => '127.0.0.1', + 'domain' => domain, + } } end before(:each) do allow(Utils).to receive(:get_vmpooler_service_config).and_return({ - 'url' => 'http://vmpooler.example.com', - 'token' => 'krypto-knight' + 'url' => 'http://vmpooler.example.com', + 'token' => 'krypto-knight' }) allow(service).to receive(:query) - .with(anything, fqdn_hostname) - .and_return(response_body_vmpooler) + .with(anything, fqdn_hostname) + .and_return(response_body_vmpooler) end let(:default_output_first_line) { "- [JobID:#{hostname}] " } @@ -642,9 +548,9 @@ describe Utils do let(:default_output_third_line) { " - #{fqdn_ns} (#{template_ns})" } it 'prints output with job id, host, and template' do - expect($stdout).to receive(:puts).with(default_output_first_line) - expect($stdout).to receive(:puts).with(default_output_second_line) - expect($stdout).to receive(:puts).with(default_output_third_line) + expect(STDOUT).to receive(:puts).with(default_output_first_line) + expect(STDOUT).to receive(:puts).with(default_output_second_line) + expect(STDOUT).to receive(:puts).with(default_output_third_line) subject end @@ -653,9 +559,9 @@ describe Utils do let(:print_to_stderr) { true } it 'outputs to stderr instead of stdout' do - expect($stderr).to receive(:puts).with(default_output_first_line) - expect($stderr).to receive(:puts).with(default_output_second_line) - expect($stderr).to receive(:puts).with(default_output_third_line) + expect(STDERR).to receive(:puts).with(default_output_first_line) + expect(STDERR).to receive(:puts).with(default_output_second_line) + expect(STDERR).to receive(:puts).with(default_output_third_line) subject end @@ -669,59 +575,54 @@ describe Utils do config = { 'user' => 'foo', 'services' => { - 'myabs' => { - 'url' => 'http://abs.com', - 'token' => 'krypto-night', - 'type' => 'abs' - } + 'myabs' => { + 'url' => 'http://abs.com', + 'token' => 'krypto-night', + 'type' => 'abs' + } } } allow(Conf).to receive(:read_config).and_return(config) - expect do - Utils.get_vmpooler_service_config(config['services']['myabs']['vmpooler_fallback']) - end.to raise_error(ArgumentError) + expect{Utils.get_vmpooler_service_config(config['services']['myabs']['vmpooler_fallback'])}.to raise_error(ArgumentError) end it 'returns an error if the vmpooler_fallback is setup but cannot be found' do config = { 'user' => 'foo', 'services' => { 'myabs' => { - 'url' => 'http://abs.com', - 'token' => 'krypto-night', - 'type' => 'abs', - 'vmpooler_fallback' => 'myvmpooler' + 'url' => 'http://abs.com', + 'token' => 'krypto-night', + 'type' => 'abs', + 'vmpooler_fallback' => 'myvmpooler' } } } allow(Conf).to receive(:read_config).and_return(config) - expect do - Utils.get_vmpooler_service_config(config['services']['myabs']['vmpooler_fallback']) - end.to raise_error(ArgumentError, - /myvmpooler/) + expect{Utils.get_vmpooler_service_config(config['services']['myabs']['vmpooler_fallback'])}.to raise_error(ArgumentError, /myvmpooler/) end it 'returns the vmpooler_fallback config' do config = { 'user' => 'foo', 'services' => { 'myabs' => { - 'url' => 'http://abs.com', - 'token' => 'krypto-night', - 'type' => 'abs', - 'vmpooler_fallback' => 'myvmpooler' + 'url' => 'http://abs.com', + 'token' => 'krypto-night', + 'type' => 'abs', + 'vmpooler_fallback' => 'myvmpooler' }, 'myvmpooler' => { - 'url' => 'http://vmpooler.com', - 'token' => 'krypto-knight' + 'url' => 'http://vmpooler.com', + 'token' => 'krypto-knight' } } } allow(Conf).to receive(:read_config).and_return(config) expect(Utils.get_vmpooler_service_config(config['services']['myabs']['vmpooler_fallback'])).to include({ - 'url' => 'http://vmpooler.com', - 'token' => 'krypto-knight', - 'user' => 'foo', - 'type' => 'vmpooler' - }) + 'url' => 'http://vmpooler.com', + 'token' => 'krypto-knight', + 'user' => 'foo', + 'type' => 'vmpooler' + }) end end end diff --git a/vmfloaty.gemspec b/vmfloaty.gemspec index 184247b..572c255 100644 --- a/vmfloaty.gemspec +++ b/vmfloaty.gemspec @@ -8,9 +8,12 @@ Gem::Specification.new do |s| s.version = Vmfloaty::VERSION s.authors = [ 'Brian Cain', - 'Puppet' + 'Puppet', + ] + s.email = [ + 'brianccain@gmail.com', + 'dio-gems@puppet.com', ] - s.email = 'info@puppet.com' s.license = 'Apache-2.0' s.homepage = 'https://github.com/puppetlabs/vmfloaty' s.description = 'A helper tool for vmpooler to help you stay afloat' @@ -21,6 +24,7 @@ Gem::Specification.new do |s| s.test_files = Dir['spec/**/*'] s.require_path = 'lib' - s.add_dependency 'commander', '>= 4.4.3', '< 4.7.0' - s.add_dependency 'faraday', '~> 1.5', '>= 1.5.1' + s.add_dependency 'colorize', '~> 0.8.1' + s.add_dependency 'commander', '>= 4.4.3', '< 4.6.0' + s.add_dependency 'faraday', '~> 0.17.0' end