mini_deploy 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
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: []