Skip to content

Commit

Permalink
Release 0.1.0
Browse files Browse the repository at this point in the history
Change-Id: I47b8921eb36543a0d27e16b7905c902a8aec3700
  • Loading branch information
Nelson Araujo committed Jan 11, 2018
0 parents commit 25a4313
Show file tree
Hide file tree
Showing 597 changed files with 48,262 additions and 0 deletions.
18 changes: 18 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Copyright 2017 Google Inc.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

*.swp
coverage/*

# Keep project coverage statistics under source control
!coverage/.last_run.json
54 changes: 54 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
[submodule "build/puppet/dns"]
path = build/puppet/dns
url = https://github.com/GoogleCloudPlatform/puppet-google-dns
[submodule "build/puppet/auth"]
path = build/puppet/auth
url = https://github.com/GoogleCloudPlatform/puppet-google-auth
[submodule "build/puppet/compute"]
path = build/puppet/compute
url = https://github.com/GoogleCloudPlatform/puppet-google-compute
[submodule "build/chef/dns"]
path = build/chef/dns
url = https://github.com/GoogleCloudPlatform/chef-google-dns
[submodule "build/chef/compute"]
path = build/chef/compute
url = https://github.com/GoogleCloudPlatform/chef-google-compute
[submodule "build/puppet/storage"]
path = build/puppet/storage
url = https://github.com/GoogleCloudPlatform/puppet-google-storage
[submodule "build/puppet/sql"]
path = build/puppet/sql
url = https://github.com/GoogleCloudPlatform/puppet-google-sql
[submodule "build/puppet/container"]
path = build/puppet/container
url = https://github.com/GoogleCloudPlatform/puppet-google-container
[submodule "build/puppet/_bundle"]
path = build/puppet/_bundle
url = https://github.com/GoogleCloudPlatform/puppet-google
[submodule "build/chef/auth"]
path = build/chef/auth
url = https://github.com/GoogleCloudPlatform/chef-google-auth
[submodule "build/chef/storage"]
path = build/chef/storage
url = https://github.com/GoogleCloudPlatform/chef-google-storage
[submodule "build/chef/container"]
path = build/chef/container
url = https://github.com/GoogleCloudPlatform/chef-google-container
[submodule "build/chef/sql"]
path = build/chef/sql
url = https://github.com/GoogleCloudPlatform/chef-google-sql
[submodule "build/puppet/logging"]
path = build/puppet/logging
url = https://github.com/GoogleCloudPlatform/puppet-google-logging
[submodule "build/chef/_bundle"]
path = build/chef/_bundle
url = https://github.com/GoogleCloudPlatform/chef-google
[submodule "build/puppet/pubsub"]
path = build/puppet/pubsub
url = https://github.com/GoogleCloudPlatform/puppet-google-pubsub
[submodule "build/puppet/spanner"]
path = build/puppet/spanner
url = https://github.com/GoogleCloudPlatform/puppet-google-spanner
[submodule "build/ansible"]
path = build/ansible
url = https://github.com/ansible/ansible.git
28 changes: 28 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
AllCops:
Exclude:
- 'build/**/*'
# We do not validate the templates as they will have code that will only be
# properly formatted when compiled for the target module. These files should
# be checked in their final generated form.
- 'products/**/files/*'
- 'templates/**/*'

Metrics/AbcSize:
Max: 20

# TODO(nelsonjr): Refactor this class and remove Rubocop exemptions below
Metrics/ClassLength:
Exclude:
- 'provider/core.rb'
- 'provider/puppet.rb'
- 'provider/legacy_test_data_formatter.rb'
# TODO(alexstephen): Remove this when generate_object is removed
- 'provider/chef.rb'
- 'tests/end2end/tester_base.rb'

Metrics/MethodLength:
Max: 15

Security/Eval:
Exclude:
- 'provider/legacy_test_data_generator.rb'
31 changes: 31 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# How to become a contributor and submit your own code

## Contributor License Agreements

