ey_resin 1.0.6

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 84fe23ef483433dd5b233293eef404a5202ae816
4
+ data.tar.gz: dfe159d4a2dea2f7c54713485e71c3bfdce1d895
5
+ SHA512:
6
+ metadata.gz: f7ae095793771c8a13e168bcac12df61f7af4b0bffbab9dd499df807ae9acf030c196967635529d9cd9d854cbefaf71d17c6b0c7785c363c81110538ee5a3574
7
+ data.tar.gz: 29472b4207055e1a69a28e1fa3f2093ab61b3f1ff74358104c84de9c40382b5e31a49693b6f35e80cd6786a47e01c6cb02be502a93551fbd9060678c0d6a3fa1
@@ -0,0 +1,10 @@
1
+ require 'ey_resin/archive'
2
+ require 'ey_resin/expand'
3
+ require 'ey_resin/manifest'
4
+ require 'ey_resin/paths'
5
+
6
+ module EY
7
+ module Resin
8
+ extend EY::Resin::Paths
9
+ end
10
+ end
@@ -0,0 +1,44 @@
1
+ require 'addressable/uri'
2
+
3
+ module EY
4
+ module Resin
5
+ class Archive
6
+ def initialize(resin_sha, bits)
7
+ self.resin_sha = resin_sha.to_s
8
+ self.arch_bits = bits.to_s
9
+
10
+ if resin_sha.empty? || arch_bits.empty?
11
+ raise ArgumentError, "Resin::Archive must be initialized with a non-blank resin_sha and arch_bits"
12
+ end
13
+ end
14
+
15
+ def version
16
+ "archive-#{resin_sha}-arch-#{arch_bits}".gsub(/[^#{Addressable::URI::CharacterClasses::UNRESERVED}]/, '').downcase
17
+ end
18
+
19
+ def inspect
20
+ %|EY::Resin::Archive(version: #{version.inspect})|
21
+ end
22
+
23
+ def filename
24
+ "resin-#{version}.tgz"
25
+ end
26
+
27
+ def uri
28
+ Addressable::URI.new(
29
+ :scheme => "https",
30
+ :host => "ey-cloud.s3.amazonaws.com",
31
+ :path => filename
32
+ )
33
+ end
34
+
35
+ def check
36
+ system("curl -s -I #{uri} | grep '200 OK' 1>/dev/null")
37
+ end
38
+
39
+ private
40
+
41
+ attr_accessor :resin_sha, :arch_bits
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,78 @@
1
+ require 'ey_resin/paths'
2
+ require 'sous_chef'
3
+
4
+ module EY
5
+ module Resin
6
+ class Expand
7
+ def initialize(resin_archive)
8
+ self.resin_archive = resin_archive
9
+ self.recipe = build_recipe
10
+
11
+ recipe.node = {
12
+ :version => resin_archive.version,
13
+ :uri => resin_archive.uri,
14
+ }
15
+ end
16
+
17
+ def check
18
+ resin_archive.check || fail("Resin archive #{resin_archive.uri} not curl-able!")
19
+ end
20
+
21
+ def to_script
22
+ recipe.to_script
23
+ end
24
+
25
+ protected
26
+
27
+ attr_accessor :resin_archive, :recipe
28
+
29
+ def build_recipe
30
+ SousChef::Recipe.new do
31
+ halt_on_failed_command
32
+
33
+ uri = node[:uri]
34
+ version = node[:version]
35
+ root = EY::Resin.archive_root
36
+ bin_dir = EY::Resin.bin_dir
37
+ version_file = EY::Resin.version_file
38
+ dummy_auto_gem_file = EY::Resin.dummy_auto_gem_file
39
+
40
+ directory "ensure the archive destination directory exists" do
41
+ path root
42
+ end
43
+
44
+ execute "download and unpack the resin archive into it if needed" do
45
+ only_if %{[[ ! -s #{version_file} ]] || [[ "#{version}" != `cat #{version_file}` ]]}
46
+ raise "Almost rm -rf'd /" if root.to_s == ''
47
+ command "rm -rf #{root}/*"
48
+ command "curl -L --connect-timeout 10 --max-time 120 --retry 3 --retry-max-time 20 #{uri} | tar xz -C #{root}"
49
+ end
50
+
51
+ file "save the version file for future deploys" do
52
+ path version_file
53
+ content version
54
+ mode 0644
55
+ end
56
+
57
+ file "/etc/env.d/93ey-resin" do
58
+ echo "Setting up ey-resin env"
59
+ content <<-EOS
60
+ PATH="#{bin_dir}"
61
+ ROOTPATH="#{bin_dir}"
62
+ EOS
63
+ end
64
+
65
+ file "set up legacy support auto_gem" do
66
+ path dummy_auto_gem_file
67
+ content "# a placeholder for legacy resin 1.8/1.9 support so we can keep RUBYOPT='-rauto_gem'"
68
+ mode 0644
69
+ end
70
+
71
+ execute "rebuild the environment" do
72
+ command "env-update"
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,41 @@
1
+ require 'digest/sha1'
2
+ require 'multi_json'
3
+ require 'jexp'
4
+
5
+ module EY
6
+ module Resin
7
+ class Manifest < Struct.new(:ruby_version, :ruby_pl, :ruby_url, :rubygems_version, :rubygems_url, :gems, :bundle)
8
+ include JEXP::Resource
9
+
10
+ def self.parse(serialized_data)
11
+ if serialized_data.nil?
12
+ raise ArgumentError, "Resin::Manifest unable to parse: nil"
13
+ end
14
+ new(MultiJson.decode(serialized_data))
15
+ rescue MultiJson::DecodeError => e
16
+ raise ArgumentError, "Resin::Manifest unable to parse: #{serialized_data.inspect}"
17
+ end
18
+
19
+ def dump
20
+ MultiJson.encode(to_hash)
21
+ end
22
+
23
+ def ==(other)
24
+ other.respond_to?(:dump) && dump == other.dump
25
+ end
26
+
27
+ def compute_sha
28
+ raw = [ruby_version, ruby_pl, ruby_url, rubygems_version, rubygems_url]
29
+ # This should reall sort by gem name to be consistent, but we're currently unsure about changing the hashing algorithm.
30
+ if bundle
31
+ raw << File.read(bundle).gsub(/\s+/, '')
32
+ else
33
+ gems.each do |(name,version)|
34
+ raw << "#{name}-#{version}"
35
+ end
36
+ end
37
+ Digest::SHA1.hexdigest(raw.join("|"))
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,47 @@
1
+ require 'pathname'
2
+
3
+ module EY
4
+ module Resin
5
+ module Paths
6
+ ARCHIVE_ROOT = Pathname.new("/usr/local/ey_resin")
7
+
8
+ def archive_root
9
+ ARCHIVE_ROOT
10
+ end
11
+
12
+ def version_file
13
+ archive_root.join('resin_archive_version.txt')
14
+ end
15
+
16
+ def bin(name)
17
+ archive_root.join('bin', name)
18
+ end
19
+
20
+ def bin_dir
21
+ archive_root.join('bin')
22
+ end
23
+
24
+ def ruby_dir
25
+ archive_root.join('ruby')
26
+ end
27
+
28
+ def ruby_bin_dir
29
+ archive_root.join('ruby', 'bin')
30
+ end
31
+
32
+ def ruby_binary
33
+ archive_root.join('ruby', 'bin', 'ruby')
34
+ end
35
+
36
+ def gem_binary
37
+ archive_root.join('ruby', 'bin', 'gem')
38
+ end
39
+
40
+ def dummy_auto_gem_file
41
+ # XXX where is the best place to put it?
42
+ # this path is in the resin load path $:
43
+ ruby_dir.join("lib","ruby", "site_ruby", "auto_gem.rb")
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,5 @@
1
+ module EY
2
+ module Resin
3
+ VERSION = '1.0.6'
4
+ end
5
+ end
@@ -0,0 +1,58 @@
1
+ require 'spec_helper'
2
+ require 'dracul/test'
3
+
4
+ describe EY::Resin::Expand do
5
+ pending do
6
+ @instance = Dracul::Test.monsoon.new_instance
7
+ @resin_archive = EY::Resin::Archive.new("integration-testing", @instance.flavor.architecture.bits)
8
+ @expand_script = described_class.new(@resin_archive).to_script
9
+ @instance.script!(@expand_script)
10
+ end
11
+
12
+ pending do
13
+ Dracul::Test.monsoon.kill_instance(@instance)
14
+ end
15
+
16
+ shared_examples_for "an expanded archive with version file" do
17
+ pending "unpacks the archive" do
18
+ @instance.ssh("test -d #{EY::Resin.archive_root}").should be_success
19
+ @instance.ssh("test -d #{EY::Resin.ruby_dir}").should be_success
20
+ @instance.ssh("test -s #{EY::Resin.ruby_binary}").should be_success
21
+ end
22
+
23
+ pending "writes the version file" do
24
+ @instance.ssh(%|[[ "#{@resin_archive.version}" == `cat #{EY::Resin.version_file}` ]]|).should be_success
25
+ end
26
+ end
27
+
28
+ describe "fresh install" do
29
+ it_should_behave_like "an expanded archive with version file"
30
+
31
+ pending "doesn't unpack twice when deployed twice" do
32
+ lambda { @instance.script!(@expand_script) }.
33
+ should_not change { @instance.ssh("stat -c '%Y' #{EY::Resin.version_file} #{EY::Resin.archive_root}/ruby").stdout }
34
+ end
35
+
36
+ pending "adds Archive.root bin/ to the PATH" do
37
+ @instance.ssh("echo $PATH | grep #{EY::Resin.archive_root}").should be_success
38
+ end
39
+ end
40
+
41
+ describe "changing versions" do
42
+ pending do
43
+ @instance.ssh("echo old_version >> #{EY::Resin.version_file}")
44
+ @instance.ssh("echo delete me >> #{EY::Resin.ruby_dir}/delete_me")
45
+ @instance.ssh("echo delete me >> #{EY::Resin.bin_dir}/delete_me")
46
+
47
+ @instance.script!(@expand_script)
48
+ end
49
+
50
+ it_should_behave_like "an expanded archive with version file"
51
+
52
+ pending "removes the old archive" do
53
+ @instance.ssh("! test -s #{EY::Resin.ruby_dir}/delete_me").should be_success
54
+ @instance.ssh("! test -s #{EY::Resin.bin_dir}/delete_me").should be_success
55
+ end
56
+ end
57
+ end
58
+
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe EY::Resin::Archive do
4
+ subject { EY::Resin::Archive.new('sha',32) }
5
+
6
+
7
+ it "generates a url for the archive" do
8
+ subject.uri.to_s.should == "https://ey-cloud.s3.amazonaws.com/resin-archive-sha-arch-32.tgz"
9
+ end
10
+
11
+ it "generates a version string" do
12
+ subject.version.should == 'archive-sha-arch-32'
13
+ end
14
+
15
+ it "checks for resin archive" do
16
+ subject.check.should be_false
17
+ end
18
+
19
+ it "finds a resin archive on check" do
20
+ rc = EY::Resin::Archive.new('43883338dd595d022c795aa03613dab0664fcd42', 32) # arbitrary archive I know existed at the time
21
+ rc.check.should be_true
22
+ end
23
+ end
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ describe "ResinManifest" do
4
+ before do
5
+ @data = {
6
+ :ruby_version => '1.9.2',
7
+ :ruby_pl => '123',
8
+ :ruby_url => 'http://ruby',
9
+ :rubygems_version => '1.2.3',
10
+ :rubygems_url => 'http://rubygems',
11
+ :gems => [
12
+ ['outoforder', '1.2.3'],
13
+ ['ey_enzyme', '7.8.9'],
14
+ ],
15
+ }
16
+ end
17
+
18
+ subject { EY::Resin::Manifest.new(@data) }
19
+
20
+ it "loads options from config" do
21
+ subject.ruby_version.should == @data[:ruby_version]
22
+ subject.ruby_pl.should == @data[:ruby_pl]
23
+ subject.ruby_url.should == @data[:ruby_url]
24
+ subject.rubygems_version.should == @data[:rubygems_version]
25
+ subject.rubygems_url.should == @data[:rubygems_url]
26
+ subject.gems.should == @data[:gems]
27
+ end
28
+
29
+ it "computes the same resin sha from the config every time" do
30
+ subject.compute_sha.should == Digest::SHA1.hexdigest('1.9.2|123|http://ruby|1.2.3|http://rubygems|outoforder-1.2.3|ey_enzyme-7.8.9')
31
+ end
32
+
33
+ it "refuses to parse nil" do
34
+ lambda { EY::Resin::Manifest.parse(nil) }.should raise_error(ArgumentError, "Resin::Manifest unable to parse: nil")
35
+ end
36
+
37
+ it "refuses to parse bad json" do
38
+ lambda { EY::Resin::Manifest.parse('||') }.should raise_error(ArgumentError, 'Resin::Manifest unable to parse: "||"')
39
+ end
40
+
41
+ it "can parse the data it dumps" do
42
+ EY::Resin::Manifest.parse(subject.dump).should == subject
43
+ end
44
+
45
+ context "with a bundle file" do
46
+ before do
47
+ @bundle = File.expand_path('../../Gemfile', File.dirname(__FILE__))
48
+ @data.delete(:gems)
49
+ @data[:bundle] = @bundle
50
+ end
51
+
52
+ subject { EY::Resin::Manifest.new(@data) }
53
+
54
+ it 'generates the sha using the content of the file' do
55
+ bundle_content = File.read(@bundle).gsub(/\s+/, '')
56
+ subject.compute_sha.should == Digest::SHA1.hexdigest("1.9.2|123|http://ruby|1.2.3|http://rubygems|#{bundle_content}")
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ describe EY::Resin do
4
+ it "contains the archive root" do
5
+ EY::Resin.archive_root.should == Pathname.new('/usr/local/ey_resin')
6
+ end
7
+
8
+ it "contains the archive root" do
9
+ EY::Resin.version_file.should == EY::Resin.archive_root.join("resin_archive_version.txt")
10
+ end
11
+
12
+ it "knows where the ruby binary is" do
13
+ EY::Resin.ruby_binary.should == EY::Resin.archive_root.join("ruby/bin/ruby")
14
+ end
15
+
16
+ it "knows where the gem binary is" do
17
+ EY::Resin.gem_binary.should == EY::Resin.archive_root.join("ruby/bin/gem")
18
+ end
19
+
20
+ it "knows where the bin dir is" do
21
+ EY::Resin.bin_dir.should == EY::Resin.archive_root.join("bin")
22
+ end
23
+
24
+ it "knows where the hax auto_gem file is" do
25
+ EY::Resin.dummy_auto_gem_file.should == EY::Resin.ruby_dir.join("lib","ruby", "site_ruby", "auto_gem.rb")
26
+ end
27
+
28
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe EY::Resin::Expand do
4
+ describe ".to_script" do
5
+ let(:resin_archive) { EY::Resin::Archive.new('hello-sha',64) }
6
+ subject { described_class.new(resin_archive).to_script }
7
+
8
+ it "outputs a script" do
9
+ subject.should_not be_empty
10
+ end
11
+
12
+ it "curls the url" do
13
+ subject.should match(/curl .*#{resin_archive.uri}/)
14
+ end
15
+
16
+ it "expands the tarball" do
17
+ subject.should match(/tar xz -C #{EY::Resin.archive_root}/)
18
+ end
19
+
20
+ it "should create a dummy auto_gem file" do
21
+ subject.should match(/#{EY::Resin.dummy_auto_gem_file}/)
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,48 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'ey_resin'
4
+ require 'ey_slater/test'
5
+ require 'rspec'
6
+
7
+ RSpec.configure do |config|
8
+ config.include(EY::Slater::Test)
9
+
10
+ def command_should_succeed(instance, command)
11
+ result = instance.ssh(command)
12
+ return if result.success?
13
+
14
+ fail <<-MESSAGE
15
+ Command expected to succeed on #{instance.public_hostname}:
16
+
17
+ #{command}
18
+
19
+ But failed with exit status $? = #{result.exit_code}.
20
+
21
+ stdout:
22
+
23
+ #{result.stdout}
24
+
25
+ stderr:
26
+
27
+ #{result.stderr}
28
+ MESSAGE
29
+ end
30
+
31
+ def command_should_output(instance, command, expected)
32
+ actual = instance.ssh("#{command} 2>&1").stdout
33
+ if expected.nil?
34
+ actual.should be_nil
35
+ else
36
+ actual.should_not be_nil
37
+ if expected.is_a?(Regexp)
38
+ actual.strip.should =~ expected
39
+ else
40
+ actual.strip.should == expected
41
+ end
42
+ end
43
+ end
44
+
45
+ def fixture_path(name)
46
+ File.expand_path("../fixtures/#{name}", __FILE__)
47
+ end
48
+ end
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ey_resin
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.6
5
+ platform: ruby
6
+ authors:
7
+ - Engine Yard
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2011-08-10 00:00:00 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: sous_chef
16
+ prerelease: false
17
+ requirement: &id001 !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 0.0.2
22
+ type: :runtime
23
+ version_requirements: *id001
24
+ - !ruby/object:Gem::Dependency
25
+ name: addressable
26
+ prerelease: false
27
+ requirement: &id002 !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - &id003
30
+ - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: "0"
33
+ type: :runtime
34
+ version_requirements: *id002
35
+ - !ruby/object:Gem::Dependency
36
+ name: multi_json
37
+ prerelease: false
38
+ requirement: &id004 !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - *id003
41
+ type: :runtime
42
+ version_requirements: *id004
43
+ - !ruby/object:Gem::Dependency
44
+ name: rspec
45
+ prerelease: false
46
+ requirement: &id005 !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ~>
49
+ - !ruby/object:Gem::Version
50
+ version: 2.0.0
51
+ type: :development
52
+ version_requirements: *id005
53
+ description: ey resin
54
+ email:
55
+ - gems@engineyard.com
56
+ executables: []
57
+
58
+ extensions: []
59
+
60
+ extra_rdoc_files: []
61
+
62
+ files:
63
+ - lib/ey_resin/archive.rb
64
+ - lib/ey_resin/expand.rb
65
+ - lib/ey_resin/manifest.rb
66
+ - lib/ey_resin/paths.rb
67
+ - lib/ey_resin/version.rb
68
+ - lib/ey_resin.rb
69
+ - spec/fixtures/resin-archive-integration-testing-arch-32.tgz
70
+ - spec/fixtures/resin-archive-integration-testing-arch-64.tgz
71
+ - spec/integration/resin_expand_spec.rb
72
+ - spec/models/archive_spec.rb
73
+ - spec/models/manifest_spec.rb
74
+ - spec/models/paths_spec.rb
75
+ - spec/models/resin_expand_spec.rb
76
+ - spec/spec_helper.rb
77
+ homepage: http://github.com/engineyard/ey_resin
78
+ licenses: []
79
+
80
+ metadata: {}
81
+
82
+ post_install_message:
83
+ rdoc_options: []
84
+
85
+ require_paths:
86
+ - lib
87
+ required_ruby_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - *id003
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">"
93
+ - !ruby/object:Gem::Version
94
+ version: 1.3.1
95
+ requirements: []
96
+
97
+ rubyforge_project:
98
+ rubygems_version: 2.0.14
99
+ signing_key:
100
+ specification_version: 3
101
+ summary: ey resin
102
+ test_files:
103
+ - spec/fixtures/resin-archive-integration-testing-arch-32.tgz
104
+ - spec/fixtures/resin-archive-integration-testing-arch-64.tgz
105
+ - spec/integration/resin_expand_spec.rb
106
+ - spec/models/archive_spec.rb
107
+ - spec/models/manifest_spec.rb
108
+ - spec/models/paths_spec.rb
109
+ - spec/models/resin_expand_spec.rb
110
+ - spec/spec_helper.rb