Class: KnifeFlow::Release

Inherits:
Chef::Knife
  • Object
show all
Defined in:
lib/chef/knife/release.rb

Constant Summary collapse

WORKING_BRANCH =
"develop"
CANDIDATE_ENVIRONMENT =
"candidate"

Instance Method Summary collapse

Instance Method Details

#apply_config(config_file_path) ⇒ Object



123
124
125
126
# File 'lib/chef/knife/release.rb', line 123

def apply_config(config_file_path)
  Chef::Config.from_file(config_file_path)
  Chef::Config.merge!(config)
end

#check_branch(name) ⇒ Object



155
156
157
158
159
160
161
162
# File 'lib/chef/knife/release.rb', line 155

def check_branch(name)
  if (`git status` =~ /#{name}/) != nil
    return true
  else
    ui.error("USAGE: you must be in the #{name} branch.")
    exit 1
  end
end

#checkout_branch(name) ⇒ Object



137
138
139
140
141
# File 'lib/chef/knife/release.rb', line 137

def checkout_branch(name)
  print "--------------------------------- \n"
  system("git checkout #{name}")
  print "--------------------------------- \n"
end

#checkout_tag(name) ⇒ Object



143
144
145
146
147
# File 'lib/chef/knife/release.rb', line 143

def checkout_tag(name)
  print "--------------------------------- \n"
  system("git checkout #{name}")
  print "--------------------------------- \n"
end

#commit_and_push_branch(branch, comment) ⇒ Object



128
129
130
131
132
133
134
135
# File 'lib/chef/knife/release.rb', line 128

def commit_and_push_branch(branch, comment)
  print "--------------------------------- \n"
  system("git pull origin #{branch}") 
  system("git add .")
  system("git commit -am  '#{comment}'")
  system("git push origin #{branch}")
  print "--------------------------------- \n"
end

#find_version(name) ⇒ Object



173
174
175
176
# File 'lib/chef/knife/release.rb', line 173

def find_version(name)
 loader = Chef::CookbookLoader.new(@cookbook_path)
 return loader[name].version
end

#increment_version(version) ⇒ Object



178
179
180
181
182
# File 'lib/chef/knife/release.rb', line 178

def increment_version(version)
 current_version = version.split(".").map{|i| i.to_i}
 current_version[2] = current_version[2] + 1
 return current_version.join('.')
end

#load_env_file(env_name) ⇒ Object



114
115
116
117
118
119
120
121
# File 'lib/chef/knife/release.rb', line 114

def load_env_file(env_name)
  if File.exist?("environments/#{env_name}.json")
    File.read("environments/#{env_name}.json")
  else
    # TODO - we should handle the creation of the environment.json file if it doesn't exist.
    raise ArgumentError, "environments/#{env_name}.json was not found; please create the environment file manually.#{env_name}"
  end
end

#parse_name_args!Object



164
165
166
167
168
169
170
171
# File 'lib/chef/knife/release.rb', line 164

def parse_name_args!
  if name_args.empty?
    ui.error("USAGE: knife release ENVIRONMENT TAG")
    exit 1
  else
    return name_args
  end
end

#pull_branch(name) ⇒ Object



149
150
151
152
153
# File 'lib/chef/knife/release.rb', line 149

def pull_branch(name)
  print "--------------------------------- \n"
  system("git pull origin #{name}")
  print "--------------------------------- \n"
end

#replace_version(search_string, replace_string, file) ⇒ Object



184
185
186
187
188
189
190
# File 'lib/chef/knife/release.rb', line 184

def replace_version(search_string, replace_string, file)
  open_file = File.open(file, "r")
  body_of_file = open_file.read
  open_file.close
  body_of_file.gsub!(search_string, replace_string)
  File.open(file, "w") { |file| file << body_of_file }
end

#runObject



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
# File 'lib/chef/knife/release.rb', line 35

def run

  all_args = parse_name_args!
  env_name = all_args[0]
  tag_name = all_args[1]
 
  self.config = Chef::Config.merge!(config)
   
  switch_org(env_name)

  self.config = Chef::Config.merge!(config)

  if !config[:cookbook_path]
    raise ArgumentError, "Default cookbook_path is not specified in the knife.rb config file, and a value to -o is not provided. Nowhere to write the new cookbook to." 
  end
  @cookbook_path = Array(config[:cookbook_path]).first
  
  if check_branch(WORKING_BRANCH)
    
    pull_branch(WORKING_BRANCH)

    system("git fetch --tags")

    # 1) start a new git-flow release
    system("git flow release start #{tag_name}")
  
    candidate_json = load_env_file(CANDIDATE_ENVIRONMENT)
    candidate_data = JSON.parse(candidate_json)
    
    env_json = load_env_file(env_name)
    env_data = JSON.parse(env_json)

    cb_a = [] 
    candidate_data.cookbook_versions.each do | book_data |
      cb_a << book_data[0]
  
      # 2) add or update the cookbook in the environment cookbook_versions list
      env_data.cookbook_versions.merge!(book_data[0] => book_data[1])
   
    end
    
    # 3) write the environment to file
    File.open("environments/#{env_name}.json","w") do |f|
      f.write(JSON.pretty_generate(env_data))
    end
    
    # 4) upload cookbooks to chef server
    cookbook_up = Chef::Knife::CookbookUpload.new
    cookbook_up.name_args = cb_a
    cookbook_up.config[:freeze] = true
    cookbook_up.run  

    # 5) upload environment to chef server
    knife_environment_from_file = Chef::Knife::EnvironmentFromFile.new
    knife_environment_from_file.name_args = ["#{env_name}.json"]
    output = knife_environment_from_file.run

    # 6) commit all changes and finish the git-flow release
    system("git commit -am 'the candidate environemnt is now in production and tagged #{tag_name}'")
    system("git flow release finish -m 'testing' #{tag_name}") 

    system("git push origin #{WORKING_BRANCH} --tags")

  end

end

#switch_org(env_name) ⇒ Object



102
103
104
105
106
107
108
109
110
111
112
# File 'lib/chef/knife/release.rb', line 102

def switch_org(env_name)
  # TODO - someone smarter than me can switch the organization without requiring 2 different knife.rb files
  current_dir = File.dirname(__FILE__)   
  case env_name
  when "innovate", "production"
    Chef::Config[:config_file] = File.join File.expand_path('.chef'), "knife-production.rb"
  when "candidate"
    Chef::Config[:config_file] = File.join File.expand_path('.chef'), "knife.rb"
  end
  ::File::open(config[:config_file]) { |f| apply_config(f.path) }
end