license-acceptance 0.0.1 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -0
  3. data/Gemfile.lock +97 -0
  4. data/config/product_info.toml +1 -0
  5. data/lib/license_acceptance/acceptor.rb +117 -0
  6. data/lib/license_acceptance/arg_acceptance.rb +33 -0
  7. data/lib/license_acceptance/cli_flags/mixlib_cli.rb +22 -0
  8. data/lib/license_acceptance/cli_flags/thor.rb +21 -0
  9. data/lib/license_acceptance/config.rb +65 -0
  10. data/lib/license_acceptance/env_acceptance.rb +19 -0
  11. data/lib/license_acceptance/file_acceptance.rb +97 -0
  12. data/lib/license_acceptance/logger.rb +19 -0
  13. data/lib/license_acceptance/product.rb +23 -0
  14. data/lib/license_acceptance/product_reader.rb +108 -0
  15. data/lib/license_acceptance/product_relationship.rb +13 -0
  16. data/lib/license_acceptance/prompt_acceptance.rb +104 -0
  17. data/lib/license_acceptance/version.rb +3 -0
  18. data/spec/license_acceptance/acceptor_spec.rb +222 -0
  19. data/spec/license_acceptance/arg_acceptance_spec.rb +37 -0
  20. data/spec/license_acceptance/cli_flags/mixlib_cli_spec.rb +14 -0
  21. data/spec/license_acceptance/cli_flags/thor_spec.rb +14 -0
  22. data/spec/license_acceptance/config_spec.rb +113 -0
  23. data/spec/license_acceptance/env_acceptance_spec.rb +43 -0
  24. data/spec/license_acceptance/file_acceptance_spec.rb +121 -0
  25. data/spec/license_acceptance/product_reader_spec.rb +139 -0
  26. data/spec/license_acceptance/product_spec.rb +13 -0
  27. data/spec/license_acceptance/prompt_acceptance_spec.rb +100 -0
  28. data/spec/spec_helper.rb +25 -0
  29. metadata +184 -22
  30. data/.gitignore +0 -11
  31. data/.rspec +0 -3
  32. data/.travis.yml +0 -7
  33. data/LICENSE +0 -1
  34. data/README.md +0 -35
  35. data/lib/license/acceptance/version.rb +0 -5
  36. data/lib/license/acceptance.rb +0 -8
  37. data/license-acceptance.gemspec +0 -42
