foreman_google 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +619 -0
  3. data/README.md +33 -0
  4. data/Rakefile +47 -0
  5. data/app/controllers/concerns/foreman_google/temporary_prepend_path.rb +16 -0
  6. data/app/models/foreman_google/gce.rb +119 -0
  7. data/app/models/foreman_google/google_compute.rb +127 -0
  8. data/config/routes.rb +2 -0
  9. data/lib/foreman_google/engine.rb +42 -0
  10. data/lib/foreman_google/google_compute_adapter.rb +91 -0
  11. data/lib/foreman_google/version.rb +3 -0
  12. data/lib/foreman_google.rb +4 -0
  13. data/lib/tasks/foreman_google_tasks.rake +31 -0
  14. data/locale/Makefile +60 -0
  15. data/locale/en/foreman_google.po +19 -0
  16. data/locale/foreman_google.pot +19 -0
  17. data/locale/gemspec.rb +2 -0
  18. data/package.json +44 -0
  19. data/test/factories/gce.rb +28 -0
  20. data/test/fixtures/images_centos_cloud.json +11 -0
  21. data/test/fixtures/images_coastal.json +12 -0
  22. data/test/fixtures/images_deprecated.json +17 -0
  23. data/test/fixtures/images_nothing_found.json +5 -0
  24. data/test/fixtures/instance.json +105 -0
  25. data/test/fixtures/instance_start.json +14 -0
  26. data/test/fixtures/instance_stop.json +14 -0
  27. data/test/fixtures/machine_types.json +12 -0
  28. data/test/fixtures/networks.json +11 -0
  29. data/test/fixtures/zones.json +1750 -0
  30. data/test/models/foreman_google/gce_test.rb +31 -0
  31. data/test/models/foreman_google/google_compute_test.rb +155 -0
  32. data/test/test_google_helper.rb +24 -0
  33. data/test/unit/foreman_google/google_compute_adapter_test.rb +126 -0
  34. data/webpack/global_index.js +17 -0
  35. data/webpack/global_test_setup.js +11 -0
  36. data/webpack/index.js +7 -0
  37. data/webpack/src/Extends/index.js +15 -0
  38. data/webpack/src/Router/routes.js +5 -0
  39. data/webpack/src/reducers.js +7 -0
  40. data/webpack/test_setup.js +17 -0
  41. metadata +127 -0
