dockerfish 0.1.3
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 +7 -0
- data/bin/dockerfish +161 -0
- data/lib/dockerfish.rb +584 -0
- metadata +46 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d0b92c9f014ead6e102e8355c92276e3145ccbad
|
4
|
+
data.tar.gz: aadbc378a49b01534d0f6c8a98c89a7c220b1ebe
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8d769840e583e4dadc85282291a326bcdddd9ce155290846b3f16f3093aee91051e79c3341a80e1ea3401a50a69ce7ea0e24e753fe77dba7509385d6e0a9915f
|
7
|
+
data.tar.gz: 2e9531a69795fd2f98ae3bbc885fe01f5b4222a9fca81e7eb784a0da032887fbfe916c988c533ceb59c73346f0ebec0e4fb9c56ad5ae9dec6cc367798ab2ab37
|
data/bin/dockerfish
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
########################################################################
|
4
|
+
# #
|
5
|
+
# Author: Brian Hood #
|
6
|
+
# Description: DockerFish Automation #
|
7
|
+
# #
|
8
|
+
# #
|
9
|
+
########################################################################
|
10
|
+
|
11
|
+
require File.expand_path(File.join(
|
12
|
+
File.dirname(__FILE__),
|
13
|
+
"../lib/dockerfish.rb"))
|
14
|
+
|
15
|
+
# GetOptLong remove argv value after processing so store to i can use it lower down.
|
16
|
+
argvstore = ARGV[0].to_s
|
17
|
+
|
18
|
+
trap("INT") {
|
19
|
+
puts "\nSee you soon !"
|
20
|
+
exit
|
21
|
+
}
|
22
|
+
|
23
|
+
def bookmarks(file)
|
24
|
+
puts "\e[1;32mBookmarks\e[0m\ "
|
25
|
+
puts "\e[1;32m=========\e[0m\ "
|
26
|
+
puts ""
|
27
|
+
def read(file)
|
28
|
+
b = 1
|
29
|
+
@bookmarks = Array.new
|
30
|
+
File.open("#{file}", 'r') {|n|
|
31
|
+
n.each_line {|l|
|
32
|
+
puts "\e[1;36m#{b})\e[0m\ #{l}"
|
33
|
+
@bookmarks[b] = l.split(" ")[1]
|
34
|
+
b = b + 1
|
35
|
+
}
|
36
|
+
}
|
37
|
+
end
|
38
|
+
if File.exists?("#{file}")
|
39
|
+
read(file)
|
40
|
+
else
|
41
|
+
# Add Localhost to your favourites as an example
|
42
|
+
File.open("#{file}", 'w') {|n|
|
43
|
+
n.puts("localhost http://localhost:2375")
|
44
|
+
}
|
45
|
+
read(file)
|
46
|
+
end
|
47
|
+
while buf4 = Readline.readline("\e[1;33m\Enter Bookmark>\e[0m\ ", true)
|
48
|
+
puts @bookmarks[buf4.to_i]
|
49
|
+
@bookmarkhost = @bookmarks[buf4.to_i]
|
50
|
+
break
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
opts = GetoptLong.new(
|
56
|
+
[ '--help', '-h', GetoptLong::NO_ARGUMENT ],
|
57
|
+
[ '--url', '-u', GetoptLong::OPTIONAL_ARGUMENT ],
|
58
|
+
[ '--bookmarks', '-b', GetoptLong::NO_ARGUMENT ],
|
59
|
+
[ '--start', '-s', GetoptLong::REQUIRED_ARGUMENT ],
|
60
|
+
[ '--stop', '-p', GetoptLong::REQUIRED_ARGUMENT ],
|
61
|
+
[ '--create', '-c', GetoptLong::REQUIRED_ARGUMENT ],
|
62
|
+
[ '--contimage', '-i', GetoptLong::REQUIRED_ARGUMENT ]
|
63
|
+
)
|
64
|
+
|
65
|
+
opts.each do |opt, arg|
|
66
|
+
case opt
|
67
|
+
when '--help'
|
68
|
+
helper = "\e[1;34mWelcome to DockerFish Version #{VERSION}\e[0m\ \n"
|
69
|
+
helper << "\e[1;34m=================================\e[0m\ "
|
70
|
+
helper << %q[
|
71
|
+
|
72
|
+
-h, --help:
|
73
|
+
show help
|
74
|
+
|
75
|
+
-u, -url Docker Host URL:
|
76
|
+
Note: Docker Host must of API Enabled to connect
|
77
|
+
Example: http://10.0.0.1:2375
|
78
|
+
|
79
|
+
Defaults to http://localhost:2375
|
80
|
+
|
81
|
+
-b, --bookmarks
|
82
|
+
Create .bookmarks file format
|
83
|
+
|
84
|
+
Example:
|
85
|
+
|
86
|
+
localhost http://127.0.0.1:2375
|
87
|
+
remoteserver http://10.0.2.15:2375
|
88
|
+
|
89
|
+
-c --create
|
90
|
+
Create container from image
|
91
|
+
|
92
|
+
-i --contimage
|
93
|
+
Create many from your container.json parameters.
|
94
|
+
|
95
|
+
# Comma separated for multiple containers supported
|
96
|
+
|
97
|
+
-s --start
|
98
|
+
Start up container name / Id
|
99
|
+
|
100
|
+
-p --stop
|
101
|
+
Stop container name / Id
|
102
|
+
]
|
103
|
+
puts helper
|
104
|
+
exit
|
105
|
+
when '--bookmarks'
|
106
|
+
bookmarks("#{BOOKMARKSFILE}")
|
107
|
+
when '--url'
|
108
|
+
@dockerurl = arg
|
109
|
+
when '--start'
|
110
|
+
@action = "start"
|
111
|
+
@container = arg
|
112
|
+
when '--stop'
|
113
|
+
@action = "stop"
|
114
|
+
@container = arg
|
115
|
+
when '--create'
|
116
|
+
@action = "create"
|
117
|
+
@container = arg
|
118
|
+
when '--contimage'
|
119
|
+
@image = arg
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
class Integer
|
124
|
+
|
125
|
+
def to_filesize
|
126
|
+
conv = [ 'B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB' ];
|
127
|
+
scale = 1024;
|
128
|
+
|
129
|
+
ndx=1
|
130
|
+
if( self < 2*(scale**ndx) ) then
|
131
|
+
return "#{(size)}#{conv[ndx-1]}"
|
132
|
+
end
|
133
|
+
size=self.to_f
|
134
|
+
[2,3,4,5,6,7].each do |ndx|
|
135
|
+
if( size < 2*(scale**ndx) ) then
|
136
|
+
return "#{'%.3f' % (size/(scale**(ndx-1)))}#{conv[ndx-1]}"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
ndx=7
|
140
|
+
return "#{'%.3f' % (size/(scale**(ndx-1)))}#{conv[ndx-1]}"
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
# Client
|
146
|
+
|
147
|
+
if argvstore.size > 0
|
148
|
+
obj = FishControl.new
|
149
|
+
if defined? @action
|
150
|
+
if @image
|
151
|
+
obj.containerctl(@container, @action, @image)
|
152
|
+
else
|
153
|
+
obj.containerctl(@container, @action)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
elsif argvstore.size == 0
|
157
|
+
obj = DockerFish.new(true)
|
158
|
+
if defined? @dockerurl; obj.baseurl = @dockerurl; end
|
159
|
+
if defined? @bookmarkhost; obj.baseurl = @bookmarkhost; end
|
160
|
+
obj.apicall("menu")
|
161
|
+
end
|
data/lib/dockerfish.rb
ADDED
@@ -0,0 +1,584 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
########################################################################
|
4
|
+
# #
|
5
|
+
# Author: Brian Hood #
|
6
|
+
# Description: DockerFish Automation #
|
7
|
+
# #
|
8
|
+
# #
|
9
|
+
########################################################################
|
10
|
+
|
11
|
+
require "net/http"
|
12
|
+
require "uri"
|
13
|
+
require "json"
|
14
|
+
require "pp"
|
15
|
+
require "readline"
|
16
|
+
require 'getoptlong'
|
17
|
+
|
18
|
+
BOOKMARKSFILE = ".bookmarks"
|
19
|
+
VERSION = 0.1
|
20
|
+
|
21
|
+
=begin
|
22
|
+
|
23
|
+
Bri's TODO list
|
24
|
+
|
25
|
+
TODO: Add Export image
|
26
|
+
TODO: Fix multiple container start
|
27
|
+
TODO: Add Pull of image from Repository
|
28
|
+
TODO: Download progress bar for images
|
29
|
+
TODO: Refactor code duplication / case statement
|
30
|
+
TODO: Websocket attach with Eventmachine / Readline
|
31
|
+
|
32
|
+
=end
|
33
|
+
|
34
|
+
class DockerFish
|
35
|
+
|
36
|
+
attr_accessor :baseurl
|
37
|
+
attr_writer :image, :hostname
|
38
|
+
|
39
|
+
def initialize(splash)
|
40
|
+
@baseurl = "http://localhost:2375"
|
41
|
+
@containerjson = "container.json"
|
42
|
+
if splash == true; banner; end
|
43
|
+
end
|
44
|
+
|
45
|
+
def banner
|
46
|
+
puts "Welcome to DockerFish Version #{VERSION}"
|
47
|
+
puts "---------------------------------"
|
48
|
+
puts "Interactive CLI Docker Interface"
|
49
|
+
print "\[\e[1;31m\] |
|
50
|
+
|
|
51
|
+
,|.
|
52
|
+
,\|/.
|
53
|
+
,' .V. `.
|
54
|
+
/ . . \
|
55
|
+
/_` '_\
|
56
|
+
,' .: ;, `.
|
57
|
+
|@)| . . |(@|
|
58
|
+
,-._ `._'; . :`_,' _,-.
|
59
|
+
'-- `-\ /,-===-.\ /-' --`
|
60
|
+
(---- _| ||___|| |_ ----)
|
61
|
+
`._,-' \ `-.-' / `-._,'
|
62
|
+
`-.___,-' ap\[\e[0m\]\n"
|
63
|
+
puts ""
|
64
|
+
puts "TIPS: Please note ContainerId's / Names are interchangeable"
|
65
|
+
puts "You can also use short ContainerId's as long as there is a unique match"
|
66
|
+
puts "Start with Docker API Enabled: /usr/bin/docker --api-enable-cors=true -H tcp://127.0.0.1:2375 -H unix:///var/run/docker.sock -d"
|
67
|
+
puts "Add a symlink ln -s /home/brian/Projects/DockerFish/dockerfish.rb /usr/bin/dockerfish\n\n"
|
68
|
+
puts "Container Config file: #{Dir.home}/.dockerfish/#{@containerjson}\n\n"
|
69
|
+
if File.exists?("#{Dir.home}/.dockerfish/#{@containerjson}") == false
|
70
|
+
puts "\e[1;31m\WARNING: \e[0m\ \e[1;32m\ To Create Containers \e[1;33m\ mkdir #{Dir.home}/.dockerfish\e[0m\ \e[1;32m\ and copy the provided container.json into it !!!\e[0m\ \n\n"
|
71
|
+
end
|
72
|
+
puts "--help # For more information"
|
73
|
+
puts "\n"
|
74
|
+
puts "Enjoy!"
|
75
|
+
puts "\n"
|
76
|
+
puts "Coded by Brian Hood"
|
77
|
+
version
|
78
|
+
end
|
79
|
+
|
80
|
+
def apiget(url)
|
81
|
+
uri = URI.parse("#{url}")
|
82
|
+
#puts "Request URI: #{url}"
|
83
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
84
|
+
begin
|
85
|
+
response = http.request(Net::HTTP::Get.new(uri.request_uri))
|
86
|
+
rescue
|
87
|
+
puts "Error retrieving data"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def apipost(url, body="")
|
92
|
+
uri = URI.parse("#{url}")
|
93
|
+
#puts "Request URI: #{url}"
|
94
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
95
|
+
request = Net::HTTP::Post.new(uri.request_uri)
|
96
|
+
request.set_content_type("application/json")
|
97
|
+
begin
|
98
|
+
request.body = body unless body.empty?
|
99
|
+
response = http.request(request)
|
100
|
+
rescue
|
101
|
+
puts "Error posting data"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def apidelete(url)
|
106
|
+
uri = URI.parse("#{url}")
|
107
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
108
|
+
begin
|
109
|
+
response = http.request(Net::HTTP::Delete.new(uri.request_uri))
|
110
|
+
rescue
|
111
|
+
puts "Error posting data"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def version
|
116
|
+
@url = "#{@baseurl}/version"
|
117
|
+
uri = URI.parse("#{@url}")
|
118
|
+
begin
|
119
|
+
response = apiget("#{@url}")
|
120
|
+
puts "Server Info:\n\n"
|
121
|
+
j = JSON.parse(response.body)
|
122
|
+
pp j
|
123
|
+
rescue JSON::ParserError, NoMethodError
|
124
|
+
puts "Could not read JSON data"
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def chooser(opts)
|
129
|
+
@url = "#{@baseurl}#{opts}"
|
130
|
+
end
|
131
|
+
|
132
|
+
def apicall(action)
|
133
|
+
|
134
|
+
case action
|
135
|
+
when action = "images"
|
136
|
+
response = apiget("#{@url}")
|
137
|
+
begin
|
138
|
+
j = JSON.parse(response.body)
|
139
|
+
rescue JSON::ParserError
|
140
|
+
puts "Could not read JSON data"
|
141
|
+
end
|
142
|
+
puts "\e[1;30mList of Docker Images\e[0m\ "
|
143
|
+
puts "\e[1;30m=====================\e[0m\ "
|
144
|
+
puts ""
|
145
|
+
0.upto(j.length - 1) {|n|
|
146
|
+
j[n].each {|s|
|
147
|
+
case s[0]
|
148
|
+
when "Created"
|
149
|
+
ftime = Time.at(s[1]).to_s
|
150
|
+
ctime = ftime[0..18]
|
151
|
+
created = "#{s[0]}: #{ctime} "
|
152
|
+
when "Id"
|
153
|
+
parentid = "#{s[0]}: #{s[1]} "
|
154
|
+
imageid = parentid[0..21]
|
155
|
+
when "RepoTags"
|
156
|
+
repotags = "#{s[0]}: #{s[1]} ".gsub("RepoTags", "Image")
|
157
|
+
when "Size"
|
158
|
+
num = s[1].to_i.to_filesize
|
159
|
+
size = "#{s[0]}: #{num} "
|
160
|
+
when "VirtualSize"
|
161
|
+
num = s[1].to_i.to_filesize
|
162
|
+
virtualsize = "#{s[0]}: #{num} "
|
163
|
+
end
|
164
|
+
print "#{created} #{imageid} #{repotags} #{size} #{virtualsize}"
|
165
|
+
}
|
166
|
+
print "\n"
|
167
|
+
}
|
168
|
+
when action = "containers"
|
169
|
+
response = apiget("#{@url}")
|
170
|
+
begin
|
171
|
+
j = JSON.parse(response.body)
|
172
|
+
rescue JSON::ParserError
|
173
|
+
puts "Could not read JSON data"
|
174
|
+
end
|
175
|
+
puts "\e[1;30mList of Docker Containers\e[0m\ "
|
176
|
+
puts "\e[1;30m=========================\e[0m\ "
|
177
|
+
puts ""
|
178
|
+
#puts j.length
|
179
|
+
0.upto(j.length - 1) {|n|
|
180
|
+
j[n].each {|s|
|
181
|
+
case s[0]
|
182
|
+
when "Command"
|
183
|
+
cmd = "#{s[0]}: #{s[1]}".strip
|
184
|
+
when "Id"
|
185
|
+
id = "#{s[0]}: #{s[1]} "
|
186
|
+
cointainerid = id[0..15].gsub("Id", "ContainerId").strip
|
187
|
+
when "Image"
|
188
|
+
image = "#{s[0]}: #{s[1]}"
|
189
|
+
when "Names"
|
190
|
+
names = "#{s[0]}: #{s[1]}".strip
|
191
|
+
when "Status"
|
192
|
+
status = "#{s[0]}: #{s[1]}"
|
193
|
+
when "Created"
|
194
|
+
ftime = Time.at(s[1]).to_s
|
195
|
+
ctime = ftime[0..18]
|
196
|
+
created = "#{s[0]}: #{ctime} ".strip
|
197
|
+
end
|
198
|
+
print "#{names} #{cointainerid} #{image} #{cmd} #{status}".gsub(" Command:", "Command:")
|
199
|
+
#pp s
|
200
|
+
}
|
201
|
+
print "\n"
|
202
|
+
}
|
203
|
+
#pp j
|
204
|
+
when action = "start"
|
205
|
+
response = apipost("#{@url}")
|
206
|
+
if response.code == "204"
|
207
|
+
puts "\e[1;30mStart Successfull\e[0m\ "
|
208
|
+
elsif response.code == "304"
|
209
|
+
puts "\e[1;30mContainer already started\e[0m\ "
|
210
|
+
elsif response.code == "404"
|
211
|
+
puts "\e[1;30mNo such container\e[0m\ "
|
212
|
+
elsif response.code == "500"
|
213
|
+
puts "\e[1;30mServer error\e[0m\ "
|
214
|
+
end
|
215
|
+
when action = "pause"
|
216
|
+
response = apipost("#{@url}")
|
217
|
+
if response.code == "204"
|
218
|
+
puts "\e[1;30mPaused Successfull\e[0m\ "
|
219
|
+
elsif response.code == "404"
|
220
|
+
puts "\e[1;30mNo such container\e[0m\ "
|
221
|
+
elsif response.code == "500"
|
222
|
+
puts "\e[1;30mServer error\e[0m\ "
|
223
|
+
end
|
224
|
+
when action = "unpause"
|
225
|
+
response = apipost("#{@url}")
|
226
|
+
if response.code == "204"
|
227
|
+
puts "\e[1;30mResumed Successfull\e[0m\ "
|
228
|
+
elsif response.code == "404"
|
229
|
+
puts "\e[1;30mNo such container\e[0m\ "
|
230
|
+
elsif response.code == "500"
|
231
|
+
puts "\e[1;30mServer error\e[0m\ "
|
232
|
+
end
|
233
|
+
when action = "rename"
|
234
|
+
response = apipost("#{@url}")
|
235
|
+
if response.code == "204"
|
236
|
+
puts "\e[1;30mRenamed Successfully\e[0m\ "
|
237
|
+
elsif response.code == "404"
|
238
|
+
puts "\e[1;30mNo such container\e[0m\ "
|
239
|
+
elsif response.code == "409"
|
240
|
+
puts "\e[1;30mName conflict with another container\e[0m\ "
|
241
|
+
elsif response.code == "500"
|
242
|
+
puts "\e[1;30mServer error\e[0m\ "
|
243
|
+
end
|
244
|
+
when action = "stop"
|
245
|
+
response = apipost("#{@url}")
|
246
|
+
if response.code == "204"
|
247
|
+
puts "\e[1;30mStopped Successfully\e[0m\ "
|
248
|
+
elsif response.code == "304"
|
249
|
+
puts "\e[1;30mContainer already stopped\e[0m\ "
|
250
|
+
elsif response.code == "404"
|
251
|
+
puts "\e[1;30mNo such container\e[0m\ "
|
252
|
+
elsif response.code == "500"
|
253
|
+
puts "\e[1;30mServer error\e[0m\ "
|
254
|
+
end
|
255
|
+
when action = "inspect"
|
256
|
+
response = apiget("#{@url}")
|
257
|
+
begin
|
258
|
+
j = JSON.parse(response.body)
|
259
|
+
rescue JSON::ParserError
|
260
|
+
puts "Could not read JSON data"
|
261
|
+
end
|
262
|
+
pp j
|
263
|
+
when action = "remove"
|
264
|
+
response = apidelete("#{@url}")
|
265
|
+
if response.code == "204"
|
266
|
+
puts "\e[1;30mRemoved Successfully\e[0m\ "
|
267
|
+
elsif response.code == "400"
|
268
|
+
puts "\e[1;30mBad parameter\e[0m\ "
|
269
|
+
elsif response.code == "404"
|
270
|
+
puts "\e[1;30mNo such container\e[0m\ "
|
271
|
+
elsif response.code == "500"
|
272
|
+
puts "\e[1;30mServer error\e[0m\ "
|
273
|
+
end
|
274
|
+
when action = "imageremove"
|
275
|
+
response = apidelete("#{@url}")
|
276
|
+
if response.code == "200"
|
277
|
+
puts "\e[1;30mRemoved Successfully\e[0m\ "
|
278
|
+
elsif response.code == "404"
|
279
|
+
puts "\e[1;30mNo such image\e[0m\ "
|
280
|
+
elsif response.code == "409"
|
281
|
+
puts "\e[1;30mConflict removing image\e[0m\ "
|
282
|
+
elsif response.code == "500"
|
283
|
+
puts "\e[1;30mServer error\e[0m\ "
|
284
|
+
end
|
285
|
+
when action = "imagecommit"
|
286
|
+
response = apipost("#{@url}")
|
287
|
+
if response.code == "201"
|
288
|
+
puts "\e[1;30mImage Commit Successfull\e[0m\ "
|
289
|
+
elsif response.code == "404"
|
290
|
+
puts "\e[1;30mNo such container\e[0m\ "
|
291
|
+
elsif response.code == "500"
|
292
|
+
puts "\e[1;30mServer error\e[0m\ "
|
293
|
+
end
|
294
|
+
when action = "create"
|
295
|
+
body = String.new
|
296
|
+
File.open("#{Dir.home}/.dockerfish/#{@containerjson}", 'r') {|n|
|
297
|
+
n.each_line {|l|
|
298
|
+
body << l
|
299
|
+
}
|
300
|
+
}
|
301
|
+
body.gsub!("##hostname##", @hostname)
|
302
|
+
body.gsub!("##image##", @image)
|
303
|
+
puts body
|
304
|
+
if !defined? @name; @name = @hostname; end
|
305
|
+
response = apipost("#{@url}?name=#{@name}", body)
|
306
|
+
if response.code == "201"
|
307
|
+
puts "\e[1;30mContainer Creation Successfull\e[0m\ "
|
308
|
+
j = JSON.parse(response.body)
|
309
|
+
n = 0
|
310
|
+
0.upto(j.length - 1) {|n|
|
311
|
+
j[n].each {|s|
|
312
|
+
puts "#{s[0]}: #{s[1]}"
|
313
|
+
}
|
314
|
+
print "\n"
|
315
|
+
}
|
316
|
+
elsif response.code == "404"
|
317
|
+
puts "\e[1;30mNo such container\e[0m\ "
|
318
|
+
elsif response.code == "406"
|
319
|
+
puts "\e[1;30mImposible to attach\e[0m\ "
|
320
|
+
elsif response.code == "500"
|
321
|
+
puts "\e[1;30mServer error\e[0m\ "
|
322
|
+
end
|
323
|
+
when action = "imagehistory"
|
324
|
+
response = apiget("#{@url}")
|
325
|
+
begin
|
326
|
+
j = JSON.parse(response.body)
|
327
|
+
rescue JSON::ParserError
|
328
|
+
puts "Could not read JSON data"
|
329
|
+
end
|
330
|
+
puts "\e[1;30mImage history\e[0m\ "
|
331
|
+
puts "\e[1;30m=================\e[0m\ "
|
332
|
+
puts ""
|
333
|
+
#puts j.length
|
334
|
+
0.upto(j.length - 1) {|n|
|
335
|
+
j[n].each {|s|
|
336
|
+
case s[0]
|
337
|
+
when "Id"
|
338
|
+
id = "#{s[0]}: #{s[1]} "
|
339
|
+
cointainerid = id[0..15].strip
|
340
|
+
when "Created"
|
341
|
+
ftime = Time.at(s[1]).to_s
|
342
|
+
ctime = ftime[0..18]
|
343
|
+
created = "#{s[0]}: #{ctime} ".strip
|
344
|
+
when "CreatedBy"
|
345
|
+
createdby = "#{s[0]}: #{s[1]}"
|
346
|
+
end
|
347
|
+
print "#{id} #{created} #{createdby}"
|
348
|
+
#pp s
|
349
|
+
}
|
350
|
+
print "\n"
|
351
|
+
}
|
352
|
+
if response.code == "404"
|
353
|
+
puts "\e[1;30mNo such image\e[0m\ "
|
354
|
+
elsif response.code == "500"
|
355
|
+
puts "\e[1;30mServer error\e[0m\ "
|
356
|
+
end
|
357
|
+
when action = "containerprocs"
|
358
|
+
response = apiget("#{@url}")
|
359
|
+
begin
|
360
|
+
j = JSON.parse(response.body)
|
361
|
+
rescue JSON::ParserError
|
362
|
+
puts "Could not read JSON data"
|
363
|
+
end
|
364
|
+
pp j
|
365
|
+
when action = "search"
|
366
|
+
response = apiget("#{@url}")
|
367
|
+
begin
|
368
|
+
j = JSON.parse(response.body)
|
369
|
+
rescue JSON::ParserError
|
370
|
+
puts "Could not read JSON data"
|
371
|
+
end
|
372
|
+
puts "\e[1;30mSearch Results\e[0m\ "
|
373
|
+
puts "\e[1;30m==============\e[0m\ "
|
374
|
+
puts ""
|
375
|
+
#puts j.length
|
376
|
+
0.upto(j.length - 1) {|n|
|
377
|
+
j[n].each {|s|
|
378
|
+
case s[0]
|
379
|
+
when "description"
|
380
|
+
description = "#{s[0]}: #{s[1]} "
|
381
|
+
when "is_offical"
|
382
|
+
offical = "#{s[0]}: #{s[1]} "
|
383
|
+
when "is_automated"
|
384
|
+
automated = "#{s[0]}: #{s[1]}"
|
385
|
+
when "name"
|
386
|
+
name = "Image: \e[1;36m\ [\"#{s[1]}\"] \e[0m\ "
|
387
|
+
when "star_count"
|
388
|
+
starcount = "Star rating: #{s[1]}"
|
389
|
+
end
|
390
|
+
print "#{name} #{starcount}".lstrip
|
391
|
+
#pp s
|
392
|
+
}
|
393
|
+
print "\n"
|
394
|
+
}
|
395
|
+
if response.code == "500"
|
396
|
+
puts "\e[1;30mServer error\e[0m\ "
|
397
|
+
end
|
398
|
+
when action = "menu"
|
399
|
+
while buf = Readline.readline("\e[1;32m\DockerFish>\e[0m\ ", true)
|
400
|
+
begin
|
401
|
+
puts "\n"
|
402
|
+
puts "\e[1;38m|Our items in the boat yard|\e[0m\ \n"
|
403
|
+
puts "\e[1;38m\\==========================/\e[0m\ "
|
404
|
+
puts "\n"
|
405
|
+
puts "\e[1;36m1)\e[0m\ List Images"
|
406
|
+
puts "\e[1;36m2)\e[0m\ List Containers"
|
407
|
+
puts "\e[1;36m3)\e[0m\ Start/Restart Container"
|
408
|
+
puts "\e[1;36m4)\e[0m\ Stop Container"
|
409
|
+
puts "\e[1;36m5)\e[0m\ Rename Container"
|
410
|
+
puts "\e[1;36m6)\e[0m\ Create Container from Image"
|
411
|
+
puts "\e[1;36m7)\e[0m\ Remove Container"
|
412
|
+
puts "\e[1;36m8)\e[0m\ Inspect Container"
|
413
|
+
puts "\e[1;36m9)\e[0m\ View Image History"
|
414
|
+
puts "\e[1;36m10)\e[0m\ Search for Images"
|
415
|
+
puts "\e[1;36m11)\e[0m\ List Container processes"
|
416
|
+
puts "\e[1;36m12)\e[0m\ Remove Image"
|
417
|
+
puts "\e[1;36m13)\e[0m\ Pause container"
|
418
|
+
puts "\e[1;36m14)\e[0m\ Resume container"
|
419
|
+
puts "\e[1;36m15)\e[0m\ Create a new image from a container's changes"
|
420
|
+
puts ""
|
421
|
+
puts "m: This menu"
|
422
|
+
puts "b: Bookmarks"
|
423
|
+
puts "q: Exit Dockerfish\n"
|
424
|
+
puts "\n"
|
425
|
+
case buf
|
426
|
+
when "1"
|
427
|
+
chooser("/images/json?all=0")
|
428
|
+
#puts "#{@url}"
|
429
|
+
apicall("images")
|
430
|
+
when "2"
|
431
|
+
chooser("/containers/json?all=1")
|
432
|
+
#puts "#{@url}"
|
433
|
+
apicall("containers")
|
434
|
+
when "3"
|
435
|
+
while buf2 = Readline.readline("\e[1;33m\Enter Container to Start>\e[0m\ ", true)
|
436
|
+
puts "\e[1;30mStarting Container #{buf2}\e[0m\ "
|
437
|
+
chooser("/containers/#{buf2}/restart")
|
438
|
+
#puts "#{@url}"
|
439
|
+
apicall("start")
|
440
|
+
break
|
441
|
+
end
|
442
|
+
when "4"
|
443
|
+
while buf2 = Readline.readline("\e[1;33m\Enter Container to Stop>\e[0m\ ", true)
|
444
|
+
puts "\e[1;30mStopping Container #{buf2}\e[0m\ "
|
445
|
+
chooser("/containers/#{buf2}/stop")
|
446
|
+
#puts "#{@url}"
|
447
|
+
apicall("stop")
|
448
|
+
break
|
449
|
+
end
|
450
|
+
when "5"
|
451
|
+
while buf2 = Readline.readline("\e[1;33m\Enter Container To Rename>\e[0m\ ", true)
|
452
|
+
while buf3 = Readline.readline("\e[1;33m\Enter new name>\e[0m\ ", true)
|
453
|
+
chooser("/containers/#{buf2}/rename?name=#{buf3}")
|
454
|
+
break
|
455
|
+
end
|
456
|
+
#puts "#{@url}"
|
457
|
+
apicall("rename")
|
458
|
+
break
|
459
|
+
end
|
460
|
+
when "6"
|
461
|
+
while buf2 = Readline.readline("\e[1;33m\Enter Image to use>\e[0m\ ", true)
|
462
|
+
@image = buf2
|
463
|
+
while buf3 = Readline.readline("\e[1;33m\Enter Container name(s)>\e[0m\ ", true)
|
464
|
+
chooser("/containers/create")
|
465
|
+
@hostname = buf3
|
466
|
+
apicall("create")
|
467
|
+
break
|
468
|
+
end
|
469
|
+
break
|
470
|
+
end
|
471
|
+
when "7"
|
472
|
+
while buf2 = Readline.readline("\e[1;33m\Enter Container to Remove>\e[0m\ ", true)
|
473
|
+
chooser("/containers/#{buf2}")
|
474
|
+
#puts "#{@url}"
|
475
|
+
apicall("remove")
|
476
|
+
break
|
477
|
+
end
|
478
|
+
when "8"
|
479
|
+
while buf2 = Readline.readline("\e[1;33m\Enter Container to Inspect>\e[0m\ ", true)
|
480
|
+
chooser("/containers/#{buf2}/json")
|
481
|
+
#puts "#{@url}"
|
482
|
+
apicall("inspect")
|
483
|
+
break
|
484
|
+
end
|
485
|
+
when "9"
|
486
|
+
while buf2 = Readline.readline("\e[1;33m\View history of image>\e[0m\ ", true)
|
487
|
+
chooser("/images/#{buf2}/history")
|
488
|
+
#puts "#{@url}"
|
489
|
+
apicall("imagehistory")
|
490
|
+
break
|
491
|
+
end
|
492
|
+
when "10"
|
493
|
+
while buf2 = Readline.readline("\e[1;33m\Search for images>\e[0m\ ", true)
|
494
|
+
chooser("/images/search?term=#{buf2}")
|
495
|
+
#puts "#{@url}"
|
496
|
+
apicall("search")
|
497
|
+
break
|
498
|
+
end
|
499
|
+
when "11"
|
500
|
+
while buf2 = Readline.readline("\e[1;33m\Enter Container to query>\e[0m\ ", true)
|
501
|
+
chooser("/containers/#{buf2}/top")
|
502
|
+
#puts "#{@url}"
|
503
|
+
apicall("containerprocs")
|
504
|
+
break
|
505
|
+
end
|
506
|
+
when "12"
|
507
|
+
while buf2 = Readline.readline("\e[1;33m\Enter Image to remove>\e[0m\ ", true)
|
508
|
+
chooser("/images/#{buf2}")
|
509
|
+
#puts "#{@url}"
|
510
|
+
apicall("imageremove")
|
511
|
+
break
|
512
|
+
end
|
513
|
+
when "13"
|
514
|
+
while buf2 = Readline.readline("\e[1;33m\Pause Container name / id>\e[0m\ ", true)
|
515
|
+
chooser("/containers/#{buf2}/pause")
|
516
|
+
#puts "#{@url}"
|
517
|
+
apicall("pause")
|
518
|
+
break
|
519
|
+
end
|
520
|
+
when "14"
|
521
|
+
while buf2 = Readline.readline("\e[1;33m\Resume Container name / id>\e[0m\ ", true)
|
522
|
+
chooser("/containers/#{buf2}/unpause")
|
523
|
+
#puts "#{@url}"
|
524
|
+
apicall("pause")
|
525
|
+
break
|
526
|
+
end
|
527
|
+
when "15"
|
528
|
+
while buf2 = Readline.readline("\e[1;33m\Enter Container to Image>\e[0m\ ", true)
|
529
|
+
while buf3 = Readline.readline("\e[1;33m\Enter your commit comment important>\e[0m\ ", true)
|
530
|
+
commentenc = URI.encode(buf3)
|
531
|
+
break
|
532
|
+
end
|
533
|
+
while buf4 = Readline.readline("\e[1;33m\Enter your Repository name>\e[0m\ ", true)
|
534
|
+
chooser("/commit?container=#{buf2}&comment=#{commentenc}&repo=#{buf4}")
|
535
|
+
break
|
536
|
+
end
|
537
|
+
#puts "#{@url}"
|
538
|
+
apicall("imagecommit")
|
539
|
+
break
|
540
|
+
end
|
541
|
+
when "m"
|
542
|
+
apicall("menu")
|
543
|
+
#when "b"
|
544
|
+
# ret = bookmarks("#{BOOKMARKSFILE}")
|
545
|
+
# @baseurl = ret
|
546
|
+
# instance_variable_set("@url", ret)
|
547
|
+
when "q"
|
548
|
+
exit
|
549
|
+
when "f"
|
550
|
+
banner
|
551
|
+
end
|
552
|
+
rescue NoMethodError
|
553
|
+
end
|
554
|
+
end
|
555
|
+
end
|
556
|
+
end
|
557
|
+
end
|
558
|
+
|
559
|
+
class FishControl
|
560
|
+
|
561
|
+
def initialize
|
562
|
+
@apiobj = DockerFish.new(false)
|
563
|
+
@containerjson = "container.json"
|
564
|
+
end
|
565
|
+
|
566
|
+
def containerctl(container, action, image="<none>:<none>")
|
567
|
+
if image != "<none>:<none>"
|
568
|
+
@apiobj.image = image
|
569
|
+
puts "My Image: #{image}"
|
570
|
+
end
|
571
|
+
container.split(",").each {|n|
|
572
|
+
@apiobj.hostname = "#{n}"
|
573
|
+
puts "Container: #{n} Action: #{action}"
|
574
|
+
if action == "create"
|
575
|
+
@apiobj.chooser("/containers/#{action}")
|
576
|
+
else
|
577
|
+
@apiobj.chooser("/containers/#{n}/#{action}")
|
578
|
+
end
|
579
|
+
@apiobj.apicall("#{action}")
|
580
|
+
}
|
581
|
+
exit
|
582
|
+
end
|
583
|
+
|
584
|
+
end
|
metadata
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dockerfish
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Brian Hood
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-07-26 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: A Sysadmin Tool for Docker fans!
|
14
|
+
email: brianh6854@googlemail.com
|
15
|
+
executables:
|
16
|
+
- dockerfish
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- bin/dockerfish
|
21
|
+
- lib/dockerfish.rb
|
22
|
+
homepage: http://rubygems.org/gems/dockerfish
|
23
|
+
licenses:
|
24
|
+
- MIT
|
25
|
+
metadata: {}
|
26
|
+
post_install_message:
|
27
|
+
rdoc_options: []
|
28
|
+
require_paths:
|
29
|
+
- lib
|
30
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
requirements: []
|
41
|
+
rubyforge_project:
|
42
|
+
rubygems_version: 2.2.2
|
43
|
+
signing_key:
|
44
|
+
specification_version: 4
|
45
|
+
summary: Dockerfish
|
46
|
+
test_files: []
|