Skip to content

Commit

Permalink
Add support for all variable scoping types
Browse files Browse the repository at this point in the history
  • Loading branch information
asos-leslielintott committed Jun 5, 2019
1 parent 98e42b5 commit 037e5bd
Show file tree
Hide file tree
Showing 6 changed files with 286 additions and 154 deletions.
33 changes: 22 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,19 @@ Find and replace Octopus Deploy formatted variables (`#{variablevalue}`) in depl
- All files in folder `scripts`, replacing values for the environment named `DevTest`:

```sh
$ octopipe sub scripts/ DevTest
$ octopipe sub scripts/ 'Environment=DevTest'
```
- Specific file(s) in folder `scripts`, replacing values for the environment named `Pre-Production`:
```sh
$ octopipe sub -f deploystep1.ps1 scripts/ Pre-Production
$ octopipe sub -f deploystep1.ps1,deploystep2.sh scripts/ Pre-Production
$ octopipe sub -f deploystep1.ps1 scripts/ 'Environment=Pre-Production'
```
- Specific file(s) in folder `scripts`, replacing values for the environment named `Pre-Production` and the machine named `deploynode01`:
```sh
$ octopipe sub -f deploystep1.ps1,deploystep2.sh scripts/ 'Environment=Pre-Production,Machine=deploynode01'
```
- Only check and report back for all files in folder `scripts`, those variables which have no matching values in **octopipe.yaml** for environment `Production`:
```sh
$ octopipe sub -c scripts/ Production
$ octopipe sub -c scripts/ 'Environment=Production'
```

Before subbing, octopipe creates a backup of each file in the same location with `.octopipe` appended to the name. After making changes to your scripts, use your favourite merge tool to merge in your changes and bring back the unsubbed variables
Expand All @@ -60,32 +63,40 @@ Write project configuration data to the server:
$ octopipe put
```
### Yaml schema

**_For interoperability with the Octopus API, types are case sensitive_**

```Yaml
project:
name: Octopipe.Test.Project # the name of the project (will create new if the slug does not resolve)
description: Project for testing the Octopipe tool # project description
group: My Octopus Project Group # the Octopus Project Group this project will belong to
lifecycle: Default.Lifecycle # the Octopus Lifecycle for the Deployment Process
tenanted: TenantedOrUntenanted # if not specified in octopipe.yaml, the default is Untenanted. Valid tenancy types are Tenanted, Untenanted, TenantedOrUntenanted

variables:
- name: processName
value: kubelet # 'value' for a single variable value

- name: environmentName
values: # 'values' for a variable with environment scopings (separated by comma), 'default' being an optional unscoped value
DevTest,Pre-Production: devtest
Production: pd
default: env
scopedValues: # 'scopedValues' for a variable with scopings
- value: devtest
Environment: DevTest,Pre-Production
- value: pd
Environment: Production
TenantTag: Azure Regions/West Europe # valid scope types are Environment, Machine, TenantTag, Channel, Action, Role
Role: web-server
- value: env # default unscoped value for the variable

- name: deployAccount
value: azureserviceprincipal-azuresuba
type: AzureAccount # types supported are AzureAccount, AWSAccount, Certificate, String (default)
value: azureserviceprincipal-azuresub
type: AzureAccount # valid variable types are AzureAccount, AWSAccount, Certificate, String (default)
description: Account used for deployment to the subscription # variable description

process:
steps:
- name: Init
type: PowerShell # types supported are PowerShell, Bash, CSharp, FSharp
type: PowerShell # valid script types are PowerShell, Bash, CSharp, FSharp
file: scripts/init.ps1 # file location relative to octopipe.yaml

- name: Deploy Kubernetes
Expand Down
110 changes: 70 additions & 40 deletions cmd/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ import (
"os"
"strings"

"github.com/spf13/cobra"
"gopkg.in/yaml.v2"

"github.com/spf13/cobra"
)

// createCmd represents the create command
Expand Down Expand Up @@ -67,56 +68,77 @@ octopipe create -i My.Octopus.Project
tl, _ := getLifecycle(l, "", p.LifecycleID)
tg, _ := getProjectGroup(g, "", p.ProjectGroupID)

