Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ansible facts modules #247

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
df54fbe
Generating facts modules
rambleraptor Jun 4, 2018
a466c1d
Baseline facts module created
rambleraptor Jun 4, 2018
c25763d
Exclude all facts modules but instance for the moment
rambleraptor Jun 4, 2018
e01e05a
moving facts into their own provider
rambleraptor Jun 5, 2018
c62679a
Rakefile update for Ansible facts
rambleraptor Jun 5, 2018
744714b
Instance fact module working
rambleraptor Jun 5, 2018
1e0bd0d
Rubocop fixes
rambleraptor Jun 5, 2018
43aa032
Ansible Facts: CI support
rambleraptor Jun 5, 2018
a2d1363
Adding verifier task to integration tests, so that gcloud can be subb…
rambleraptor Jun 20, 2018
53a7def
list returns nil when empty because of course it does
rambleraptor Jun 21, 2018
05de810
Rubocop fixes
rambleraptor Jun 21, 2018
a5ca310
Ignore facts generation by default
rambleraptor Jul 10, 2018
c082f24
Fixing ansible linter issues
rambleraptor Jul 10, 2018
b9c4152
Added EXAMPLES and RETURNS to facts modules
rambleraptor Jul 10, 2018
d30ae80
Rubocop fixes
rambleraptor Jul 10, 2018
9aaf6c2
PR changes
rambleraptor Jul 11, 2018
559cbde
Adding generic datasource support and combining Ansible into a single…
rambleraptor Jul 17, 2018
1ca3e70
rubocop fixes
rambleraptor Jul 17, 2018
ba31600
Removing old facts provider
rambleraptor Jul 18, 2018
69b5bc3
Magician should use different remote on non-GCP pushes
rambleraptor Jul 18, 2018
df2393e
Merge 69b5bc3d380cbe67e1362eb447467f3af973a871 into a6d8316517c0bb4a8…
rambleraptor Jul 18, 2018
5d49f95
Update tracked submodules -> HEAD on Wed Jul 18 21:54:44 UTC 2018
modular-magician Jul 18, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .ci/magic-modules/merge-pr.sh
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ echo "Merged PR #$ID." > ./commit_message

set +e
if [ "$REPO" != "GoogleCloudPlatform/magic-modules" ]; then
git remote add push-target "git@github.com:$REPO"
git remote add non-gcp-push-target "git@github.com:$REPO"
# We know we have a commit, so all the machinery of the git resources is
# unnecessary. We can just try to push directly, without forcing.
ssh-agent bash -c "ssh-add ~/github_private_key; git push push-target $BRANCH"
ssh-agent bash -c "ssh-add ~/github_private_key; git push non-gcp-push-target $BRANCH"
fi
set -e
2 changes: 1 addition & 1 deletion build/terraform
76 changes: 76 additions & 0 deletions products/compute/ansible.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,82 @@ manifest: !ruby/object:Provider::Ansible::Manifest
version_added: '2.6'
author: Google Inc. (@googlecloudplatform)
# This is where custom code would be defined eventually.
datasources: !ruby/object:Provider::ResourceOverrides
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry to keep hassling you here, but it seems like off-by-default would be the right approach. Most resources don't need datasources.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the Ansible world, we're looking to build datasources for everything. I'm inclined to keep this as-is because my intent is for most of these lines to go away (very, very soon).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, in the Terraform world we agree also!