@@ -0,0 +1,37 @@
1
+ require "spec_helper"
2
+ require "license_acceptance/arg_acceptance"
3
+
4
+ RSpec.describe LicenseAcceptance::ArgAcceptance do
5
+ let(:acc) { LicenseAcceptance::ArgAcceptance.new }
6
+
7
+ describe "#check" do
8
+ it "returns true if the args contain the required flag with spaces" do
9
+ expect(acc.check(["--chef-license", "accept"])).to eq(true)
10
+ end
11
+
12
+ it "returns true if the args contain the required flag with equal" do
13
+ expect(acc.check(["--chef-license=accept"])).to eq(true)
14
+ end
15
+
16
+ it "returns false if the args do not contain the required value" do
17
+ expect(acc.check(["--chef-license"])).to eq(false)
18
+ end
19
+ end
20
+
21
+ describe "#check_no_persist" do
22
+ it "returns true if the args contain the required flag with spaces" do
23
+ expect(acc.check_no_persist(["--chef-license", "accept-no-persist"])).to eq(true)
24
+ end
25
+
26
+ it "returns true if the args contain the required flag with equal" do
27
+ expect(acc.check_no_persist(["--chef-license=accept-no-persist"])).to eq(true)
28
+ end
29
+
30
+ it "returns false if the args do not contain the required value" do
31
+ expect(acc.check_no_persist(["--chef-license"])).to eq(false)
32
+ expect(acc.check_no_persist(["--chef-license=accept"])).to eq(false)
33
+ expect(acc.check_no_persist(["--chef-license","accept"])).to eq(false)
34
+ end
35
+ end
36
+
37
+ end
@@ -0,0 +1,14 @@
1
+ require "spec_helper"
2
+ require "license_acceptance/cli_flags/mixlib_cli"
3
+
4
+ class TestMixlibKlass
5
+ include Mixlib::CLI
6
+ include LicenseAcceptance::CLIFlags::MixlibCLI
7
+ end
8
+
9
+ RSpec.describe LicenseAcceptance::CLIFlags::MixlibCLI do
10
+ let(:klass) { TestMixlibKlass.new }
11
+ it "adds the correct command line flag" do
12
+ expect(klass.options).to include(:chef_license)
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ require "spec_helper"
2
+ require "license_acceptance/cli_flags/thor"
3
+ require "thor"
4
+
5
+ class TestThorKlass < Thor
6
+ include LicenseAcceptance::CLIFlags::Thor
7
+ end
8
+
9
+ RSpec.describe LicenseAcceptance::CLIFlags::Thor do
10
+ let(:klass) { TestThorKlass.new }
11
+ it "adds the correct command line flag" do
12
+ expect(klass.class.class_options.keys).to eq([:chef_license])
13
+ end
14
+ end
@@ -0,0 +1,113 @@
1
+ require "spec_helper"
2
+ require "climate_control"
3
+ require "license_acceptance/config"
4
+ require "license_acceptance/product_relationship"
5
+
6
+ RSpec.describe LicenseAcceptance::Config do
7
+ let(:opts) { {} }
8
+ let(:config) { LicenseAcceptance::Config.new(opts) }
9
+ let(:platform) { instance_double(TTY::Platform) }
10
+
11
+ it "loads correctly with default values" do
12
+ config
13
+ end
14
+
15
+ describe "with overwritten values" do
16
+ let(:output) { StringIO.new }
17
+ let(:logger) { "logger" }
18
+ let(:license_locations) { [] }
19
+ let(:persist_location) { "foo" }
20
+ let(:persist) { false }
21
+ let(:opts) { { output: output, logger: logger, license_locations: license_locations, persist_location: persist_location, persist: persist } }
22
+
23
+ it "loads correctly" do
24
+ expect(config.output).to eq(output)
25
+ expect(config.logger).to eq(logger)
26
+ expect(config.license_locations).to eq(license_locations)
27
+ expect(config.persist_location).to eq("foo")
28
+ expect(config.persist).to eq(false)
29
+ end
30
+ end
31
+
32
+ describe "#default_license_locations and #default_persist_location" do
33
+ before do
34
+ expect(TTY::Platform).to receive(:new).and_return(platform)
35
+ expect(Process).to receive(:uid).and_return(uid)
36
+ end
37
+
38
+ describe "when platform is Windows" do
39
+ before do
40
+ expect(platform).to receive(:windows?).and_return(true)
41
+ end
42
+
43
+ describe "when user is Administrator" do
44
+ let(:uid) { 0 }
45
+
46
+ it "returns the default value" do
47
+ ClimateControl.modify HOMEDRIVE: "C:" do
48
+ expect(config.license_locations).to eq(["C:/chef/accepted_licenses/"])
49
+ expect(config.persist_location).to eq("C:/chef/accepted_licenses/")
50
+ end
51
+ end
52
+ end
53
+
54
+ describe "when user is not Administrator" do
55
+ let(:uid) { 1000 }
56
+
57
+ it "returns the default USERPROFILE value" do
58
+ ClimateControl.modify HOMEDRIVE: "C:", USERPROFILE: "C:/Users/foo", HOME: nil do
59
+ expect(Dir).to receive(:exist?).with("C:/Users/foo").and_return(true)
60
+ expect(config.license_locations).to eq([
61
+ "C:/chef/accepted_licenses/",
62
+ "C:/Users/foo/.chef/accepted_licenses/"
63
+ ])
64
+ expect(config.persist_location).to eq("C:/Users/foo/.chef/accepted_licenses/")
65
+ end
66
+ end
67
+
68
+ it "returns the default HOMEDRIVE + HOMEPATH value" do
69
+ ClimateControl.modify HOMEDRIVE: "C:", USERPROFILE: "C:/Users/bar", HOME: nil do
70
+ expect(Dir).to receive(:exist?).with("C:/Users/bar").and_return(true)
71
+ expect(config.license_locations).to eq([
72
+ "C:/chef/accepted_licenses/",
73
+ "C:/Users/bar/.chef/accepted_licenses/"
74
+ ])
75
+ expect(config.persist_location).to eq("C:/Users/bar/.chef/accepted_licenses/")
76
+ end
77
+ end
78
+ end
79
+
80
+ end
81
+
82
+ describe "when platform is non-Windows" do
83
+ before do
84
+ expect(platform).to receive(:windows?).and_return(false)
85
+ end
86
+
87
+ describe "when user is root" do
88
+ let(:uid) { 0 }
89
+
90
+ it "returns the default value" do
91
+ expect(config.license_locations).to eq(["/etc/chef/accepted_licenses/"])
92
+ expect(config.persist_location).to eq("/etc/chef/accepted_licenses/")
93
+ end
94
+ end
95
+
96
+ describe "when user is not root" do
97
+ let(:uid) { 1000 }
98
+
99
+ it "returns the default user value" do
100
+ ClimateControl.modify HOME: "/Users/foo" do
101
+ expect(config.license_locations).to eq([
102
+ "/etc/chef/accepted_licenses/",
103
+ "/Users/foo/.chef/accepted_licenses/"
104
+ ])
105
+ expect(config.persist_location).to eq("/Users/foo/.chef/accepted_licenses/")
106
+ end
107
+ end
108
+ end
109
+
110
+ end
111
+ end
112
+
113
+ end
@@ -0,0 +1,43 @@
1
+ require "spec_helper"
2
+ require "license_acceptance/env_acceptance"
3
+
4
+ RSpec.describe LicenseAcceptance::EnvAcceptance do
5
+ let(:acc) { LicenseAcceptance::EnvAcceptance.new }
6
+
7
+ describe "#check" do
8
+ it "returns true if the env contains the correct key and value" do
9
+ env = {"CHEF_LICENSE" => "accept"}
10
+ expect(acc.check(env)).to eq(true)
11
+ end
12
+
13
+ it "returns false if the env has a key but nil value" do
14
+ env = {"CHEF_LICENSE" => nil}
15
+ expect(acc.check(env)).to eq(false)
16
+ end
17
+
18
+ it "returns false if the env has a key but incorrect value" do
19
+ env = {"CHEF_LICENSE" => "foo"}
20
+ expect(acc.check(env)).to eq(false)
21
+ end
22
+ end
23
+
24
+ describe "#check_no_persist" do
25
+ it "returns true if the env contains the correct key and value" do
26
+ env = {"CHEF_LICENSE" => "accept-no-persist"}
27
+ expect(acc.check_no_persist(env)).to eq(true)
28
+ end
29
+
30
+ it "returns false if the env has a key but nil value" do
31
+ env = {"CHEF_LICENSE" => nil}
32
+ expect(acc.check_no_persist(env)).to eq(false)
33
+ end
34
+
35
+ it "returns false if the env has a key but incorrect value" do
36
+ env = {"CHEF_LICENSE" => "foo"}
37
+ expect(acc.check_no_persist(env)).to eq(false)
38
+ env = {"CHEF_LICENSE" => "accept"}
39
+ expect(acc.check_no_persist(env)).to eq(false)
40
+ end
41
+ end
42
+
43
+ end
@@ -0,0 +1,121 @@
1
+ require "spec_helper"
2
+ require "license_acceptance/config"
3
+ require "license_acceptance/file_acceptance"
4
+ require "license_acceptance/product_relationship"
5
+ require "license_acceptance/product"
6
+
7
+ RSpec.describe LicenseAcceptance::FileAcceptance do
8
+ let(:dir1) { "/dir1" }
9
+ let(:dir2) { "/dir2" }
10
+ let(:dir3) { "/dir3" }
11
+ let(:config) do
12
+ instance_double(LicenseAcceptance::Config, license_locations: [dir1, dir2], persist_location: dir3)
13
+ end
14
+ let(:acc) { LicenseAcceptance::FileAcceptance.new(config) }
15
+ let(:p1_name) { "chef_client" }
16
+ let(:p1_filename) { "p1_filename" }
17
+ let(:p1) { instance_double(LicenseAcceptance::Product, name: p1_name, filename: p1_filename) }
18
+ let(:version) { "0.1.0" }
19
+ let(:product_relationship) { instance_double(LicenseAcceptance::ProductRelationship, parent: p1, children: [], parent_version: version) }
20
+ let(:mode) { File::WRONLY | File::CREAT | File::EXCL }
21
+
22
+ describe "#check" do
23
+ describe "when there is an existing license file" do
24
+ it "returns an empty missing product list" do
25
+ expect(File).to receive(:exist?).with(File.join(dir1, p1_filename)).and_return(true)
26
+ expect(acc.check(product_relationship)).to eq([])
27
+ end
28
+ end
29
+
30
+ describe "when there is not an existing license file" do
31
+ it "returns the product in the missing product list" do
32
+ expect(File).to receive(:exist?).with(File.join(dir1, p1_filename)).and_return(false)
33
+ expect(File).to receive(:exist?).with(File.join(dir2, p1_filename)).and_return(false)
34
+ expect(acc.check(product_relationship)).to eq([p1])
35
+ end
36
+ end
37
+
38
+ describe "#persist" do
39
+ let(:file) { double("file") }
40
+
41
+ it "stores a single license without children" do
42
+ expect(Dir).to receive(:exist?).with(dir3).and_return(true)
43
+ expect(File).to receive(:open).with(File.join(dir3, p1_filename), mode).and_yield(file)
44
+ expect(file).to receive(:<<) do |yaml|
45
+ yaml = YAML.load(yaml)
46
+ expect(yaml["name"]).to eq(p1_name)
47
+ expect(yaml["accepting_product"]).to eq(p1_name)
48
+ expect(yaml["accepting_product_version"]).to eq(version)
49
+ end
50
+ expect(acc.persist(product_relationship, [p1])).to eq([])
51
+ end
52
+
53
+ describe "when license has children" do
54
+ let(:p2_name) { "inspec" }
55
+ let(:p2_filename) { "p2_filename" }
56
+ let(:p2) { instance_double(LicenseAcceptance::Product, name: p2_name, filename: p2_filename) }
57
+ let(:product_relationship) {
58
+ instance_double(
59
+ LicenseAcceptance::ProductRelationship,
60
+ parent: p1,
61
+ children: [p2],
62
+ parent_version: version
63
+ )
64
+ }
65
+
66
+ it "stores a license file for all" do
67
+ expect(Dir).to receive(:exist?).with(dir3).and_return(true)
68
+ expect(File).to receive(:open).with(File.join(dir3, p1_filename), mode).and_yield(file)
69
+ expect(file).to receive(:<<) do |yaml|
70
+ yaml = YAML.load(yaml)
71
+ expect(yaml["name"]).to eq(p1_name)
72
+ expect(yaml["accepting_product"]).to eq(p1_name)
73
+ expect(yaml["accepting_product_version"]).to eq(version)
74
+ end
75
+ expect(File).to receive(:open).with(File.join(dir3, p2_filename), mode).and_yield(file)
76
+ expect(file).to receive(:<<) do |yaml|
77
+ yaml = YAML.load(yaml)
78
+ expect(yaml["name"]).to eq(p2_name)
79
+ expect(yaml["accepting_product"]).to eq(p1_name)
80
+ expect(yaml["accepting_product_version"]).to eq(version)
81
+ end
82
+ expect(acc.persist(product_relationship, [p1, p2])).to eq([])
83
+ end
84
+
85
+ describe "when parent is already persisted" do
86
+ it "only stores a license file for the child" do
87
+ expect(Dir).to receive(:exist?).with(dir3).and_return(true)
88
+ expect(File).to receive(:open).once.with(File.join(dir3, p2_filename), mode).and_yield(file)
89
+ expect(file).to receive(:<<) do |yaml|
90
+ yaml = YAML.load(yaml)
91
+ expect(yaml["name"]).to eq(p2_name)
92
+ expect(yaml["accepting_product"]).to eq(p1_name)
93
+ expect(yaml["accepting_product_version"]).to eq(version)
94
+ end
95
+ expect(acc.persist(product_relationship, [p2])).to eq([])
96
+ end
97
+ end
98
+ end
99
+
100
+ describe "when the folder cannot be created" do
101
+ let(:err) { StandardError.new("foo") }
102
+ it "returns the error" do
103
+ expect(Dir).to receive(:exist?).with(dir3).and_return(false)
104
+ expect(FileUtils).to receive(:mkdir_p).and_raise(err)
105
+ expect(File).to_not receive(:open)
106
+ expect(acc.persist(product_relationship, [p1])).to eq([err])
107
+ end
108
+ end
109
+
110
+ describe "when the file cannot be written" do
111
+ let(:err) { StandardError.new("bar") }
112
+ it "returns the error" do
113
+ expect(Dir).to receive(:exist?).with(dir3).and_return(true)
114
+ expect(File).to receive(:open).with(File.join(dir3, p1_filename), mode).and_raise(err)
115
+ expect(acc.persist(product_relationship, [p1])).to eq([err])
116
+ end
117
+ end
118
+ end
119
+
120
+ end
121
+ end
@@ -0,0 +1,139 @@
1
+ require "spec_helper"
2
+ require "license_acceptance/product_reader"
3
+ require "license_acceptance/product_relationship"
4
+
5
+ RSpec.describe LicenseAcceptance::ProductReader do
6
+ let(:reader) { LicenseAcceptance::ProductReader.new }
7
+ let(:version) { "0.1.0" }
8
+ let(:location) { "location" }
9
+
10
+ let(:p1) { {"name" => "p1", "pretty_name" => "P1", "filename" => "f1"} }
11
+ let(:p2) { {"name" => "p2", "pretty_name" => "P2", "filename" => "f2"} }
12
+ # defined the `==` operator on Product for ease of comparison
13
+ let(:product1) { LicenseAcceptance::Product.new(p1["name"], p1["pretty_name"], p1["filename"]) }
14
+ let(:product2) { LicenseAcceptance::Product.new(p2["name"], p2["pretty_name"], p2["filename"]) }
15
+ let(:r1) { {p1 => p2} }
16
+ let(:toml) { {"products" => [p1, p2], "relationships" => {"p1" => ["p2"]}} }
17
+
18
+ describe "#read" do
19
+ it "reads products and relationships" do
20
+ expect(reader).to receive(:get_location).and_return(location)
21
+ expect(Tomlrb).to receive(:load_file).with(location, symbolize_keys: false).and_return(toml)
22
+ reader.read
23
+ expect(reader.products).to eq({
24
+ "p1" => product1,
25
+ "p2" => product2
26
+ })
27
+ expect(reader.relationships.size).to eq(1)
28
+ expect(reader.relationships.first).to eq([product1, [product2]])
29
+ end
30
+
31
+ describe "with an empty file" do
32
+ it "raises a InvalidProductInfo error" do
33
+ expect(reader).to receive(:get_location).and_return(location)
34
+ expect(Tomlrb).to receive(:load_file).with(location, symbolize_keys: false).and_return({})
35
+
36
+ expect { reader.read }.to raise_error(LicenseAcceptance::InvalidProductInfo)
37
+ end
38
+ end
39
+
40
+ describe "with an unknown parent" do
41
+ let(:toml) { {"products" => [p1, p2], "relationships" => {"p3" => ["p2"]}} }
42
+
43
+ it "raises a UnknownParent error" do
44
+ expect(reader).to receive(:get_location).and_return(location)
45
+ expect(Tomlrb).to receive(:load_file).with(location, symbolize_keys: false).and_return(toml)
46
+
47
+ expect { reader.read }.to raise_error(LicenseAcceptance::UnknownParent)
48
+ end
49
+ end
50
+
51
+ describe "with a relationship of nil children" do
52
+ let(:toml) { {"products" => [p1], "relationships" => {"p1" => nil}} }
53
+
54
+ it "raises a NoChildRelationships error" do
55
+ expect(reader).to receive(:get_location).and_return(location)
56
+ expect(Tomlrb).to receive(:load_file).with(location, symbolize_keys: false).and_return(toml)
57
+
58
+ expect { reader.read }.to raise_error(LicenseAcceptance::NoChildRelationships)
59
+ end
60
+ end
61
+
62
+ describe "with a relationship of empty children" do
63
+ let(:toml) { {"products" => [p1], "relationships" => {"p1" => []}} }
64
+
65
+ it "raises a NoChildRelationships error" do
66
+ expect(reader).to receive(:get_location).and_return(location)
67
+ expect(Tomlrb).to receive(:load_file).with(location, symbolize_keys: false).and_return(toml)
68
+
69
+ expect { reader.read }.to raise_error(LicenseAcceptance::NoChildRelationships)
70
+ end
71
+ end
72
+
73
+ describe "with a relationship of non-array children" do
74
+ let(:toml) { {"products" => [p1], "relationships" => {"p1" => "p2"}} }
75
+
76
+ it "raises a NoChildRelationships error" do
77
+ expect(reader).to receive(:get_location).and_return(location)
78
+ expect(Tomlrb).to receive(:load_file).with(location, symbolize_keys: false).and_return(toml)
79
+
80
+ expect { reader.read }.to raise_error(LicenseAcceptance::NoChildRelationships)
81
+ end
82
+ end
83
+
84
+ describe "with an unknown child" do
85
+ let(:toml) { {"products" => [p1, p2], "relationships" => {"p1" => ["p2", "p3"]}} }
86
+
87
+ it "raises a UnknownChild error" do
88
+ expect(reader).to receive(:get_location).and_return(location)
89
+ expect(Tomlrb).to receive(:load_file).with(location, symbolize_keys: false).and_return(toml)
90
+
91
+ expect { reader.read }.to raise_error(LicenseAcceptance::UnknownChild)
92
+ end
93
+ end
94
+ end
95
+
96
+ describe "::lookup" do
97
+ before do
98
+ expect(reader).to receive(:get_location).and_return(location)
99
+ expect(Tomlrb).to receive(:load_file).with(location, symbolize_keys: false).and_return(toml)
100
+ reader.read
101
+ end
102
+
103
+ it "returns a ProductRelationship instance successfully" do
104
+ expect(reader.lookup("p1", version)).to be_an_instance_of(LicenseAcceptance::ProductRelationship) do |instance|
105
+ expect(instance.parent_product).to eq(product1)
106
+ expect(instance.children).to eq([prouct2])
107
+ expect(instance.version).to eq(version)
108
+ end
109
+ end
110
+
111
+ describe "when called on an unknown product" do
112
+ it "raises an UnknownProduct error" do
113
+ expect { reader.lookup("DNE", nil) }.to raise_error(LicenseAcceptance::UnknownProduct)
114
+ end
115
+ end
116
+
117
+ let(:nonya) { LicenseAcceptance::Product.new("nonya", "NonYa", "nofile") }
118
+ describe "when called on a product with no relationship" do
119
+ before do
120
+ reader.products = { "nonya" => nonya }
121
+ end
122
+
123
+ it "returns the product" do
124
+ expect(reader.lookup('nonya', version)).to be_an_instance_of(LicenseAcceptance::ProductRelationship) do |instance|
125
+ expect(instance.parent_product).to eq(nonya)
126
+ expect(instance.children).to eq([])
127
+ expect(instance.version).to eq(version)
128
+ end
129
+ end
130
+ end
131
+
132
+ describe "when called with an invalid parent version type" do
133
+ it "raises an ProductVersionTypeError error" do
134
+ expect { reader.lookup("p1", 1) }.to raise_error(LicenseAcceptance::ProductVersionTypeError)
135
+ end
136
+ end
137
+ end
138
+
139
+ end