lxc_forge 0.0.1 → 0.0.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a46630faab99e6cbac68630c73bc3b6536947865
4
- data.tar.gz: 7110dd9ead9d48c5ea95928fb947e64aa91cb28f
3
+ metadata.gz: 31e8f63bfff899437fbbf1b2557424b62bf04f1c
4
+ data.tar.gz: b7d0f1b6f8a6f14b766cac9a47b78e5e74de2096
5
5
  SHA512:
6
- metadata.gz: 13b7604b78718afe100c50823a6c2fe369657af27b3e97f1365ee4adb54ce0cfe5f0d9350f63169ec6a35052302328bdcbd67c64762530e97290d021f6f5cdc4
7
- data.tar.gz: 50ba48a42bc9958e155a365873bbbe63fa633b0744df4ef6b27b4f9ce4b70052a339db43929b58eb444774d07225988d6a31befc78e4a24881871e220c35666b
6
+ metadata.gz: 5821e09407804138ad8fcd971d66e821bfa40b5f9f01e83445d3a65bea5c0bd79efbc190ab31be598114d3b4582c103aacf671c852a39034d069d90ecd552d27
7
+ data.tar.gz: 25530eb1e13b6ecd4701c94971a62aa292a39f240ff6bb15d7227f198f0e7725d3fefd14230feb20a97b9d7058ddd61a7d05c9c75a785c192459ba968067d34e
data/.gitignore CHANGED
@@ -15,3 +15,4 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
+ config/application.yml
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color --format doc
@@ -0,0 +1,5 @@
1
+ rvm:
2
+ - 1.9.3
3
+ - 2.0.0
4
+ - 2.1.1
5
+ script: rspec
data/Gemfile CHANGED
@@ -1,4 +1,6 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
+ gem 'coveralls', require: false
4
+
3
5
  # Specify your gem's dependencies in lxc_forge.gemspec
4
6
  gemspec