Instance: !ruby/object:Provider::Ansible::ResourceOverride
version_added: '2.7'
Address: !ruby/object:Provider::Ansible::ResourceOverride
exclude: true
Autoscaler: !ruby/object:Provider::Ansible::ResourceOverride
exclude: true
BackendBucket: !ruby/object:Provider::Ansible::ResourceOverride
exclude: true
BackendService: !ruby/object:Provider::Ansible::ResourceOverride
exclude: true
Disk: !ruby/object:Provider::Ansible::ResourceOverride
exclude: true
Firewall: !ruby/object:Provider::Ansible::ResourceOverride
exclude: true
ForwardingRule: !ruby/object:Provider::Ansible::ResourceOverride
exclude: true
GlobalAddress: !ruby/object:Provider::Ansible::ResourceOverride
exclude: true
GlobalForwardingRule: !ruby/object:Provider::Ansible::ResourceOverride
exclude: true
HealthCheck: !ruby/object:Provider::Ansible::ResourceOverride
exclude: true
HttpHealthCheck: !ruby/object:Provider::Ansible::ResourceOverride
exclude: true
HttpsHealthCheck: !ruby/object:Provider::Ansible::ResourceOverride
exclude: true
Image: !ruby/object:Provider::Ansible::ResourceOverride
exclude: true
InstanceGroup: !ruby/object:Provider::Ansible::ResourceOverride
exclude: true
InstanceGroupManager: !ruby/object:Provider::Ansible::ResourceOverride
exclude: true
InstanceTemplate: !ruby/object:Provider::Ansible::ResourceOverride
exclude: true
Network: !ruby/object:Provider::Ansible::ResourceOverride
exclude: true
RegionAutoscaler: !ruby/object:Provider::Ansible::ResourceOverride
exclude: true
Route: !ruby/object:Provider::Ansible::ResourceOverride
exclude: true
Router: !ruby/object:Provider::Ansible::ResourceOverride
exclude: true
Snapshot: !ruby/object:Provider::Ansible::ResourceOverride
exclude: true
SslCertificate: !ruby/object:Provider::Ansible::ResourceOverride
exclude: true
SslPolicy: !ruby/object:Provider::Ansible::ResourceOverride
exclude: true
Subnetwork: !ruby/object:Provider::Ansible::ResourceOverride
exclude: true
TargetPool: !ruby/object:Provider::Ansible::ResourceOverride
exclude: true
TargetHttpProxy: !ruby/object:Provider::Ansible::ResourceOverride
exclude: true
TargetHttpsProxy: !ruby/object:Provider::Ansible::ResourceOverride
exclude: true
TargetSslProxy: !ruby/object:Provider::Ansible::ResourceOverride
exclude: true
TargetTcpProxy: !ruby/object:Provider::Ansible::ResourceOverride
exclude: true
TargetVpnGateway: !ruby/object:Provider::Ansible::ResourceOverride
exclude: true
UrlMap: !ruby/object:Provider::Ansible::ResourceOverride
exclude: true
# Readonly resources.
DiskType: !ruby/object:Provider::Ansible::ResourceOverride
exclude: true
License: !ruby/object:Provider::Ansible::ResourceOverride
exclude: true
MachineType: !ruby/object:Provider::Ansible::ResourceOverride
exclude: true
Region: !ruby/object:Provider::Ansible::ResourceOverride
exclude: true
Zone: !ruby/object:Provider::Ansible::ResourceOverride
exclude: true
overrides: !ruby/object:Provider::ResourceOverrides
BackendService: !ruby/object:Provider::Ansible::ResourceOverride
properties:
Expand Down
19 changes: 10 additions & 9 deletions products/compute/examples/ansible/instance.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,13 @@ task: !ruby/object:Provider::Ansible::Task
project: <%= ctx[:project] %>
auth_kind: <%= ctx[:auth_kind] %>
service_account_file: <%= ctx[:service_account_file] %>
verifier: !ruby/object:Provider::Ansible::Verifier
command: |
gcloud compute instances describe
--project="{{ gcp_project }}"
--zone="us-central1-a"
"{{ resource_name }}"
failure: !ruby/object:Provider::Ansible::ComputeFailureCondition
region: zones/us-central1-a
type: instances
verifier: !ruby/object:Provider::Ansible::FactsVerifier
parameters:
zone: 'us-central1-a'
facts: !ruby/object:Provider::Ansible::Task
name: gcp_compute_instance_facts
code: |
zone: 'us-central1-a'
project: <%= ctx[:project] %>
auth_kind: <%= ctx[:auth_kind] %>
service_account_file: <%= ctx[:service_account_file] %>
15 changes: 15 additions & 0 deletions provider/ansible.rb
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,10 @@ def wrap_field(field, spaces)
field.scan(/\S.{0,#{avail_columns}}\S(?=\s|$)|\S+/)
end

def list_kind(object)
"#{object.kind}List"
end

private

def get_example(cfg_file)
Expand Down Expand Up @@ -302,6 +306,17 @@ def generate_resource_tests(data)
)
end

def compile_datasource(data)
target_folder = data[:output_folder]
FileUtils.mkpath target_folder
name = "#{module_name(data[:object])}_facts"
generate_resource_file data.clone.merge(
default_template: 'templates/ansible/facts.erb',
out_file: File.join(target_folder,
"lib/ansible/modules/cloud/google/#{name}.py")
)
end

def generate_network_datas(data, object) end

def generate_base_property(data) end
Expand Down
76 changes: 69 additions & 7 deletions provider/ansible/example.rb
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,65 @@ def build_task(state, object)

private

def verbs
{
present: 'created',
absent: 'deleted',
facts: 'verify'
}
end
end

# Holds all information necessary to run a facts module and verify the
# creation / deletion of a resource.
# Takes in a set of parameters, which are used as properties on the facts
# module.
class FactsVerifier < Api::Object
include Compile::Core

def validate
@failure ||= FailureCondition.new

check_property :parameters, Hash
end

# rubocop:disable Metrics/AbcSize
# rubocop:disable Metrics/MethodLength
def build_task(state, object)
obj_name = Google::StringUtils.underscore(object.name)
verb = verbs[state.to_sym]
number = state == 'present' ? 1 : 0
module_name = ["gcp_#{object.__product.prefix[1..-1]}",
Google::StringUtils.underscore(object.name),
'facts'].join('_')
[
"- name: verify that #{obj_name} was #{verb}",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a lot of formatting things in here- would it make sense for this part to be an erb template? Or is there enough regular ruby going on that this is better?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the moment, I think it's alright to keep this as Ruby. I'm going to do a small refactor of this code in a separate PR. It should clean it up and make generating facts examples from regular examples possible.

Copy link
Contributor Author

@rambleraptor rambleraptor Jul 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As part of #343, I ended up using ERB templates. Thanks for the idea!

#343 should also enable me to build the facts examples from the regular examples, which would be super awesome and allow facts modules to be generated with no additional configuration (yay!)

indent([
"#{module_name}:",
indent([
'filters:',
' - name = "{{ resource_name }}"',
@parameters.map { |k, v| "#{k}: #{v}" },
'project: "{{ gcp_project }}"',
'auth_kind: "{{ gcp_cred_kind }}"',
'service_account_file: "{{ gcp_cred_file }}"',
'scopes:',
" - #{object.__product.scopes[0]}"
], 4),
'register: results'
].flatten.compact, 2),

'- name: verify that command succeeded',
' assert:',
' that:',
indent("- results['items'] | length == #{number}", 6)
].compact
end
# rubocop:enable Metrics/MethodLength
# rubocop:enable Metrics/AbcSize

private

def verbs
{
present: 'created',
Expand Down Expand Up @@ -196,6 +255,7 @@ def verbs
private

# rubocop:disable Metrics/CyclomaticComplexity
# rubocop:disable Metrics/PerceivedComplexity
def build_task(state, hash, object, noop = false)
verb = verbs[state.to_sym]

Expand All @@ -208,17 +268,17 @@ def build_task(state, hash, object, noop = false)
indent([
"#{@name}:",
indent([
compile_string(hash, @code),
'scopes:',
indent(lines(scopes), 2),
"state: #{state}"
], 4),
compile_string(hash, @code),
'scopes:',
indent(lines(scopes), 2),
("state: #{state}" if state != 'facts')
].compact, 4),
("register: #{@register}" unless @register.nil?)
].compact, 2)
]
end
# rubocop:enable Metrics/MethodLength
# rubocop:enable Metrics/CyclomaticComplexity
# rubocop:enable Metrics/PerceivedComplexity

