biosphere 0.0.11 → 0.0.12

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0459a0449bf2038aed5733a7c5797a16d05565c7
4
- data.tar.gz: 0ba58ee53dd1cced9c435ce00daa960997bb217a
3
+ metadata.gz: 347ecc8394215627d48fae451787d293607fdbad
4
+ data.tar.gz: 8f8e03cc288495d430e0477fa74b5eeb12a933fe
5
5
  SHA512:
6
- metadata.gz: 4d063d3d43599ac7b9ff2dd63541aeefa3e70362478cba3e12db3c08086aa880a63892fde8ddf1f450c913a446e7c94cb17818ed59d87d645e9e1e5010c80730
7
- data.tar.gz: fa7f3248955060ce0ac67539c0d5ac99b376f9bd8961936a167cee9c1b87142ff09686fbff0f85f7b23ce740d309f8beb223eb949cd8a6e7810b02362782afbb
6
+ metadata.gz: 8238bcfcc308dde2a1ee51d88cd6eed69f092f22cef45813b275219358811fd88c12e62c2063ddea6661c6a16c03085bb6b637a3765b896920ed4dbb37700f8c
7
+ data.tar.gz: a3d298603618dcd1163b7e46e8d9578873d471c0378b858be6afb343a8763f9db160e7ecd692e4cda45a703c9a7d0819ba3637d55bcb4d17f7ee15f86d99a58c
@@ -6,13 +6,21 @@ require 'ostruct'
6
6
  require 'pp'
7
7
  require "awesome_print"
8
8
  require 'colorize'
9
+ require 'biosphere/s3.rb'
9
10
 
10
11
  class BiosphereOpts
11
12
 
13
+ def self.normalize_path(path)
14
+ if path[-1] != '/'
15
+ path += '/'
16
+ end
17
+ return path
18
+ end
19
+
12
20
  def self.parse(args)
13
21
 
14
22
  options = OpenStruct.new
15
- options.build = "build"
23
+ options.build_dir = "build"
16
24
  options.src = "./"
17
25
  options.version = ::Biosphere::Version
18
26
 
@@ -23,8 +31,11 @@ class BiosphereOpts
23
31
 
24
32
  opts.separator ""
25
33
  opts.separator "Commands:"
34
+ opts.separator "\tbuild\tWrite tf files as json into build directory"
26
35
  opts.separator "\tplan\tRun the planning phase"
27
- opts.separator "\tjson\tWrite tf files as json into build directory"
36
+ opts.separator "\tcommit\tCommit changes and update the infrastructure"
37
+ opts.separator "\tlock\tAcquire lock for remote state"
38
+ opts.separator "\tunlock\tRelease lock for remote state"
28
39
  opts.separator "\taction [action]\tCall an action defined in the application .rb files"
29
40
  opts.separator ""
30
41
 
@@ -34,12 +45,11 @@ class BiosphereOpts
34
45
  end
35
46
 
36
47
  opts.on("--src PATH", "Directory where the application .rb files are") do |path|
37
- options.src = path
48
+ options.src = normalize_path(path)
38
49
  end
39
50
 
40
-
41
- opts.on("--build PATH", "Directory where to build json files") do |path|
42
- options.build = path
51
+ opts.on("--build-dir PATH", "Directory where to build json files") do |path|
52
+ options.build_dir = normalize_path(path)
43
53
  end
44
54
 
45
55
  end
@@ -62,7 +72,7 @@ if ARGV.length == 0
62
72
  end
63
73
 
64
74
  if !File.directory?(options.src)
65
- STDERR.puts "Directory #{options.build} is not a directory or it doesn't exists."
75
+ STDERR.puts "Directory #{options.build_dir} is not a directory or it doesn't exists."
66
76
  exit -1
67
77
  end
68
78
 
@@ -76,40 +86,47 @@ if options.src
76
86
  STDERR.puts "No files found. Are you in the right directory where your biosphere .rb files are?"
77
87
  exit -1
78
88
  end
79
- end
80
89
 
81
- if options.build
82
- if !File.directory?(options.build)
83
- STDERR.puts "Creating build directory #{options.build} because it was missing"
84
- Dir.mkdir(options.build)
90
+ if suite.node[:settings][:s3_bucket].nil? || suite.node[:settings][:s3_bucket].empty? || suite.node[:settings][:cluster_name].nil? || suite.node[:settings][:cluster_name].empty?
91
+ puts "\nNo S3 bucket or cluster name defined in configuration, can't continue"
92
+ exit 1
85
93
  end
