Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,18 @@ You need to [register a new domain](https://docs.aws.amazon.com/Route53/latest/D

___

### Building blocks of Zero

### Project Definition:
Each project is defined by this project definition file, this manifest contains your project details, and is the source of truth for the templating(`zero create`) and provision(`zero apply`) steps.

See [`zero-project.yml` reference](./docs/project-definition.md) for details.
### Module Definition
Module definition defines the information needed for the module to run (`zero apply`).
Also declares dependency used to determine the order of execution with other modules.

See [`zero-module.yml` reference](./docs/module-definition.md) for details.
___
## Using zero to spin up your own stack

Using Zero to spin up your infrastructure and application is easy and straightforward. Using just a few commands, you can configure and deploy your very own scalable, high-performance, production-ready infrastructure.
Expand Down
8 changes: 5 additions & 3 deletions cmd/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"path"
"strings"

"github.com/commitdev/zero/internal/config/globalconfig"
"github.com/commitdev/zero/internal/config/projectconfig"
"github.com/commitdev/zero/internal/constants"
"github.com/commitdev/zero/internal/generate"
Expand Down Expand Up @@ -47,9 +46,12 @@ func Create(dir string, createConfigPath string) {
if projectConfig.ShouldPushRepositories {
flog.Infof(":up_arrow: Done Rendering - committing repositories to version control.")

globalConfig := globalconfig.GetProjectCredentials(projectConfig.Name)
for _, module := range projectConfig.Modules {
vcs.InitializeRepository(module.Files.Repository, globalConfig.GithubResourceConfig.AccessToken)
err, githubApiKey := projectconfig.ReadVendorCredentialsFromModule(module, "github")
if err != nil {
flog.Errorf(err.Error())
}
vcs.InitializeRepository(module.Files.Repository, githubApiKey)
}
} else {
flog.Infof(":up_arrow: Done Rendering - you will need to commit the created projects to version control.")
Expand Down
79 changes: 79 additions & 0 deletions docs/module-definition.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
## Module Definition: `zero-module.yml`
This file is the definition of a Zero module. It contains a list of all the required parameters to be able to prompt a user for choices during `zero init`, information about how to template the contents of the module during `zero create`, and the information needed for the module to run (`zero apply`).
It also declares the module's dependencies to determine the order of execution in relation to other modules.

| Parameters | type | Description |
|---------------|-----------------|--------------------------------------------------|
| `name` | string | Name of module |
| `description` | string | Description of the module |
| `template` | template | default settings for templating out the module |
| `author` | string | Author of the module |
| `icon` | string | Path to logo image |
| `parameters` | list(Parameter) | Parameters to prompt users |


### Template
| Parameters | Type | Description |
|--------------|---------|-----------------------------------------------------------------------|
| `strictMode` | boolean | whether strict mode is enabled |
| `delimiters` | tuple | A tuple of open delimiter and ending delimiter eg: `<%` and `%>` |
| `inputDir` | string | Folder to template from the module, becomes the module root for users |
| `outputDir` | string | local directory name for the module, gets commited to version control |

### Condition(module)
Module conditions are considered during template phase (`zero create`), based on parameters supplied from project-definition,
modules can decide to have specific files ignored from the user's module. For example if user picks `userAuth: no`, we can ignore the auth resources via templating.

| Parameters | Type | Description |
|--------------|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------------|
| `action` | enum(string) | type of condition, currently supports [`ignoreFile`] |
| `matchField` | string | Allows you to condition prompt based on another parameter's value |
| `WhenValue` | string | Matches for this value to satisfy the condition |
| `data` | list(string) | Supply extra data for condition to run `ignoreFile`: provide list of paths (file or directory path) to omit from module when condition is satisfied |

### Parameter:
Parameter defines the prompt during zero-init.
There are multiple ways of obtaining the value for each parameter.
Parameters may have `Conditions` and must be fulfilled when supplied, otherwise it skips the field entirely.

The precedence for different types of parameter prompts are as follow.
1. Execute
2. type: specific ways of obtaining values (in AWS credential case it will set 2 values to the map)
3. value: directly assigns a value to a parameter
4. prompt: requires users to select an option OR input a string
Note: Default is supplied as the starting point of the user's manual input (Not when value passed in is empty)

| Parameters | Type | Description |
|-----------------------|-----------------|---------------------------------------------------------------------------------------------------------------------------|
| `field` | string | key to store result for project definition |
| `label` | string | displayed name for the prompt |
| `options` | list(string) | A list of values for users to pick from |
| `default` | string | Defaults to this value during prompt |
| `value` | string | Skips prompt entirely when set |
| `info` | string | Displays during prompt as extra information guiding user's input |
| `fieldValidation` | Validation | Validations for the prompt value |
| `type` | enum(string) | Built in custom prompts: currently supports [`AWSProfilePicker`] |
| `execute` | string | executes commands and takes stdout as prompt result |
| `omitFromProjectFile` | bool | Field is skipped from adding to project definition |
| `conditions` | list(Condition) | Conditions for prompt to run, if supplied all conditions must pass |
| `envVarName` | string | During `zero apply` parameters are available as env-vars, defaults to field name but can be overwritten with `envVarName` |

### Condition(paramters)
Parameters conditions are considered while running user prompts, prompts are
executed in order of the yml, and will be skipped if conditions are not satisfied.
For example if a user decide to not use circleCI, condition can be used to skip the circleCI_api_key prompt.

| Parameters | Type | Description |
|--------------|--------------|-------------------------------------------------------------------|
| `action` | enum(string) | type of condition, currently supports [`KeyMatchCondition`] |
| `matchField` | string | Allows you to condition prompt based on another parameter's value |
| `WhenValue` | string | Matches for this value to satisfy the condition |
| `data` | list(string) | Supply extra data for condition to run |

### Validation
Copy link
Contributor

Choose a reason for hiding this comment

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

Missing info on some of the other things like the contitions and template fields related to templating.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

definitely good call to add this documentation, I looked at conditions and thought oh its there, but theres actually 2 types

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah the naming might be a bit confusing..


| Parameters | type | Description |
|----------------|--------------|-------------------------------------|
| `type` | enum(string) | Currently supports [`regex`] |
| `value` | string | Regular expression string |
| `errorMessage` | string | Error message when validation fails |
27 changes: 27 additions & 0 deletions docs/project-definition.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
### Project Definition: `zero-project.yml`
Each project is defined by this file. This manifest reflects all the options a user chose during the `zero init` step. It defines which modules are part of the project, each of their parameters, and is the source of truth for the templating (`zero create`) and provision (`zero apply`) steps.

_Note: This file contains credentials, so make sure it is not shared with others._

| Parameters | Type | Description |
|--------------------------|--------------|------------------------------------------------|
| `name` | string | name of the project |
| `shouldPushRepositories` | boolean | whether to push the modules to version control |
| `modules` | map(modules) | a map containing modules of your project |


### Modules
| Parameters | Type | Description |
|--------------|-----------------|-------------------------------------------------------------------------|
| `parameters` | map(string) | key-value map of all the parameters to run the module |
| `files` | File | Stores information such as source-module location and destination |
| `dependsOn` | list(string) | a list of dependencies that should be fulfilled before this module |
| `conditions` | list(condition) | conditions to apply while templating out the module based on parameters |

### Condition
| Parameters | Type | Description |
|--------------|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------------|
| `action` | enum(string) | type of condition, currently supports [`ignoreFile`] |
| `matchField` | string | Allows you to condition prompt based on another parameter's value |
| `WhenValue` | string | Matches for this value to satisfy the condition |
| `data` | list(string) | Supply extra data for condition to run `ignoreFile`: provide list of paths (file or directory path) to omit from module when condition is satisfied |
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ require (
github.com/matryer/is v1.3.0 // indirect
github.com/mattn/go-colorable v0.1.2 // indirect
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/pkg/errors v0.9.1
github.com/sirupsen/logrus v1.2.0
github.com/spf13/cobra v0.0.6
github.com/stretchr/testify v1.5.1
Expand Down
15 changes: 8 additions & 7 deletions internal/apply/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (
"github.com/commitdev/zero/internal/util"
"github.com/hashicorp/terraform/dag"

"github.com/commitdev/zero/internal/config/globalconfig"
"github.com/commitdev/zero/internal/config/projectconfig"
"github.com/commitdev/zero/pkg/util/exit"
"github.com/commitdev/zero/pkg/util/flog"
Expand Down Expand Up @@ -87,11 +86,8 @@ func applyAll(dir string, projectConfig projectconfig.ZeroProjectConfig, applyEn
exit.Fatal("Failed to load module config, credentials cannot be injected properly")
}

// Get project credentials for the makefile
credentials := globalconfig.GetProjectCredentials(projectConfig.Name)
credentialEnvs := credentials.SelectedVendorsCredentialsAsEnv(modConfig.RequiredCredentials)
envList = util.AppendProjectEnvToCmdEnv(mod.Parameters, envList)
envList = util.AppendProjectEnvToCmdEnv(credentialEnvs, envList)
envVarTranslationMap := modConfig.GetParamEnvVarTranslationMap()
envList = util.AppendProjectEnvToCmdEnv(mod.Parameters, envList, envVarTranslationMap)
flog.Debugf("Env injected: %#v", envList)
flog.Infof("Executing apply command for %s...", modConfig.Name)
util.ExecuteCommand(exec.Command("make"), modulePath, envList)
Expand Down Expand Up @@ -160,7 +156,12 @@ func summarizeAll(dir string, projectConfig projectconfig.ZeroProjectConfig, app
}
flog.Debugf("Loaded module: %s from %s", name, modulePath)

envList = util.AppendProjectEnvToCmdEnv(mod.Parameters, envList)
modConfig, err := module.ParseModuleConfig(modulePath)
if err != nil {
exit.Fatal("Failed to load module config, credentials cannot be injected properly")
}
envVarTranslationMap := modConfig.GetParamEnvVarTranslationMap()
envList = util.AppendProjectEnvToCmdEnv(mod.Parameters, envList, envVarTranslationMap)
flog.Debugf("Env injected: %#v", envList)
util.ExecuteCommand(exec.Command("make", "summary"), modulePath, envList)
return nil
Expand Down
7 changes: 7 additions & 0 deletions internal/apply/apply_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,11 @@ func TestApply(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, "baz: qux\n", string(content))
})

t.Run("Zero apply honors the envVarName overwrite from module definition", func(t *testing.T) {
content, err := ioutil.ReadFile(filepath.Join(tmpDir, "project1/feature.out"))
assert.NoError(t, err)
assert.Equal(t, "envVarName of viaEnvVarName: baz\n", string(content))
})

}
183 changes: 0 additions & 183 deletions internal/config/globalconfig/global_config.go

This file was deleted.

Loading