Skip to content
This repository has been archived by the owner on Dec 8, 2020. It is now read-only.

Promote() should use the version that the user defined in YAML, not just latest #62

Open
lvw5264 opened this issue Jan 30, 2019 · 1 comment

Comments

@lvw5264
Copy link

lvw5264 commented Jan 30, 2019

I had a use case where we don't use composite content views, yet I wanted the promote command to use the content view version I defined. However, for some reason the promote command always uses the latest and does not check for the version the user defined in :cv: under YAML at all.

I suggest a solution in the code below, allowing the user specified version in YAML to be used, as well as latest. since I just hacked this together by combining aspects of the update() function, I will just paste the promote() function I made.

Also when the request in promote() gave a 400 bad request, as the exception was not handled, so I added a rescue statement, which now helpfully tells the command line user that they "Cannot promote environment out of sequence. Use force to bypass restriction.".

The YAML I use, where i have Library.yaml , dev.yaml (always kept up to date with Library), test.yaml, prod.yaml.

# prod.yaml
:settings:
  :user: admin
  :pass: YOURPASSWORD
  :uri: https://localhost
  :timeout: 300
  :org: 1              # always 1 
  :lifecycle: 6        # ID of the lifecycle, not always obvious
  :checkrepos: true    # check if the latest repo packages are already in the curre
nt content view
  :promote_cvs: true   # don't use composite content views for publishing
  :keep: 5
  :wait: false         # should cvmanager wait for tasks to finish, or run them in 
the background
  :sequential: 1       # run only one task at once
:cv:
  rhel7: 10.0   # I specifically want version 10 and not the latest 12
:publish:
  - rhel7
:promote:
  - rhel7

The promote() function:

def promote()
  tasks = []

  ccvs = []
  req = @api.resource(:content_views).call(:index, {:organization_id => @options[:org], :full_results => true})
  ccvs.concat(req['results'])
  while (req['results'].length == req['per_page'].to_i)
    req = @api.resource(:content_views).call(:index, {:organization_id => @options[:org], :full_results => true, :per_page => req['per_page'], :page => req['page'].to_i+1})
    ccvs.concat(req['results'])
  end

  ccvs.each do |ccv|
    next if not ccv['composite'] and not @options[:promote_cvs]
    next if not @yaml[:promote].include?(ccv['label']) and not @yaml[:promote].include?("all")

    puts "Inspecting #{ccv['label']}"

    # get the desired version for this component from the YAML
    # either the version for the component in this CCV is set
    # or it is set globally
    # never touch non-mentioned components
    if @yaml[:cv].is_a?(Hash) and @yaml[:cv].has_key?(ccv['label'])
      users_version = @yaml[:cv][ccv['label']]
      puts_verbose "  Desired version #{users_version} found in CV"

      # instead of hard-coding the versions, the user can also specify "latest"
      # figure out the latest content view version, choose it, unless there is none
      if users_version == 'latest'
        desired_version = ccv['versions'].sort_by { |v| v['version'].to_f }.reverse[0]
        next if ! desired_version
      else
        desired_version = ccv['versions'].select {|v| v["version"].to_f == users_version }[0]
        next if ! desired_version
      end
    else
      puts_verbose "  Desired version not found, skipping"
      next
    end

    if not desired_version['environment_ids'].include?(@options[:lifecycle])
      puts " Promoting version #{desired_version['version']} to lifecycle-environment #{@options[:lifecycle]}"
      if not @options[:noop]
        begin
          req = @api.resource(:content_view_versions).call(:promote, {:id => desired_version['id'], :environment_id => @options[:lifecycle], :force => @options[:force]})
          tasks << req['id']
          wait([req['id']]) if @options[:sequential]
        rescue RestClient::ExceptionWithResponse => e # catch exceptions with more helpful error content
          puts e.response
        end
      else
        puts " [noop] Promoting #{desired_version['version']} to lifecycle-environment #{@options[:lifecycle]}"
      end
    end
  end

  wait(tasks)
end
@kallies
Copy link

kallies commented Mar 12, 2019

We ran into the same issue. We divided our systems into patching units and the first unit gets patches from the current month ad the second unit gets patches from last month. There are additional LCEs around (for testing, different states and so on), but I'd say they can be ignored in this case.

We keep two cvmanager configurations:

current month example:

---
:settings:
...
:ccv:
  ccv-lin-7:
    cv-lin-7-os: 150.0
    cv-lin-7-base: 162.0
:promote:
  - ccv-lin-7

last month example:

---
:settings:
...
:ccv:
  ccv-lin-7:
    cv-lin-7-os: 139.0
    cv-lin-7-base: 136.0
:promote:
  - ccv-lin-7

To make your proposal work, this requires an additional cv hash:

...
:cv:
  ccv-lin-7: 12.0
...

This example worked in a test. Nice would be to auto-detect the CCV version ID based on the configured CV version IDs (if not present the CCV it would be necessary to publish a new CCV anyway).

We do incremental CV updates from time to time (if a critical patch needs to find its way to an existing view) which increment the CCVs as well. This is more a topic of updating the config (e.g. ccv-lin-7: 12.1) but should be kept in mind when testing this feature.

@lvw5264 can you create a pull request with your code? This would simplify comments on particular lines of code.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants