ssc 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +3 -3
- data/VERSION +1 -1
- data/lib/directory_manager.rb +9 -2
- data/lib/handlers/all.rb +1 -1
- data/lib/handlers/build.rb +1 -1
- data/lib/handlers/file.rb +63 -25
- data/ssc.gemspec +3 -3
- data/test/integration/test_file.rb +77 -6
- data/test/unit/test_directory_manager.rb +60 -0
- metadata +4 -4
data/README.rdoc
CHANGED
@@ -15,9 +15,9 @@ This is the new version of the the Suse Studio command line client. Built as a p
|
|
15
15
|
|
16
16
|
=== Command Listing
|
17
17
|
|
18
|
-
ssc checkout --appliance-id=N --password=PASSWORD --username=USERNAME # checkout the latest changes to an appliance
|
19
|
-
ssc commit --appliance-id=N --password=PASSWORD --username=USERNAME # commit changes to studio
|
20
|
-
ssc status --appliance-id=N --password=PASSWORD --username=USERNAME # show status of the appliance
|
18
|
+
ssc checkout --appliance-id=N --password=PASSWORD --username=USERNAME # checkout the latest changes to an appliance
|
19
|
+
ssc commit --appliance-id=N --password=PASSWORD --username=USERNAME # commit changes to studio
|
20
|
+
ssc status --appliance-id=N --password=PASSWORD --username=USERNAME # show status of the appliance
|
21
21
|
|
22
22
|
ssc appliance # manage appliances
|
23
23
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.4.0
|
data/lib/directory_manager.rb
CHANGED
@@ -98,13 +98,13 @@ module SSC
|
|
98
98
|
file_params= options.slice(:permissions, :group, :owner).merge(:path => file_path)
|
99
99
|
push("add", {file_name => file_params})
|
100
100
|
end
|
101
|
-
|
101
|
+
destination_path
|
102
102
|
end
|
103
103
|
|
104
104
|
def is_uploaded?(file_name)
|
105
105
|
read
|
106
106
|
list= @parsed_file["list"].select{|i| i.keys[0] == file_name}
|
107
|
-
list
|
107
|
+
list[0][file_name]["id"] if list.length > 0
|
108
108
|
end
|
109
109
|
|
110
110
|
end
|
@@ -141,6 +141,13 @@ module SSC
|
|
141
141
|
def valid?
|
142
142
|
Dir.exists?(@path) && File.exists?(File.join(@path, '.sscrc'))
|
143
143
|
end
|
144
|
+
|
145
|
+
class << self
|
146
|
+
def show_file(relative_path)
|
147
|
+
path= File.join(@path, relative_path)
|
148
|
+
File.read(path)
|
149
|
+
end
|
150
|
+
end
|
144
151
|
end
|
145
152
|
end
|
146
153
|
end
|
data/lib/handlers/all.rb
CHANGED
data/lib/handlers/build.rb
CHANGED
@@ -8,7 +8,7 @@ module SSC
|
|
8
8
|
require_appliance_id
|
9
9
|
method_option :image_type, :type => :string
|
10
10
|
def build
|
11
|
-
|
11
|
+
require_appliance_directory do |appliance, files|
|
12
12
|
if appliance.status.state != "ok"
|
13
13
|
raise Thor::Error, "Appliance is not OK. Please fix before building.\n#{appliance.status.issues.join("\n")}\n"
|
14
14
|
else
|
data/lib/handlers/file.rb
CHANGED
@@ -49,8 +49,8 @@ module SSC
|
|
49
49
|
require_appliance_id
|
50
50
|
allow_remote_option
|
51
51
|
def remove(file_name)
|
52
|
-
|
53
|
-
file_id=
|
52
|
+
file_list= FileListFile.new
|
53
|
+
file_id= file_list.is_uploaded?(file_name)
|
54
54
|
if options.remote? && file_id
|
55
55
|
begin
|
56
56
|
StudioApi::File.find(file_id).destroy
|
@@ -61,8 +61,8 @@ module SSC
|
|
61
61
|
elsif options.remote? && !file_id
|
62
62
|
raise Thor::Error, "File '#{file_name}' not found"
|
63
63
|
else
|
64
|
-
|
65
|
-
|
64
|
+
file_list.push('remove', {file_name => nil})
|
65
|
+
file_list.save
|
66
66
|
say "File '#{file_name}' marked for removal"
|
67
67
|
end
|
68
68
|
end
|
@@ -70,51 +70,89 @@ module SSC
|
|
70
70
|
desc 'file show FILE_NAME', 'show the contents of the file'
|
71
71
|
require_appliance_id
|
72
72
|
allow_remote_option
|
73
|
+
method_option :file_id, :type => :string
|
73
74
|
def show(file_name)
|
74
75
|
if options.remote?
|
75
|
-
|
76
|
-
|
77
|
-
|
76
|
+
begin
|
77
|
+
require_appliance_directory do |appliance, files|
|
78
|
+
id= files[:file_list].is_uploaded?(file_name)
|
79
|
+
if id
|
80
|
+
response= StudioApi::File.find(id)
|
81
|
+
say response.content
|
82
|
+
else
|
83
|
+
say "File hasn't been uploaded.\nLocal Copy:", :red
|
84
|
+
say ApplianceDirectory.show_file(File.join('files',file_name))
|
85
|
+
end
|
86
|
+
end
|
87
|
+
rescue ApplianceDirectoryError
|
88
|
+
if options.file_id
|
89
|
+
say StudioApi::File.find(options.file_id).content
|
90
|
+
else
|
91
|
+
files= StudioApi::File.find(:all)
|
92
|
+
files= files.select {|f| f.filename == file_name}
|
93
|
+
raise Thor::Error, "File not found or ambiguous file name " unless files.length == 1
|
94
|
+
say files[0].content
|
95
|
+
end
|
96
|
+
end
|
78
97
|
else
|
79
|
-
say show_file(file_name)
|
98
|
+
say ApplianceDirectory.show_file(File.join('files', file_name))
|
80
99
|
end
|
81
100
|
end
|
82
101
|
|
83
102
|
desc 'file diff FILE_NAME', 'show the diff of the remote file and the local one'
|
84
103
|
require_appliance_id
|
85
104
|
def diff(file_name)
|
86
|
-
|
87
|
-
id=
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
begin
|
105
|
+
require_appliance_directory do |appliance, files|
|
106
|
+
id= files[:file_list].is_uploaded?(file_name)
|
107
|
+
raise Thor::Error, "File hasn't been uploaded" unless id
|
108
|
+
response= StudioApi::File.find(id)
|
109
|
+
remote_content= response.content
|
110
|
+
local_file= File.join(Dir.pwd, 'files', file_name)
|
94
111
|
tempfile=Tempfile.new('ssc_file')
|
95
|
-
tempfile.write(
|
96
|
-
say find_diff(tempfile.path,
|
112
|
+
tempfile.write(remote_content)
|
113
|
+
say find_diff(tempfile.path, local_file)
|
97
114
|
tempfile.close; tempfile.unlink
|
98
|
-
rescue Errno::ENOENT
|
99
|
-
say "diff not installed", :red
|
100
115
|
end
|
116
|
+
rescue ApplianceDirectoryError
|
117
|
+
raise Thor::Error, "diff can only be performed in the appliance directory"
|
101
118
|
end
|
102
119
|
|
103
120
|
desc 'file list', 'show all overlay files'
|
104
121
|
require_appliance_id
|
105
122
|
allow_remote_option
|
106
123
|
def list
|
107
|
-
|
108
|
-
|
124
|
+
require_appliance_directory do |appliance, files|
|
125
|
+
file_list= files[:file_list]
|
126
|
+
out= if options.remote? || file_list.empty_list?
|
109
127
|
response= StudioApi::File.find(:all, :params => {:appliance_id => appliance.id})
|
110
|
-
response.collect do |file|
|
111
|
-
{file.filename => {"id" => file.id, "path" => file.path}}
|
128
|
+
response= response.collect do |file|
|
129
|
+
item= {file.filename => {"id" => file.id, "path" => file.path}}
|
130
|
+
file_list.push('list', item)
|
112
131
|
end
|
132
|
+
file_list.save
|
133
|
+
response
|
113
134
|
else
|
114
|
-
|
135
|
+
file_list["list"]
|
115
136
|
end
|
116
137
|
say out.to_yaml
|
117
138
|
end
|
139
|
+
rescue ApplianceDirectoryError
|
140
|
+
require_appliance do |appliance|
|
141
|
+
print_table StudioApi::File.find(:all, :params => {:appliance_id => appliance.id}).collect do |file|
|
142
|
+
[file.id, File.join(file.path, file.filename)]
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
private
|
148
|
+
|
149
|
+
def get_file_list(appliance_id)
|
150
|
+
end
|
151
|
+
|
152
|
+
def find_diff(file1, file2)
|
153
|
+
`diff #{file1} #{file2}`
|
154
|
+
rescue Errno::ENOENT
|
155
|
+
raise Thor::Error, "'diff' not installed"
|
118
156
|
end
|
119
157
|
end
|
120
158
|
end
|
data/ssc.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{ssc}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.4.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Ratan Sebastian"]
|
12
|
-
s.date = %q{2011-08-
|
12
|
+
s.date = %q{2011-08-31}
|
13
13
|
s.default_executable = %q{ssc}
|
14
14
|
s.description = %q{Command-line client for Suse Studio}
|
15
15
|
s.email = %q{rjsvaljean@gmail.com}
|
@@ -46,7 +46,7 @@ Gem::Specification.new do |s|
|
|
46
46
|
s.licenses = ["MIT"]
|
47
47
|
s.require_paths = ["lib"]
|
48
48
|
s.rubygems_version = %q{1.3.7}
|
49
|
-
s.summary = %q{Command-line client for Suse Studio}
|
49
|
+
s.summary = %q{Command-line client for Suse Studio.}
|
50
50
|
|
51
51
|
if s.respond_to? :specification_version then
|
52
52
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
@@ -1,6 +1,9 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
3
|
class TestOverlayFile < Test::Unit::TestCase
|
4
|
+
|
5
|
+
include SSC::DirectoryManager
|
6
|
+
|
4
7
|
context "file" do
|
5
8
|
setup do
|
6
9
|
@client= SSC::Client.new
|
@@ -10,7 +13,7 @@ class TestOverlayFile < Test::Unit::TestCase
|
|
10
13
|
StudioApi::Appliance.stubs(:clone).returns(@default_mock_appliance)
|
11
14
|
@client.invoke('s_s_c:handler:appliance:create', ['test_appliance'], {:source_id => 1234}.merge(@auth_params))
|
12
15
|
@default_mock_package= StudioApi::Package.new('test_package', :version => '1', :repository_id => 9876)
|
13
|
-
StudioApi::Appliance.stubs(:find).
|
16
|
+
StudioApi::Appliance.stubs(:find).returns(@default_mock_appliance)
|
14
17
|
end
|
15
18
|
context "add" do
|
16
19
|
setup do
|
@@ -25,7 +28,7 @@ class TestOverlayFile < Test::Unit::TestCase
|
|
25
28
|
should "upload file and create a new file locally" do
|
26
29
|
StudioApi::File.expects(:upload).returns(stub(:id => 1))
|
27
30
|
mock_file_list= mock()
|
28
|
-
|
31
|
+
FileListFile.stubs(:new).returns(mock_file_list)
|
29
32
|
mock_file_list.expects(:initiate_file).with(@test_file_path, anything)
|
30
33
|
@client.invoke('s_s_c:handler:overlay_file:add', [@test_file_path], {:remote => true, :appliance_id => 5678})
|
31
34
|
end
|
@@ -33,7 +36,7 @@ class TestOverlayFile < Test::Unit::TestCase
|
|
33
36
|
context "when the remote flag is not set" do
|
34
37
|
should "just add the file to the file_list in the add section" do
|
35
38
|
mock_file_list= mock()
|
36
|
-
|
39
|
+
FileListFile.stubs(:new).returns(mock_file_list)
|
37
40
|
mock_file_list.expects(:initiate_file).with(@test_file_path, anything)
|
38
41
|
@client.invoke('s_s_c:handler:overlay_file:add', [@test_file_path], {:appliance_id => 5678})
|
39
42
|
end
|
@@ -42,7 +45,7 @@ class TestOverlayFile < Test::Unit::TestCase
|
|
42
45
|
context "when not in the appliance directory" do
|
43
46
|
setup do
|
44
47
|
Dir.chdir('..') if File.exist?('./.sscrc')
|
45
|
-
|
48
|
+
ApplianceDirectory.any_instance.stubs(:valid).returns(false)
|
46
49
|
end
|
47
50
|
context "when the remote flag is set" do
|
48
51
|
should "just upload the file" do
|
@@ -56,7 +59,7 @@ class TestOverlayFile < Test::Unit::TestCase
|
|
56
59
|
context "remove" do
|
57
60
|
context "when the remote flag is set" do
|
58
61
|
should "destroy the file remotely" do
|
59
|
-
|
62
|
+
FileListFile.any_instance.stubs(:is_uploaded?).returns(:id)
|
60
63
|
mock_file_object= mock()
|
61
64
|
mock_file_object.expects(:destroy)
|
62
65
|
StudioApi::File.expects(:find).with(:id).returns(mock_file_object)
|
@@ -70,11 +73,79 @@ class TestOverlayFile < Test::Unit::TestCase
|
|
70
73
|
mock_file_list.stubs(:is_uploaded?).returns(:id)
|
71
74
|
mock_file_list.expects(:push).with('remove', has_key('test_file'))
|
72
75
|
mock_file_list.expects(:save)
|
73
|
-
|
76
|
+
FileListFile.stubs(:new).returns(mock_file_list)
|
74
77
|
@client.invoke('s_s_c:handler:overlay_file:remove', ["test_file"], {})
|
75
78
|
end
|
76
79
|
end
|
77
80
|
end
|
81
|
+
context "show" do
|
82
|
+
context "when not in the appliance directory" do
|
83
|
+
setup do
|
84
|
+
Dir.chdir('..') if File.exists?('.sscrc')
|
85
|
+
end
|
86
|
+
context "and when the remote flag is set with the file_id option" do
|
87
|
+
should "show the file using the file_id" do
|
88
|
+
StudioApi::File.expects(:find).with(1).returns(stub(:content => ''))
|
89
|
+
@client.invoke('s_s_c:handler:overlay_file:show', ['test_file'], @appliance_params.merge({:remote => true, :file_id => 1}))
|
90
|
+
end
|
91
|
+
end
|
92
|
+
context "and when the remote flag is set without the file_id option" do
|
93
|
+
should "show the file using the file_name" do
|
94
|
+
StudioApi::File.expects(:find).with(:all).returns([stub(:content => '', :filename => 'test_file')])
|
95
|
+
@client.invoke('s_s_c:handler:overlay_file:show', ['test_file'], @appliance_params.merge({:remote => true}))
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
context "when in the appliance directory" do
|
100
|
+
setup do
|
101
|
+
Dir.chdir('test_appliance') if Dir.exists?('test_appliance')
|
102
|
+
end
|
103
|
+
context "and when the remote flag is set" do
|
104
|
+
should "show the file if file has been uploaded" do
|
105
|
+
FileListFile.any_instance.stubs(:is_uploaded?).returns(:id)
|
106
|
+
StudioApi::File.expects(:find).with(:id).returns(stub(:content => ''))
|
107
|
+
@client.invoke('s_s_c:handler:overlay_file:show', ['test_file'], @appliance_params.merge({:remote => true}))
|
108
|
+
end
|
109
|
+
|
110
|
+
should "show the local file if the file hasn't been uploaded" do
|
111
|
+
FileListFile.any_instance.stubs(:is_uploaded?).returns(nil)
|
112
|
+
ApplianceDirectory.expects(:show_file).with('files/test_file')
|
113
|
+
@client.invoke('s_s_c:handler:overlay_file:show', ['test_file'], @appliance_params.merge({:remote => true}))
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
context "diff" do
|
120
|
+
context "when in the appliance directory" do
|
121
|
+
setup do
|
122
|
+
Dir.chdir('test_appliance') if Dir.exists?('test_appliance')
|
123
|
+
File.open('files/test_file', 'w') {|f| f.write('test')}
|
124
|
+
end
|
125
|
+
should "show the diff of the two files" do
|
126
|
+
FileListFile.any_instance.expects(:is_uploaded?).returns(:id)
|
127
|
+
StudioApi::File.expects(:find).with(:id).returns(stub(:content => ''))
|
128
|
+
@client.invoke('s_s_c:handler:overlay_file:diff', ['test_file'], @appliance_params)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
context "list" do
|
134
|
+
context "when in an appliance directory" do
|
135
|
+
setup do
|
136
|
+
Dir.chdir('test_appliance') if Dir.exists?('test_appliance')
|
137
|
+
end
|
138
|
+
should "list the files and save to the file list file" do
|
139
|
+
FileListFile.any_instance.stubs(:empty_list? => true, :push => {}, :[] => {})
|
140
|
+
mock_file= StudioApi::File.new(:path => 'path', :id => 1,
|
141
|
+
:filename => 'filename')
|
142
|
+
StudioApi::File.expects(:find).with(:all, anything).returns([mock_file])
|
143
|
+
@client.invoke('s_s_c:handler:overlay_file:list', [], @appliance_params)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
context "when not in an appliance directory" do
|
147
|
+
end
|
148
|
+
end
|
78
149
|
end
|
79
150
|
|
80
151
|
|
@@ -1,5 +1,49 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
|
+
class TestFileListFile < Test::Unit::TestCase
|
4
|
+
include SSC::DirectoryManager
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@file_list_file= FileListFile.new
|
8
|
+
@data = {"list" => [{'file2' => {'path' => '/file/path'}},
|
9
|
+
{'file1' => {'id' => 1,
|
10
|
+
'path' => '/file/path',
|
11
|
+
'owner' => 'root',
|
12
|
+
'group' => 'root' }}],
|
13
|
+
"add" => [],
|
14
|
+
"remove" => []}
|
15
|
+
@file_list_file.instance_variable_set('@parsed_file', @data)
|
16
|
+
end
|
17
|
+
|
18
|
+
context "#pop" do
|
19
|
+
should "reformat the file list hash" do
|
20
|
+
assert_equal({:name=>"file1", :full_path=>"/file/path",
|
21
|
+
:params=>{"owner"=>"root", "group"=>"root"}},
|
22
|
+
@file_list_file.pop('list'))
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context "#initiate_file" do
|
27
|
+
should "create a file and make an entry in the file_list file" do
|
28
|
+
FileUtils.mkdir_p('files')
|
29
|
+
File.open('test_file', 'w') {|f| f.write('test')}
|
30
|
+
@file_list_file.initiate_file('test_file', {'key' => 'value'})
|
31
|
+
assert File.exists? 'files/test_file'
|
32
|
+
FileUtils.rm_rf('files')
|
33
|
+
FileUtils.rm('test_file')
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context "#is_uploaded?" do
|
38
|
+
should "return the id if the file is uploaded" do
|
39
|
+
assert_equal 1, @file_list_file.is_uploaded?('file1')
|
40
|
+
end
|
41
|
+
should "return false if file is not uploaded" do
|
42
|
+
assert_equal nil, @file_list_file.is_uploaded?('file2')
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
3
47
|
class TestDirectoryManager < Test::Unit::TestCase
|
4
48
|
include SSC::DirectoryManager
|
5
49
|
|
@@ -40,6 +84,9 @@ class TestDirectoryManager < Test::Unit::TestCase
|
|
40
84
|
assert_equal 4, @file.pop('add')
|
41
85
|
assert !@file.instance_variable_get('@parsed_file')["add"].include?(4)
|
42
86
|
end
|
87
|
+
should "return nil if the section is empty" do
|
88
|
+
assert_equal nil, @file.pop("empty_section")
|
89
|
+
end
|
43
90
|
end
|
44
91
|
|
45
92
|
context "#push" do
|
@@ -58,6 +105,19 @@ class TestDirectoryManager < Test::Unit::TestCase
|
|
58
105
|
end
|
59
106
|
end
|
60
107
|
|
108
|
+
context "#[]" do
|
109
|
+
context "when the section exists" do
|
110
|
+
should "return the list from the section" do
|
111
|
+
assert @file["add"] == [{"sub" => {1 => "one", 2 => "two"}}, 2, 3, 4]
|
112
|
+
end
|
113
|
+
end
|
114
|
+
context "when the section does not exist" do
|
115
|
+
should "return a empty list" do
|
116
|
+
assert @file["empty_section"] == []
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
61
121
|
context "#read" do
|
62
122
|
should "return the parsed contents of the file if the file is available" do
|
63
123
|
assert @file.read.is_a?(Hash)
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
7
|
+
- 4
|
8
8
|
- 0
|
9
|
-
version: 0.
|
9
|
+
version: 0.4.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Ratan Sebastian
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2011-08-
|
17
|
+
date: 2011-08-31 00:00:00 +02:00
|
18
18
|
default_executable: ssc
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -179,6 +179,6 @@ rubyforge_project:
|
|
179
179
|
rubygems_version: 1.3.7
|
180
180
|
signing_key:
|
181
181
|
specification_version: 3
|
182
|
-
summary: Command-line client for Suse Studio
|
182
|
+
summary: Command-line client for Suse Studio.
|
183
183
|
test_files: []
|
184
184
|
|