ssc 0.3.0 → 0.4.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.
@@ -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.3.0
1
+ 0.4.0
@@ -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
- destination_file
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.length > 0 ? list[0]["id"].to_i : nil
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
@@ -12,7 +12,7 @@ module SSC
12
12
 
13
13
  include Helper
14
14
 
15
- API_URL= 'https://susestudio.com/api/v1/user'
15
+ API_URL= 'https://susestudio.com/api/v2/user'
16
16
 
17
17
  def initialize(*args)
18
18
  super
@@ -8,7 +8,7 @@ module SSC
8
8
  require_appliance_id
9
9
  method_option :image_type, :type => :string
10
10
  def build
11
- require_appliance_dir do |appliance, files|
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
@@ -49,8 +49,8 @@ module SSC
49
49
  require_appliance_id
50
50
  allow_remote_option
51
51
  def remove(file_name)
52
- @file_list= FileListFile.new
53
- file_id= @file_list.is_uploaded?(file_name)
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
- @file_list.push('remove', {file_name => nil})
65
- @file_list.save
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
- id= find_file_id(file_name)
76
- response= StudioApi::File.find(id)
77
- say response.content
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
- begin
87
- id= find_file_id(file_name)
88
- file_content= StudioApi::File.find(id).content
89
- rescue
90
- say "unable to connect or not in appliance directory", :red
91
- end
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(file_content)
96
- say find_diff(tempfile.path, full_local_file_path(file_name))
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
- require_appliance do |appliance|
108
- out= if options.remote? || file_list_empty?
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
- list_local_files
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
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{ssc}
8
- s.version = "0.3.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-15}
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).with(5678).returns(@default_mock_appliance)
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
- SSC::DirectoryManager::FileListFile.stubs(:new).returns(mock_file_list)
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
- SSC::DirectoryManager::FileListFile.stubs(:new).returns(mock_file_list)
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
- SSC::DirectoryManager::ApplianceDirectory.any_instance.stubs(:valid).returns(false)
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
- SSC::DirectoryManager::FileListFile.any_instance.stubs(:is_uploaded?).returns(:id)
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
- SSC::DirectoryManager::FileListFile.stubs(:new).returns(mock_file_list)
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
- - 3
7
+ - 4
8
8
  - 0
9
- version: 0.3.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-15 00:00:00 +02:00
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