We'd love to accept your sample apps and patches! Before we can take them, we
have to jump a couple of legal hurdles.

Please fill out either the individual or corporate Contributor License Agreement
(CLA).

* If you are an individual writing original source code and you're sure you
own the intellectual property, then you'll need to sign an [individual CLA]
(http://code.google.com/legal/individual-cla-v1.0.html).
* If you work for a company that wants to allow you to contribute your work,
then you'll need to sign a [corporate CLA]
(http://code.google.com/legal/corporate-cla-v1.0.html).

Follow either of the two links above to access the appropriate CLA and
instructions for how to sign and return it. Once we receive it, we'll be able to
accept your pull requests.

## Contributing A Patch

1. Submit an issue describing your proposed change to the repo in question.
1. The repo owner will respond to your issue promptly.
1. If your proposed change is accepted, and you haven't already done so, sign a
Contributor License Agreement (see details above).
1. Fork the desired repo, develop and test your code changes.
1. Ensure that your code is clear and comprehensible.
1. Ensure that your code has an appropriate set of unit tests which all pass.
1. Submit a pull request.
197 changes: 197 additions & 0 deletions DEVELOPER.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
# Developer Guide

All the information required for Magic Modules (MM) to compile a specific
product is usually contained within its folder under the [`products`](products/)
folder. For example all the sources for the Google Compute Engine are inside the
[`products/compute`](products/compute) folder.

When compiling a product you specify the path to the products folder with the
`-p` parameter.


## Anatomy of a Product

A product definition for a specific provider contains a few basic components:

1. Product definition: `api.yaml`
2. Provider dependent product definitions: `<provider>.yaml`
3. Examples
4. Tests

### Product definition: api.yaml

The `api.yaml` contains all the object definitions for the GCP product. It also
contains the relationships between objects.

It also includes other product specific information, such as product version and
API endpoint.

#### Resource

A resource is an object defined and supported by the product. For example a
virtual machine, a disk, a network, a container, a container cluster are all
resources from MM's point of view.

A resource defines some basic properties about the resource such as name,
endpoint name, as well as its properties and parameters.

- !ruby/object:Api::Resource
name: 'Address'
kind: 'compute#address'
base_url: projects/{{project}}/regions/{{region}}/addresses
exports:
...
description: |
...
parameters:
...
properties:
...

##### Resource / [ parameters | properties ]

Specifies fields that the user can specify to define the object and its desired
state.

> The main difference between a parameter and a property is that a parameter is
> not part of the object, and will be used by the user to convey data to the
> generated code, usually to help locate the object. Every property will be
> eventually persisted as fields of the remote object in GCP.
Required fields:

- `type`: Specifies the type of the parameter / property
- `name`: The user facing name of the parameter / property
- `description`: The description for the parameter / property

Optional fields:

- `required`: true|false indicating if the field if required to be specified by
the user
- `input`: true|false indicating if the field will be used as "input", which
means that the field will be used only during the _creation_ of the object
- `output`: true|false indicating that the field is produced and controlled by
the server. The user can use an output field to ensure the value matches
what's expected.
- `field`: In case we want the user facing name to be different from the
corresponding API property we can use `field` to map the user facing name
(specified by the `name` parameter) to the backend API (specified by the
`field` parameter)

Example:

- !ruby/object:Api::Type::ResourceRef
name: 'region'
resource: 'Region'
imports: 'name'
description: |
URL of the region where the regional address resides.
This field is not applicable to global addresses.
required: true

> Please describe these fields from the user's perspective and not from the API
> perspective. That will allow the generated documentation be useful for the
> provider user that should not care about how the internals work. This is a
> core strength of the MM paradigm: the user should neither need to know nor
> care how the backend works. All he cares is how to describe in a high-level,
> uniform and elegant way his dependencies.
>
> For example a in a virtual machine disk, do not say "disk: array or full URI
> (self link) to the disks". Instead you should say "disks: reference to a list
> disks to attach to the machine".
>
> Also avoid language or provider specific lingo in the product definitions.
>
> For example instead of saying "a hash array of name to datetime" say "a map
> from name to timestamps". While the former may be correct for a provider in
> Java it will not be in a Ruby or Python based output.

### Provider dependent product definitions: <provider>.yaml

Each provider has their own product specific definitions that are relevant and
necessary to properly build the product for such provider.

For example a Puppet provider requires to specify the Puppet Forge URL for the
module being created. That goes into the product `puppet.yaml`. Similarly a Chef
provider requires metadata about dependencies of other cookbooks. That goes into
the product `chef.yaml`.

Detailed provider documentation:

- [`puppet.yaml`][puppet-yaml] on how to create Puppet product definitions
- [`chef.yaml`][chef-yaml] on how to create Chef product definitions

### Examples

It is strongly encouraged to provide live, working examples to end users. It is
also good practice to test the examples to make sure they do not become stale.

To test examples you can use our `[end2end](tests/end2end)` mini framework.


## Types

When defining a property you have to specify its type. Although some products
may not care about types and may convert from/to strings, it is important to
know the type so the compiler can do the best job possible to validate the
input, ensure consistency, etc.

Currently MM supports the following types:

- `Api::Type::Array`: Represents an array of values. The type of the values is
identified by the `item\_type`property.
- `Api::Type::Boolean`: A boolean (true or false) value.
- `Api::Type::Constant`: A constant that will be passed to the API.
- `Api::Type::Double`: A double number.
- `Api::Type::Enum`: Input is allowed only from a fixed list of values,
specified by the `values` property.
- `Api::Type::Integer`: An integer number.
- `Api::Type::Long`: A long number
- Api::Type::NameValues
- `Api::Type::NestedObject`: A composite field, composed of inner fields. This
is used for structures that are nested.
- `Api::Type::ResourceRef`: A reference to another object described in the
product. This is used to create strong relationship binding between the
objects, where the generated code will make sure the object depended upon
exists. A `ResourceRef` also specifies which property from the dependent
object we are interested to fetch, by specifying the `resource` and `imports`
fields.
- `Api::Type::String`: A string field.
- `Api::Type::Time`: An RFC 3339 representation of a time stamp.


## Exports

When data needs to be read from another object that we depend on we use exports.

For example a virtual machine has many disks. When specifying the disks we do
not want the user to worry about which representation Google developers chose
for that object (is it the self\_link? is it just the disk name? is it the
zone+name?).

Instead we describe the relationship in `api.yaml` and let the generated code
deal with that. The user will only say "vm X uses disks [A, B, C]". As GCP VM
requires the disk self\_link the generated code will compute their values and
pass along.

All fields need to be explicitly exported before they can be imported and
dependent upon by other objects. This allows us to track and verify the
dependencies more reliably.

The following exports are allowed:

- `<property-name>`: By specifying the `name` of an existing property of the
object, we're allowing other objects to import it.
- `Api::Type::FetchedExternal`: Exports the version of the data that was
returned from the API. That's useful when the user specification of the
property is different from the representation coming from the API
- `Api::Type::SelfLink`: URI that represents the object

> To avoid overexposure and inefficient code, only export the fields you
> actively require to access from dependent objects, and practice housecleaning
> by removing exports if you change or remove an object that depends on it.

[puppet-yaml]: docs/puppet.yaml.md
[chef-yaml]: docs/chef.yaml.md
16 changes: 16 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
source 'https://rubygems.org'

gem 'binding_of_caller'

group :test do
gem 'mocha'
gem 'rspec'
# TODO(alexstephen): Monitor rubocop upsteam changes
# https://github.com/bbatsov/rubocop/pull/4329
# Change will allow rubocop to use --ignore-parent-exclusion flag
# Current rubocop upstream will not check Chef files because of
# AllCops/Exclude
gem 'rubocop', git: 'https://github.com/nelsonjr/rubocop.git',
branch: 'feature/ignore-parent-exclude'
gem 'simplecov'
end
Loading

0 comments on commit 25a4313

Please sign in to comment.