joumae 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/README.md +16 -1
- data/exe/joumae +4 -0
- data/integration_test.rb +10 -4
- data/lib/joumae/cli.rb +50 -0
- data/lib/joumae/client.rb +42 -16
- data/lib/joumae/command.rb +57 -0
- data/lib/joumae/command_failed_error.rb +10 -0
- data/lib/joumae/logging.rb +24 -0
- data/lib/joumae/transaction.rb +15 -6
- data/lib/joumae/version.rb +1 -1
- data/lib/joumae.rb +1 -0
- metadata +9 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5d1c747df9f623727c13160a5717d41f3aa0393d
|
4
|
+
data.tar.gz: 5a5a8885e10c261ff9a0c9bc7cfcedc1a00ae1f4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 93c49e86d5d8c965a0092db4cfad1daf54308a4e7c822b5e2abc8a9fe0accdd2549d6f6f9a6a012b280fbe84462e757688d43f001234e95d5bd0efda30059033
|
7
|
+
data.tar.gz: 99491532511ca7b8c12e9ba2b9477fdf6fd50ee73b013d66dc8d014418d46acb3050f6a482629a98864fa4f0790209f9662d7e4ca452f7c95ec7ea3d76ed481c
|
data/README.md
CHANGED
@@ -22,7 +22,22 @@ Or install it yourself as:
|
|
22
22
|
|
23
23
|
## Usage
|
24
24
|
|
25
|
-
|
25
|
+
### CLI
|
26
|
+
|
27
|
+
The `joumae` command allows you to run arbitrary commands while locking a named resource:
|
28
|
+
|
29
|
+
```
|
30
|
+
$ joumae --resource-name your-app-servers run -- bash -c "\"echo Deployment started.; sleep 10; echo Deployment finished.\""
|
31
|
+
```
|
32
|
+
|
33
|
+
If you consecutively ran the command twice, the latter one fails because the resource is already locked.
|
34
|
+
|
35
|
+
The `joumae` command requires two environment variables to be present:
|
36
|
+
|
37
|
+
```
|
38
|
+
export JOUMAE_API_ENDPOINT="https://yourid.execute-api.ap-northeast-1.amazonaws.com/yourstage/"
|
39
|
+
export JOUMAE_API_KEY="eyJ0eXAiOiJKV1QiLCJhbGc..."
|
40
|
+
```
|
26
41
|
|
27
42
|
## Development
|
28
43
|
|
data/exe/joumae
ADDED
data/integration_test.rb
CHANGED
@@ -7,14 +7,20 @@ client = Joumae::Client.create
|
|
7
7
|
|
8
8
|
uuid = SecureRandom.uuid
|
9
9
|
p client.create(uuid)
|
10
|
-
p client.acquire(uuid
|
11
|
-
p client.renew(uuid
|
12
|
-
p client.release(uuid
|
10
|
+
p client.acquire(uuid)
|
11
|
+
p client.renew(uuid)
|
12
|
+
p client.release(uuid)
|
13
13
|
|
14
|
-
|
14
|
+
#Joumae::Command.new(resource_name: "app-development-deployment", owner: "kuoka", client: Joumae::Client.create)
|
15
|
+
|
16
|
+
transaction = Joumae::Transaction.new(resource_name: uuid, client: client)
|
15
17
|
|
16
18
|
transaction.start
|
17
19
|
|
18
20
|
sleep 10
|
19
21
|
|
20
22
|
transaction.finish
|
23
|
+
|
24
|
+
command = Joumae::Command.new("sleep 10", resource_name: uuid, client: client)
|
25
|
+
|
26
|
+
command.run!
|
data/lib/joumae/cli.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
require 'joumae'
|
4
|
+
require "joumae/logging"
|
5
|
+
|
6
|
+
module Joumae
|
7
|
+
class CLI
|
8
|
+
include Logging
|
9
|
+
|
10
|
+
def initialize(argv)
|
11
|
+
@argv = argv
|
12
|
+
end
|
13
|
+
|
14
|
+
def parse!
|
15
|
+
argv = @argv.dup
|
16
|
+
|
17
|
+
opt = OptionParser.new
|
18
|
+
opt.on('--resource-name VALUE') { |v| @resource_name = v }
|
19
|
+
opt.parse!(argv)
|
20
|
+
@sub, *@args= argv
|
21
|
+
debug [@sub, @args]
|
22
|
+
end
|
23
|
+
|
24
|
+
def run!
|
25
|
+
parse!
|
26
|
+
|
27
|
+
case @sub
|
28
|
+
when "run"
|
29
|
+
client = Joumae::Client.create
|
30
|
+
cmd = @args.join(" ")
|
31
|
+
command = Joumae::Command.new(cmd, resource_name: @resource_name, client: client)
|
32
|
+
begin
|
33
|
+
command.run!
|
34
|
+
rescue Joumae::CommandFailedError => e
|
35
|
+
$stderr.puts "#{e.message} Aborting."
|
36
|
+
exit e.status
|
37
|
+
rescue Joumae::Client::ResourceAlreadyLockedError => e
|
38
|
+
$stderr.puts "#{e.message} Aborting."
|
39
|
+
exit 1
|
40
|
+
end
|
41
|
+
else
|
42
|
+
fail "The sub-command #{@sub} does not exist."
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.run!
|
47
|
+
new(ARGV).run!
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/lib/joumae/client.rb
CHANGED
@@ -20,21 +20,21 @@ module Joumae
|
|
20
20
|
post_json(resources_url, {api_key: api_key, name: name})
|
21
21
|
end
|
22
22
|
|
23
|
-
def acquire(name
|
24
|
-
post_json(acquire_resource_url, {api_key: api_key
|
23
|
+
def acquire(name)
|
24
|
+
post_json(acquire_resource_url(name), {api_key: api_key})
|
25
25
|
end
|
26
26
|
|
27
|
-
def renew(name
|
28
|
-
post_json(renew_resource_url, {api_key: api_key
|
27
|
+
def renew(name)
|
28
|
+
post_json(renew_resource_url(name), {api_key: api_key})
|
29
29
|
end
|
30
30
|
|
31
|
-
def release(name
|
32
|
-
post_json(release_resource_url, {api_key: api_key
|
31
|
+
def release(name)
|
32
|
+
post_json(release_resource_url(name), {api_key: api_key})
|
33
33
|
end
|
34
34
|
|
35
35
|
def post_json(url, params={})
|
36
36
|
begin
|
37
|
-
|
37
|
+
debug "POST #{url} #{params.to_json}"
|
38
38
|
request = Net::HTTP::Post.new(url.path, {'Content-Type' =>'application/json'})
|
39
39
|
request.body = params.to_json
|
40
40
|
https = Net::HTTP.new(url.hostname, 443)
|
@@ -45,11 +45,17 @@ module Joumae
|
|
45
45
|
# response = httpclient.post_content(url, params.to_json, header: {'Content-Type' => 'application/json'})
|
46
46
|
|
47
47
|
if response.code == '404'
|
48
|
-
fail "Not found."
|
48
|
+
fail ResourceNotFoundError, "Not found."
|
49
|
+
elsif response.code == '423'
|
50
|
+
response_body_as_json = JSON.parse(response.body)
|
51
|
+
raise ResourceAlreadyLockedError, response_body_as_json["message"]
|
49
52
|
elsif response.code != '200'
|
50
|
-
fail "Unexpected status: #{response.code}"
|
53
|
+
fail UnexpectedError, "Unexpected status: #{response.code}"
|
51
54
|
end
|
52
55
|
|
56
|
+
debug "Code: #{response.code}"
|
57
|
+
debug "Result: #{response.body}"
|
58
|
+
|
53
59
|
response_body = JSON.parse(response.body)
|
54
60
|
response_body
|
55
61
|
rescue => e
|
@@ -62,24 +68,44 @@ module Joumae
|
|
62
68
|
URI.parse("#{api_endpoint}/resources")
|
63
69
|
end
|
64
70
|
|
65
|
-
def acquire_resource_url
|
66
|
-
URI.parse("#{api_endpoint}/resources/acquire")
|
71
|
+
def acquire_resource_url(name)
|
72
|
+
URI.parse("#{api_endpoint}/resources/#{name}/lock/acquire")
|
73
|
+
end
|
74
|
+
|
75
|
+
def renew_resource_url(name)
|
76
|
+
URI.parse("#{api_endpoint}/resources/#{name}/lock/renew")
|
67
77
|
end
|
68
78
|
|
69
|
-
def
|
70
|
-
URI.parse("#{api_endpoint}/resources/
|
79
|
+
def release_resource_url(name)
|
80
|
+
URI.parse("#{api_endpoint}/resources/#{name}/lock/release")
|
71
81
|
end
|
72
82
|
|
73
|
-
|
74
|
-
|
83
|
+
protected
|
84
|
+
|
85
|
+
def debug(msg)
|
86
|
+
logger.debug msg
|
75
87
|
end
|
76
88
|
|
89
|
+
private
|
90
|
+
|
77
91
|
def httpclient
|
78
92
|
@httpclient ||= HTTPClient.new
|
79
93
|
end
|
80
94
|
|
81
95
|
def logger
|
82
|
-
@logger ||= Logger.new(STDOUT)
|
96
|
+
@logger ||= Logger.new(STDOUT).tap do |logger|
|
97
|
+
log_level_from_env = ENV['JOUMAE_LOG_LEVEL'] || 'INFO'
|
98
|
+
logger.level = Logger.const_get(log_level_from_env)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
class ResourceAlreadyLockedError < StandardError
|
103
|
+
end
|
104
|
+
|
105
|
+
class ResourceNotFoundError < StandardError
|
106
|
+
end
|
107
|
+
|
108
|
+
class UnexpectedError < StandardError
|
83
109
|
end
|
84
110
|
end
|
85
111
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'joumae/transaction'
|
2
|
+
require 'joumae/client'
|
3
|
+
require "joumae/command_failed_error"
|
4
|
+
require 'open3'
|
5
|
+
|
6
|
+
module Joumae
|
7
|
+
class Command
|
8
|
+
attr_reader :cmd
|
9
|
+
|
10
|
+
def initialize(cmd, resource_name:, client:)
|
11
|
+
@cmd = cmd
|
12
|
+
@resource_name = resource_name
|
13
|
+
@client = client
|
14
|
+
end
|
15
|
+
|
16
|
+
def logger
|
17
|
+
@logger ||= Logger.new(STDOUT).tap do |logger|
|
18
|
+
log_level_from_env = ENV['JOUMAE_LOG_LEVEL'] || 'INFO'
|
19
|
+
logger.level = Logger.const_get(log_level_from_env)
|
20
|
+
logger.formatter = proc do |severity, datetime, progname, msg|
|
21
|
+
date_format = datetime.strftime("%Y-%m-%d %H:%M:%S")
|
22
|
+
"#{cmd} (#{severity}): #{msg}\n"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def run!
|
28
|
+
status = Joumae::Transaction.run!(resource_name: @resource_name, client: @client) do
|
29
|
+
Open3.popen3("bash") do |i, o, e, w|
|
30
|
+
i.write cmd
|
31
|
+
i.close
|
32
|
+
o.each do |line| puts line end
|
33
|
+
e.each do |line| $stderr.puts line end
|
34
|
+
|
35
|
+
debug w.value
|
36
|
+
|
37
|
+
w.value.exitstatus
|
38
|
+
end
|
39
|
+
end
|
40
|
+
raise Joumae::CommandFailedError.new("Exit status(=#{status}) is non-zero.", status) if status != 0
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def info(msg)
|
46
|
+
logger.info msg
|
47
|
+
end
|
48
|
+
|
49
|
+
def warn(msg)
|
50
|
+
logger.warn msg
|
51
|
+
end
|
52
|
+
|
53
|
+
def debug(msg)
|
54
|
+
logger.debug msg
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Joumae
|
2
|
+
module Logging
|
3
|
+
protected
|
4
|
+
|
5
|
+
def info(msg)
|
6
|
+
logger.info msg
|
7
|
+
end
|
8
|
+
|
9
|
+
def warn(msg)
|
10
|
+
logger.warn msg
|
11
|
+
end
|
12
|
+
|
13
|
+
def debug(msg)
|
14
|
+
logger.debug msg
|
15
|
+
end
|
16
|
+
|
17
|
+
def logger
|
18
|
+
@logger ||= Logger.new(STDOUT).tap do |logger|
|
19
|
+
log_level_from_env = ENV['JOUMAE_LOG_LEVEL'] || 'INFO'
|
20
|
+
logger.level = Logger.const_get(log_level_from_env)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/joumae/transaction.rb
CHANGED
@@ -1,15 +1,14 @@
|
|
1
1
|
module Joumae
|
2
2
|
class Transaction
|
3
|
-
def initialize(resource_name:,
|
3
|
+
def initialize(resource_name:, client:, renew_interval: 1)
|
4
4
|
@resource_name = resource_name
|
5
|
-
@owner = owner
|
6
5
|
@client = client
|
7
6
|
@renew_interval = renew_interval
|
8
7
|
@finished = false
|
9
8
|
end
|
10
9
|
|
11
10
|
def start
|
12
|
-
@client.acquire(@resource_name
|
11
|
+
@client.acquire(@resource_name)
|
13
12
|
|
14
13
|
start_thread
|
15
14
|
end
|
@@ -20,8 +19,8 @@ module Joumae
|
|
20
19
|
@thread = Thread.start {
|
21
20
|
loop do
|
22
21
|
sleep @renew_interval
|
23
|
-
exit if finished?
|
24
|
-
@client.renew(@resource_name
|
22
|
+
@thread.exit if finished?
|
23
|
+
@client.renew(@resource_name)
|
25
24
|
end
|
26
25
|
}
|
27
26
|
end
|
@@ -34,11 +33,21 @@ module Joumae
|
|
34
33
|
|
35
34
|
def finish
|
36
35
|
stop_thread
|
37
|
-
@client.release(@resource_name
|
36
|
+
@client.release(@resource_name)
|
38
37
|
end
|
39
38
|
|
40
39
|
def finished?
|
41
40
|
@finished
|
42
41
|
end
|
42
|
+
|
43
|
+
def self.run!(resource_name:, client:, &block)
|
44
|
+
t = new(resource_name: resource_name, client: client)
|
45
|
+
t.start
|
46
|
+
begin
|
47
|
+
block.call
|
48
|
+
ensure
|
49
|
+
t.finish
|
50
|
+
end
|
51
|
+
end
|
43
52
|
end
|
44
53
|
end
|
data/lib/joumae/version.rb
CHANGED
data/lib/joumae.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: joumae
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yusuke KUOKA
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-11-
|
11
|
+
date: 2015-11-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -55,7 +55,8 @@ dependencies:
|
|
55
55
|
description: A Ruby client library for the Joumae lock service.
|
56
56
|
email:
|
57
57
|
- yusuke.kuoka@crowdworks.co.jp
|
58
|
-
executables:
|
58
|
+
executables:
|
59
|
+
- joumae
|
59
60
|
extensions: []
|
60
61
|
extra_rdoc_files: []
|
61
62
|
files:
|
@@ -68,10 +69,15 @@ files:
|
|
68
69
|
- Rakefile
|
69
70
|
- bin/console
|
70
71
|
- bin/setup
|
72
|
+
- exe/joumae
|
71
73
|
- integration_test.rb
|
72
74
|
- joumae.gemspec
|
73
75
|
- lib/joumae.rb
|
76
|
+
- lib/joumae/cli.rb
|
74
77
|
- lib/joumae/client.rb
|
78
|
+
- lib/joumae/command.rb
|
79
|
+
- lib/joumae/command_failed_error.rb
|
80
|
+
- lib/joumae/logging.rb
|
75
81
|
- lib/joumae/transaction.rb
|
76
82
|
- lib/joumae/version.rb
|
77
83
|
homepage: https://github.com/crowdworks/joumae-ruby
|