mini_deploy 0.8.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 29a7da0cbac3dccd9249d18a48cbd3fb76df7c1d
4
+ data.tar.gz: 501865051060a1cf435f307c58be370dceded0d2
5
+ SHA512:
6
+ metadata.gz: e98a97777c6e39c88e5ed104589e07110a959a73b8974f430ab98d575685dc20006602d21d543c579c7bf4c639b22cf2fc5f4b4530fdca9b582e2d16d85bf166
7
+ data.tar.gz: 963983a9442785d8e03af7acea3bc82b509f899081d1c58b818124ffeca9eb16e1e5a1df094033181f5b77d2f3479b99bbb96daadcfe575d55eb8273f4507012
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ /sample/
11
+ /config/
12
+ /receipts/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in mini_deploy.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Guanting Chen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,14 @@
1
+ Mini Deploy Tools ( beta )
2
+ =================================================
3
+
4
+ [![Gem Version](https://badge.fury.io/rb/mini_deploy.svg)](https://badge.fury.io/rb/mini_deploy)
5
+ [![Code Climate](https://codeclimate.com/github/guanting112/mini_deploy/badges/gpa.svg)](https://codeclimate.com/github/guanting112/mini_deploy)
6
+
7
+ Installation
8
+ --------
9
+
10
+ Via Rubygems
11
+
12
+ ```shell
13
+ gem install mini_deploy
14
+ ```
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "mini_deploy"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/exe/md ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require 'mini_deploy'
3
+
4
+ MiniDeploy::Cli.start ARGV
@@ -0,0 +1,58 @@
1
+ require 'thor'
2
+ require 'mini_deploy'
3
+ require 'fileutils'
4
+
5
+ module MiniDeploy
6
+ class Cli < Thor
7
+
8
+ desc 'start RECEIPT_FILE --host HOST_FILE', 'Start Task'
9
+ method_option :host, :type => :string
10
+ def start(path)
11
+ Setting[:receipt_file_path] = File.expand_path(path)
12
+ Setting[:host_file_path] = File.expand_path(options[:host])
13
+
14
+ if options[:host].nil?
15
+ puts "Host File Not Found "
16
+ else
17
+ start_tasks_runner
18
+ end
19
+ end
20
+
21
+ desc 'version', 'Prints version'
22
+ def version
23
+ puts VERSION
24
+ end
25
+
26
+ desc 'install', 'Create sample config and receipt file '
27
+ def install
28
+ puts "Create sample config and receipt file. "
29
+
30
+ sample_file = SampleFile.new
31
+
32
+ [ './config/', './receipts/' ].each do |dir_path|
33
+ if Dir.exist?(dir_path)
34
+ puts "* #{dir_path} exists."
35
+ else
36
+ FileUtils.mkdir_p(dir_path)
37
+ puts "* #{dir_path} created."
38
+ end
39
+ end
40
+
41
+ sample_hosts_default_path = './config/sample_hosts.yml'
42
+
43
+ IO.write(sample_hosts_default_path, sample_file.hosts)
44
+ puts "* #{sample_hosts_default_path} create."
45
+
46
+ sample_receipt_default_path = './receipts/sample.yml'
47
+
48
+ IO.write(sample_receipt_default_path, sample_file.receipt)
49
+ puts "* #{sample_receipt_default_path} create."
50
+ end
51
+
52
+ private
53
+
54
+ def start_tasks_runner
55
+ MiniDeploy::TasksRunner.new.start
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,73 @@
1
+ require 'net/ftp'
2
+ require 'mini_deploy/temporary_file'
3
+
4
+ module MiniDeploy
5
+ class ConnectFtp
6
+
7
+ def initialize(host, username, password, passive_mode=false)
8
+ @host = host
9
+ @username = username
10
+ @password = password
11
+ @passive_mode = passive_mode
12
+ @client = Net::FTP.new(host)
13
+ @connect_success = false
14
+ end
15
+
16
+ def connect_success?
17
+ @connect_success
18
+ end
19
+
20
+ def connect
21
+ @client.passive = true if @passive_mode
22
+ @connect_success = @client.login @username, @password
23
+ end
24
+
25
+ def download_to_temp_file(remote_path, options={})
26
+ temp_file = TemporaryFile.new
27
+ happened_error = false
28
+
29
+ @client.getbinaryfile(remote_path, temp_file.current_path)
30
+ rescue Net::FTPPermError
31
+ happened_error = true
32
+ rescue StandardError
33
+ happened_error = true
34
+ ensure
35
+ temp_file.destroy if happened_error
36
+
37
+ return happened_error ? nil : temp_file
38
+ end
39
+
40
+ def upload(upload_local_source, remote_path, mode=:text)
41
+ if mode == :text
42
+ @client.put(upload_local_source, remote_path)
43
+ else
44
+ @client.putbinaryfile(upload_local_source, remote_path)
45
+ end
46
+ end
47
+
48
+ def exists(remote_path)
49
+ @client.size(remote_path)
50
+
51
+ true
52
+ rescue Net::FTPPermError => e
53
+ false
54
+ end
55
+
56
+ def remove(remote_path)
57
+ @client.delete(remote_path)
58
+
59
+ true
60
+ rescue Net::FTPPermError => e
61
+ false
62
+ end
63
+
64
+ def list(arg='*')
65
+ @client.list(arg)
66
+ end
67
+
68
+ def done
69
+ @client.close
70
+ end
71
+
72
+ end
73
+ end
@@ -0,0 +1,7 @@
1
+ module MiniDeploy
2
+ class Error < StandardError; end
3
+ class HostsDataReaderLoadError < Error; end
4
+ class ReceiptReaderLoadError < Error; end
5
+ class ReceiptReaderParseError < Error; end
6
+ class HostsDataNoMatchFound < Error; end
7
+ end
@@ -0,0 +1,35 @@
1
+ require 'yaml'
2
+ require 'mini_deploy/setting'
3
+ require 'mini_deploy/exception'
4
+
5
+ module MiniDeploy
6
+ class HostsDataReader
7
+
8
+ def initialize(host_file_path)
9
+ @host_file_path = host_file_path
10
+ end
11
+
12
+ def fetch
13
+ read_host_data.map { |host_data| format_host_data(host_data) }
14
+ end
15
+
16
+ def format_host_data(host_data)
17
+ {
18
+ node_id: host_data.fetch('node_id'),
19
+ host: host_data.fetch('host'),
20
+ ftp_username: host_data.fetch('ftp_username'),
21
+ ftp_password: host_data.fetch('ftp_password'),
22
+ ftp_passive_mode: host_data.fetch('ftp_passive_mode') { false },
23
+ info: host_data.fetch('info') { nil },
24
+ time: Time.now.utc
25
+ }
26
+ end
27
+
28
+ def read_host_data
29
+ YAML.load(IO.read(@host_file_path))
30
+ rescue StandardError
31
+ raise HostsDataReaderLoadError
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,213 @@
1
+ require 'http'
2
+
3
+ module MiniDeploy
4
+ class Processor
5
+ def initialize(console, original_script, host_data, receipt_data)
6
+ @console = console
7
+ @script = marshal_copy(original_script)
8
+ @host_data = host_data
9
+ @receipt_data = receipt_data
10
+ @ftp = nil
11
+
12
+ create_ftp_client_connect if needs_to_create_ftp
13
+ end
14
+
15
+ def script_tag
16
+ @script[:tag]
17
+ end
18
+
19
+ def script_type
20
+ @script[:process]
21
+ end
22
+
23
+ def upload_file
24
+ @console.log "Upload file to remote server"
25
+
26
+ format_script_data(:upload_local_source, :remote_path)
27
+
28
+ @console.log "Uploading #{@script[:upload_local_source]} "
29
+ @console.log "to #{@script[:remote_path]} "
30
+
31
+ upload_file_content =
32
+ replace_data(IO.read(@script[:upload_local_source]), @host_data[:info])
33
+
34
+ temp_file = TemporaryFile.new
35
+ temp_file.write upload_file_content
36
+
37
+ @ftp.upload(temp_file.current_path, @script[:remote_path])
38
+
39
+ @console.done "Upload Successful"
40
+
41
+ temp_file.done
42
+ @ftp.done
43
+ rescue StandardError => e
44
+ @console.error e.message
45
+ end
46
+
47
+ def find_file_content
48
+ @console.log "Find file on remote server"
49
+
50
+ format_script_data(:remote_file)
51
+
52
+ @console.log "Search \"#{@script[:remote_file]}\" content"
53
+
54
+ temp_file = @ftp.download_to_temp_file(@script[:remote_file])
55
+ file_exists = temp_file.nil? != true
56
+
57
+ if file_exists
58
+ @console.done "File is found"
59
+ match_content = find_file_content_by_io(temp_file.current_path, filter: @script[:search_content], ignore_case: @script[:ignore_case])
60
+
61
+ if match_content.nil?
62
+ @console.error "No match content"
63
+ else
64
+ @console.data match_content
65
+ end
66
+ else
67
+ @console.error "File not found"
68
+ end
69
+
70
+ @ftp.done
71
+ rescue StandardError => e
72
+ @console.error e.message
73
+ end
74
+
75
+ def check_file
76
+ @console.log "Check file on remote server"
77
+
78
+ format_script_data(:remote_file)
79
+
80
+ @console.log "Check \"#{@script[:remote_file]}\""
81
+
82
+ if @ftp.exists(@script[:remote_file])
83
+ @console.done "File is found"
84
+ else
85
+ @console.error "File not found"
86
+ end
87
+
88
+ @ftp.done
89
+ rescue StandardError => e
90
+ @console.error "Unable to connect to the remote server"
91
+ @console.error e.message
92
+ end
93
+
94
+
95
+ def remove_file
96
+ @console.log "Remove file on remote server"
97
+
98
+ format_script_data(:remote_file)
99
+
100
+ @console.log "Remove \"#{@script[:remote_file]}\""
101
+
102
+ if @ftp.remove(@script[:remote_file])
103
+ @console.done "File is removed."
104
+ else
105
+ @console.error "File not found or Can't removed"
106
+ end
107
+
108
+ @ftp.done
109
+ rescue StandardError => e
110
+ @console.error "Unable to connect to the remote server"
111
+ @console.error e.message
112
+ end
113
+
114
+
115
+ def send_http_request
116
+ @console.log "Sent http request to remote server"
117
+
118
+ format_script_data(:url)
119
+
120
+ @console.log "url: #{@script[:url]}"
121
+
122
+ if @script[:params].is_a? Hash
123
+ @script[:params].each do |key, value|
124
+ if value.is_a? String
125
+ @script[:params][key] = replace_data(value, @host_data[:info])
126
+ end
127
+ end
128
+ end
129
+
130
+ http_client = HTTP.headers('user-agent' => @receipt_data[:agent_name])
131
+
132
+ case @script[:method]
133
+ when :get
134
+ @console.data http_client.get(@script[:url], params: @script[:params]).body.to_s
135
+ when :post
136
+ @console.data http_client.post(@script[:url], form: @script[:params]).body.to_s
137
+ else
138
+ @console.error "Unknown http method"
139
+ end
140
+
141
+ rescue StandardError => e
142
+ @console.error "Unable to connect to the remote server"
143
+ @console.error e.message
144
+ end
145
+
146
+ private
147
+
148
+ def format_script_data(*keys)
149
+ keys.each do |key|
150
+ @script[key] = replace_data(@script[key], @host_data[:info])
151
+ end
152
+ end
153
+
154
+ def create_ftp_client_connect
155
+ @ftp = ConnectFtp.new(@host_data[:host], @host_data[:ftp_username], @host_data[:ftp_password], @host_data[:ftp_passive_mode])
156
+
157
+ @ftp.connect
158
+ end
159
+
160
+ def needs_to_create_ftp
161
+ [
162
+ :upload_file,
163
+ :find_file_content,
164
+ :check_file,
165
+ :remove_file
166
+ ].include?(script_type)
167
+ end
168
+
169
+ def marshal_copy(object)
170
+ Marshal.load(Marshal.dump(object))
171
+ end
172
+
173
+ def replace_data(data, info=nil)
174
+ return data if info.nil?
175
+
176
+ info.each do |key, value|
177
+ data.gsub!("[info.#{key}]", value)
178
+ end
179
+
180
+ data
181
+ end
182
+
183
+ def find_file_content_by_io(file_path, options={})
184
+ result = nil
185
+
186
+ needs_to_filter_data = !options[:filter].nil?
187
+
188
+ if needs_to_filter_data
189
+ match_lines = []
190
+
191
+ if options[:ignore_case]
192
+ search_condition = Regexp.new(options[:filter], Regexp::IGNORECASE)
193
+ else
194
+ search_condition = Regexp.new(options[:filter])
195
+ end
196
+
197
+ data = IO.readlines(file_path)
198
+
199
+ data.each do |line|
200
+ match_lines.push line if line =~ search_condition
201
+ end
202
+
203
+ result = match_lines.join
204
+ result = nil if result.length == 0
205
+ else
206
+ result = IO.read(file_path)
207
+ end
208
+
209
+ result
210
+ end
211
+
212
+ end
213
+ end
@@ -0,0 +1,54 @@
1
+
2
+ module MiniDeploy
3
+ module ReceiptFormatter
4
+
5
+ def format_default_task_value(old_task)
6
+ new_task = { }
7
+ new_task[:tag] = old_task['tag'] || ''
8
+ new_task[:process] = old_task['process'].to_sym
9
+ new_task
10
+ end
11
+
12
+ def format_upload_file_task(old_task)
13
+ return nil if old_task['upload_local_source'].nil? ||
14
+ old_task['remote_path'].nil?
15
+
16
+ new_task = {}
17
+ new_task[:upload_local_source] = old_task['upload_local_source']
18
+ new_task[:remote_path] = old_task['remote_path']
19
+ new_task[:upload_mode] = old_task['upload_mode'].to_s.downcase.to_sym
20
+ new_task[:upload_mode] = :text if new_task[:upload_mode] == :""
21
+ new_task
22
+ end
23
+
24
+ def format_check_or_remove_file_task(old_task)
25
+ return nil if old_task['remote_file'].nil?
26
+
27
+ new_task = {}
28
+ new_task[:remote_file] = old_task['remote_file']
29
+ new_task
30
+ end
31
+
32
+ def format_send_http_request_task(old_task)
33
+ return nil if ( old_task['url'].to_s =~ /https?:\/\// ).nil?
34
+
35
+ new_task = {}
36
+ new_task[:method] = old_task['method'].to_s.downcase.to_sym
37
+ new_task[:method] = :get if new_task[:method] == :""
38
+ new_task[:url] = old_task['url']
39
+ new_task[:params] = old_task['params'] || nil
40
+ new_task
41
+ end
42
+
43
+ def format_find_file_content_task(old_task)
44
+ return nil if old_task['remote_file'].nil?
45
+
46
+ new_task = {}
47
+ new_task[:ignore_case] = old_task['ignore_case'] || false
48
+ new_task[:search_content] = old_task['search_content'] || nil
49
+ new_task[:remote_file] = old_task['remote_file']
50
+ new_task
51
+ end
52
+
53
+ end
54
+ end
@@ -0,0 +1,80 @@
1
+ require 'yaml'
2
+ require 'mini_deploy/receipt_formatter'
3
+
4
+ module MiniDeploy
5
+ class ReceiptReader
6
+ include MiniDeploy::ReceiptFormatter
7
+
8
+ def initialize(receipt_file_path)
9
+ @receipt_file_path = receipt_file_path
10
+
11
+ @receipt = nil
12
+ end
13
+
14
+ def fetch
15
+ format(read_receipt)
16
+ end
17
+
18
+ def format(receipt_data)
19
+ new_data = {
20
+ is_valid: false,
21
+ deploy_nodes: receipt_data.fetch('deploy_nodes'),
22
+ receipt_title: receipt_data.fetch('title') { 'Untitled Receipt' },
23
+ receipt_create_at: receipt_data.fetch('date') { 'No Data' },
24
+ receipt_author: receipt_data.fetch('author') { 'No Author Name '},
25
+ receipt_tasks: nil,
26
+ agent_name: receipt_data.fetch('agent_name') { "MiniDeploy/#{MiniDeploy::VERSION}" },
27
+ time: Time.now.utc
28
+ }
29
+
30
+ new_data[:receipt_tasks] = format_tasks(receipt_data['tasks'])
31
+
32
+ new_data
33
+ rescue StandardError
34
+ raise ReceiptReaderParseError
35
+ end
36
+
37
+ def format_tasks(tasks_data)
38
+ [] unless tasks_data.is_a?(Array)
39
+
40
+ tasks_data.map! do |task|
41
+ format_task(task)
42
+ end
43
+
44
+ tasks_data.compact
45
+ end
46
+
47
+ def format_task(old_task)
48
+ new_task = format_default_task_value(old_task)
49
+ new_option = nil
50
+
51
+ case new_task[:process]
52
+ when :check_file
53
+ new_option = format_check_or_remove_file_task(old_task)
54
+ when :send_http_request
55
+ new_option = format_send_http_request_task(old_task)
56
+ when :remove_file
57
+ new_option = format_check_or_remove_file_task(old_task)
58
+ when :upload_file
59
+ new_option = format_upload_file_task(old_task)
60
+ when :find_file_content
61
+ new_option = format_find_file_content_task(old_task)
62
+ else
63
+ new_option = nil
64
+ end
65
+
66
+ if new_option.is_a?(Hash)
67
+ new_task.merge(new_option)
68
+ else
69
+ nil
70
+ end
71
+ end
72
+
73
+ def read_receipt
74
+ YAML.load(IO.read(@receipt_file_path))
75
+ rescue StandardError
76
+ raise ReceiptReaderLoadError
77
+ end
78
+
79
+ end
80
+ end
@@ -0,0 +1,86 @@
1
+ module MiniDeploy
2
+ class SampleFile
3
+ def hosts
4
+ content = <<SAMPLE_CONTENT
5
+ ---
6
+
7
+ - node_id: NODE_ID_1
8
+ host: 10.10.10.101
9
+ ftp_username: sample
10
+ ftp_password: "pass^00^"
11
+ info:
12
+ domain: example.com
13
+ sample_file: sample.php
14
+ error_log_file: error_log
15
+
16
+ - node_id: NODE_ID_2
17
+ host: 10.10.10.102
18
+ ftp_username: sample
19
+ ftp_password: "pass^00^"
20
+ info:
21
+ domain: example-2.com
22
+ sample_file: sample.php
23
+ error_log_file: error_log
24
+
25
+ SAMPLE_CONTENT
26
+
27
+ content
28
+ end
29
+
30
+ def receipt
31
+ content = <<SAMPLE_CONTENT
32
+ ---
33
+
34
+ title: Sample Deploy
35
+ date: 2017-01-02
36
+ author: Your Name
37
+ agent_name: SampleDeploy/1.0.0
38
+
39
+ deploy_nodes:
40
+ - NODE_ID_1
41
+ - NODE_ID_2
42
+
43
+ tasks:
44
+
45
+ - process: upload_file
46
+ upload_local_source: ./[info.sample_file]
47
+ remote_path: ./[info.sample_file]
48
+ upload_mode: binary
49
+ tag: Test Upload File
50
+
51
+ - process: send_http_request
52
+ method: get
53
+ url: http://[info.domain]/get
54
+ tag: Test Http Get Request
55
+ params:
56
+ test: "[info.domain]"
57
+
58
+ - process: remove_file
59
+ remote_file: ./[info.sample_file]
60
+ tag: Remove file
61
+
62
+ - process: send_http_request
63
+ method: post
64
+ params:
65
+ author: Guanting Chen
66
+ do: start_parse
67
+ test: "[info.domain]"
68
+ url: https://httpbin.org/post
69
+ tag: Test Http Post Request
70
+
71
+ - process: check_file
72
+ remote_file: ./[info.sample_file]
73
+ tag: Check sample.php
74
+
75
+ - process: find_file_content
76
+ remote_file: ./[info.sample_file]
77
+ search_content: "[a-z]pple ="
78
+ ignore_case: yes
79
+ tag: Find sample.php content
80
+
81
+ SAMPLE_CONTENT
82
+
83
+ content
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,22 @@
1
+ module MiniDeploy
2
+ module Setting
3
+
4
+ @data_storage = {}
5
+
6
+ def self.all
7
+ @data_storage
8
+ end
9
+
10
+ def self.[](key)
11
+ all[key]
12
+ end
13
+
14
+ def self.[]=(key, value)
15
+ all[key] = value
16
+ end
17
+
18
+ end
19
+
20
+ Setting[:receipt_file_path] = ''
21
+ Setting[:host_file_path] = ''
22
+ end
@@ -0,0 +1,33 @@
1
+ require 'tempfile'
2
+
3
+ module MiniDeploy
4
+ class TemporaryFile
5
+ def initialize
6
+ @tempfile = Tempfile.new('mwd')
7
+ end
8
+
9
+ def write(data)
10
+ @tempfile.write data
11
+ @tempfile.rewind
12
+ end
13
+
14
+ def close
15
+ @tempfile.close
16
+ end
17
+
18
+ def destroy
19
+ @tempfile.unlink
20
+ end
21
+
22
+ def done
23
+ close
24
+ destroy
25
+ rescue StandardError => e
26
+ # ignore
27
+ end
28
+
29
+ def current_path
30
+ @tempfile.path
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,3 @@
1
+ module MiniDeploy
2
+ VERSION = "0.8.0"
3
+ end
@@ -0,0 +1,126 @@
1
+ require 'mini_deploy/version'
2
+ require 'mini_deploy/hosts_data_reader'
3
+ require 'mini_deploy/receipt_reader'
4
+ require 'mini_deploy/connect_ftp'
5
+ require 'mini_deploy/cli'
6
+ require 'mini_deploy/processor'
7
+ require 'mini_deploy/sample_file'
8
+ require 'pretty_console_output'
9
+ require 'json'
10
+ require 'readline'
11
+
12
+ module MiniDeploy
13
+ class TasksRunner
14
+ def initialize
15
+ console_tag "Load Important File"
16
+ console.info "Load host and receipt file."
17
+
18
+ @receipt_data =
19
+ ReceiptReader.new(Setting[:receipt_file_path]).fetch
20
+
21
+ @chose_hosts = @receipt_data[:deploy_nodes]
22
+
23
+ @hosts_data =
24
+ HostsDataReader.new(Setting[:host_file_path]).fetch
25
+
26
+ @hosts_data.select! do |item|
27
+ @chose_hosts.include?(item[:node_id])
28
+ end
29
+
30
+ raise HostsDataNoMatchFound if @hosts_data.length < 1
31
+
32
+ console.done 'Loaded.'
33
+
34
+ rescue HostsDataNoMatchFound
35
+ show_important_error "Hosts Data No Match Found"
36
+
37
+ rescue HostsDataReaderLoadError
38
+ show_important_error "Can't load hosts file."
39
+
40
+ rescue ReceiptReaderLoadError
41
+ show_important_error "Can't load receipt hosts file."
42
+
43
+ rescue ReceiptReaderParseError
44
+ show_important_error "Can't parse receipt hosts file."
45
+ end
46
+
47
+ def start
48
+ console_tag 'Start Receipt Script'
49
+ console.done "Load Receipt: #{@receipt_data[:receipt_title]} ( by #{@receipt_data[:receipt_author]}, #{@receipt_data[:receipt_create_at]} )"
50
+
51
+ show_chose_hosts
52
+
53
+ console_tag "Confirm execute."
54
+ show_important_error "User stop task." unless confirmed_start
55
+
56
+ @hosts_data.each do |host_data|
57
+ process_host_task host_data
58
+ end
59
+
60
+ console_tag "All Done"
61
+ console.done "Receipt processed: " + Time.now.to_s
62
+
63
+ rescue StandardError => e
64
+ show_important_error e.message
65
+ end
66
+
67
+ private
68
+
69
+ def process_host_task(host_data)
70
+ console_tag "Connect #{host_data[:host]} ( #{host_data[:node_id]} )"
71
+
72
+ @receipt_data[:receipt_tasks].each do |original_script|
73
+ processor = Processor.new(console, original_script, host_data, @receipt_data)
74
+
75
+ console.info "Process Task: #{processor.script_tag}"
76
+
77
+ case processor.script_type
78
+ when :check_file
79
+ processor.check_file
80
+ when :remove_file
81
+ processor.remove_file
82
+ when :find_file_content
83
+ processor.find_file_content
84
+ when :send_http_request
85
+ processor.send_http_request
86
+ when :upload_file
87
+ processor.upload_file
88
+ else
89
+ console.error "Ignore unknown task"
90
+ end
91
+ end
92
+ end
93
+
94
+ def console
95
+ @console ||= PrettyConsoleOutput::Console.new(theme: { tag_underscore: false })
96
+ end
97
+
98
+ def console_tag(tag_message)
99
+ console.tag "#{tag_message} →"
100
+ end
101
+
102
+ def show_important_error(message)
103
+ console_tag 'Error happened'
104
+ console.error message
105
+ exit
106
+ end
107
+
108
+ def confirmed_start
109
+ user_input = Readline.readline("yes or no ? ( y/n/ok ) ", true)
110
+ user_input.downcase!
111
+
112
+ [ 'yes', 'y', 'ok' ].include?(user_input)
113
+ rescue Interrupt
114
+ false
115
+ end
116
+
117
+ def show_chose_hosts
118
+ console_tag 'Servers'
119
+
120
+ @hosts_data.each do |host|
121
+ console.log "* #{host[:node_id]} - #{host[:host]}"
122
+ end
123
+ end
124
+
125
+ end
126
+ end
@@ -0,0 +1,42 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'mini_deploy/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "mini_deploy"
8
+ spec.version = MiniDeploy::VERSION
9
+ spec.authors = ["Guanting Chen (@Sif)"]
10
+ spec.email = ["cgt886@gmail.com "]
11
+ spec.summary = %q{mini deploy tools}
12
+ spec.description = %q{upload script to remote server}
13
+ spec.homepage = "https://github.com/guanting112/mini_deploy"
14
+ spec.license = "MIT"
15
+ spec.platform = Gem::Platform::RUBY
16
+ spec.required_ruby_version = '~> 2'
17
+
18
+
19
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
20
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
21
+ if spec.respond_to?(:metadata)
22
+ spec.metadata['allowed_push_host'] = "https://rubygems.org"
23
+ else
24
+ raise "RubyGems 2.0 or newer is required to protect against " \
25
+ "public gem pushes."
26
+ end
27
+
28
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
29
+ f.match(%r{^(test|spec|features)/})
30
+ end
31
+ spec.bindir = "exe"
32
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
33
+ spec.require_paths = ["lib"]
34
+
35
+ spec.add_runtime_dependency 'pretty_console_output', '~> 1.0'
36
+ spec.add_runtime_dependency 'http', '~> 2.0'
37
+
38
+ spec.add_development_dependency "bundler", "~> 1.13"
39
+ spec.add_development_dependency "rake", "~> 10.0"
40
+ spec.add_development_dependency 'minitest', '~> 5.0'
41
+ spec.add_development_dependency "thor", "~> 0.18"
42
+ end
metadata ADDED
@@ -0,0 +1,151 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mini_deploy
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.8.0
5
+ platform: ruby
6
+ authors:
7
+ - Guanting Chen (@Sif)
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-03-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: pretty_console_output
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: http
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.13'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.13'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: minitest
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '5.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '5.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: thor
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.18'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.18'
97
+ description: upload script to remote server
98
+ email:
99
+ - 'cgt886@gmail.com '
100
+ executables:
101
+ - md
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - ".gitignore"
106
+ - Gemfile
107
+ - LICENSE.txt
108
+ - README.md
109
+ - Rakefile
110
+ - bin/console
111
+ - bin/setup
112
+ - exe/md
113
+ - lib/mini_deploy.rb
114
+ - lib/mini_deploy/cli.rb
115
+ - lib/mini_deploy/connect_ftp.rb
116
+ - lib/mini_deploy/exception.rb
117
+ - lib/mini_deploy/hosts_data_reader.rb
118
+ - lib/mini_deploy/processor.rb
119
+ - lib/mini_deploy/receipt_formatter.rb
120
+ - lib/mini_deploy/receipt_reader.rb
121
+ - lib/mini_deploy/sample_file.rb
122
+ - lib/mini_deploy/setting.rb
123
+ - lib/mini_deploy/temporary_file.rb
124
+ - lib/mini_deploy/version.rb
125
+ - mini_deploy.gemspec
126
+ homepage: https://github.com/guanting112/mini_deploy
127
+ licenses:
128
+ - MIT
129
+ metadata:
130
+ allowed_push_host: https://rubygems.org
131
+ post_install_message:
132
+ rdoc_options: []
133
+ require_paths:
134
+ - lib
135
+ required_ruby_version: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - "~>"
138
+ - !ruby/object:Gem::Version
139
+ version: '2'
140
+ required_rubygems_version: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ requirements: []
146
+ rubyforge_project:
147
+ rubygems_version: 2.5.2
148
+ signing_key:
149
+ specification_version: 4
150
+ summary: mini deploy tools
151
+ test_files: []