ssc 0.1 → 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.
- data/Gemfile +14 -0
- data/Gemfile.lock +39 -0
- data/README.rdoc +22 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/bin/ssc +4 -231
- data/lib/directory_manager.rb +194 -0
- data/lib/handlers/all.rb +33 -0
- data/lib/handlers/appliance.rb +74 -0
- data/lib/handlers/file.rb +102 -0
- data/lib/handlers/helper.rb +79 -0
- data/lib/handlers/package.rb +153 -0
- data/lib/handlers/repository.rb +109 -0
- data/lib/handlers/template.rb +25 -0
- data/lib/ssc.rb +18 -0
- data/test/handlers/test_appliance.rb +20 -0
- data/test/handlers/test_helper.rb +45 -0
- data/test/handlers/test_repository.rb +20 -0
- data/test/handlers/test_template.rb +27 -0
- data/test/helper.rb +19 -0
- data/test/test_argument_parser.rb +55 -0
- data/test/test_directory_manager.rb +40 -0
- data/test/test_ssc.rb +39 -0
- metadata +147 -31
- data/README +0 -1
- data/lib/appliancehandler.rb +0 -69
- data/lib/buildhandler.rb +0 -125
- data/lib/checkouthandler.rb +0 -322
- data/lib/commandhandler.rb +0 -38
- data/lib/request.rb +0 -29
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
class TestDirectoryManager < Test::Unit::TestCase
|
5
|
+
context "SSC::DirectoryManager" do
|
6
|
+
setup do
|
7
|
+
class B; include SSC::DirectoryManager; end
|
8
|
+
@app_dir= B.create_appliance_directory('test_dir','user','pass',1)
|
9
|
+
Dir.chdir('test_dir')
|
10
|
+
class A
|
11
|
+
include SSC::DirectoryManager
|
12
|
+
manage 'software'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
should "set the @@local_source variable correctly" do
|
17
|
+
assert_equal File.join(@app_dir, 'software'), A.class_variable_get('@@local_source')
|
18
|
+
end
|
19
|
+
|
20
|
+
context "#save" do
|
21
|
+
should "save data to the local cache file" do
|
22
|
+
A.new.save(['some', 'data'])
|
23
|
+
assert_equal "some\ndata\n", File.read('software')
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context "#read" do
|
28
|
+
should "fetch data from local_source" do
|
29
|
+
A.new.save(['some', 'data'])
|
30
|
+
assert_equal ['some', 'data'], A.new.read
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
def teardown
|
37
|
+
Dir.chdir('..')
|
38
|
+
FileUtils.rm_r('test_dir')
|
39
|
+
end
|
40
|
+
end
|
data/test/test_ssc.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestSsc < Test::Unit::TestCase
|
4
|
+
context "SSC::Base" do
|
5
|
+
setup do
|
6
|
+
File.open('.sscrc', 'w') {|f| f.write("username: user\npassword: pass")}
|
7
|
+
@client= SSC::Base.new(['appliance', 'create', '--option', 'value',
|
8
|
+
'-o', 'v', '--flag', '-f'])
|
9
|
+
@specific_client= SSC::Base.new(['appliance', 'create',
|
10
|
+
'--username', 'user1',
|
11
|
+
'--password', 'pass1'])
|
12
|
+
FileUtils.rm('.sscrc')
|
13
|
+
end
|
14
|
+
|
15
|
+
context "when username and password are passed in the command line" do
|
16
|
+
should "override username and password in ./.sscrc" do
|
17
|
+
assert_equal({:username => 'user1', :password => 'pass1'},
|
18
|
+
@specific_client.instance_variable_get('@options'))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
should "initialize handler class correctly" do
|
23
|
+
assert_equal SSC::Handler::Appliance,
|
24
|
+
@client.instance_variable_get('@klass')
|
25
|
+
end
|
26
|
+
|
27
|
+
should "initialize @args with an ArgumentParser object" do
|
28
|
+
args= @client.instance_variable_get('@args')
|
29
|
+
assert_equal SSC::ArgumentParser, args.class
|
30
|
+
end
|
31
|
+
|
32
|
+
should "initialize @config with the config from .sscrc" do
|
33
|
+
options= @client.instance_variable_get('@options')
|
34
|
+
assert_equal('user', options[:username])
|
35
|
+
assert_equal('pass', options[:password])
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
metadata
CHANGED
@@ -1,78 +1,194 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ssc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 23
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 2
|
9
|
+
- 0
|
10
|
+
version: 0.2.0
|
5
11
|
platform: ruby
|
6
12
|
authors:
|
7
|
-
-
|
13
|
+
- Ratan Sebastian
|
8
14
|
autorequire:
|
9
15
|
bindir: bin
|
10
16
|
cert_chain: []
|
11
17
|
|
12
|
-
date:
|
13
|
-
default_executable:
|
18
|
+
date: 2011-07-20 00:00:00 +02:00
|
19
|
+
default_executable: ssc
|
14
20
|
dependencies:
|
15
21
|
- !ruby/object:Gem::Dependency
|
16
|
-
name:
|
17
|
-
|
18
|
-
|
19
|
-
|
22
|
+
name: studio_api
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
20
26
|
requirements:
|
21
27
|
- - ">="
|
22
28
|
- !ruby/object:Gem::Version
|
23
|
-
|
24
|
-
|
29
|
+
hash: 7
|
30
|
+
segments:
|
31
|
+
- 3
|
32
|
+
- 1
|
33
|
+
- 2
|
34
|
+
version: 3.1.2
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
25
37
|
- !ruby/object:Gem::Dependency
|
26
|
-
name:
|
38
|
+
name: thor
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 43
|
46
|
+
segments:
|
47
|
+
- 0
|
48
|
+
- 14
|
49
|
+
- 6
|
50
|
+
version: 0.14.6
|
27
51
|
type: :runtime
|
28
|
-
|
29
|
-
|
52
|
+
version_requirements: *id002
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: shoulda
|
55
|
+
prerelease: false
|
56
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
hash: 3
|
62
|
+
segments:
|
63
|
+
- 0
|
64
|
+
version: "0"
|
65
|
+
type: :development
|
66
|
+
version_requirements: *id003
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
name: mocha
|
69
|
+
prerelease: false
|
70
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
hash: 3
|
76
|
+
segments:
|
77
|
+
- 0
|
78
|
+
version: "0"
|
79
|
+
type: :development
|
80
|
+
version_requirements: *id004
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: bundler
|
83
|
+
prerelease: false
|
84
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ~>
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
hash: 23
|
90
|
+
segments:
|
91
|
+
- 1
|
92
|
+
- 0
|
93
|
+
- 0
|
94
|
+
version: 1.0.0
|
95
|
+
type: :development
|
96
|
+
version_requirements: *id005
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: jeweler
|
99
|
+
prerelease: false
|
100
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
101
|
+
none: false
|
102
|
+
requirements:
|
103
|
+
- - ~>
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
hash: 15
|
106
|
+
segments:
|
107
|
+
- 1
|
108
|
+
- 6
|
109
|
+
- 0
|
110
|
+
version: 1.6.0
|
111
|
+
type: :development
|
112
|
+
version_requirements: *id006
|
113
|
+
- !ruby/object:Gem::Dependency
|
114
|
+
name: rcov
|
115
|
+
prerelease: false
|
116
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
117
|
+
none: false
|
30
118
|
requirements:
|
31
119
|
- - ">="
|
32
120
|
- !ruby/object:Gem::Version
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
121
|
+
hash: 3
|
122
|
+
segments:
|
123
|
+
- 0
|
124
|
+
version: "0"
|
125
|
+
type: :development
|
126
|
+
version_requirements: *id007
|
127
|
+
description: Command-line client for Suse Studio
|
128
|
+
email: rjsvaljean@gmail.com
|
37
129
|
executables:
|
38
130
|
- ssc
|
39
131
|
extensions: []
|
40
132
|
|
41
133
|
extra_rdoc_files:
|
42
|
-
- README
|
134
|
+
- README.rdoc
|
43
135
|
files:
|
136
|
+
- Gemfile
|
137
|
+
- Gemfile.lock
|
138
|
+
- README.rdoc
|
139
|
+
- Rakefile
|
140
|
+
- VERSION
|
44
141
|
- bin/ssc
|
45
|
-
- lib/
|
46
|
-
- lib/
|
47
|
-
- lib/
|
48
|
-
- lib/
|
49
|
-
- lib/
|
50
|
-
-
|
51
|
-
|
52
|
-
|
142
|
+
- lib/directory_manager.rb
|
143
|
+
- lib/handlers/all.rb
|
144
|
+
- lib/handlers/appliance.rb
|
145
|
+
- lib/handlers/file.rb
|
146
|
+
- lib/handlers/helper.rb
|
147
|
+
- lib/handlers/package.rb
|
148
|
+
- lib/handlers/repository.rb
|
149
|
+
- lib/handlers/template.rb
|
150
|
+
- lib/ssc.rb
|
151
|
+
- test/handlers/test_appliance.rb
|
152
|
+
- test/handlers/test_helper.rb
|
153
|
+
- test/handlers/test_repository.rb
|
154
|
+
- test/handlers/test_template.rb
|
155
|
+
- test/helper.rb
|
156
|
+
- test/test_argument_parser.rb
|
157
|
+
- test/test_directory_manager.rb
|
158
|
+
- test/test_ssc.rb
|
159
|
+
has_rdoc: true
|
160
|
+
homepage: http://github.com/rjsvaljean/ssc
|
161
|
+
licenses:
|
162
|
+
- MIT
|
53
163
|
post_install_message:
|
54
164
|
rdoc_options: []
|
55
165
|
|
56
166
|
require_paths:
|
57
167
|
- lib
|
58
168
|
required_ruby_version: !ruby/object:Gem::Requirement
|
169
|
+
none: false
|
59
170
|
requirements:
|
60
171
|
- - ">="
|
61
172
|
- !ruby/object:Gem::Version
|
173
|
+
hash: 3
|
174
|
+
segments:
|
175
|
+
- 0
|
62
176
|
version: "0"
|
63
|
-
version:
|
64
177
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
178
|
+
none: false
|
65
179
|
requirements:
|
66
180
|
- - ">="
|
67
181
|
- !ruby/object:Gem::Version
|
182
|
+
hash: 3
|
183
|
+
segments:
|
184
|
+
- 0
|
68
185
|
version: "0"
|
69
|
-
version:
|
70
186
|
requirements: []
|
71
187
|
|
72
188
|
rubyforge_project:
|
73
|
-
rubygems_version: 1.
|
189
|
+
rubygems_version: 1.5.2
|
74
190
|
signing_key:
|
75
|
-
specification_version:
|
76
|
-
summary:
|
191
|
+
specification_version: 3
|
192
|
+
summary: Command-line client for Suse Studio
|
77
193
|
test_files: []
|
78
194
|
|
data/README
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
A commandline client for SUSE Studio.
|
data/lib/appliancehandler.rb
DELETED
@@ -1,69 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'commandhandler'
|
4
|
-
|
5
|
-
class ApplianceHandler < CommandHandler
|
6
|
-
def self.list_appliances
|
7
|
-
r = Request.new
|
8
|
-
r.method = "GET"
|
9
|
-
r.call = "appliances"
|
10
|
-
s = doRequest(r)
|
11
|
-
|
12
|
-
xml = XML::Smart.string( s )
|
13
|
-
res = String.new
|
14
|
-
xml.find("/appliances/appliance").each do |a|
|
15
|
-
res << "#{a.find("id").first.to_s}: #{a.find("name").first.to_s} (based on #{a.find("basesystem").first.to_s})\n"
|
16
|
-
res << " Cloned from: #{a.find("parent/name").first.to_s} (#{a.find("parent/id").first.to_s})\n" unless a.find("parent/name").length == 0
|
17
|
-
res << " Builds: #{a.find("builds/build").length} (#{a.find("builds/build/compressed_image_size").inject(0){|sum,item| sum + item.to_i}})\n"
|
18
|
-
res << "\n"
|
19
|
-
end
|
20
|
-
puts res
|
21
|
-
end
|
22
|
-
|
23
|
-
def self.clone_appliance args
|
24
|
-
clonefrom = args[1]
|
25
|
-
if clonefrom.nil? || clonefrom.empty?
|
26
|
-
STDERR.puts "You need to specify a template."
|
27
|
-
exit 1
|
28
|
-
end
|
29
|
-
r = Request.new
|
30
|
-
r.method = "POST"
|
31
|
-
r.call = "appliances?clone_from=#{clonefrom}"
|
32
|
-
s = doRequest(r)
|
33
|
-
|
34
|
-
xml = XML::Smart.string( s )
|
35
|
-
res = String.new
|
36
|
-
res << "Created Appliance: #{xml.find("/appliance/name").first.to_s}\n"
|
37
|
-
res << " Id: " + xml.find("/appliance/id").first.to_s + "\n"
|
38
|
-
res << " Based on: " + xml.find("/appliance/basesystem").first.to_s + "\n"
|
39
|
-
res << " Cloned from: #{xml.find("/appliance/parent/name").first.to_s} (#{xml.find("/appliance/parent/id").first.to_s})\n" unless xml.find("/appliance/parent/name").length == 0
|
40
|
-
puts res
|
41
|
-
end
|
42
|
-
|
43
|
-
def self.delete_appliance args
|
44
|
-
appliance = get_appliance_from_args_or_config args
|
45
|
-
r = Request.new
|
46
|
-
r.method = "DELETE"
|
47
|
-
r.call = "appliances/#{appliance}"
|
48
|
-
doRequest(r)
|
49
|
-
puts "Success."
|
50
|
-
end
|
51
|
-
|
52
|
-
def self.template_sets
|
53
|
-
r = Request.new
|
54
|
-
r.method = "GET"
|
55
|
-
r.call = "template_sets"
|
56
|
-
s = doRequest(r)
|
57
|
-
|
58
|
-
xml = XML::Smart.string( s )
|
59
|
-
res = String.new
|
60
|
-
xml.find("/template_sets/template_set").each do |ts|
|
61
|
-
res << "'#{ts.find("name").first.to_s}' Templates (#{ts.find("description").first.to_s}):\n"
|
62
|
-
ts.find("template").each do |t|
|
63
|
-
res << " #{t.find("appliance_id").first.to_s}: #{t.find("name").first.to_s} (based on #{t.find("basesystem").first.to_s})\n"
|
64
|
-
res << " Description: #{t.find("description").first.to_s}\n\n"
|
65
|
-
end
|
66
|
-
end
|
67
|
-
puts res
|
68
|
-
end
|
69
|
-
end
|
data/lib/buildhandler.rb
DELETED
@@ -1,125 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'commandhandler'
|
4
|
-
|
5
|
-
class BuildHandler < CommandHandler
|
6
|
-
def self.build_appliance args, force
|
7
|
-
appliance = get_appliance_from_args_or_config args
|
8
|
-
r = Request.new
|
9
|
-
r.method = "POST"
|
10
|
-
r.call = "running_builds?appliance_id=#{appliance}"
|
11
|
-
r.call += "&force=1" if force
|
12
|
-
s = doRequest(r)
|
13
|
-
|
14
|
-
xml = XML::Smart.string( s )
|
15
|
-
res = String.new
|
16
|
-
res << "Triggered build: #{xml.find("/build/id").first.to_s}" unless xml.find("/build/id").length == 0
|
17
|
-
puts res
|
18
|
-
end
|
19
|
-
|
20
|
-
def self.list_running_builds args
|
21
|
-
appliance = get_appliance_from_args_or_config args
|
22
|
-
r = Request.new
|
23
|
-
r.method = "GET"
|
24
|
-
r.call = "running_builds/?appliance_id=#{appliance}"
|
25
|
-
s = doRequest(r)
|
26
|
-
|
27
|
-
xml = XML::Smart.string( s )
|
28
|
-
res = String.new
|
29
|
-
xml.find("/running_builds/running_build").each do |rb|
|
30
|
-
res << "#{rb.find("id").first.to_s}: #{rb.find("state").first.to_s}"
|
31
|
-
res << ", #{rb.find("percent").first.to_s}% done - #{rb.find("message").first.to_s} (#{rb.find("time_elapsed").first.to_s}s elapsed)" unless xml.find("state").first.to_s == "error"
|
32
|
-
end
|
33
|
-
puts res unless res.empty?
|
34
|
-
end
|
35
|
-
|
36
|
-
def self.show_running_build args, follow
|
37
|
-
build = args[1]
|
38
|
-
if build.nil? || build.empty?
|
39
|
-
STDERR.puts "You need to specify a running build."
|
40
|
-
exit 1
|
41
|
-
end
|
42
|
-
r = Request.new
|
43
|
-
r.method = "GET"
|
44
|
-
r.call = "running_builds/#{build}"
|
45
|
-
while 1
|
46
|
-
s = doRequest(r)
|
47
|
-
|
48
|
-
xml = XML::Smart.string( s )
|
49
|
-
res = String.new
|
50
|
-
return unless xml.find("/running_build/id").length > 0
|
51
|
-
res << xml.find("/running_build/state").first.to_s
|
52
|
-
res << ", #{xml.find("/running_build/percent").first.to_s}% done - #{xml.find("/running_build/message").first.to_s} (#{xml.find("/running_build/time_elapsed").first.to_s}s elapsed)" unless xml.find("/running_build/state").first.to_s == "error"
|
53
|
-
puts res
|
54
|
-
exit 0 unless follow
|
55
|
-
sleep 5
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def self.list_builds args
|
60
|
-
appliance = get_appliance_from_args_or_config args
|
61
|
-
r = Request.new
|
62
|
-
r.method = "GET"
|
63
|
-
r.call = "builds/?appliance_id=#{appliance}"
|
64
|
-
s = doRequest(r)
|
65
|
-
|
66
|
-
xml = XML::Smart.string( s )
|
67
|
-
res = String.new
|
68
|
-
xml.find("/builds/build").each do |rb|
|
69
|
-
res << "#{rb.find("id").first.to_s}: #{rb.find("state").first.to_s}"
|
70
|
-
res << ", v#{rb.find("version").first.to_s} (#{rb.find("image_type").first.to_s})"
|
71
|
-
res << " (#{rb.find("compressed_image_size").first.to_s} MB)" if rb.find("compressed_image_size").length > 0
|
72
|
-
res << " #{rb.find("download_url").first.to_s}" if rb.find("download_url").length > 0
|
73
|
-
res << "\n"
|
74
|
-
end
|
75
|
-
puts res unless res.empty?
|
76
|
-
end
|
77
|
-
|
78
|
-
def self.show_build args
|
79
|
-
build = args[1]
|
80
|
-
if build.nil? || build.empty?
|
81
|
-
STDERR.puts "You need to specify a build."
|
82
|
-
exit 1
|
83
|
-
end
|
84
|
-
r = Request.new
|
85
|
-
r.method = "GET"
|
86
|
-
r.call = "builds/#{build}"
|
87
|
-
s = doRequest(r)
|
88
|
-
|
89
|
-
xml = XML::Smart.string( s )
|
90
|
-
res = String.new
|
91
|
-
xml.find("/build").each do |rb|
|
92
|
-
res << "#{rb.find("id").first.to_s}: #{rb.find("state").first.to_s}"
|
93
|
-
res << ", v#{rb.find("version").first.to_s} (#{rb.find("image_type").first.to_s})"
|
94
|
-
res << " (#{rb.find("size").first.to_s}/#{rb.find("compressed_image_size").first.to_s} MB)" if rb.find("size").length > 0
|
95
|
-
res << " #{rb.find("download_url").first.to_s}" if rb.find("download_url").length > 0
|
96
|
-
end
|
97
|
-
puts res unless res.empty?
|
98
|
-
end
|
99
|
-
|
100
|
-
def self.cancel_build args
|
101
|
-
build = args[1]
|
102
|
-
if build.nil? || build.empty?
|
103
|
-
STDERR.puts "You need to specify a build."
|
104
|
-
exit 1
|
105
|
-
end
|
106
|
-
r = Request.new
|
107
|
-
r.method = "DELETE"
|
108
|
-
r.call = "running_builds/#{build}"
|
109
|
-
doRequest(r)
|
110
|
-
puts "Success."
|
111
|
-
end
|
112
|
-
|
113
|
-
def self.delete_build args
|
114
|
-
build = args[1]
|
115
|
-
if build.nil? || build.empty?
|
116
|
-
STDERR.puts "You need to specify a build."
|
117
|
-
exit 1
|
118
|
-
end
|
119
|
-
r = Request.new
|
120
|
-
r.method = "DELETE"
|
121
|
-
r.call = "builds/#{build}"
|
122
|
-
doRequest(r)
|
123
|
-
puts "Success."
|
124
|
-
end
|
125
|
-
end
|