def object_name_from_module_name(mod_name)
product_name = mod_name.match(/gcp_[a-z]*_(.*)/).captures[0]
Expand All @@ -234,13 +294,15 @@ def dependency_name(dependency, resource)
# examples.
class Example < Api::Object
attr_reader :task
attr_reader :facts
attr_reader :verifier
attr_reader :dependencies

def validate
super
check_property :task, Task
check_optional_property :verifier, Verifier
check_optional_property :facts, Task
check_optional_property :verifier, [Verifier, FactsVerifier]
check_optional_property_list :dependencies, Task
end
end
Expand Down
3 changes: 3 additions & 0 deletions provider/ansible/resource_override.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ module OverrideProperties
attr_reader :create
attr_reader :delete
attr_reader :editable
attr_reader :filter_url
attr_reader :hidden
attr_reader :imports
attr_reader :provider_helpers
Expand All @@ -45,6 +46,7 @@ def validate
default_value_property :custom_update_resource, false
default_value_property :exclude, false
default_value_property :editable, true
default_value_property :filter_url, ''
default_value_property :imports, []
default_value_property :provider_helpers, []
default_value_property :unwrap_resource, false
Expand All @@ -56,6 +58,7 @@ def validate
check_optional_property :create, ::String
check_optional_property :delete, ::String
check_property :editable, :boolean
check_property :filter_url, ::String
check_optional_property :hidden, ::Array
check_property :imports, ::Array
check_property :provider_helpers, ::Array
Expand Down
2 changes: 2 additions & 0 deletions provider/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ class Config < Api::Object
extend Compile::Core