@@ -0,0 +1,24 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard :rspec do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+
9
+ # Rails example
10
+ watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
11
+ watch(%r{^app/(.*)(\.erb|\.haml|\.slim)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
12
+ watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
13
+ watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
14
+ watch('config/routes.rb') { "spec/routing" }
15
+ watch('app/controllers/application_controller.rb') { "spec/controllers" }
16
+
17
+ # Capybara features specs
18
+ watch(%r{^app/views/(.+)/.*\.(erb|haml|slim)$}) { |m| "spec/features/#{m[1]}_spec.rb" }
19
+
20
+ # Turnip features and steps
21
+ watch(%r{^spec/acceptance/(.+)\.feature$})
22
+ watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
23
+ end
24
+
data/README.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # LXC Forge
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/lxc_forge.svg)](http://badge.fury.io/rb/lxc_forge)
4
+ [![Build Status](https://travis-ci.org/jbussdieker/lxc_forge.svg?branch=master)](https://travis-ci.org/jbussdieker/lxc_forge)
5
+ [![Dependency Status](https://gemnasium.com/jbussdieker/lxc_forge.svg)](https://gemnasium.com/jbussdieker/lxc_forge)
6
+ [![Code Climate](https://codeclimate.com/github/jbussdieker/lxc_forge.png)](https://codeclimate.com/github/jbussdieker/lxc_forge)
7
+ [![Coverage Status](https://coveralls.io/repos/jbussdieker/lxc_forge/badge.png)](https://coveralls.io/r/jbussdieker/lxc_forge)
8
+
3
9
  Upload and download LXC containers from S3
4
10
 
5
11
  ## Installation
@@ -20,7 +26,7 @@ Upload a container to S3:
20
26
 
21
27
  Download a container from S3:
22
28
 
23
- $ lxc-forge download -o mycontainer
29
+ $ lxc-forge download -n mycontainer
24
30
 
25
31
  ## Contributing
26
32
 
@@ -1,2 +1,17 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'lxc_forge'
3
+
4
+ options = LxcForge::Options.new(ARGV).parse
5
+ config = LxcForge::Config.new(options)
6
+ config.load
7
+
8
+ begin
9
+ LxcForge::Command.new(config, options).run
10
+ rescue Exception => e
11
+ if options[:verbose]
12
+ raise e
13
+ else
14
+ $stderr.puts e.message
15
+ exit 1
16
+ end
17
+ end
@@ -1,5 +1,8 @@
1
1
  require "lxc_forge/version"
2
+ require "lxc_forge/config"
3
+ require "lxc_forge/container"
4
+ require "lxc_forge/command"
5
+ require "lxc_forge/options"
2
6
 
3
7
  module LxcForge
4
- # Your code goes here...
5
8
  end
@@ -0,0 +1,72 @@
1
+ module LxcForge
2
+ class Command
3
+ attr_accessor :config, :options
4
+
5
+ def initialize(config, options)
6
+ @config = config
7
+ @options = options
8
+ end
9
+
10
+ def run
11
+ start = Time.now
12
+ send(options[:command])
13
+ finish = Time.now
14
+ puts "Completed in #{finish - start} seconds" if options[:verbose]
15
+ end
16
+
17
+ def container
18
+ @container ||= LxcForge::Container.new(options[:name], config)
19
+ end
20
+
21
+ def prompt(msg)
22
+ print msg
23
+ STDIN.gets.chomp()
24
+ end
25
+
26
+ def prompt_yes_no(msg)
27
+ raise "Aborted" unless prompt(msg) == "y"
28
+ end
29
+
30
+ def upload
31
+ raise "Container doesn't exist" unless container.exists?
32
+
33
+ if container.remote_exists?
34
+ prompt_yes_no "Remote file already exists. Replace it (y/n) " unless options[:force]
35
+ container.destroy_remote
36
+ end
37
+
38
+ print "Compressing..."
39
+ container.compress
40
+ print "Uploading..."
41
+ container.upload
42
+ end
43
+
44
+ def download
45
+ raise "Remote file doesn't exist" unless container.remote_exists?
46
+
47
+ if container.exists?
48
+ prompt_yes_no "Container already exists. Replace it (y/n) " unless options[:force]
49
+ container.destroy
50
+ end
51
+
52
+ print "Downloading..."
53
+ container.download
54
+ print "Installing..."
55
+ container.uncompress
56
+ end
57
+
58
+ def configure
59
+ config = Config.new(options)
60
+ config.access_key_id = prompt("Access Key ID: ")
61
+ config.secret_access_key = prompt("Secret Access Key: ")
62
+ config.region = prompt("Region: ")
63
+ config.bucket = prompt("Bucket: ")
64
+ config.save
65
+ puts "Configuration Saved"
66
+ end
67
+
68
+ def list
69
+ container.list
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,44 @@
1
+ require 'yaml'
2
+
3
+ module LxcForge
4
+ class Config
5
+ attr_accessor :options, :access_key_id, :secret_access_key, :region, :bucket
6
+
7
+ def initialize(options)
8
+ @options = options
9
+ end
10
+
11
+ def config_file
12
+ File.join(ENV["HOME"], ".lxc_forge.yml")
13
+ end
14
+
15
+ def load
16
+ load_file(config_file)
17
+ end
18
+
19
+ def to_hash
20
+ {
21
+ :access_key_id => access_key_id,
22
+ :secret_access_key => secret_access_key,
23
+ :region => region,
24
+ :bucket => bucket
25
+ }
26
+ end
27
+
28
+ # TODO: Break up
29
+ def save
30
+ File.open(config_file, 'w') do |f|
31
+ f.write(to_hash.to_yaml)
32
+ end
33
+ end
34
+
35
+ # TODO: Break up
36
+ def load_file(filename)
37
+ data = File.read(filename)
38
+ c = YAML.load(data)
39
+ c.each do |k, v|
40
+ send("#{k}=", v)
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,127 @@
1
+ require 'lxc'
2
+ require 'tempfile'
3
+ require 'aws-sdk'
4
+
5
+ module LxcForge
6
+ class Container
7
+ attr_accessor :name, :config
8
+
9
+ def initialize(name, config)
10
+ @name = name
11
+ @config = config
12
+ end
13
+
14
+ def lxc
15
+ LXC.new
16
+ end
17
+
18
+ def lxc_container
19
+ LXC::Container.new(:lxc => lxc, :name => name)
20
+ end
21
+
22
+ def list
23
+ bucket.objects.each do |o|
24
+ puts o.key
25
+ end
26
+ end
27
+
28
+ def exists?
29
+ lxc_container.exists?
30
+ end
31
+
32
+ def destroy
33
+ lxc_container.destroy
34
+ end
35
+
36
+ def destroy_remote
37
+ obj.delete
38
+ end
39
+
40
+ def remote_exists?
41
+ obj.exists?
42
+ end
43
+
44
+ def tmp_file
45
+ @tmp_file ||= (
46
+ name = Dir::Tmpname.make_tmpname "lxc-forge-#{name}", nil
47
+ File.join(Dir::Tmpname.tmpdir, name)
48
+ )
49
+ end
50
+
51
+ # TODO: Break up
52
+ def compress
53
+ Dir.chdir "/var/lib/lxc"
54
+ count = 0
55
+ IO.popen("tar -zcvf #{tmp_file} #{name} 2>&1") do |io|
56
+ while !io.eof? do
57
+ io.gets
58
+ count += 1
59
+ print "." if count % 200 == 0
60
+ end
61
+ end
62
+ puts
63
+ raise "Error compressing" unless $?.to_i == 0
64
+ end
65
+
66
+ # TODO: Break up
67
+ def uncompress
68
+ Dir.chdir "/var/lib/lxc"
69
+ count = 0
70
+ IO.popen("tar -zxvf #{tmp_file} 2>&1") do |io|
71
+ while !io.eof? do
72
+ io.gets
73
+ count += 1
74
+ print "." if count % 200 == 0
75
+ end
76
+ end
77
+ puts
78
+ raise "Error uncompressing" unless $?.to_i == 0
79
+ end
80
+
81
+ def s3_config
82
+ {
83
+ :access_key_id => config.access_key_id,
84
+ :secret_access_key => config.secret_access_key,
85
+ :region => config.region
86
+ }
87
+ end
88
+
89
+ def s3
90
+ AWS::S3.new(s3_config)
91
+ end
92
+
93
+ def bucket
94
+ s3.buckets[config.bucket]
95
+ end
96
+
97
+ def obj
98
+ bucket.objects[@name]
99
+ end
100
+
101
+ # TODO: Break up
102
+ def upload
103
+ count = 0
104
+ File.open(tmp_file, 'r') do |file|
105
+ obj.write(:content_length => file.size) do |buffer, bytes|
106
+ count += 1
107
+ print "." if count % 1 == 0
108
+ buffer.write(file.read(bytes))
109
+ end
110
+ end
111
+ puts
112
+ end
113
+
114
+ # TODO: Break up
115
+ def download
116
+ count = 0
117
+ File.open(tmp_file, 'wb') do |file|
118
+ obj.read do |chunk|
119
+ count += 1
120
+ print "." if count % 500 == 0
121
+ file.write(chunk)
122
+ end
123
+ end
124
+ puts
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,53 @@
1
+ require 'optparse'
2
+
3
+ module LxcForge
4
+ class Options
5
+ attr_accessor :options
6
+
7
+ def initialize(argv)
8
+ @argv = argv
9
+ @options = {}
10
+ end
11
+
12
+ def parser
13
+ OptionParser.new do |opts|
14
+ opts.banner = "Usage: lxc-forge ACTION [options]
15
+
16
+ Actions:
17
+ configure - Configure LXC Forge settings
18
+ upload - Upload an LXC container to S3
19
+ download - Download an LXC container from S3
20
+ list - List available containers on S3
21
+
22
+ "
23
+
24
+ opts.on("-n NAME", "--name NAME", "Set container name") do |v|
25
+ options[:name] = v
26
+ end
27
+
28
+ opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
29
+ options[:verbose] = v
30
+ end
31
+
32
+ opts.on("-f", "--[no-]force", "Force overwrite") do |v|
33
+ options[:force] = v
34
+ end
35
+ end
36
+ end
37
+
38
+ def parse
39
+ parser.parse!(@argv)
40
+
41
+ if @argv.length == 0
42
+ puts parser.help
43
+ exit 0
44
+ elsif @argv.length == 1
45
+ options[:command] = @argv.first
46
+ else
47
+ raise ArgumentError.new "Multiple actions not supported"
48
+ end
49
+
50
+ options
51
+ end
52
+ end
53
+ end
@@ -1,3 +1,3 @@
1
1
  module LxcForge
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -19,4 +19,9 @@ Gem::Specification.new do |spec|
19
19
 
20
20
  spec.add_development_dependency "bundler", "~> 1.3"
21
21
  spec.add_development_dependency "rake"
22
+ spec.add_development_dependency "rspec"
23
+ spec.add_development_dependency "guard-rspec"
24
+ spec.add_runtime_dependency "lxc", "~> 0.6"
25
+ spec.add_runtime_dependency "minitar", "~> 0.5"
26
+ spec.add_runtime_dependency "aws-sdk", "~> 1.38"
22
27
  end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe LxcForge::Config do
4
+ let(:options) { {} }
5
+ let(:config) { LxcForge::Config.new(options) }
6
+ subject { config }
7
+
8
+ its(:config_file) { should == File.join(ENV["HOME"], ".lxc_forge.yml") }
9
+ its(:to_hash) { should == { :access_key_id => nil, :secret_access_key => nil, :region => nil, :bucket => nil } }
10
+
11
+ end
@@ -0,0 +1,72 @@
1
+ require 'spec_helper'
2
+
3
+ describe LxcForge::Container do
4
+ let(:name) { "test-container" }
5
+ let(:options) { {} }
6
+ let(:config) { LxcForge::Config.new(options) }
7
+ let(:container) { LxcForge::Container.new(name, config) }
8
+ subject { container }
9
+
10
+ its(:name) { should == name }
11
+ its(:config) { should == config }
12
+ its(:lxc) { should be_kind_of LXC }
13
+ its(:lxc_container) { should be_kind_of LXC::Container }
14
+
15
+ describe "list" do
16
+ # TODO
17
+ end
18
+
19
+ describe "exists?" do
20
+ let(:lxc_container) { double().as_null_object }
21
+ before { container.stub(:lxc_container).and_return(lxc_container) }
22
+
23
+ context "when container exists" do
24
+ before { lxc_container.stub(:exists?).and_return(true) }
25
+ its(:exists?) { should == true }
26
+ end
27
+
28
+ context "when container does not exist" do
29
+ before { lxc_container.stub(:exists?).and_return(false) }
30
+ its(:exists?) { should == false }
31
+ end
32
+ end
33
+
34
+ describe "destroy" do
35
+ let(:lxc_container) { double().as_null_object }
36
+ before { container.stub(:lxc_container).and_return(lxc_container) }
37
+
38
+ it "calls destroy on lxc_container" do
39
+ lxc_container.should_recieve(:destroy)
40
+ subject.destroy
41
+ end
42
+ end
43
+
44
+ describe "destroy_remote" do
45
+ let(:obj) { double().as_null_object }
46
+ before { container.stub(:obj).and_return(obj) }
47
+
48
+ it "calls delete on obj" do
49
+ obj.should_recieve(:delete)
50
+ subject.destroy_remote
51
+ end
52
+ end
53
+
54
+ describe "remote_exists?" do
55
+ let(:obj) { double().as_null_object }
56
+ before { container.stub(:obj).and_return(obj) }
57
+
58
+ it "calls exists? on obj" do
59
+ obj.should_recieve(:exists?)
60
+ subject.remote_exists?
61
+ end
62
+ end
63
+
64
+ describe "tmp_file" do
65
+ its(:tmp_file) { should start_with "/tmp/lxc-forge-" }
66
+ end
67
+
68
+ its(:s3_config) { should == {:access_key_id => nil, :region => nil, :secret_access_key => nil} }
69
+ its(:s3) { should be_kind_of AWS::S3 }
70
+ its(:bucket) { should be_kind_of AWS::S3::Bucket }
71
+ its(:obj) { should be_kind_of AWS::S3::S3Object }
72
+ end
@@ -0,0 +1,4 @@
1
+ require 'spec_helper'
2
+
3
+ describe LxcForge do
4
+ end
@@ -0,0 +1,4 @@
1
+ require 'coveralls'
2
+ Coveralls.wear!
3
+
4
+ require 'lxc_forge'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lxc_forge
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joshua B. Bussdieker
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-10 00:00:00.000000000 Z
11
+ date: 2014-04-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -38,6 +38,76 @@ dependencies:
38
38
  - - '>='
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: guard-rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: lxc
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: '0.6'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: '0.6'
83
+ - !ruby/object:Gem::Dependency
84
+ name: minitar
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: '0.5'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ~>
95
+ - !ruby/object:Gem::Version
96
+ version: '0.5'
97
+ - !ruby/object:Gem::Dependency
98
+ name: aws-sdk
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ~>
102
+ - !ruby/object:Gem::Version
103
+ version: '1.38'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ~>
109
+ - !ruby/object:Gem::Version
110
+ version: '1.38'
41
111
  description:
42
112
  email:
43
113
  - jbussdieker@gmail.com
@@ -47,14 +117,25 @@ extensions: []
47
117
  extra_rdoc_files: []
48
118
  files:
49
119
  - .gitignore
120
+ - .rspec
121
+ - .travis.yml
50
122
  - Gemfile
123
+ - Guardfile
51
124
  - LICENSE.txt
52
125
  - README.md
53
126
  - Rakefile
54
127
  - bin/lxc-forge
55
128
  - lib/lxc_forge.rb
129
+ - lib/lxc_forge/command.rb
130
+ - lib/lxc_forge/config.rb
131
+ - lib/lxc_forge/container.rb
132
+ - lib/lxc_forge/options.rb
56
133
  - lib/lxc_forge/version.rb
57
134
  - lxc_forge.gemspec
135
+ - spec/lib/lxc_forge/config_spec.rb
136
+ - spec/lib/lxc_forge/container_spec.rb
137
+ - spec/lib/lxc_forge_spec.rb
138
+ - spec/spec_helper.rb
58
139
  homepage: https://github.com/jbussdieker/lxc_forge
59
140
  licenses:
60
141
  - MIT
@@ -79,4 +160,8 @@ rubygems_version: 2.1.11
79
160
  signing_key:
80
161
  specification_version: 4
81
162
  summary: Upload and download LXC containers from S3
82
- test_files: []
163
+ test_files:
164
+ - spec/lib/lxc_forge/config_spec.rb
165
+ - spec/lib/lxc_forge/container_spec.rb
166
+ - spec/lib/lxc_forge_spec.rb
167
+ - spec/spec_helper.rb