Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue #8: Support capturing output artifacts from dynamic fixtures #9

Merged
merged 1 commit into from
Aug 23, 2017
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
42 changes: 42 additions & 0 deletions .argo/test-yamls/fixtures-dynamic.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,45 @@ args: ["
resources:
cpu_cores: 0.05
mem_mib: 64

---
type: workflow
version: 1
name: test-fixtures-dynamic-outputs
description: Workflow which exports artifacts produced by dynamic fixtures
inputs:
parameters:
COMMIT:
default: "%%session.commit%%"
REPO:
default: "%%session.repo%%"
fixtures:
- DYN_FIX_WITH_OUTPUTS:
template: test-dynamic-fixture-container-with-outputs
steps:
- WEB-CLIENT-INLINED:
image: alpine:latest
command: [sh, -c]
args: ["sleep 60"]
resources:
cpu_cores: 0.05
mem_mib: 64
outputs:
artifacts:
WF_OUTPUTS:
from: "%%fixtures.DYN_FIX_WITH_OUTPUTS.outputs.artifacts.BIN-DIR%%"

---
type: container
version: 1
name: test-dynamic-fixture-container-with-outputs
image: alpine:latest
command: [sh, -c]
args: ["sleep 999999"]
resources:
cpu_cores: 0.05
mem_mib: 64
outputs:
artifacts:
BIN-DIR:
path: /bin
21 changes: 19 additions & 2 deletions saas/axops/src/applatix.io/axops/service/preprocess.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,10 +221,27 @@ func buildReplaceMap(tmpl EmbeddedTemplateIf, arguments template.Arguments) (map
}
}

// For any immediate children of this template, replace usages of %%steps.STEPNAME.outputs.artifacts.ARTNAME%% with concrete services IDs.
// This is only needed with workflows, since containers don't have children, and deployments do not use outputs from child containers
// For any immediate children of this template, replace usages of %%steps.STEPNAME.outputs.artifacts.ARTNAME%% or
// %%fixtures.FIXNAME.outputs.artifacts.ARTNAME%% with concrete services IDs. This is only needed with workflows,
// since containers don't have children, and deployments do not use outputs from child containers
if tmpl.GetType() == template.TemplateTypeWorkflow {
wft := tmpl.(*EmbeddedWorkflowTemplate)
for _, parallelFixtures := range wft.Fixtures {
for fixRefName, ftr := range parallelFixtures {
if !ftr.IsDynamicFixture() {
continue
}
outputs := ftr.Template.GetOutputs()
if outputs == nil {
continue
}
// The following converts %%fixtures.STEP1.outputs.artifacts.ARTNAME%% to %%service.service_id.outputs.artifacts.ARTNAME%%
for artName := range outputs.Artifacts {
serviceOutputRef := fmt.Sprintf("%%%%service.%s.outputs.artifacts.%s%%%%", ftr.Id, artName)
replaceMap[fmt.Sprintf("%%%%fixtures.%s.outputs.artifacts.%s%%%%", fixRefName, artName)] = &serviceOutputRef
}
}
}
for _, parallelSteps := range wft.Steps {
for stepName, step := range parallelSteps {
if step.Template == nil {
Expand Down
2 changes: 1 addition & 1 deletion saas/common/src/applatix.io/template/param.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const (
var (
paramNameRegexStr = "[-0-9A-Za-z_]+"
paramNameRegex = regexp.MustCompile("^[-0-9A-Za-z_]+$")
ouputArtifactRegexp = regexp.MustCompile(`^%%steps\.` + paramNameRegexStr + `\.outputs\.artifacts\.` + paramNameRegexStr + `%%$`)
ouputArtifactRegexp = regexp.MustCompile(`^%%(steps|fixtures)\.` + paramNameRegexStr + `\.outputs\.artifacts\.` + paramNameRegexStr + `%%$`)
VarRegex = regexp.MustCompile("%%[-0-9A-Za-z_]+(\\.[-0-9A-Za-z_]+)*%%")
varRegexExact = regexp.MustCompile("^%%[-0-9A-Za-z_]+(\\.[-0-9A-Za-z_]+)*%%$")
listExpansionParamRegex = regexp.MustCompile("\\$\\$\\[(.*)\\]\\$\\$")
Expand Down
25 changes: 22 additions & 3 deletions saas/common/src/applatix.io/template/workflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,10 @@ func (tmpl *WorkflowTemplate) ValidateContext(context *TemplateBuildContext) *ax
// the previous step group to the current scope
scopedParams := tmpl.parametersInScope()

// dynFixtureOutputs keeps track of any outputs produced by dynamic fixtures.
// We will add this to the scope after all steps complete
dynFixtureOutputs := paramMap{}

// Verify any dynamic fixtures. Template references must be container type
for i, parallelFixtures := range tmpl.Fixtures {
for fixRefName, ftr := range parallelFixtures {
Expand All @@ -190,6 +194,15 @@ func (tmpl *WorkflowTemplate) ValidateContext(context *TemplateBuildContext) *ax
if axErr != nil {
return axerror.ERR_AXDB_INVALID_PARAM.NewWithMessagef("fixtures[%d].%s: %v", i, fixRefName, axErr)
}
if ctrTemplate.Outputs != nil {
for artRefName := range ctrTemplate.Outputs.Artifacts {
p := param{
name: fmt.Sprintf("fixtures.%s.outputs.artifacts.%s", fixRefName, artRefName),
paramType: paramTypeArtifact,
}
dynFixtureOutputs[p.name] = p
}
}
}
}

Expand Down Expand Up @@ -271,6 +284,12 @@ func (tmpl *WorkflowTemplate) ValidateContext(context *TemplateBuildContext) *ax
}
}

// Add dynamic fixtures outputs to the scope
axErr := scopedParams.merge(dynFixtureOutputs)
if axErr != nil {
return axErr
}

// Do one last validation of all parameters used in the template
usedParams, axErr := tmpl.usedParameters()
if axErr != nil {
Expand All @@ -281,8 +300,8 @@ func (tmpl *WorkflowTemplate) ValidateContext(context *TemplateBuildContext) *ax
return axErr
}

// See if this workflow is exporting any artifacs. If so, verify that 'from' is
// referencing a valid step, and that step has expected artifact with the name.
// See if this workflow is exporting any artifacts. If so, verify that 'from' is
// referencing a valid step or fixture, and that step has expected artifact with the name.
if tmpl.Outputs != nil && tmpl.Outputs.Artifacts != nil {
for refName, art := range tmpl.Outputs.Artifacts {
if art.Path != "" {
Expand All @@ -292,7 +311,7 @@ func (tmpl *WorkflowTemplate) ValidateContext(context *TemplateBuildContext) *ax
return axerror.ERR_API_INVALID_PARAM.NewWithMessagef("outputs.artifacts.%s.from is required", refName)
}
if !ouputArtifactRegexp.MatchString(art.From) {
return axerror.ERR_API_INVALID_PARAM.NewWithMessagef("outputs.artifacts.%s.from invalid format '%s'. expected format: '%%%%steps.<step_name>.outputs.artifacts.<artifact_name>%%%%'", refName, art.From)
return axerror.ERR_API_INVALID_PARAM.NewWithMessagef("outputs.artifacts.%s.from invalid format '%s'. expected format: '%%%%(steps|fixtures).<REF_NAME>.outputs.artifacts.<ARTIFACT_NAME>%%%%'", refName, art.From)
}
pName := strings.Trim(art.From, "%")
_, ok := scopedParams[pName]
Expand Down