Skip to content

Commit b5885a0

Browse files
author
Nelson Araujo
committed
Release 0.1.0
Change-Id: I47b8921eb36543a0d27e16b7905c902a8aec3700
0 parents  commit b5885a0

File tree

597 files changed

+48262
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

597 files changed

+48262
-0
lines changed

.gitignore

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Copyright 2017 Google Inc.
2+
# Licensed under the Apache License, Version 2.0 (the "License");
3+
# you may not use this file except in compliance with the License.
4+
# You may obtain a copy of the License at
5+
#
6+
# http://www.apache.org/licenses/LICENSE-2.0
7+
#
8+
# Unless required by applicable law or agreed to in writing, software
9+
# distributed under the License is distributed on an "AS IS" BASIS,
10+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
# See the License for the specific language governing permissions and
12+
# limitations under the License.
13+
14+
*.swp
15+
coverage/*
16+
17+
# Keep project coverage statistics under source control
18+
!coverage/.last_run.json

.gitmodules

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
[submodule "build/puppet/dns"]
2+
path = build/puppet/dns
3+
url = https://github.com/GoogleCloudPlatform/puppet-google-dns
4+
[submodule "build/puppet/auth"]
5+
path = build/puppet/auth
6+
url = https://github.com/GoogleCloudPlatform/puppet-google-auth
7+
[submodule "build/puppet/compute"]
8+
path = build/puppet/compute
9+
url = https://github.com/GoogleCloudPlatform/puppet-google-compute
10+
[submodule "build/chef/dns"]
11+
path = build/chef/dns
12+
url = https://github.com/GoogleCloudPlatform/chef-google-dns
13+
[submodule "build/chef/compute"]
14+
path = build/chef/compute
15+
url = https://github.com/GoogleCloudPlatform/chef-google-compute
16+
[submodule "build/puppet/storage"]
17+
path = build/puppet/storage
18+
url = https://github.com/GoogleCloudPlatform/puppet-google-storage
19+
[submodule "build/puppet/sql"]
20+
path = build/puppet/sql
21+
url = https://github.com/GoogleCloudPlatform/puppet-google-sql
22+
[submodule "build/puppet/container"]
23+
path = build/puppet/container
24+
url = https://github.com/GoogleCloudPlatform/puppet-google-container
25+
[submodule "build/puppet/_bundle"]
26+
path = build/puppet/_bundle
27+
url = https://github.com/GoogleCloudPlatform/puppet-google
28+
[submodule "build/chef/auth"]
29+
path = build/chef/auth
30+
url = https://github.com/GoogleCloudPlatform/chef-google-auth
31+
[submodule "build/chef/storage"]
32+
path = build/chef/storage
33+
url = https://github.com/GoogleCloudPlatform/chef-google-storage
34+
[submodule "build/chef/container"]
35+
path = build/chef/container
36+
url = https://github.com/GoogleCloudPlatform/chef-google-container
37+
[submodule "build/chef/sql"]
38+
path = build/chef/sql
39+
url = https://github.com/GoogleCloudPlatform/chef-google-sql
40+
[submodule "build/puppet/logging"]
41+
path = build/puppet/logging
42+
url = https://github.com/GoogleCloudPlatform/puppet-google-logging
43+
[submodule "build/chef/_bundle"]
44+
path = build/chef/_bundle
45+
url = https://github.com/GoogleCloudPlatform/chef-google
46+
[submodule "build/puppet/pubsub"]
47+
path = build/puppet/pubsub
48+
url = https://github.com/GoogleCloudPlatform/puppet-google-pubsub
49+
[submodule "build/puppet/spanner"]
50+
path = build/puppet/spanner
51+
url = https://github.com/GoogleCloudPlatform/puppet-google-spanner
52+
[submodule "build/ansible"]
53+
path = build/ansible
54+
url = https://github.com/ansible/ansible.git

.rubocop.yml

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
AllCops:
2+
Exclude:
3+
- 'build/**/*'
4+
# We do not validate the templates as they will have code that will only be
5+
# properly formatted when compiled for the target module. These files should
6+
# be checked in their final generated form.
7+
- 'products/**/files/*'
8+
- 'templates/**/*'
9+
10+
Metrics/AbcSize:
11+
Max: 20
12+
13+
# TODO(nelsonjr): Refactor this class and remove Rubocop exemptions below
14+
Metrics/ClassLength:
15+
Exclude:
16+
- 'provider/core.rb'
17+
- 'provider/puppet.rb'
18+
- 'provider/legacy_test_data_formatter.rb'
19+
# TODO(alexstephen): Remove this when generate_object is removed
20+
- 'provider/chef.rb'
21+
- 'tests/end2end/tester_base.rb'
22+
23+
Metrics/MethodLength:
24+
Max: 15
25+
26+
Security/Eval:
27+
Exclude:
28+
- 'provider/legacy_test_data_generator.rb'

