bento-ya 0.1.4 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +19 -0
- data/CHANGELOG.md +20 -1
- data/Gemfile +11 -2
- data/README.md +1 -1
- data/Rakefile +22 -1
- data/bento-ya.gemspec +4 -5
- data/bin/bento +1 -1
- data/lib/bento.rb +2 -2
- data/lib/bento/build.rb +19 -13
- data/lib/bento/buildmetadata.rb +10 -10
- data/lib/bento/cli.rb +47 -64
- data/lib/bento/common.rb +55 -17
- data/lib/bento/delete.rb +6 -6
- data/lib/bento/normalize.rb +5 -6
- data/lib/bento/packerexec.rb +0 -1
- data/lib/bento/providermetadata.rb +26 -12
- data/lib/bento/release.rb +7 -7
- data/lib/bento/revoke.rb +7 -7
- data/lib/bento/test.rb +15 -11
- data/lib/bento/upload.rb +19 -10
- data/lib/bento/version.rb +1 -1
- data/templates/bootstrap.sh.erb +1 -0
- data/templates/kitchen.yml.erb +3 -3
- metadata +11 -26
- data/lib/bento/build_remote.rb +0 -116
- data/lib/bento/httpstuff.rb +0 -73
- data/lib/bento/vagrantcloud.rb +0 -138
data/lib/bento/build_remote.rb
DELETED
@@ -1,116 +0,0 @@
|
|
1
|
-
require 'buildkit'
|
2
|
-
|
3
|
-
class BuildRemoteRunner
|
4
|
-
include Common
|
5
|
-
|
6
|
-
attr_reader :bento_version, :dry_run, :platforms, :queue, :token, :s3_endpoint, :s3_bucket
|
7
|
-
|
8
|
-
def initialize(opts)
|
9
|
-
@dry_run = opts.dry_run
|
10
|
-
@bento_version = opts.override_version
|
11
|
-
@platforms = opts.platforms
|
12
|
-
@org = ENV['BUILDKITE_ORG']
|
13
|
-
@queue = ENV['BUILDKITE_QUEUE']
|
14
|
-
@token = ENV['BUILDKITE_TOKEN']
|
15
|
-
@s3_endpoint ||= ENV['BENTO_S3_ENDPOINT'] # 'https://s3.amazonaws.com''
|
16
|
-
@s3_bucket ||= ENV['BENTO_S3_BUCKET'] # 'opscode-vm-bento''
|
17
|
-
end
|
18
|
-
|
19
|
-
def start
|
20
|
-
msg_pre = dry_run ? "DRY RUN: " : ""
|
21
|
-
|
22
|
-
banner("#{msg_pre}Scheduling builds for Bento Version: #{bento_version}")
|
23
|
-
time = Benchmark.measure do
|
24
|
-
builds['public'].each do |platform, versions|
|
25
|
-
versions.each do |version, archs|
|
26
|
-
archs.each do |arch|
|
27
|
-
builds['providers'].each do |provider|
|
28
|
-
build(platform, version, arch, provider, bento_version, dry_run)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
banner("#{msg_pre}Scheduling finished in #{duration(time.real)}.")
|
35
|
-
end
|
36
|
-
|
37
|
-
private
|
38
|
-
|
39
|
-
def bk_uri
|
40
|
-
"v1/organizations/#{org}"
|
41
|
-
end
|
42
|
-
|
43
|
-
def bento_upload
|
44
|
-
"1"
|
45
|
-
end
|
46
|
-
|
47
|
-
def build(platform, version, arch, provider, bento_version, dry_run)
|
48
|
-
plat = platform.include?('omnios') ? "#{platform}-#{version}" : "#{platform}-#{version}-#{arch}"
|
49
|
-
atlas_name = /(.*)64/.match(arch) ? plat.chomp("-#{arch}") : plat
|
50
|
-
no_shared = builds['no_shared_folder'].include?("#{platform}-#{version}-#{arch}-#{provider}") || builds['no_shared_folder'].include?("#{platform}-#{version}-#{arch}-all")
|
51
|
-
test_shared = no_shared ? "0" : "1"
|
52
|
-
unless builds['broken'].include?("#{plat}-#{provider}") || builds['broken'].include?("#{plat}-all")
|
53
|
-
build = {
|
54
|
-
"commit"=> "HEAD",
|
55
|
-
"branch"=> "master",
|
56
|
-
"message"=> "#{plat}-#{provider}",
|
57
|
-
"env"=> {
|
58
|
-
"ATLAS_ORG" => atlas_org,
|
59
|
-
"ATLAS_TOKEN" => atlas_token,
|
60
|
-
"ATLAS_NAME" => atlas_name,
|
61
|
-
"AWS_ACCESS_KEY_ID" => ENV['AWS_ACCESS_KEY_ID'],
|
62
|
-
"AWS_SECRET_ACCESS_KEY" => ENV['AWS_SECRET_ACCESS_KEY'],
|
63
|
-
"AWS_REGION" => 'us-east-1',
|
64
|
-
"BENTO_TEST_SHARED_FOLDER" => test_shared,
|
65
|
-
"BENTO_UPLOAD" => bento_upload,
|
66
|
-
"BENTO_VERSION" => bento_version,
|
67
|
-
"BENTO_S3_ENDPOINT" => s3_endpoint,
|
68
|
-
"BENTO_S3_BUCKET" => s3_bucket,
|
69
|
-
"BENTO_PROVIDERS" => provider,
|
70
|
-
"PLATFORM" => plat,
|
71
|
-
}
|
72
|
-
}
|
73
|
-
puts " - #{plat}-#{provider}"
|
74
|
-
client.post("/#{bk_uri}/projects/bento-#{provider.chomp('-iso')}/builds", build) unless dry_run
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
def client
|
79
|
-
Buildkit.new(token: token)
|
80
|
-
end
|
81
|
-
|
82
|
-
def create_project
|
83
|
-
project = {
|
84
|
-
"name"=> project,
|
85
|
-
"repository"=>"git@github.com:chef/bento.git",
|
86
|
-
"env"=>{"BUILDKITE_BIN_PATH" => "/usr/local/opt/buildkite-agent/bin"},
|
87
|
-
"steps"=>
|
88
|
-
[{"type"=>"script",
|
89
|
-
"name"=>"build",
|
90
|
-
"command"=>"build.sh",
|
91
|
-
"agent_query_rules"=>["queue=#{queue}"]
|
92
|
-
}
|
93
|
-
]
|
94
|
-
}
|
95
|
-
|
96
|
-
puts "Creating Project #{project['name']}"
|
97
|
-
client.post("/#{bk_uri}/projects", project)
|
98
|
-
end
|
99
|
-
|
100
|
-
def delete_project
|
101
|
-
banner("Deleting Project #{project['name']}")
|
102
|
-
client.delete("/#{bk_uri}/projects/#{project}")
|
103
|
-
end
|
104
|
-
|
105
|
-
def get_builders(provider)
|
106
|
-
organization = client.organization(org)
|
107
|
-
agents = organization.rels[:agents].get.data
|
108
|
-
|
109
|
-
banner("Available Builders for provider: #{provider}")
|
110
|
-
agents.each do |agent|
|
111
|
-
if agent[:meta_data].include? "#{provider.chomp('-iso')}=true"
|
112
|
-
puts " - #{agent[:name]}"
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|
data/lib/bento/httpstuff.rb
DELETED
@@ -1,73 +0,0 @@
|
|
1
|
-
require 'net/http'
|
2
|
-
|
3
|
-
module HttpStuff
|
4
|
-
|
5
|
-
def class_for_request(verb)
|
6
|
-
Net::HTTP.const_get(verb.to_s.capitalize)
|
7
|
-
end
|
8
|
-
|
9
|
-
def build_uri(verb, path, params = {})
|
10
|
-
if %w(delete, get).include?(verb)
|
11
|
-
path = [path, to_query_string(params)].compact.join('?')
|
12
|
-
end
|
13
|
-
|
14
|
-
# Parse the URI
|
15
|
-
uri = URI.parse(path)
|
16
|
-
|
17
|
-
# Don't merge absolute URLs
|
18
|
-
uri = URI.parse(File.join(endpoint, path)) unless uri.absolute?
|
19
|
-
|
20
|
-
# Return the URI object
|
21
|
-
uri
|
22
|
-
end
|
23
|
-
|
24
|
-
def to_query_string(hash)
|
25
|
-
hash.map do |key, value|
|
26
|
-
"#{CGI.escape(key)}=#{CGI.escape(value)}"
|
27
|
-
end.join('&')[/.+/]
|
28
|
-
end
|
29
|
-
|
30
|
-
def request(verb, url, data = {}, headers = {})
|
31
|
-
uri = build_uri(verb, url, data)
|
32
|
-
|
33
|
-
# Build the request.
|
34
|
-
request = class_for_request(verb).new(uri.request_uri)
|
35
|
-
if %w(patch post put delete).include?(verb)
|
36
|
-
if data.respond_to?(:read)
|
37
|
-
request.content_length = data.size
|
38
|
-
request.body_stream = data
|
39
|
-
elsif data.is_a?(Hash)
|
40
|
-
request.form_data = data
|
41
|
-
else
|
42
|
-
request.body = data
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
# Add headers
|
47
|
-
headers.each do |key, value|
|
48
|
-
request.add_field(key, value)
|
49
|
-
end
|
50
|
-
|
51
|
-
connection = Net::HTTP.new(uri.host, uri.port)
|
52
|
-
|
53
|
-
if uri.scheme == 'https'
|
54
|
-
require 'net/https' unless defined?(Net::HTTPS)
|
55
|
-
|
56
|
-
# Turn on SSL
|
57
|
-
connection.use_ssl = true
|
58
|
-
connection.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
59
|
-
end
|
60
|
-
|
61
|
-
connection.start do |http|
|
62
|
-
response = http.request(request)
|
63
|
-
|
64
|
-
case response
|
65
|
-
when Net::HTTPRedirection
|
66
|
-
redirect = URI.parse(response['location'])
|
67
|
-
request(verb, redirect, data, headers)
|
68
|
-
else
|
69
|
-
response
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
data/lib/bento/vagrantcloud.rb
DELETED
@@ -1,138 +0,0 @@
|
|
1
|
-
require 'bento/common'
|
2
|
-
require 'bento/httpstuff'
|
3
|
-
|
4
|
-
module VgCloud
|
5
|
-
include Common
|
6
|
-
include HttpStuff
|
7
|
-
|
8
|
-
def vgc_api
|
9
|
-
@vgc_api ||= 'https://vagrantcloud.com/api/v1'
|
10
|
-
end
|
11
|
-
|
12
|
-
def vgc_org
|
13
|
-
@vgc_org ||= ENV['ATLAS_ORG']
|
14
|
-
end
|
15
|
-
|
16
|
-
def vgc_token
|
17
|
-
@vgc_token ||= ENV['ATLAS_TOKEN']
|
18
|
-
end
|
19
|
-
|
20
|
-
def box_create(boxname)
|
21
|
-
req = request('get', "#{vgc_api}/box/#{vgc_org}/#{boxname}", { 'box[username]' => vgc_org, 'access_token' => vgc_token } )
|
22
|
-
if req.code.eql?('404')
|
23
|
-
req = request('post', "#{vgc_api}/boxes", { 'box[name]' => boxname, 'box[username]' => vgc_org, 'access_token' => vgc_token }, { 'Content-Type' => 'application/json' } )
|
24
|
-
box_set_public(boxname) unless private_box?(boxname)
|
25
|
-
else
|
26
|
-
banner("The box #{boxname} exists in Atlas, continuing...")
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def box_create_providers(boxname, version, provider_names)
|
31
|
-
provider_names.each do |provider|
|
32
|
-
banner("Creating provider #{provider} for #{boxname} #{version}")
|
33
|
-
req = request('post', "#{vgc_api}/box/#{vgc_org}/#{boxname}/version/#{version}/providers", { 'provider[name]' => provider, 'access_token' => vgc_token }, { 'Content-Type' => 'application/json' } )
|
34
|
-
banner("Created #{provider} for #{boxname} #{version}") if req.code == '200'
|
35
|
-
banner("Provider #{provider} for #{boxname} #{version} already exists, continuing.") if req.code == '422'
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def box_create_version(boxname, version, md_json)
|
40
|
-
payload = {
|
41
|
-
'version[version]' => version,
|
42
|
-
'access_token' => vgc_token,
|
43
|
-
'version[description]' => File.read(md_json)
|
44
|
-
}
|
45
|
-
req = request('post', "#{vgc_api}/box/#{vgc_org}/#{boxname}/versions", payload, { 'Content-Type' => 'application/json' } )
|
46
|
-
|
47
|
-
banner("Created box version #{boxname} #{version}.") if req.code == '200'
|
48
|
-
banner("Box version #{boxname} #{version} already exists, continuing.") if req.code == '422'
|
49
|
-
end
|
50
|
-
|
51
|
-
def box_delete_version(boxname, version)
|
52
|
-
banner("Deleting version #{version} of box #{boxname}")
|
53
|
-
req = request('delete', "#{vgc_api}/box/#{vgc_org}/#{boxname}/version/#{version}", { 'access_token' => vgc_token }, { 'Content-Type' => 'application/json' })
|
54
|
-
|
55
|
-
case req.code
|
56
|
-
when '200'
|
57
|
-
banner("Version #{version} of box #{boxname} has been successfully deleted")
|
58
|
-
when '404'
|
59
|
-
warn("No box exists for this version")
|
60
|
-
else
|
61
|
-
warn("Something went wrong #{req.code}")
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def box_release_version(boxname, version)
|
66
|
-
case box_status(boxname, version)
|
67
|
-
when 'unreleased'
|
68
|
-
banner("Releasing version #{version} of box #{boxname}")
|
69
|
-
req = request('put', "#{vgc_api}/box/#{vgc_org}/#{boxname}/version/#{version}/release", { 'access_token' => vgc_token }, { 'Content-Type' => 'application/json' })
|
70
|
-
if req.code == '200'
|
71
|
-
banner("Version #{version} of box #{boxname} has been successfully released")
|
72
|
-
else
|
73
|
-
warn("Something went wrong #{req.code}")
|
74
|
-
end
|
75
|
-
when 'active'
|
76
|
-
banner("Version #{version} of box #{boxname} has already been released - nothing to do")
|
77
|
-
else
|
78
|
-
warn("Unexpected status retrieved from Atlas")
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
def box_revoke_version(boxname, version)
|
83
|
-
banner("Revoking version #{version} of box #{boxname}")
|
84
|
-
req = request('put', "#{vgc_api}/box/#{vgc_org}/#{boxname}/version/#{version}/revoke", { 'access_token' => vgc_token }, { 'Content-Type' => 'application/json' })
|
85
|
-
if req.code == '200'
|
86
|
-
banner("Version #{version} of box #{boxname} has been successfully revoked")
|
87
|
-
else
|
88
|
-
banner("Something went wrong #{req.code}")
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
def box_status(boxname, version)
|
93
|
-
req = request('get', "#{vgc_api}/box/#{vgc_org}/#{boxname}/version/#{version}", { 'access_token' => vgc_token }, { 'Content-Type' => 'application/json' })
|
94
|
-
status = JSON.parse(req.body)['status']
|
95
|
-
end
|
96
|
-
|
97
|
-
def box_set_public(boxname)
|
98
|
-
banner("Making #{boxname} public")
|
99
|
-
req = request('put', "#{vgc_api}/box/#{vgc_org}/#{boxname}", { 'box[is_private]' => false, 'access_token' => vgc_token }, { 'Content-Type' => 'application/json' } )
|
100
|
-
banner("#{boxname} successfully made public") if req.code == '200'
|
101
|
-
end
|
102
|
-
|
103
|
-
def box_upload(md_file)
|
104
|
-
md = box_metadata(md_file)
|
105
|
-
boxname = md['name']
|
106
|
-
version = md['version']
|
107
|
-
providers = md['providers']
|
108
|
-
|
109
|
-
box_create(boxname)
|
110
|
-
box_create_version(boxname, version, md_file)
|
111
|
-
box_create_providers(boxname, version, providers.keys)
|
112
|
-
|
113
|
-
providers.each do |provider, provider_data|
|
114
|
-
boxfile = provider_data['file']
|
115
|
-
req = request('get', "#{vgc_api}/box/#{vgc_org}/#{boxname}/version/#{version}/provider/#{provider}/upload?access_token=#{vgc_token}")
|
116
|
-
upload_path = JSON.parse(req.body)['upload_path']
|
117
|
-
token = JSON.parse(req.body)['token']
|
118
|
-
|
119
|
-
banner("Vagrant Cloud: Uploading #{boxfile}")
|
120
|
-
info("Name: #{boxname}")
|
121
|
-
info("Version: #{version}")
|
122
|
-
info("Provider: #{provider}")
|
123
|
-
|
124
|
-
upload_request = request('put', upload_path, File.open("builds/#{boxfile}"))
|
125
|
-
|
126
|
-
req = request('get', "#{vgc_api}/box/#{vgc_org}/#{boxname}/version/#{version}/provider/#{provider}?access_token=#{vgc_token}")
|
127
|
-
hosted_token = JSON.parse(req.body)['hosted_token']
|
128
|
-
|
129
|
-
if token == hosted_token
|
130
|
-
banner("Successful upload of box #{boxfile}")
|
131
|
-
else
|
132
|
-
banner("Failed upload due to non-matching tokens of box #{boxfile} to atlas box: #{boxname}, version: #{version}, provider: #{provider}")
|
133
|
-
warn("Code: #{req.code}")
|
134
|
-
warn("Body: #{req.body}")
|
135
|
-
end
|
136
|
-
end
|
137
|
-
end
|
138
|
-
end
|