lxc_forge 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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