CONTRIBUTING.md

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# How to become a contributor and submit your own code
2+
3+
## Contributor License Agreements
4+
5+
We'd love to accept your sample apps and patches! Before we can take them, we
6+
have to jump a couple of legal hurdles.
7+
8+
Please fill out either the individual or corporate Contributor License Agreement
9+
(CLA).
10+
11+
* If you are an individual writing original source code and you're sure you
12+
own the intellectual property, then you'll need to sign an [individual CLA]
13+
(http://code.google.com/legal/individual-cla-v1.0.html).
14+
* If you work for a company that wants to allow you to contribute your work,
15+
then you'll need to sign a [corporate CLA]
16+
(http://code.google.com/legal/corporate-cla-v1.0.html).
17+
18+
Follow either of the two links above to access the appropriate CLA and
19+
instructions for how to sign and return it. Once we receive it, we'll be able to
20+
accept your pull requests.
21+
22+
## Contributing A Patch
23+
24+
1. Submit an issue describing your proposed change to the repo in question.
25+
1. The repo owner will respond to your issue promptly.
26+
1. If your proposed change is accepted, and you haven't already done so, sign a
27+
Contributor License Agreement (see details above).
28+
1. Fork the desired repo, develop and test your code changes.
29+
1. Ensure that your code is clear and comprehensible.
30+
1. Ensure that your code has an appropriate set of unit tests which all pass.
31+
1. Submit a pull request.

DEVELOPER.md

+197
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
# Developer Guide
2+
3+
All the information required for Magic Modules (MM) to compile a specific
4+
product is usually contained within its folder under the [`products`](products/)
5+
folder. For example all the sources for the Google Compute Engine are inside the
6+
[`products/compute`](products/compute) folder.
7+
8+
When compiling a product you specify the path to the products folder with the
9+
`-p` parameter.
10+
11+
12+
## Anatomy of a Product
13+
14+
A product definition for a specific provider contains a few basic components:
15+
16+
1. Product definition: `api.yaml`
17+
2. Provider dependent product definitions: `<provider>.yaml`
18+
3. Examples
19+
4. Tests
20+
21+
### Product definition: api.yaml
22+
23+
The `api.yaml` contains all the object definitions for the GCP product. It also
24+
contains the relationships between objects.
25+
26+
It also includes other product specific information, such as product version and
27+
API endpoint.
28+
29+
#### Resource
30+
31+
A resource is an object defined and supported by the product. For example a
32+
virtual machine, a disk, a network, a container, a container cluster are all
33+
resources from MM's point of view.
34+
35+
A resource defines some basic properties about the resource such as name,
36+
endpoint name, as well as its properties and parameters.
37+
38+
- !ruby/object:Api::Resource
39+
name: 'Address'
40+
kind: 'compute#address'
41+
base_url: projects/{{project}}/regions/{{region}}/addresses
42+
exports:
43+
...
44+
description: |
45+
...
46+
parameters:
47+
...
48+
properties:
49+
...
50+
51+
##### Resource / [ parameters | properties ]
52+
53+
Specifies fields that the user can specify to define the object and its desired
54+
state.
55+
56+
> The main difference between a parameter and a property is that a parameter is
57+
> not part of the object, and will be used by the user to convey data to the
58+
> generated code, usually to help locate the object. Every property will be
59+
> eventually persisted as fields of the remote object in GCP.
60+
61+
Required fields:
62+
63+
- `type`: Specifies the type of the parameter / property
64+
- `name`: The user facing name of the parameter / property
65+
- `description`: The description for the parameter / property
66+
67+
Optional fields:
68+
69+
- `required`: true|false indicating if the field if required to be specified by
70+
the user
71+
- `input`: true|false indicating if the field will be used as "input", which
72+
means that the field will be used only during the _creation_ of the object
73+
- `output`: true|false indicating that the field is produced and controlled by
74+
the server. The user can use an output field to ensure the value matches
75+
what's expected.
76+
- `field`: In case we want the user facing name to be different from the
77+
corresponding API property we can use `field` to map the user facing name
78+
(specified by the `name` parameter) to the backend API (specified by the
79+
`field` parameter)
80+
81+
Example:
82+
83+
- !ruby/object:Api::Type::ResourceRef
84+
name: 'region'
85+
resource: 'Region'
86+
imports: 'name'
87+
description: |
88+
URL of the region where the regional address resides.
89+
This field is not applicable to global addresses.
90+
required: true
91+
92+
> Please describe these fields from the user's perspective and not from the API
93+
> perspective. That will allow the generated documentation be useful for the
94+
> provider user that should not care about how the internals work. This is a
95+
> core strength of the MM paradigm: the user should neither need to know nor
96+
> care how the backend works. All he cares is how to describe in a high-level,
97+
> uniform and elegant way his dependencies.
98+
>
99+
> For example a in a virtual machine disk, do not say "disk: array or full URI
100+
> (self link) to the disks". Instead you should say "disks: reference to a list
101+
> disks to attach to the machine".
102+
>
103+
> Also avoid language or provider specific lingo in the product definitions.
104+
>
105+
> For example instead of saying "a hash array of name to datetime" say "a map
106+
> from name to timestamps". While the former may be correct for a provider in
107+
> Java it will not be in a Ruby or Python based output.
108+
109+
110+
### Provider dependent product definitions: <provider>.yaml
111+
112+
Each provider has their own product specific definitions that are relevant and
113+
necessary to properly build the product for such provider.
114+
115+
For example a Puppet provider requires to specify the Puppet Forge URL for the
116+
module being created. That goes into the product `puppet.yaml`. Similarly a Chef
117+
provider requires metadata about dependencies of other cookbooks. That goes into
118+
the product `chef.yaml`.
119+
120+
Detailed provider documentation:
121+
122+
- [`puppet.yaml`][puppet-yaml] on how to create Puppet product definitions
123+
- [`chef.yaml`][chef-yaml] on how to create Chef product definitions
124+
125+
### Examples
126+
127+
It is strongly encouraged to provide live, working examples to end users. It is
128+
also good practice to test the examples to make sure they do not become stale.
129+
130+
To test examples you can use our `[end2end](tests/end2end)` mini framework.
131+
132+
133+
## Types
134+
135+
When defining a property you have to specify its type. Although some products
136+
may not care about types and may convert from/to strings, it is important to
137+
know the type so the compiler can do the best job possible to validate the
138+
input, ensure consistency, etc.
139+
140+
Currently MM supports the following types:
141+
142+
- `Api::Type::Array`: Represents an array of values. The type of the values is
143+
identified by the `item\_type`property.
144+
- `Api::Type::Boolean`: A boolean (true or false) value.
145+
- `Api::Type::Constant`: A constant that will be passed to the API.
146+
- `Api::Type::Double`: A double number.
147+
- `Api::Type::Enum`: Input is allowed only from a fixed list of values,
148+
specified by the `values` property.
149+
- `Api::Type::Integer`: An integer number.
150+
- `Api::Type::Long`: A long number
151+
- Api::Type::NameValues
152+
- `Api::Type::NestedObject`: A composite field, composed of inner fields. This
153+
is used for structures that are nested.
154+
- `Api::Type::ResourceRef`: A reference to another object described in the
155+
product. This is used to create strong relationship binding between the
156+
objects, where the generated code will make sure the object depended upon
157+
exists. A `ResourceRef` also specifies which property from the dependent
158+
object we are interested to fetch, by specifying the `resource` and `imports`
159+
fields.
160+
- `Api::Type::String`: A string field.
161+
- `Api::Type::Time`: An RFC 3339 representation of a time stamp.
162+
163+
164+
## Exports
165+
166+
When data needs to be read from another object that we depend on we use exports.
167+
168+
For example a virtual machine has many disks. When specifying the disks we do
169+
not want the user to worry about which representation Google developers chose
170+
for that object (is it the self\_link? is it just the disk name? is it the
171+
zone+name?).
172+
173+
Instead we describe the relationship in `api.yaml` and let the generated code
174+
deal with that. The user will only say "vm X uses disks [A, B, C]". As GCP VM
175+
requires the disk self\_link the generated code will compute their values and
176+
pass along.
177+
178+
All fields need to be explicitly exported before they can be imported and
179+
dependent upon by other objects. This allows us to track and verify the
180+
dependencies more reliably.
181+
182+
The following exports are allowed:
183+
184+
- `<property-name>`: By specifying the `name` of an existing property of the
185+
object, we're allowing other objects to import it.
186+
- `Api::Type::FetchedExternal`: Exports the version of the data that was
187+
returned from the API. That's useful when the user specification of the
188+
property is different from the representation coming from the API
189+
- `Api::Type::SelfLink`: URI that represents the object
190+
191+
> To avoid overexposure and inefficient code, only export the fields you
192+
> actively require to access from dependent objects, and practice housecleaning
193+
> by removing exports if you change or remove an object that depends on it.
194+
195+
196+
[puppet-yaml]: docs/puppet.yaml.md
197+
[chef-yaml]: docs/chef.yaml.md

Gemfile

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
source 'https://rubygems.org'
2+
3+
gem 'binding_of_caller'
4+
5+
group :test do
6+
gem 'mocha'
7+
gem 'rspec'
8+
# TODO(alexstephen): Monitor rubocop upsteam changes
9+
# https://github.com/bbatsov/rubocop/pull/4329
10+
# Change will allow rubocop to use --ignore-parent-exclusion flag
11+
# Current rubocop upstream will not check Chef files because of
12+
# AllCops/Exclude
13+
gem 'rubocop', git: 'https://github.com/nelsonjr/rubocop.git',
14+
branch: 'feature/ignore-parent-exclude'
15+
gem 'simplecov'
16+
end

0 commit comments

Comments
 (0)