ds := v.ScopeValues.makeScopeDataSet()

// Variables
vss := []variable{}
exist := false

for _, vs := range v.Variables {
exist = false
tv := variable{}
for i, av := range vss {
if av.Name == vs.Name {
exist := false
for i, sv := range vss {
if sv.Name == vs.Name {
exist = true
senvs := ""
for _, es := range vs.Scope["Environment"] {
_, envName, _ := v.ScopeValues.getEnvironment("", es)
senvs = senvs + envName + ","
}
senvs = strings.TrimRight(senvs, ",")
if len(av.Values) == 0 {
av.Values = make(map[string]string)
tv := variable{}
tv.Name = vs.Name
tv.Description = vs.Description
if vs.Type != "String" {
tv.Type = vs.Type
}
av.Values[senvs] = vs.Value
av.Values["default"] = av.Value

nav := variable{
Values: av.Values,
Name: av.Name,
Type: av.Type,
Description: av.Description,

values := sv.ScopedValues

if vs.Scope != nil {
scvalue := make(map[string]string)
for sc, es := range vs.Scope {
_, scopeNames, _ := v.ScopeValues.getScope(ds, "", es, sc)
j := ""
for _, sc := range scopeNames {
j = j + sc + ","
}
j = strings.TrimRight(j, ",")
scvalue[sc] = j
}
scvalue["value"] = vs.Value
values = append(values, scvalue)
} else {
scvalue := make(map[string]string)
scvalue["value"] = vs.Value
values = append(values, scvalue)
}

vss[i] = nav
tv.ScopedValues = values

vss[i] = tv

break
}
}
if exist {
continue
}

tv := variable{}
tv.Name = vs.Name
tv.Description = vs.Description
tv.Type = vs.Type
if vs.Type != "String" {
tv.Type = vs.Type
}

if len(vs.Scope) != 0 {
values := make(map[string]string)
senvs := ""
for _, es := range vs.Scope["Environment"] {
_, envName, _ := v.ScopeValues.getEnvironment("", es)
senvs = senvs + envName + ","
values := make([]map[string]string, 0)
scvalue := make(map[string]string)
for sc, es := range vs.Scope {
_, scopeNames, _ := v.ScopeValues.getScope(ds, "", es, sc)
j := ""
for _, sc := range scopeNames {
j = j + sc + ","
}
j = strings.TrimRight(j, ",")
scvalue[sc] = j
}
senvs = strings.TrimRight(senvs, ",")
values[senvs] = vs.Value
tv.Values = values
scvalue["value"] = vs.Value
values = append(values, scvalue)
tv.ScopedValues = values
} else {
tv.Value = vs.Value
}
Expand Down Expand Up @@ -166,6 +188,7 @@ octopipe create -i My.Octopus.Project

op.Project.Name = p.Name
op.Project.Description = p.Description
op.Project.Tenanted = p.TenantedDeploymentMode
op.Project.Lifecycle = tl.Name
op.Project.ProjectGroup = tg.Name

Expand Down Expand Up @@ -196,13 +219,19 @@ octopipe create -i My.Octopus.Project
logAndExitf("octopipe.yaml already exists, will not overwrite")
}

values := make(map[string]string)
values["Dev"] = "aks-dev-rg"
values["Test"] = "aks-test-rg"
values := make([]map[string]string, 0)
values1 := make(map[string]string)
values2 := make(map[string]string)
values1["Environment"] = "Dev,Test"
values1["value"] = "aks-devtest-rg"
values2["Environment"] = "Production"
values2["Machine"] = "deploynode01"
values2["value"] = "aks-pd-rg"
values = append(values, values1, values2)

variables := make([]variable, 0)
variables = append(variables, variable{Name: "AksName", Value: "aks-01"})
variables = append(variables, variable{Name: "AksResourceGroupName", Values: values})
variables = append(variables, variable{Name: "AksResourceGroupName", ScopedValues: values})
variables = append(variables, variable{Name: "AzureUsername", Value: "[email protected]"})
variables = append(variables, variable{Name: "AzureTenantId", Value: "1234-5678-abcd-efgh"})
variables = append(variables, variable{Name: "variable3", Value: "octopusdeploy-account", Type: "AzureAccount", Description: "Account used for deployments"})
Expand All @@ -217,6 +246,7 @@ octopipe create -i My.Octopus.Project
Description: "My Octopus Project",
ProjectGroup: "Octopus Project Group",
Lifecycle: "OctopusProject.Lifecycle",
Tenanted: "TenantedOrUntenanted",
},
Variables: variables,
Process: process{
Expand All @@ -225,11 +255,11 @@ octopipe create -i My.Octopus.Project
}

inits := `$credential = New-Object PSCredential -ArgumentList @("#{AzureUsername}", ("#{AzurePassword}" | ConvertTo-SecureString -Force -AsPlainText))
Login-AzAccount -ServicePrincipal -Tenant "#{AzureTenantId}" -Credential $credential
`
Login-AzAccount -ServicePrincipal -Tenant "#{AzureTenantId}" -Credential $credential
`
deps := `az aks create -g "#{AksResourceGroupName}" -n "#{AksName}" --node-count 5
$cluster = az aks show -n "#{AksName}" -g "#{AksResourceGroupName}" | ConvertFrom-Json
Write-Host $cluster.Status`
$cluster = az aks show -n "#{AksName}" -g "#{AksResourceGroupName}" | ConvertFrom-Json
Write-Host $cluster.Status`

_, err := os.Stat("scripts")
if os.IsNotExist(err) {
Expand Down
38 changes: 34 additions & 4 deletions cmd/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ func verifyVariableType(svtype variable) (vtype string, err error) {

var errorstring string
for _, vvar := range validVariableTypes {
errorstring = errorstring + vvar + ","
errorstring = errorstring + vvar + ", "
}
errorstring = strings.TrimSuffix(errorstring, ",")
errorstring = strings.TrimSuffix(errorstring, ", ")
return "", errors.New("Variable type '" + svtype.Type + "' for variable '" + svtype.Name + "' is not valid. Valid types are " + errorstring)
}

Expand All @@ -87,12 +87,42 @@ func verifySyntaxType(satype step) (atype string, err error) {

var errorstring string
for _, vsyn := range validScriptSyntaxTypes {
errorstring = errorstring + vsyn + ","
errorstring = errorstring + vsyn + ", "
}
errorstring = strings.TrimSuffix(errorstring, ",")
errorstring = strings.TrimSuffix(errorstring, ", ")
return "", errors.New("Script syntax type '" + satype.Type + "' for process step '" + satype.Name + "' is not valid. Syntax types are case sensitive. Valid types are " + errorstring)
}

func verifyTenancyType(tp project) (ap string, err error) {
for _, validType := range validTenancyTypes {
if validType == tp.Tenanted {
return tp.Tenanted, nil
}
}

var errorstring string
for _, vsyn := range validTenancyTypes {
errorstring = errorstring + vsyn + ", "
}
errorstring = strings.TrimSuffix(errorstring, ", ")
return "", errors.New("Tenancy type '" + tp.Tenanted + "' for project '" + tp.Name + "' is not valid. Valid tenancy types are " + errorstring)
}

func verifyScopeType(sctype string) (vtype string, err error) {
for _, validType := range validScopeTypes {
if validType == sctype {
return sctype, nil
}
}

var errorstring string
for _, vsc := range validScopeTypes {
errorstring = errorstring + vsc + ", "
}
errorstring = strings.TrimSuffix(errorstring, ", ")
return "", errors.New("Scope type '" + sctype + "' is invalid. Valid scope types are " + errorstring)
}

func getProjectSlug(name string) (slug string) {
name = strings.ToLower(name)
regex := regexp.MustCompile("[^0-9A-Za-z]+")
Expand Down
Loading

0 comments on commit 037e5bd

Please sign in to comment.