-
Notifications
You must be signed in to change notification settings - Fork 6
/
coa_version_update.rb
executable file
·154 lines (128 loc) · 4.84 KB
/
coa_version_update.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#!/usr/bin/env ruby
require 'yaml'
require 'open3'
require 'json'
require 'optparse'
class CommandLineParser
OPTIONS = {
concourse_url: '',
concourse_username: 'atc',
concourse_password: '',
concourse_target: 'coa-version',
coa_version: ''
}.freeze
def initialize(options = OPTIONS.dup)
@options = options
end
def parse
options = @options
opt_parser = OptionParser.new do |opts|
opts.banner = "Incomplete/wrong parameter(s): #{opts.default_argv}.\n Usage: ./#{opts.program_name} <options>"
opts.on('-c', '--config URL', "MANDATORY - concourse url. Default: #{options[:concourse_url]}") do |c_string|
options[:concourse_url] = c_string
end
opts.on('-v', '--version VERSION', 'MANDATORY - coa version to switch to v<x.y.z>') do |v_string|
options[:coa_version] = v_string if v_string =~ /v\d{1,2}\.\d{1,2}\.\d{1,2}/
end
opts.on('-p', '--password VALUE', "MANDATORY - concourse admin password. Default: #{options[:concourse_password]}") do |p_string|
options[:concourse_password] = p_string
end
opts.on('-u', '--username VALUE', "concourse admin username. Default: #{options[:concourse_username]}") do |u_string|
options[:concourse_username] = u_string
end
opts.on('-t', '--target VALUE', "concourse target name. Default: #{options[:concourse_target]}") do |t_string|
options[:concourse_target] = t_string
end
end
opt_parser.parse!
raise OptionParser::MissingArgument, "'concourse_url', please check required parameter using --help" if options[:concourse_url].to_s.empty?
raise OptionParser::MissingArgument, "'concourse_password', please check required parameter using --help" if options[:concourse_password].to_s.empty?
@options = options
end
end
class CoaVersionUpdate
COA_RESOURCE_NAME = 'cf-ops-automation'.freeze
def initialize(options)
@config = options
@fly_target_base = @config[:concourse_target]
@fly_main = Fly.new(@fly_target_base)
@coa_version = @config[:coa_version]
end
def run
concourse_url = @config[:concourse_url]
concourse_password = @config[:concourse_password]
concourse_username = @config[:concourse_username]
@fly_main.login(url = concourse_url, password = concourse_password)
puts "Teams:"
teams = @fly_main.teams
logged = teams.map do |team|
fly_current_team = Fly.new("#{@fly_target_base}-#{team}")
fly_current_team.login(concourse_url, team, concourse_username, concourse_password)
end
logged.each do |current_fly|
puts "Pipelines:"
pipelines = current_fly.pipelines
pipelines.each do |name, _|
coa_version = @coa_version
begin
check_output = current_fly.check_resource(name, COA_RESOURCE_NAME, coa_version)
puts check_output
rescue FlyError => e
raise e unless e.message =~ /resource 'cf-ops-automation' not found/
puts " > Ignoring #{name}, resource #{COA_RESOURCE_NAME} not found"
end
end
end
end
end
class Fly
def initialize(target)
@target = target
end
def fly(arg, env = {})
env_var = env.collect { |k, v| "#{k}=#{v}" }.join(' ')
out, err, status = Open3.capture3("env #{env_var} fly --target #{@target} #{arg} | tee /tmp/fly.log")
raise FlyError, "Failed: env #{env_var} fly --target #{@target} #{arg} | tee /tmp/fly.log\n #{err unless err.empty?} " if !status.success? || !err.empty? # err =~ /error: websocket: bad handshake/
out
end
def login(url, team = 'main', username = 'atc', password, insecure: false, env: {})
options = ''
options += '--insecure ' if insecure
puts "login --team-name #{team} -u #{username} -p **redacted** -c #{url} #{options}"
fly("login --team-name #{team} -u #{username} -p #{password} -c #{url} #{options}", env)
self
end
def execute(cmd, env = {})
fly("execute #{cmd}", env)
end
def teams(env = {})
teams = []
output = fly("teams", env)
output.each_line do |line|
teams << line.rstrip unless line.to_s.empty?
end
teams
end
def pipelines(env = {})
pipelines = {}
output = fly("pipelines", env)
output.each_line do |line|
matches = line.match /^([\w|-]+)\s+(\w*)\s+(\w*)/
next if matches.nil?
name = matches[1]
paused = matches[2]
public = matches[3]
pipelines[name] = { paused: paused == 'yes', public: public == 'yes' }
end
pipelines
end
def check_resource(pipeline, resource_name, version = '', env = {})
puts "Checking #{pipeline}/#{resource_name}: #{+ version}"
check_resource_cmd = "check-resource --resource #{pipeline}/#{resource_name}"
check_resource_cmd += " -from ref:#{version} " unless version.empty?
fly(check_resource_cmd, env)
end
end
class FlyError < RuntimeError; end
options = CommandLineParser.new.parse
CoaVersionUpdate.new(options).run