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
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
+ }