@@ -0,0 +1,31 @@
1
+ require 'test_google_helper'
2
+
3
+ module ForemanGoogle
4
+ class GCETest < GoogleTestCase
5
+ subject { ForemanGoogle::GCE.new(zone: 'zone', password: gauth_json) }
6
+ let(:service) { mock('GoogleAdapter') }
7
+
8
+ setup do
9
+ subject.stubs(client: service)
10
+ service.stubs(:project_id).returns('project_id')
11
+ end
12
+
13
+ describe '#find_vm_by_uuid' do
14
+ it 'does query gce' do
15
+ instance = stub(status: 'RUNNING')
16
+ service.expects(:instance).with(subject.zone, 'instance_name').returns(instance)
17
+ compute = subject.find_vm_by_uuid('instance_name')
18
+ value(compute).must_be_kind_of(ForemanGoogle::GoogleCompute)
19
+ end
20
+
21
+ it 'throws 404 when instance not found on GCE' do
22
+ service
23
+ .expects(:instance)
24
+ .with(subject.zone, 'non-existing-name-or-id')
25
+ .raises(Foreman::WrappedException.new(Google::Cloud::NotFoundError.new, 'not found'))
26
+
27
+ value { subject.find_vm_by_uuid('non-existing-name-or-id') }.must_raise(Foreman::WrappedException)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,155 @@
1
+ require 'test_google_helper'
2
+
3
+ module ForemanGoogle
4
+ class GoogleComputeTest < GoogleTestCase
5
+ let(:client) { mock('GoogleAdapter') }
6
+ let(:zone) { 'zone-1' }
7
+ let(:identity) { 'instance-id-or-name' }
8
+
9
+ subject { ForemanGoogle::GoogleCompute.new(client: client, zone: zone, identity: identity) }
10
+
11
+ setup do
12
+ client.stubs(:project_id).returns('project_id')
13
+ end
14
+
15
+ describe '#reload' do
16
+ let(:zone) { 'http://test.org/fullurl/zones/zone-1' }
17
+ let(:zone_name) { zone.split('/').last }
18
+
19
+ it 'reloads the instance from gce and returns self' do
20
+ client.expects(:instance).with(zone_name, identity).twice
21
+ value(subject.reload).must_equal(subject)
22
+ end
23
+ end
24
+
25
+ describe '#persisted?' do
26
+ context 'with identity' do
27
+ it 'is persisted' do
28
+ client.stubs(:instance).with(zone, identity)
29
+ value(subject).must_be(:persisted?)
30
+ end
31
+ end
32
+
33
+ context 'without identity' do
34
+ let(:identity) { nil }
35
+
36
+ it 'is not persisted' do
37
+ value(subject).wont_be(:persisted?)
38
+ end
39
+ end
40
+ end
41
+
42
+ describe '#ready?' do
43
+ let(:instance) { mock('Google::Compute::Instance') }
44
+
45
+ setup do
46
+ client.expects(:instance).with(zone, identity).returns(instance)
47
+ end
48
+
49
+ it 'is ready with running instance' do
50
+ instance.expects(:status).returns('RUNNING')
51
+ value(subject).must_be(:ready?)
52
+ end
53
+
54
+ it 'is not ready for not running instance' do
55
+ instance.expects(:status).returns('PROVISIONING')
56
+ value(subject).wont_be(:ready?)
57
+ end
58
+ end
59
+
60
+ describe '#name & #hostname' do
61
+ it 'default value' do
62
+ args = { network: '' }
63
+ cr = ForemanGoogle::GoogleCompute.new(client: client, zone: zone, args: args)
64
+
65
+ assert_includes cr.name, 'foreman_'
66
+ assert_includes cr.hostname, 'foreman_'
67
+ end
68
+
69
+ it 'is parameterized' do
70
+ args = { name: 'My new name' }
71
+ cr = ForemanGoogle::GoogleCompute.new(client: client, zone: zone, args: args)
72
+ assert_includes cr.name, 'my-new-name'
73
+ assert_includes cr.hostname, 'my-new-name'
74
+ end
75
+ end
76
+
77
+ describe '#network_interfaces' do
78
+ it 'with default value' do
79
+ cr = ForemanGoogle::GoogleCompute.new(client: client, zone: zone)
80
+ assert_includes cr.network_interfaces[0][:network], '/projects/project_id/global/networks/default'
81
+ end
82
+
83
+ it 'with custom value' do
84
+ args = { network: 'custom' }
85
+ cr = ForemanGoogle::GoogleCompute.new(client: client, zone: zone, args: args)
86
+ assert_includes cr.network_interfaces[0][:network], '/projects/project_id/global/networks/custom'
87
+ end
88
+
89
+ it 'with associated external ip' do
90
+ args = { associate_external_ip: '1' }
91
+ cr = ForemanGoogle::GoogleCompute.new(client: client, zone: zone, args: args)
92
+ expected_nics = [{ network: 'global/networks/default', access_configs: [{ name: 'External NAT', type: 'ONE_TO_ONE_NAT' }] }]
93
+
94
+ assert_equal cr.network_interfaces, expected_nics
95
+ end
96
+
97
+ it 'with nics' do
98
+ nics = [{ network: 'global/networks/custom' }]
99
+ args = { associate_external_ip: '1', network_interfaces: nics }
100
+ cr = ForemanGoogle::GoogleCompute.new(client: client, zone: zone, args: args)
101
+ expected_nics = [{ network: 'global/networks/custom', access_configs: [{ name: 'External NAT', type: 'ONE_TO_ONE_NAT' }] }]
102
+
103
+ assert_equal cr.network_interfaces, expected_nics
104
+ end
105
+ end
106
+
107
+ describe '#disks' do
108
+ setup do
109
+ client.stubs(:images).returns([OpenStruct.new(id: 1, name: 'coastal-image')])
110
+ end
111
+
112
+ it 'no volumes' do
113
+ args = { volumes: [] }
114
+ cr = ForemanGoogle::GoogleCompute.new(client: client, zone: zone, args: args)
115
+
116
+ assert_equal cr.disks, []
117
+ end
118
+
119
+ it 'without image_id' do
120
+ args = { volumes: [{ size_gb: '23' }] }
121
+ cr = ForemanGoogle::GoogleCompute.new(client: client, zone: zone, args: args)
122
+ disk = cr.disks.first
123
+
124
+ assert_equal disk.name, "#{cr.name}-disk1"
125
+ assert_nil disk.source_image
126
+ end
127
+
128
+ it 'image not found' do
129
+ args = { volumes: [{ size_gb: '23' }], image_id: '0' }
130
+ value { ForemanGoogle::GoogleCompute.new(client: client, zone: zone, args: args) }.must_raise(::Foreman::Exception)
131
+ end
132
+
133
+ it 'with source_image' do
134
+ args = { volumes: [{ size_gb: '23', source_image: 'centos-stream-8-v20220317' }], image_id: '1' }
135
+ cr = ForemanGoogle::GoogleCompute.new(client: client, zone: zone, args: args)
136
+
137
+ disk = cr.disks.first
138
+ assert_equal disk.source_image, 'coastal-image'
139
+ end
140
+ end
141
+
142
+ describe '#metadata' do
143
+ it 'with user_data' do
144
+ args = { user_data: 'test' }
145
+ cr = ForemanGoogle::GoogleCompute.new(client: client, zone: zone, args: args)
146
+ assert_equal cr.metadata, { items: [{ key: 'user-data', value: 'test' }] }
147
+ end
148
+
149
+ it 'no user_data' do
150
+ cr = ForemanGoogle::GoogleCompute.new(client: client, zone: zone)
151
+ assert_nil cr.metadata
152
+ end
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,24 @@
1
+ # This calls the main test_helper in Foreman-core
2
+ require 'test_helper'
3
+
4
+ # Add plugin to FactoryBot's paths
5
+ FactoryBot.definition_file_paths << File.join(File.dirname(__FILE__), 'factories')
6
+ FactoryBot.reload
7
+
8
+ if ENV['VCR'] == '1'
9
+ VCR.configure do |c|
10
+ c.cassette_library_dir = ForemanGoogle::Engine.root.join('test', 'fixtures')
11
+ c.hook_into :webmock
12
+ end
13
+ end
14
+
15
+ class GoogleTestCase < ActiveSupport::TestCase
16
+ let(:google_access_token) { 'ya29.c.stubbed_token' }
17
+ let(:gce_cr) { FactoryBot.create(:compute_resource, :google_gce) }
18
+ let(:google_project_id) { gce_cr.google_project_id }
19
+ let(:gauth_json) { (ENV['VCR'] == '1' ? ENV['GCE_AUTH'] : nil) || gce_cr.password }
20
+
21
+ setup do
22
+ ::Signet::OAuth2::Client.any_instance.stubs(fetch_access_token!: google_access_token) unless ENV['VCR'] == '1'
23
+ end
24
+ end
@@ -0,0 +1,126 @@
1
+ require 'test_google_helper'
2
+ require 'foreman_google/google_compute_adapter'
3
+
4
+ require 'google/cloud/compute/v1/zones/credentials'
5
+ module ForemanGoogle
6
+ class GoogleComputeAdapterTest < GoogleTestCase
7
+ subject { ForemanGoogle::GoogleComputeAdapter.new(auth_json_string: gauth_json) }
8
+
9
+ describe 'authentication' do
10
+ it 'passes the auth json to the service client' do
11
+ credentials = stub(client: stub(apply: { authorization: "Bearer #{google_access_token}" }))
12
+ ::Google::Cloud::Compute::V1::Zones::Credentials.expects(:new).with(JSON.parse(gauth_json), has_key(:scope)).returns(credentials)
13
+ stub_request(:get, 'https://compute.googleapis.com/compute/v1/projects/coastal-haven-123456/zones')
14
+ .to_return(body: '{
15
+ "id": "projects/coastal-haven-123456/zones",
16
+ "items": [],
17
+ "selfLink": "https://www.googleapis.com/compute/v1/projects/coastal-haven-123456/zones",
18
+ "kind": "compute#zoneList"
19
+ }')
20
+ subject.zones
21
+ end
22
+ end
23
+
24
+ describe '#instance' do
25
+ setup do
26
+ stub_request(:get, 'https://compute.googleapis.com/compute/v1/projects/coastal-haven-123456/zones/us-east1-b/instances/instance-1')
27
+ .to_return(body: File.read(File.join(__dir__, '..', '..', 'fixtures', 'instance.json')))
28
+ end
29
+
30
+ it 'gets instance by id' do
31
+ instance = subject.instance('us-east1-b', 'instance-1')
32
+ value(instance).must_be_kind_of(Google::Cloud::Compute::V1::Instance)
33
+ value(instance.id).must_equal(123_456_789)
34
+ end
35
+ end
36
+
37
+ describe '#zones' do
38
+ setup do
39
+ stub_request(:get, 'https://compute.googleapis.com/compute/v1/projects/coastal-haven-123456/zones')
40
+ .to_return(body: File.read(File.join(__dir__, '..', '..', 'fixtures', 'zones.json')))
41
+ end
42
+
43
+ it 'show zones' do
44
+ zones = subject.zones
45
+ value(zones.first.name).must_be_kind_of(String)
46
+ value(zones.first.description).must_be_kind_of(String)
47
+ end
48
+ end
49
+
50
+ describe '#networks' do
51
+ setup do
52
+ stub_request(:get, 'https://compute.googleapis.com/compute/v1/projects/coastal-haven-123456/global/networks')
53
+ .to_return(body: File.read(File.join(__dir__, '..', '..', 'fixtures', 'networks.json')))
54
+ end
55
+
56
+ it 'show networks' do
57
+ assert_equal ['default'], subject.networks.map(&:name)
58
+ end
59
+ end
60
+
61
+ describe '#machine_types' do
62
+ setup do
63
+ stub_request(:get, 'https://compute.googleapis.com/compute/v1/projects/coastal-haven-123456/zones/us-east1-b/machineTypes')
64
+ .to_return(body: File.read(File.join(__dir__, '..', '..', 'fixtures', 'machine_types.json')))
65
+ end
66
+
67
+ it 'list machine_types' do
68
+ assert_equal ['machine_type_001'], subject.machine_types('us-east1-b').map(&:name)
69
+ end
70
+ end
71
+
72
+ describe '#images' do
73
+ setup do
74
+ stub_request(:get, 'https://compute.googleapis.com/compute/v1/projects/coastal-haven-123456/global/images')
75
+ .to_return(body: File.read(File.join(__dir__, '..', '..', 'fixtures', 'images_coastal.json')))
76
+ end
77
+
78
+ it 'list images' do
79
+ stub_request(:get, 'https://compute.googleapis.com/compute/v1/projects/centos-cloud/global/images')
80
+ .to_return(body: File.read(File.join(__dir__, '..', '..', 'fixtures', 'images_centos_cloud.json')))
81
+
82
+ subject.stub(:all_projects, %w[centos-cloud]) do
83
+ assert_equal %w[coastal-image centos-6], subject.images.map(&:name)
84
+ end
85
+ end
86
+
87
+ it 'list images with filter' do
88
+ not_found_body = File.read(File.join(__dir__, '..', '..', 'fixtures', 'images_nothing_found.json'))
89
+ %w[coastal-haven-123456 centos-cloud].each do |project|
90
+ url = "https://compute.googleapis.com/compute/v1/projects/#{project}/global/images?filter=name%20=%20%22NOTHING_FOUND%22"
91
+ stub_request(:get, url).to_return(body: not_found_body)
92
+ end
93
+
94
+ subject.stub(:all_projects, %w[centos-cloud]) do
95
+ assert_empty subject.images(filter: 'name = "NOTHING_FOUND"')
96
+ end
97
+ end
98
+
99
+ it 'ignore deprecated images' do
100
+ stub_request(:get, 'https://compute.googleapis.com/compute/v1/projects/deprecated/global/images')
101
+ .to_return(body: File.read(File.join(__dir__, '..', '..', 'fixtures', 'images_deprecated.json')))
102
+
103
+ subject.stub(:all_projects, %w[deprecated]) do
104
+ assert_equal ['coastal-image'], subject.images.map(&:name)
105
+ end
106
+ end
107
+ end
108
+
109
+ describe 'manage vm' do
110
+ it '#start' do
111
+ stub_request(:post, 'https://compute.googleapis.com/compute/v1/projects/coastal-haven-123456/zones/us-east1-b/instances/instance_name/start')
112
+ .to_return(status: 200, body: File.read(File.join(__dir__, '..', '..', 'fixtures', 'instance_start.json')), headers: {})
113
+ result = subject.start('us-east1-b', 'instance_name')
114
+ assert 'start', result.operation.operation_type
115
+ end
116
+
117
+ it '#stop' do
118
+ stub_request(:post, 'https://compute.googleapis.com/compute/v1/projects/coastal-haven-123456/zones/us-east1-b/instances/instance_name/stop').
119
+
120
+ to_return(status: 200, body: File.read(File.join(__dir__, '..', '..', 'fixtures', 'instance_stop.json')), headers: {})
121
+ result = subject.stop('us-east1-b', 'instance_name')
122
+ assert 'stop', result.operation.operation_type
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,17 @@
1
+ import { registerReducer } from 'foremanReact/common/MountingService';
2
+ // import { addGlobalFill } from 'foremanReact/components/common/Fill/GlobalFill';
3
+ import { registerRoutes } from 'foremanReact/routes/RoutingService';
4
+ import Routes from './src/Router/routes';
5
+ import reducers from './src/reducers';
6
+
7
+ // register reducers
8
+ Object.entries(reducers).forEach(([key, reducer]) =>
9
+ registerReducer(key, reducer)
10
+ );
11
+
12
+ // register client routes
13
+ registerRoutes('ForemanGoogle', Routes);
14
+
15
+ // register fills for extending foreman core
16
+ // http://foreman.surge.sh/?path=/docs/introduction-slot-and-fill--page
17
+ // addGlobalFill('<slotId>', '<fillId>', <div key='plugin-template-example' />, 300);
@@ -0,0 +1,11 @@
1
+ // runs before each test to make sure console.error output will
2
+ // fail a test (i.e. default PropType missing). Check the error
3
+ // output and traceback for actual error.
4
+ global.console.error = (error, stack) => {
5
+ /* eslint-disable-next-line no-console */
6
+ if (stack) console.log(stack); // Prints out original stack trace
7
+ throw new Error(error);
8
+ };
9
+
10
+ // Increase jest timeout as some tests using multiple http mocks can time out on CI systems.
11
+ jest.setTimeout(10000);
data/webpack/index.js ADDED
@@ -0,0 +1,7 @@
1
+ import componentRegistry from 'foremanReact/components/componentRegistry';
2
+
3
+ // register components for erb mounting
4
+ componentRegistry.register({
5
+ // name: 'Component',
6
+ // type: Component,
7
+ });
@@ -0,0 +1,15 @@
1
+ // This is an example of extending foreman-core's component via slot&fill
2
+ // http://foreman.surge.sh/?path=/docs/introduction-slot-and-fill--page
3
+ /*
4
+ import React from 'react';
5
+ import { addGlobalFill } from 'foremanReact/components/common/Fill/GlobalFill';
6
+
7
+ addGlobalFill('slotId', 'fillId', <SomeComponent key="some-key" />, 300);
8
+
9
+ addGlobalFill(
10
+ 'slotId',
11
+ 'fillId',
12
+ { someProp: 'this is an override prop' },
13
+ 300
14
+ );
15
+ */
@@ -0,0 +1,5 @@
1
+ // import React from 'react';
2
+
3
+ const routes = [];
4
+
5
+ export default routes;
@@ -0,0 +1,7 @@
1
+ import { combineReducers } from 'redux';
2
+
3
+ const reducers = {
4
+ ForemanGoogle: combineReducers({}),
5
+ };
6
+
7
+ export default reducers;
@@ -0,0 +1,17 @@
1
+ import 'core-js/shim';
2
+ import 'regenerator-runtime/runtime';
3
+ import MutationObserver from '@sheerun/mutationobserver-shim';
4
+
5
+ import { configure } from 'enzyme';
6
+ import Adapter from 'enzyme-adapter-react-16';
7
+
8
+ configure({ adapter: new Adapter() });
9
+
10
+ // Mocking translation function
11
+ global.__ = text => text; // eslint-disable-line
12
+
13
+ // Mocking locales to prevent unnecessary fallback messages
14
+ window.locales = { en: { domain: 'app', locale_data: { app: { '': {} } } } };
15
+
16
+ // see https://github.com/testing-library/dom-testing-library/releases/tag/v7.0.0
17
+ window.MutationObserver = MutationObserver;
metadata ADDED
@@ -0,0 +1,127 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: foreman_google
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - The Foreman Team
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-04-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: google-cloud-compute
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rdoc
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Google Compute Engine plugin for the Foreman
42
+ email:
43
+ - dev@community.theforeman.org
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - LICENSE
49
+ - README.md
50
+ - Rakefile
51
+ - app/controllers/concerns/foreman_google/temporary_prepend_path.rb
52
+ - app/models/foreman_google/gce.rb
53
+ - app/models/foreman_google/google_compute.rb
54
+ - config/routes.rb
55
+ - lib/foreman_google.rb
56
+ - lib/foreman_google/engine.rb
57
+ - lib/foreman_google/google_compute_adapter.rb
58
+ - lib/foreman_google/version.rb
59
+ - lib/tasks/foreman_google_tasks.rake
60
+ - locale/Makefile
61
+ - locale/en/foreman_google.po
62
+ - locale/foreman_google.pot
63
+ - locale/gemspec.rb
64
+ - package.json
65
+ - test/factories/gce.rb
66
+ - test/fixtures/images_centos_cloud.json
67
+ - test/fixtures/images_coastal.json
68
+ - test/fixtures/images_deprecated.json
69
+ - test/fixtures/images_nothing_found.json
70
+ - test/fixtures/instance.json
71
+ - test/fixtures/instance_start.json
72
+ - test/fixtures/instance_stop.json
73
+ - test/fixtures/machine_types.json
74
+ - test/fixtures/networks.json
75
+ - test/fixtures/zones.json
76
+ - test/models/foreman_google/gce_test.rb
77
+ - test/models/foreman_google/google_compute_test.rb
78
+ - test/test_google_helper.rb
79
+ - test/unit/foreman_google/google_compute_adapter_test.rb
80
+ - webpack/global_index.js
81
+ - webpack/global_test_setup.js
82
+ - webpack/index.js
83
+ - webpack/src/Extends/index.js
84
+ - webpack/src/Router/routes.js
85
+ - webpack/src/reducers.js
86
+ - webpack/test_setup.js
87
+ homepage: https://github.com/theforeman/foreman_google
88
+ licenses:
89
+ - GPL-3.0
90
+ metadata:
91
+ is_foreman_plugin: 'true'
92
+ rubygems_mfa_required: 'true'
93
+ post_install_message:
94
+ rdoc_options: []
95
+ require_paths:
96
+ - lib
97
+ required_ruby_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: '2.5'
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: '0'
107
+ requirements: []
108
+ rubygems_version: 3.3.7
109
+ signing_key:
110
+ specification_version: 4
111
+ summary: Google Compute Engine plugin for the Foreman
112
+ test_files:
113
+ - test/models/foreman_google/google_compute_test.rb
114
+ - test/models/foreman_google/gce_test.rb
115
+ - test/unit/foreman_google/google_compute_adapter_test.rb
116
+ - test/factories/gce.rb
117
+ - test/fixtures/networks.json
118
+ - test/fixtures/instance.json
119
+ - test/fixtures/zones.json
120
+ - test/fixtures/instance_stop.json
121
+ - test/fixtures/machine_types.json
122
+ - test/fixtures/images_coastal.json
123
+ - test/fixtures/instance_start.json
124
+ - test/fixtures/images_deprecated.json
125
+ - test/fixtures/images_centos_cloud.json
126
+ - test/fixtures/images_nothing_found.json
127
+ - test/test_google_helper.rb