Skip to content
This repository was archived by the owner on Apr 13, 2020. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
8f322dc
manage identity test docs
NathanielRose Mar 31, 2020
f7efff2
fixing tf module
NathanielRose Mar 31, 2020
c3b1902
Merge branch 'master' of github.com:CatalystCode/spk into nate.infra.…
NathanielRose Mar 31, 2020
a650e51
code planning
NathanielRose Apr 2, 2020
1c0cc3c
Merge branch 'master' of github.com:CatalystCode/spk into nate.infra.…
NathanielRose Apr 2, 2020
e62bfa6
Merge branch 'master' of github.com:CatalystCode/spk into nate.infra.…
NathanielRose Apr 7, 2020
c469120
init relative path support
NathanielRose Apr 7, 2020
c0103fe
updated parsing logic
NathanielRose Apr 7, 2020
453a4b3
additional changes
NathanielRose Apr 7, 2020
63d97c4
resolving generate.ts conflicts
NathanielRose Apr 7, 2020
685bba2
Merge branch 'master' of github.com:CatalystCode/spk into nate.infra.…
NathanielRose Apr 8, 2020
742097c
updated generated
NathanielRose Apr 8, 2020
28b4f7e
add docs for local paths
NathanielRose Apr 8, 2020
1a6ea6f
Merge branch 'master' of github.com:CatalystCode/spk into nate.infra.…
NathanielRose Apr 8, 2020
2998e62
merging changes
NathanielRose Apr 8, 2020
252eaaa
Merge branch 'master' into nate.infra.relative-paths
NathanielRose Apr 9, 2020
219bfda
Merge branch 'master' into nate.infra.relative-paths
NathanielRose Apr 9, 2020
1cb9030
updated changes
NathanielRose Apr 9, 2020
936d092
Merge branch 'nate.infra.relative-paths' of github.com:NathanielRose/…
NathanielRose Apr 9, 2020
158962e
Merge branch 'master' into nate.infra.relative-paths
NathanielRose Apr 9, 2020
b3f0e9e
Merge branch 'master' into nate.infra.relative-paths
dennisseah Apr 9, 2020
4074e22
dennis updates
NathanielRose Apr 9, 2020
cf2506a
Merge branch 'nate.infra.relative-paths' of github.com:NathanielRose/…
NathanielRose Apr 9, 2020
6966c2b
Merge branch 'master' into nate.infra.relative-paths
NathanielRose Apr 9, 2020
2cd1d79
add unit tests
dennisseah Apr 9, 2020
cef77f7
Merge branch 'master' into nate.infra.relative-paths
NathanielRose Apr 10, 2020
f3a0cc2
Merge branch 'master' into nate.infra.relative-paths
NathanielRose Apr 10, 2020
4b90ab0
remove unwanted eslint disable and correct doc
dennisseah Apr 10, 2020
91572e4
Merge branch 'master' into nate.infra.relative-paths
dennisseah Apr 10, 2020
873b460
Merge branch 'master' into nate.infra.relative-paths
NathanielRose Apr 10, 2020
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
78 changes: 78 additions & 0 deletions guides/cloud-infra-management.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,81 @@ following:
- **Using arguments** - Pass in your formatted source url for your private AzDO
repo with the PAT and arbitrary username specified. Example
`spk infra scaffold --name fabrikam --source https://spk:{$PAT}@dev.azure.com/microsoft/spk/_git/infra_repo --version master --template cluster/environments/azure-single-keyvault`

## Terraform Modules with Local Paths