94
+ s3 = S3.new(suite.node[:settings][:s3_bucket], suite.node[:settings][:cluster_name])
86
95
  end
87
96
 
97
+ if options.build_dir
98
+ if !File.directory?(options.build_dir)
99
+ STDERR.puts "Creating build directory #{options.build_dir} because it was missing"
100
+ Dir.mkdir(options.build_dir)
101
+ end
102
+ end
88
103
 
89
- if ARGV[0] == "json" && options.src
104
+ if ARGV[0] == "build" && options.src
90
105
  suite.evaluate_resources()
91
106
 
92
- if !File.directory?(options.build)
93
- STDERR.puts "Directory #{options.build} is not a directory or it doesn't exists."
107
+ if !File.directory?(options.build_dir)
108
+ STDERR.puts "Directory #{options.build_dir} is not a directory or it doesn't exists."
94
109
  exit -1
95
110
  end
96
111
 
97
112
  count = 0
98
- suite.write_json_to(options.build) do |file_name, destination, str, proxy|
113
+ suite.write_json_to(options.build_dir) do |file_name, destination, str, proxy|
99
114
  puts "Wrote #{str.length} bytes from #{file_name} to #{destination} (#{proxy.export["resource"].length} resources)"
100
115
  count = count + 1
101
116
  end
102
117
 
103
- puts "Wrote #{count} files into #{options.build}"
118
+ puts "Wrote #{count} files into #{options.build_dir}"
104
119
  suite.save_node()
105
120
 
106
121
  elsif ARGV[0] == "plan" && options.src
107
122
  suite.evaluate_plans()
108
123
  ap suite.node, :indent=>-4
124
+
109
125
  elsif ARGV[0] == "action" && options.src
126
+ s3.retrieve("#{options.build_dir}terraform.tfstate")
127
+ s3.retrieve("#{options.build_dir}state.node")
110
128
  context = Biosphere::ActionContext.new()
111
-
112
- context.build_directory = options.build
129
+ context.build_directory = options.build_dir
113
130
 
114
131
  if suite.call_action(ARGV[1], context)
115
132
  STDERR.puts "Executing action #{ARGV[1]}"
@@ -118,6 +135,37 @@ elsif ARGV[0] == "action" && options.src
118
135
  end
119
136
 
120
137
  suite.save_node()