attr_reader :overrides
# Overrides for datasources
attr_reader :datasources
attr_reader :objects
attr_reader :examples
attr_reader :properties # TODO(nelsonjr): Remove this once bug 193 is fixed.
Expand Down
39 changes: 39 additions & 0 deletions provider/core.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ def generate(output_folder, types, version_name)
# or compiled.
compile_files(output_folder) \
unless @config.files.nil? || @config.files.compile.nil?

generate_datasources(output_folder, types, version) \
unless @config.datasources.nil?
apply_file_acls(output_folder) \
unless @config.files.nil? || @config.files.permissions.nil?
verify_test_matrixes
Expand Down Expand Up @@ -237,6 +240,42 @@ def generate_object(object, output_folder, version)
generate_network_datas data, object
end

# rubocop:disable Metrics/AbcSize
# rubocop:disable Metrics/CyclomaticComplexity
# rubocop:disable Metrics/PerceivedComplexity
def generate_datasources(output_folder, types, version)
# We need to apply overrides for datasources
@config.datasources.validate

@api.set_properties_based_on_version(version)
@api.objects.each do |object|
if !types.empty? && !types.include?(object.name)
Google::LOGGER.info(
"Excluding #{object.name} datasource per user request"
)
elsif types.empty? && object.exclude
Google::LOGGER.info(
"Excluding #{object.name} datasource per API catalog"
)
elsif types.empty? && object.exclude_if_not_in_version(version)
Google::LOGGER.info(
"Excluding #{object.name} datasource per API version"
)
else
generate_datasource object, output_folder, version
end
end
end
# rubocop:enable Metrics/CyclomaticComplexity
# rubocop:enable Metrics/PerceivedComplexity
# rubocop:enable Metrics/AbcSize

def generate_datasource(object, output_folder, version)
data = build_object_data(object, output_folder, version)

compile_datasource data
end

# Generates all 6 network data files for a object.
# This includes all combinations of seeds [0-2] and title == / != name
# Each data file is a YAML file with all properties possible on an object.
Expand Down
1 change: 1 addition & 0 deletions tasks/common.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

PROVIDER_FOLDERS = {
ansible: 'build/ansible',
ansible_facts: 'build/ansible',
puppet: 'build/puppet/%s',
chef: 'build/chef/%s',
terraform: 'build/terraform'
Expand Down
Loading