Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 48 additions & 1 deletion lib/puppet_x/puppetlabs/cd4pe_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ class CD4PEClient < Object
SIGNUP_ENDPOINT = '/signup'.freeze
HW_CONFIG_ENDPOINT = '/root/hw-config'.freeze

def initialize(hostname, email = nil, password = nil)
def initialize(hostname, email = nil, password = nil, base64_cacert = nil, insecure_https = false)
uri = URI.parse(hostname)

@config = {
server: uri.host,
port: uri.port || '8080',
scheme: uri.scheme || 'http',
base64_cacert: base64_cacert,
insecure_https: insecure_https,
email: email,
password: password,
}
Expand Down Expand Up @@ -592,6 +594,32 @@ def list_servers
make_request(:get, endpoint)
end

def promote_pipeline_to_stage(workspace, repo_name, repo_type, branch_name, stage_name, commit_sha, commit_message)
pipeline = get_pipeline_for_branch(workspace, repo_name, repo_type, branch_name)
stage_index = CD4PEPipelineUtils.get_stage_index_by_name(pipeline[:stages], stage_name)
unless pipeline[:buildStage] && pipeline[:buildStage][:imageEvent]
raise Puppet::Error "It looks like pipeline has not run before. Please run the pipeline and try promoting again."
end

payload = {
op: 'PipelinePromote',
content: {
pipelineId: pipeline[:id],
branch: branch_name,
sha: commit_sha ? commit_sha : pipeline[:buildStage][:imageEvent][:commitId],
stageNumber: stage_index + 1, # (stage_index starts with 0)
commitMsg: commit_message ? commit_message : pipeline[:buildStage][:imageEvent][:commitMsg],
}
}
if repo_type == 'control'
payload[:content][:controlRepoName] = repo_name
else
payload[:content][:moduleName] = repo_name
end

make_request(:post, get_ajax_endpoint(workspace), payload.to_json)
end

private

def get_repo_payload_key(repo_type)
Expand All @@ -606,7 +634,26 @@ def get_repo_payload_key(repo_type)
end

def make_request(type, api_url, payload = '')
api_url = "#{@config[:path]}#{api_url}"
connection = Net::HTTP.new(@config[:server], @config[:port])

if @config[:scheme] == 'https'
connection.use_ssl = true
if @config[:insecure_https]
connection.verify_mode = OpenSSL::SSL::VERIFY_NONE
else
connection.verify_mode = OpenSSL::SSL::VERIFY_PEER
end
unless @config[:base64_cacert].nil?
store = OpenSSL::X509::Store.new
store.set_default_paths
decoded_cert = Base64.decode64(@config[:base64_cacert])
certificate = OpenSSL::X509::Certificate.new(decoded_cert)
store.add_cert(certificate)
connection.cert_store = store
end
end

headers = {
'Content-Type' => 'application/json',
'Cookie' => @cookie,
Expand Down
64 changes: 64 additions & 0 deletions tasks/promote_pipeline_to_stage.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
{
"description": "Promotes a pipeline to a specified Stage.",
"parameters": {
"email": {
"type": "String[1]",
"description": "The email address associated with the Continuous Delivery for PE login."
},
"password": {
"type": "String[1]",
"sensitive": true,
"description": "The password associated with the account."
},
"base64_cacert": {
"type": "Optional[String[1]]",
"description": "The CA cert of the CD4PE instance, base64 encoded"
},
"insecure_https": {
"type": "Optional[Boolean]",
"description": "Whether or not to make the https calls without verifying the CA cert. Only use this on test systems."
},
"workspace": {
"type": "String[1]",
"description": "Designates the workspace that the repo and pipeline are associated with"
},
"repo_name": {
"type": "String[1]",
"description": "The name of the repo."
},
"repo_type": {
"type": "Enum['module', 'control']",
"description": "The type of repository."
},
"branch_name": {
"type": "String[1]",
"description": "The name of the branch associated with the pipeline."
},
"stage_name": {
"type": "String[1]",
"description": "The name of the pipeline stage that the pipeline should be promoted to."
},
"commit_sha": {
"type": "Optional[String[1]]",
"description": "The commit to promote. If not specified, takes the commit from the latest pipeline run."
},
"commit_message": {
"type": "Optional[String[1]]",
"description": "The commit message to use for the promotion. If not specified, the original commit message of the promoted commit will be used."
},
"resolvable_hostname": {
"type": "Optional[String[1]]",
"description": "Optional. A resolvable internet address where the Continuous Delivery for PE server can be reached. Required only if the agent certificate is not the machine's resolvable internet address."
},
"web_ui_endpoint": {
"type": "Optional[String[1]]",
"description": "Optional. The endpoint where the web UI can be reached, in the form http://<resolvable_hostname>:<port>. Required if you set the web_ui_port parameter in the cd4pe class during installation."
}
},
"files": [
"cd4pe/lib/puppet_x/puppetlabs/cd4pe_client.rb",
"cd4pe/lib/puppet_x/puppetlabs/cd4pe_pipeline_utils.rb"
],

"input_method": "stdin"
}
47 changes: 47 additions & 0 deletions tasks/promote_pipeline_to_stage.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#!/opt/puppetlabs/puppet/bin/ruby

require 'puppet'
require 'uri'

Puppet.initialize_settings
$LOAD_PATH.unshift(Puppet[:plugindest])

params = JSON.parse(STDIN.read)
hostname = params['resolvable_hostname'] || Puppet[:certname]
base64_cacert = params['base64_cacert']
insecure_https = params['insecure_https'] || false
username = params['email']
password = params['password']
workspace = params['workspace']
repo_name = params['repo_name']
repo_type = params['repo_type']
branch_name = params['branch_name']
stage_name = params['stage_name']
commit_message = params['commit_message']
commit_sha = params['commit_sha']

require_relative File.join(params['_installdir'], 'cd4pe', 'lib', 'puppet_x', 'puppetlabs', 'cd4pe_client')
require_relative File.join(params['_installdir'], 'cd4pe', 'lib', 'puppet_x', 'puppetlabs', 'cd4pe_pipeline_utils')

uri = URI.parse(hostname)
hostname = "http://#{hostname}" if uri.scheme.nil?

web_ui_endpoint = params['web_ui_endpoint'] || "#{hostname}:8080"

exitcode = 0
result = {}

begin
client = PuppetX::Puppetlabs::CD4PEClient.new(web_ui_endpoint, username, password, base64_cacert, insecure_https)
result = client.promote_pipeline_to_stage(workspace, repo_name, repo_type, branch_name, stage_name, commit_sha, commit_message).body
rescue => e
result[:_error] = {
msg: "Task failed: #{e.message}",
kind: 'puppetlabs-cd4pe/promote_pipeline_to_stage_error',
details: e.class.to_s,
}
exitcode = 1
end

puts result
exit exitcode