138
+
139
+ elsif ARGV[0] == "commit" && options.src
140
+ s3.set_lock()
141
+ s3.retrieve("#{options.build_dir}terraform.tfstate")
142
+ s3.retrieve("#{options.build_dir}state.node")
143
+ tf_plan = %x( terraform plan -state=#{options.build_dir}terraform.tfstate #{options.build_dir} )
144
+ puts "\n" + tf_plan
145
+ answer = ""
146
+ while answer.empty? || (answer != "y" && answer != "n")
147
+ print "\nDoes the plan look reasonable? (Answering yes will apply the changes) y/n: "
148
+ answer = STDIN.gets.chomp
149
+ end
150
+
151
+ if answer == "n"
152
+ puts "\nOk, will not proceed with commit"
153
+ elsif answer == "y"
154
+ puts "\nApplying the changes (this may take several minutes)"
155
+ tf_apply = %x( terraform apply -state=#{options.build_dir}terraform.tfstate #{options.build_dir})
156
+ puts "\n" + tf_apply
157
+ s3.save("#{options.build_dir}terraform.tfstate")
158
+ s3.save("#{options.src}state.node")
159
+ end
160
+
161
+ s3.release_lock()
162
+
163
+ elsif ARGV[0] == "lock"
164
+ s3.set_lock()
165
+
166
+ elsif ARGV[0] == "unlock"
167
+ s3.release_lock()
168
+
121
169
  else
122
170
  STDERR.puts "\nERROR: Unknown command #{ARGV[0]}. Maybe you wanted to do: \"biosphere action #{ARGV[0]}\"?"
123
171
  exit -1
@@ -66,6 +66,7 @@ class Biosphere
66
66
  end
67
67
 
68
68
  ns_prefix = client.build_namespace_prefix(resource[:metadata][:namespace])
69
+ ns_prefix = ns_prefix.empty? ? "namespaces/default/" : ns_prefix
69
70
  ret = client.rest_client[ns_prefix + resource_name].post(resource.to_h.to_json, { 'Content-Type' => 'application/json' }.merge(client.instance_variable_get("@headers")))
70
71
  return {
71
72
  action: :post,
@@ -0,0 +1,82 @@
1
+ require 'aws-sdk'
2
+
3
+ class S3
4
+ def initialize(bucket, main_key)
5
+ @client = Aws::S3::Client.new
6
+ @bucket_name = bucket
7
+ @main_key = main_key
8
+ end
9
+
10
+ def save(path_to_file)
11
+ puts "\nSaving #{path_to_file} to S3"
12
+ filename = path_to_file.split('/')[-1]
13
+ begin
14
+ File.open(path_to_file, 'rb') do |file|
15
+ @client.put_object({
16
+ :bucket => @bucket_name,
17
+ :key => "#{@main_key}/#{filename}",
18
+ :body => file
19
+ })
20
+ end
21
+ rescue
22
+ puts "\nError occurred while saving the remote state, can't continue"
23
+ puts "Error: #{$!}"
24
+ exit 1
25
+ end
26
+ end
27
+
28
+ def retrieve(path_to_file)
29
+ filename = path_to_file.split('/')[-1]
30
+ puts "\nFetching #{filename} from S3"
31
+ begin
32
+ resp = @client.get_object({
33
+ :bucket => @bucket_name,
34
+ :key => "#{@main_key}/#{filename}"
35
+ })
36
+ File.open(path_to_file, 'w') do |f|
37
+ f.puts(resp.body.read)
38
+ end
39
+ rescue Aws::S3::Errors::NoSuchKey
40
+ puts "\nCouldn't find remote file #{filename} from S3."
41
+ rescue
42
+ puts "\nError occurred while fetching the remote state, can't continue."
43
+ puts "Error: #{$!}"
44
+ exit 1
45
+ end
46
+ end
47
+
48
+ def set_lock()
49
+ begin
50
+ resp = @client.get_object({
51
+ :bucket => @bucket_name,
52
+ :key => "#{@main_key}/biosphere.lock"
53
+ })
54
+ puts "\nThe remote state is locked since #{resp.last_modified}\nCan't continue."
55
+ exit 1
56
+ rescue Aws::S3::Errors::NoSuchKey
57
+ puts "\nRemote state was not locked, adding the lockfile.\n"
58
+ @client.put_object({
59
+ :bucket => @bucket_name,
60
+ :key => "#{@main_key}/biosphere.lock"
61
+ })
62
+ rescue
63
+ puts "\There was an error while accessing the lock. Can't continue.'"
64
+ puts "Error: #{$!}"
65
+ exit 1
66
+ end
67
+ end
68
+
69
+ def release_lock()
70
+ begin
71
+ @client.delete_object({
72
+ :bucket => @bucket_name,
73
+ :key => "#{@main_key}/biosphere.lock"
74
+ })
75
+ rescue
76
+ puts "\nCouldn't release the lock!"
77
+ puts "Error: #{$!}"
78
+ exit 1
79
+ end
80
+ puts "\nLock released successfully"
81
+ end
82
+ end
@@ -1,3 +1,3 @@
1
1
  class Biosphere
2
- Version = "0.0.11"
2
+ Version = "0.0.12"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: biosphere
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.11
4
+ version: 0.0.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Juho Mäkinen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-11-09 00:00:00.000000000 Z
11
+ date: 2017-02-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -94,6 +94,20 @@ dependencies:
94
94
  - - '='
95
95
  - !ruby/object:Gem::Version
96
96
  version: 0.8.1
97
+ - !ruby/object:Gem::Dependency
98
+ name: aws-sdk
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '2'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '2'
97
111
  description: "Terraform's HCL lacks quite many programming features like iterators,
98
112
  true variables, advanced string manipulation, functions etc.\n\n This Ruby tool
99
113
  provides an easy-to-use DSL to define Terraform compatible .json files which can
@@ -111,6 +125,7 @@ files:
111
125
  - lib/biosphere/kube.rb
112
126
  - lib/biosphere/mixing/from_file.rb
113
127
  - lib/biosphere/node.rb
128
+ - lib/biosphere/s3.rb
114
129
  - lib/biosphere/suite.rb
115
130
  - lib/biosphere/terraformproxy.rb
116
131
  - lib/biosphere/version.rb