`spk` now supports Terraform source templates that use a
[local repository path](https://www.terraform.io/docs/modules/sources.html#local-paths)
for references to modules. To obtain the modules for further teraform
deployment, `spk generate` will shape a module source value from the `source`,
`tempate`, and `version` arguments passed.

**Example:**

Template Main.tf

```tf
"aks-gitops" {
source = "../../azure/aks-gitops"
acr_enabled = var.acr_enabled
agent_vm_count = var.agent_vm_count
agent_vm_size = var.agent_vm_size
cluster_name = var.cluster_name
dns_prefix = var.dns_prefix
flux_recreate = var.flux_recreate
gc_enabled = var.gc_enabled
gitops_ssh_url = var.gitops_ssh_url
gitops_ssh_key = var.gitops_ssh_key
gitops_path = var.gitops_path
gitops_poll_interval = var.gitops_poll_interval
gitops_label = var.gitops_label
gitops_url_branch = var.gitops_url_branch
ssh_public_key = var.ssh_public_key
resource_group_name = data.azurerm_resource_group.cluster_rg.name
service_principal_id = var.service_principal_id
service_principal_secret = var.service_principal_secret
vnet_subnet_id = tostring(element(module.vnet.vnet_subnet_ids, 0))
service_cidr = var.service_cidr
dns_ip = var.dns_ip
docker_cidr = var.docker_cidr
network_plugin = var.network_plugin
network_policy = var.network_policy
oms_agent_enabled = var.oms_agent_enabled
kubernetes_version = var.kubernetes_version
}`;

```

SPK-generated Main.tf

```tf
"aks-gitops" {
source = "github.com/microsoft/bedrock?ref=master//cluster/azure/aks-gitops/"
acr_enabled = var.acr_enabled
agent_vm_count = var.agent_vm_count
agent_vm_size = var.agent_vm_size
cluster_name = var.cluster_name
dns_prefix = var.dns_prefix
flux_recreate = var.flux_recreate
gc_enabled = var.gc_enabled
gitops_ssh_url = var.gitops_ssh_url
gitops_ssh_key = var.gitops_ssh_key
gitops_path = var.gitops_path
gitops_poll_interval = var.gitops_poll_interval
gitops_label = var.gitops_label
gitops_url_branch = var.gitops_url_branch
ssh_public_key = var.ssh_public_key
resource_group_name = data.azurerm_resource_group.cluster_rg.name
service_principal_id = var.service_principal_id
service_principal_secret = var.service_principal_secret
vnet_subnet_id = tostring(element(module.vnet.vnet_subnet_ids, 0))
service_cidr = var.service_cidr
dns_ip = var.dns_ip
docker_cidr = var.docker_cidr
network_plugin = var.network_plugin
network_policy = var.network_policy
oms_agent_enabled = var.oms_agent_enabled
kubernetes_version = var.kubernetes_version
}`;

```
88 changes: 86 additions & 2 deletions src/commands/infra/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { copyTfTemplate } from "./scaffold";
import { build as buildError, log as logError } from "../../lib/errorBuilder";
import { errorStatusCode } from "../../lib/errorStatusCode";
import { exec } from "../../lib/shell";
import { file } from "mock-fs";

interface CommandOptions {
project: string | undefined;
Expand Down Expand Up @@ -368,7 +369,7 @@ export const generateTfvars = (
* Checks if an spk.tfvars already exists
*
* @param generatedPath Path to the spk.tfvars file
* @param tfvarsFilename Name of .tfvars file
* @param tfvarsFilename Name of .tfvars fileb
*/
export const checkTfvars = (
generatedPath: string,
Expand Down Expand Up @@ -501,6 +502,60 @@ export const singleDefinitionGeneration = async (
await copyTfTemplate(templatePath, childDirectory, true);
};

/**
* Checks to see if module sources are local
*
* @param tfFile path to the terraform file in child directory
*/
export const checkModuleSource = (tfData: string): boolean => {
// Check if the file string matches an instance of a module source value as a local path
const matches = tfData.match(/^\s*source\s+=\s+["'](\.\.?\/[^"']*)["']$/gm);
if (matches != null) {
return true;
}
return false;
};

/**
* Checks to see if module sources are local
*
* @param sourceConfig Array of source configuration
*/
export const moduleSourceModify = async (
fileSource: SourceInformation,
tfData: string
): Promise<string> => {
let result = "";
const sourceFolder = getSourceFolderNameFromURL(fileSource.source);
const sourcePath = path.join(spkTemplatesPath, sourceFolder);
// Split data by line and iterate
for (let line of tfData.split(/\r?\n/)) {
// Match line to expected module source format
if (line.match(/^\s*source\s+=\s+["'](\.\.?\/[^"']*)["']$/gm) != null) {
// Split the line into segments, the third element is the source value
const splitLine = line.split(/\s+/);
// Filter on module source value
const moduleSource = new RegExp(splitLine[3].replace(/['"]+/g, ""), "g");
// Get relative path of terraform module local to the repo
const repoModulePath = await simpleGit(
path.join(
sourcePath,
fileSource.template,
splitLine[3].replace(/["']/g, "")
)
).revparse(["--show-prefix"]);
// Concatendate the Git URL with munged data
const gitSource = fileSource.source
.replace(/(^\w+:|^)\/\//g, "")
.concat("?ref=", fileSource.version, "//", repoModulePath);
// Replace the line
line = line.replace(moduleSource, gitSource);
}
result += line + "\n";
}
return result;
};

/**
* Creates "generated" directory if it does not already exists
*
Expand Down Expand Up @@ -543,7 +598,6 @@ export const generateConfig = async (
createGenerated(parentDirectory);
createGenerated(childDirectory);
}

combineVariable(
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
parentInfraConfig.variables!,
Expand Down Expand Up @@ -576,6 +630,36 @@ export const generateConfig = async (
templatePath
);
}
// TODO: Function to check for relative paths:
// CheckLocal: check source value, is value = ./ or ../ (Local syntax)
// ModifyLocal: munge url from YAML, apply url to relative source path
// Throw exception if failed
const files = await fsExtra.readdirSync(childDirectory, "utf-8");
// Check to test outsource: terraform registry,
// Iterate through 'TF' files / Parse of tf files? (Code Coverage?)
for (const file of files) {
if (path.extname(file) === ".tf") {
const tfData = fsExtra.readFileSync(
path.join(childDirectory, file),
"utf8"
);
const containsLocalSource = await checkModuleSource(tfData);
if (containsLocalSource) {
logger.info(
`Local relative paths for module source values detected in terraform file: ${file}`
);
const mungeData = await moduleSourceModify(sourceConfig, tfData);
logger.info(
`Terraform File: ${file} local module source values successfully converted to git source paths`
);
fsExtra.writeFileSync(
path.join(childDirectory, file),
mungeData,
"utf8"
);
}
}
}
};

export const execute = async (
Expand Down