foreman_google 0.0.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 (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
data/Rakefile ADDED
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = 'ForemanGoogle'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+ APP_RAKEFILE = File.expand_path('test/dummy/Rakefile', __dir__)
24
+
25
+ Bundler::GemHelper.install_tasks
26
+
27
+ require 'rake/testtask'
28
+
29
+ Rake::TestTask.new(:test) do |t|
30
+ t.libs << 'lib'
31
+ t.libs << 'test'
32
+ t.pattern = 'test/**/*_test.rb'
33
+ t.verbose = false
34
+ end
35
+
36
+ task default: :test
37
+
38
+ begin
39
+ require 'rubocop/rake_task'
40
+ RuboCop::RakeTask.new
41
+ rescue StandardError => _e
42
+ puts 'Rubocop not loaded.'
43
+ end
44
+
45
+ task :default do
46
+ Rake::Task['rubocop'].execute
47
+ end
@@ -0,0 +1,16 @@
1
+ module ForemanGoogle
2
+ # This module prepends core paths so view for gce takes precedence over core ones
3
+ # This module NEEDS to get deleted once the core support for gce is dropped.
4
+ # or this plugin is merged to core
5
+ module TemporaryPrependPath
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ before_action :prepare_views
10
+ end
11
+
12
+ def prepare_views
13
+ prepend_view_path ForemanGoogle::Engine.root.join('app', 'views')
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,119 @@
1
+ require 'foreman_google/google_compute_adapter'
2
+
3
+ module ForemanGoogle
4
+ class GCE < ::ComputeResource
5
+ def self.available?
6
+ true
7
+ end
8
+
9
+ def self.provider_friendly_name
10
+ 'Google'
11
+ end
12
+
13
+ def user_data_supported?
14
+ true
15
+ end
16
+
17
+ def test_connection(options = {})
18
+ end
19
+
20
+ def to_label
21
+ end
22
+
23
+ def capabilities
24
+ %i[image new_volume]
25
+ end
26
+
27
+ def zones
28
+ client.zones.map(&:name)
29
+ end
30
+ alias_method :available_zones, :zones
31
+
32
+ def zone
33
+ url
34
+ end
35
+
36
+ def zone=(zone)
37
+ self.url = zone
38
+ end
39
+
40
+ def networks
41
+ client.networks.map(&:name)
42
+ end
43
+
44
+ def available_networks(_cluster_id = nil)
45
+ client.networks.items
46
+ end
47
+
48
+ def machine_types
49
+ client.machine_types(zone)
50
+ end
51
+ alias_method :available_flavors, :machine_types
52
+
53
+ def disks
54
+ end
55
+
56
+ # def interfaces_attrs_name
57
+ # super # :interfaces
58
+ # end
59
+
60
+ # This should return interface compatible with Fog::Server
61
+ # implemented by ForemanGoogle::Compute
62
+ def find_vm_by_uuid(uuid)
63
+ GoogleCompute.new(client: client, zone: zone, identity: uuid.to_s)
64
+ end
65
+
66
+ def new_vm(args = {})
67
+ vm_args = args.deep_symbolize_keys
68
+
69
+ # convert rails nested_attributes into a plain hash
70
+ volumes_nested_attrs = vm_args.delete(:volumes_attributes)
71
+ vm_args[:volumes] = nested_attributes_for(:volumes, volumes_nested_attrs) if volumes_nested_attrs
72
+
73
+ GoogleCompute.new(client: client, zone: zone, args: vm_args)
74
+ end
75
+
76
+ def destroy_vm(uuid)
77
+ end
78
+
79
+ def create_volumes(args)
80
+ end
81
+
82
+ def create_vm(args = {})
83
+ new_vm(args)
84
+ create_volumes(args)
85
+ # TBD
86
+ end
87
+
88
+ def vm_options(args)
89
+ end
90
+
91
+ def new_volume(attrs = {})
92
+ end
93
+
94
+ def normalize_vm_attrs(vm_attrs)
95
+ end
96
+
97
+ def console(uuid)
98
+ end
99
+
100
+ def associated_host(vm)
101
+ end
102
+
103
+ def available_images(filter: nil)
104
+ client.images(filter: filter)
105
+ end
106
+
107
+ # ----# Google specific #-----
108
+
109
+ def google_project_id
110
+ client.project_id
111
+ end
112
+
113
+ private
114
+
115
+ def client
116
+ @client ||= ForemanGoogle::GoogleComputeAdapter.new(auth_json_string: password)
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,127 @@
1
+ module ForemanGoogle
2
+ class GoogleCompute
3
+ attr_reader :identity, :name, :hostname, :machine_type, :network_interfaces,
4
+ :associate_external_ip, :image_id, :disks, :metadata
5
+
6
+ # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
7
+ def initialize(client:, zone:, identity: nil, args: {})
8
+ @client = client
9
+ @zone = zone
10
+ @identity = identity
11
+
12
+ @name = parameterize_name(args[:name])
13
+ @hostname = @name
14
+ @machine_type = args[:machine_type]
15
+ @network_interfaces = construct_network(args[:network] || 'default', args[:associate_external_ip] || '0', args[:network_interfaces] || [])
16
+ @image_id = args[:image_id]
17
+ @disks = load_disks(args[:image_id], args[:volumes])
18
+ @metadata = construct_metadata(args[:user_data])
19
+
20
+ identity && load
21
+ end
22
+ # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
23
+
24
+ def persisted?
25
+ !!identity
26
+ end
27
+
28
+ def ready?
29
+ status == 'RUNNING'
30
+ end
31
+
32
+ def reload
33
+ return unless identity
34
+ load
35
+ self
36
+ end
37
+
38
+ # @returns [String] one of PROVISIONING, STAGING, RUNNING, STOPPING, SUSPENDING, SUSPENDED, REPAIRING, and TERMINATED
39
+ # if nil, instance is not persisted as VM on GCE
40
+ def status
41
+ persisted? && instance.status
42
+ end
43
+
44
+ def start
45
+ raise Foreman::Exception('unable to start machine that is not persisted') unless persisted?
46
+ @client.start(@zone, identity)
47
+ end
48
+
49
+ def stop
50
+ raise Foreman::Exception('unable to stop machine that is not persisted') unless persisted?
51
+ @client.stop(@zone, identity)
52
+ end
53
+
54
+ def to_s
55
+ end
56
+
57
+ def interfaces
58
+ @network_interfaces
59
+ end
60
+
61
+ def interfaces_attributes=(attrs)
62
+ end
63
+
64
+ def volumes
65
+ @disks
66
+ end
67
+
68
+ private
69
+
70
+ def instance
71
+ return unless identity
72
+ @instance || load
73
+ end
74
+
75
+ def load
76
+ @instance = @client.instance(@zone.split('/').last, identity)
77
+ end
78
+
79
+ def parameterize_name(name)
80
+ name&.parameterize || "foreman_#{Time.now.to_i}"
81
+ end
82
+
83
+ def construct_network(network_name, associate_external_ip, network_interfaces)
84
+ # handle network_interface for external ip
85
+ # assign ephemeral external IP address using associate_external_ip
86
+ if ActiveModel::Type::Boolean.new.cast(associate_external_ip)
87
+ network_interfaces = [{ network: 'global/networks/default' }] if network_interfaces.empty?
88
+ access_config = { name: 'External NAT', type: 'ONE_TO_ONE_NAT' }
89
+
90
+ # Note - no support for external_ip from foreman
91
+ # access_config[:nat_ip] = external_ip if external_ip
92
+ network_interfaces[0][:access_configs] = [access_config]
93
+ return network_interfaces
94
+ end
95
+
96
+ network = "https://compute.googleapis.com/compute/v1/projects/#{@client.project_id}/global/networks/#{network_name}"
97
+ [{ network: network }]
98
+ end
99
+
100
+ def load_image(image_id)
101
+ return unless image_id
102
+
103
+ image = @client.images.find { |img| img.id == image_id.to_i }
104
+ raise ::Foreman::Exception, N_('selected image does not exist') if image.nil?
105
+ image
106
+ end
107
+
108
+ def load_disks(image_id, volumes = [])
109
+ return [] if volumes.empty?
110
+ image = load_image(image_id)
111
+
112
+ volumes.first[:source_image] = image.name if image
113
+ # TODO: Is OpenStruct enough to replace Fog::Compute::Google::Disk
114
+ # or do we need our own class?
115
+ volumes.map.with_index do |vol_attrs, i|
116
+ OpenStruct.new(**vol_attrs.merge(name: "#{@name}-disk#{i + 1}"))
117
+ end
118
+ end
119
+
120
+ # Note - GCE only supports cloud-init for Container Optimized images and
121
+ # for custom images with cloud-init setup
122
+ def construct_metadata(user_data)
123
+ return if user_data.blank?
124
+ { items: [{ key: 'user-data', value: user_data }] }
125
+ end
126
+ end
127
+ end
data/config/routes.rb ADDED
@@ -0,0 +1,2 @@
1
+ Rails.application.routes.draw do
2
+ end
@@ -0,0 +1,42 @@
1
+ module ForemanGoogle
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace ForemanGoogle
4
+ engine_name 'foreman_google'
5
+
6
+ # Add any db migrations
7
+ initializer 'foreman_google.load_app_instance_data' do |app|
8
+ ForemanGoogle::Engine.paths['db/migrate'].existent.each do |path|
9
+ app.config.paths['db/migrate'] << path
10
+ end
11
+ end
12
+
13
+ initializer 'foreman_google.register_plugin', before: :finisher_hook do |_app|
14
+ Foreman::Plugin.register :foreman_google do
15
+ requires_foreman '>= 2.4.0'
16
+
17
+ in_to_prepare do
18
+ compute_resource(ForemanGoogle::GCE)
19
+ end
20
+ end
21
+ end
22
+
23
+ # Include concerns in this config.to_prepare block
24
+ config.to_prepare do
25
+ ::ComputeResourcesController.include ForemanGoogle::TemporaryPrependPath
26
+ rescue StandardError => e
27
+ Rails.logger.warn "ForemanGoogle: skipping engine hook (#{e})"
28
+ end
29
+
30
+ rake_tasks do
31
+ Rake::Task['db:seed'].enhance do
32
+ ForemanGoogle::Engine.load_seed
33
+ end
34
+ end
35
+
36
+ initializer 'foreman_google.register_gettext', after: :load_config_initializers do |_app|
37
+ locale_dir = File.join(File.expand_path('../..', __dir__), 'locale')
38
+ locale_domain = 'foreman_google'
39
+ Foreman::Gettext::Support.add_text_domain locale_domain, locale_dir
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,91 @@
1
+ require 'google-cloud-compute'
2
+
3
+ module ForemanGoogle
4
+ class GoogleComputeAdapter
5
+ def initialize(auth_json_string:)
6
+ @auth_json = JSON.parse(auth_json_string)
7
+ end
8
+
9
+ def project_id
10
+ @auth_json['project_id']
11
+ end
12
+
13
+ # ------ RESOURCES ------
14
+
15
+ # Returns an Google::Instance identified by instance_identity within given zone.
16
+ # @param zone [String] eighter full url or just zone name
17
+ # @param instance_identity [String] eighter an instance name or its id
18
+ def instance(zone, instance_identity)
19
+ get('instances', instance: instance_identity, zone: zone)
20
+ end
21
+
22
+ def zones
23
+ list('zones')
24
+ end
25
+
26
+ def networks
27
+ list('networks')
28
+ end
29
+
30
+ def machine_types(zone)
31
+ list('machine_types', zone: zone)
32
+ end
33
+
34
+ def start(zone, instance_identity)
35
+ manage_instance(:start, zone, instance_identity)
36
+ end
37
+
38
+ def stop(zone, instance_identity)
39
+ manage_instance(:stop, zone, instance_identity)
40
+ end
41
+
42
+ # Setting filter to '(deprecated.state != "DEPRECATED") AND (deprecated.state != "OBSOLETE")'
43
+ # doesn't work and returns empty array, no idea what is happening there
44
+ def images(filter: nil)
45
+ projects = [project_id] + all_projects
46
+ all_images = projects.map { |project| list_images(project, filter: filter) }
47
+ all_images.flatten.reject(&:deprecated)
48
+ end
49
+
50
+ private
51
+
52
+ def list(resource_name, **opts)
53
+ response = resource_client(resource_name).list(project: project_id, **opts).response
54
+ response.items
55
+ rescue ::Google::Cloud::Error => e
56
+ raise Foreman::WrappedException.new(e, 'Cannot list Google resource %s', resource_name)
57
+ end
58
+
59
+ def list_images(project, **opts)
60
+ resource_name = 'images'
61
+ response = resource_client(resource_name).list(project: project, **opts).response
62
+ response.items
63
+ rescue ::Google::Cloud::Error => e
64
+ raise Foreman::WrappedException.new(e, 'Cannot list Google resource %s', resource_name)
65
+ end
66
+
67
+ def get(resource_name, **opts)
68
+ resource_client(resource_name).get(project: project_id, **opts)
69
+ rescue ::Google::Cloud::Error => e
70
+ raise Foreman::WrappedException.new(e, 'Could not fetch Google resource %s', resource_name)
71
+ end
72
+
73
+ def manage_instance(action, zone, instance_identity)
74
+ resource_client('instances').send(action, project: project_id, zone: zone, instance: instance_identity)
75
+ rescue ::Google::Cloud::Error => e
76
+ raise Foreman::WrappedException.new(e, 'Could not %s Google resource %s', action.to_s, resource_name)
77
+ end
78
+
79
+ def resource_client(resource_name)
80
+ ::Google::Cloud::Compute.public_send(resource_name) do |config|
81
+ config.credentials = @auth_json
82
+ end
83
+ end
84
+
85
+ def all_projects
86
+ %w[centos-cloud cos-cloud coreos-cloud debian-cloud opensuse-cloud
87
+ rhel-cloud rhel-sap-cloud suse-cloud suse-sap-cloud
88
+ ubuntu-os-cloud windows-cloud windows-sql-cloud].freeze
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,3 @@
1
+ module ForemanGoogle
2
+ VERSION = '0.0.1'.freeze
3
+ end
@@ -0,0 +1,4 @@
1
+ require 'foreman_google/engine'
2
+
3
+ module ForemanGoogle
4
+ end
@@ -0,0 +1,31 @@
1
+ require 'rake/testtask'
2
+
3
+ # Tasks
4
+ namespace :foreman_google do
5
+ namespace :example do
6
+ desc 'Example Task'
7
+ task task: :environment do
8
+ # Task goes here
9
+ end
10
+ end
11
+ end
12
+
13
+ # Tests
14
+ namespace :test do
15
+ desc 'Test ForemanGoogle'
16
+ Rake::TestTask.new(:foreman_google) do |t|
17
+ test_dir = File.expand_path('../../test', __dir__)
18
+ t.libs << 'test'
19
+ t.libs << test_dir
20
+ t.pattern = "#{test_dir}/**/*_test.rb"
21
+ t.verbose = true
22
+ t.warning = false
23
+ end
24
+ end
25
+
26
+ Rake::Task[:test].enhance ['test:foreman_google']
27
+
28
+ load 'tasks/jenkins.rake'
29
+ if Rake::Task.task_defined?(:'jenkins:unit')
30
+ Rake::Task['jenkins:unit'].enhance ['test:foreman_google', 'foreman_google:rubocop']
31
+ end
data/locale/Makefile ADDED
@@ -0,0 +1,60 @@
1
+ #
2
+ # Makefile for PO merging and MO generation. More info in the README.
3
+ #
4
+ # make all-mo (default) - generate MO files
5
+ # make check - check translations using translate-tool
6
+ # make tx-update - download and merge translations from Transifex
7
+ # make clean - clean everything
8
+ #
9
+ DOMAIN = foreman_google
10
+ VERSION = $(shell ruby -e 'require "rubygems";spec = Gem::Specification::load(Dir.glob("../*.gemspec")[0]);puts spec.version')
11
+ POTFILE = $(DOMAIN).pot
12
+ MOFILE = $(DOMAIN).mo
13
+ POFILES = $(shell find . -name '$(DOMAIN).po')
14
+ MOFILES = $(patsubst %.po,%.mo,$(POFILES))
15
+ POXFILES = $(patsubst %.po,%.pox,$(POFILES))
16
+ EDITFILES = $(patsubst %.po,%.edit.po,$(POFILES))
17
+
18
+ %.mo: %.po
19
+ mkdir -p $(shell dirname $@)/LC_MESSAGES
20
+ msgfmt -o $(shell dirname $@)/LC_MESSAGES/$(MOFILE) $<
21
+
22
+ # Generate MO files from PO files
23
+ all-mo: $(MOFILES)
24
+
25
+ # Check for malformed strings
26
+ %.pox: %.po
27
+ msgfmt -c $<
28
+ pofilter --nofuzzy -t variables -t blank -t urls -t emails -t long -t newlines \
29
+ -t endwhitespace -t endpunc -t puncspacing -t options -t printf -t validchars --gnome $< > $@
30
+ cat $@
31
+ ! grep -q msgid $@
32
+
33
+ %.edit.po:
34
+ touch $@
35
+
36
+ check: $(POXFILES)
37
+
38
+ # Unify duplicate translations
39
+ uniq-po:
40
+ for f in $(shell find ./ -name "*.po") ; do \
41
+ msguniq $$f -o $$f ; \
42
+ done
43
+
44
+ tx-pull: $(EDITFILES)
45
+ tx pull -f
46
+ for f in $(EDITFILES) ; do \
47
+ sed -i 's/^\("Project-Id-Version: \).*$$/\1$(DOMAIN) $(VERSION)\\n"/' $$f; \
48
+ done
49
+
50
+ tx-update: tx-pull
51
+ @echo
52
+ @echo Run rake plugin:gettext[$(DOMAIN)] from the Foreman installation, then make -C locale mo-files to finish
53
+ @echo
54
+
55
+ mo-files: $(MOFILES)
56
+ git add $(POFILES) $(POTFILE) ../locale/*/LC_MESSAGES
57
+ git commit -m "i18n - pulling from tx"
58
+ @echo
59
+ @echo Changes commited!
60
+ @echo
@@ -0,0 +1,19 @@
1
+ # foreman_google
2
+ #
3
+ # This file is distributed under the same license as foreman_google.
4
+ #
5
+ #, fuzzy
6
+ msgid ""
7
+ msgstr ""
8
+ "Project-Id-Version: version 0.0.1\n"
9
+ "Report-Msgid-Bugs-To: \n"
10
+ "POT-Creation-Date: 2014-08-20 08:46+0100\n"
11
+ "PO-Revision-Date: 2014-08-20 08:54+0100\n"
12
+ "Last-Translator: Foreman Team <foreman-dev@googlegroups.com>\n"
13
+ "Language-Team: Foreman Team <foreman-dev@googlegroups.com>\n"
14
+ "Language: \n"
15
+ "MIME-Version: 1.0\n"
16
+ "Content-Type: text/plain; charset=UTF-8\n"
17
+ "Content-Transfer-Encoding: 8bit\n"
18
+ "Plural-Forms: nplurals=2; plural=(n != 1);\n"
19
+
@@ -0,0 +1,19 @@
1
+ # foreman_google
2
+ #
3
+ # This file is distributed under the same license as foreman_google.
4
+ #
5
+ #, fuzzy
6
+ msgid ""
7
+ msgstr ""
8
+ "Project-Id-Version: version 0.0.1\n"
9
+ "Report-Msgid-Bugs-To: \n"
10
+ "POT-Creation-Date: 2014-08-20 08:46+0100\n"
11
+ "PO-Revision-Date: 2014-08-20 08:46+0100\n"
12
+ "Last-Translator: Foreman Team <foreman-dev@googlegroups.com>\n"
13
+ "Language-Team: Foreman Team <foreman-dev@googlegroups.com>\n"
14
+ "Language: \n"
15
+ "MIME-Version: 1.0\n"
16
+ "Content-Type: text/plain; charset=UTF-8\n"
17
+ "Content-Transfer-Encoding: 8bit\n"
18
+ "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
19
+
data/locale/gemspec.rb ADDED
@@ -0,0 +1,2 @@
1
+ # Matches foreman_google.gemspec
2
+ _('TODO: Description of ForemanGoogle.')
data/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "foreman_google",
3
+ "version": "1.0.0",
4
+ "description": "DESCRIPTION",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "lint": "tfm-lint --plugin -d /webpack",
8
+ "test": "tfm-test --config jest.config.js",
9
+ "test:watch": "tfm-test --plugin --watchAll",
10
+ "test:current": "tfm-test --plugin --watch",
11
+ "publish-coverage": "tfm-publish-coverage",
12
+ "stories": "tfm-stories --plugin",
13
+ "stories:build": "tfm-build-stories --plugin",
14
+ "create-react-component": "yo react-domain"
15
+ },
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+https://github.com/theforeman/foreman_google.git"
19
+ },
20
+ "bugs": {
21
+ "url": "http://projects.theforeman.org/projects/foreman_google/issues"
22
+ },
23
+ "peerDependencies": {
24
+ "@theforeman/vendor": ">= 6.0.0"
25
+ },
26
+ "dependencies": {
27
+ "react-intl": "^2.8.0"
28
+ },
29
+ "devDependencies": {
30
+ "@babel/core": "^7.7.0",
31
+ "@sheerun/mutationobserver-shim": "^0.3.3",
32
+ "@theforeman/builder": "^6.0.0",
33
+ "@theforeman/eslint-plugin-foreman": "6.0.0",
34
+ "@theforeman/find-foreman": "^4.8.0",
35
+ "@theforeman/stories": "^7.0.0",
36
+ "@theforeman/test": "^8.0.0",
37
+ "@theforeman/vendor-dev": "^6.0.0",
38
+ "babel-eslint": "^10.0.3",
39
+ "eslint": "^6.7.2",
40
+ "prettier": "^1.19.1",
41
+ "stylelint-config-standard": "^18.0.0",
42
+ "stylelint": "^9.3.0"
43
+ }
44
+ }
@@ -0,0 +1,28 @@
1
+ FactoryBot.modify do
2
+ factory :compute_resource do
3
+ trait :google_gce do
4
+ transient do
5
+ project_id { 'coastal-haven-123456' }
6
+ end
7
+ provider { 'GCE' }
8
+ password do
9
+ # instead of private_key, we hand size of new key to generate
10
+ # this generate valid mocked key, due to overload of OpenSSL::PKey::RSA.new
11
+ <<-END_AUTHTOKEN
12
+ {
13
+ "type": "service_account",
14
+ "project_id": "#{project_id}",
15
+ "private_key_id": "7b1afc23bdfd510c49d827f3151fac94b089b42b",
16
+ "private_key": 2048,
17
+ "client_email": "xxxxxxx-compute@developer.gserviceaccount.com",
18
+ "client_id": "111235611116543210000",
19
+ "auth_uri": "https://accounts.google.com/o/oauth2/auth",
20
+ "token_uri": "https://oauth2.googleapis.com/token",
21
+ "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
22
+ "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/552404852006-compute%40developer.gserviceaccount.com"
23
+ }
24
+ END_AUTHTOKEN
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,11 @@
1
+ {
2
+ "id": "projects/centos-cloud/global/images",
3
+ "items": [
4
+ {
5
+ "name": "centos-6",
6
+ "kind": "compute#image"
7
+ }
8
+ ],
9
+ "selfLink": "https://www.googleapis.com/compute/v1/projects/centos-cloud/global/images",
10
+ "kind": "compute#imageList"
11
+ }