license-acceptance 0.0.1 → 0.2.1

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.
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