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.
- checksums.yaml +7 -0
- data/LICENSE +619 -0
- data/README.md +33 -0
- data/Rakefile +47 -0
- data/app/controllers/concerns/foreman_google/temporary_prepend_path.rb +16 -0
- data/app/models/foreman_google/gce.rb +119 -0
- data/app/models/foreman_google/google_compute.rb +127 -0
- data/config/routes.rb +2 -0
- data/lib/foreman_google/engine.rb +42 -0
- data/lib/foreman_google/google_compute_adapter.rb +91 -0
- data/lib/foreman_google/version.rb +3 -0
- data/lib/foreman_google.rb +4 -0
- data/lib/tasks/foreman_google_tasks.rake +31 -0
- data/locale/Makefile +60 -0
- data/locale/en/foreman_google.po +19 -0
- data/locale/foreman_google.pot +19 -0
- data/locale/gemspec.rb +2 -0
- data/package.json +44 -0
- data/test/factories/gce.rb +28 -0
- data/test/fixtures/images_centos_cloud.json +11 -0
- data/test/fixtures/images_coastal.json +12 -0
- data/test/fixtures/images_deprecated.json +17 -0
- data/test/fixtures/images_nothing_found.json +5 -0
- data/test/fixtures/instance.json +105 -0
- data/test/fixtures/instance_start.json +14 -0
- data/test/fixtures/instance_stop.json +14 -0
- data/test/fixtures/machine_types.json +12 -0
- data/test/fixtures/networks.json +11 -0
- data/test/fixtures/zones.json +1750 -0
- data/test/models/foreman_google/gce_test.rb +31 -0
- data/test/models/foreman_google/google_compute_test.rb +155 -0
- data/test/test_google_helper.rb +24 -0
- data/test/unit/foreman_google/google_compute_adapter_test.rb +126 -0
- data/webpack/global_index.js +17 -0
- data/webpack/global_test_setup.js +11 -0
- data/webpack/index.js +7 -0
- data/webpack/src/Extends/index.js +15 -0
- data/webpack/src/Router/routes.js +5 -0
- data/webpack/src/reducers.js +7 -0
- data/webpack/test_setup.js +17 -0
- 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,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,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
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
|