2019-11-13 15:43:53 +02:00
|
|
|
package helper
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/SAP/jenkins-library/pkg/config"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
)
|
|
|
|
|
2020-04-24 11:21:33 +02:00
|
|
|
var expectedResultDocument string = "# testStep\n\n\t## Description \n\nLong Test description\n\n\t\n\t## Prerequisites\n\t\n\tnone\n\n\t\n\t\n\t## Parameters\n\n| name | mandatory | default | possible values |\n| ------- | --------- | ------- | ------- |\n | param0 | No | val0 | |\n | param1 | No | | |\n | param2 | Yes | | |\n \n\n## Details\n\n * ` param0 ` : param0 description \n * ` param1 ` : param1 description \n * ` param2 ` : param1 description \n \n\t\n\t## We recommend to define values of step parameters via [config.yml file](../configuration.md). \n\nIn following sections of the config.yml the configuration is possible:\n\n| parameter | general | step/stage |\n|-----------|---------|------------|\n | param0 | X | | \n | param1 | | | \n | param2 | | | \n \n\t\n\t## Side effects\n\t\n\tnone\n\t\n\t## Exceptions\n\t\n\tnone\n\t\n\t## Example\n\n\tnone\n"
|
2019-11-13 15:43:53 +02:00
|
|
|
|
|
|
|
func configMetaDataMock(name string) (io.ReadCloser, error) {
|
|
|
|
meta1 := `metadata:
|
|
|
|
name: testStep
|
|
|
|
description: Test description
|
|
|
|
longDescription: |
|
|
|
|
Long Test description
|
|
|
|
spec:
|
|
|
|
inputs:
|
|
|
|
params:
|
|
|
|
- name: param0
|
|
|
|
type: string
|
|
|
|
description: param0 description
|
|
|
|
default: val0
|
|
|
|
scope:
|
|
|
|
- GENERAL
|
|
|
|
- PARAMETERS
|
|
|
|
mandatory: true
|
|
|
|
- name: param1
|
|
|
|
type: string
|
|
|
|
description: param1 description
|
|
|
|
scope:
|
|
|
|
- PARAMETERS
|
|
|
|
- name: param2
|
|
|
|
type: string
|
|
|
|
description: param1 description
|
|
|
|
scope:
|
|
|
|
- PARAMETERS
|
|
|
|
mandatory: true
|
|
|
|
`
|
|
|
|
var r string
|
|
|
|
switch name {
|
|
|
|
case "test.yaml":
|
|
|
|
r = meta1
|
|
|
|
default:
|
|
|
|
r = ""
|
|
|
|
}
|
|
|
|
return ioutil.NopCloser(strings.NewReader(r)), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func configOpenDocTemplateFileMock(docTemplateFilePath string) (io.ReadCloser, error) {
|
|
|
|
meta1 := `# ${docGenStepName}
|
|
|
|
|
|
|
|
## ${docGenDescription}
|
|
|
|
|
|
|
|
## Prerequisites
|
|
|
|
|
|
|
|
none
|
|
|
|
|
|
|
|
## ${docJenkinsPluginDependencies}
|
|
|
|
|
|
|
|
## ${docGenParameters}
|
|
|
|
|
|
|
|
## ${docGenConfiguration}
|
|
|
|
|
|
|
|
## Side effects
|
|
|
|
|
|
|
|
none
|
|
|
|
|
|
|
|
## Exceptions
|
|
|
|
|
|
|
|
none
|
|
|
|
|
|
|
|
## Example
|
|
|
|
|
|
|
|
none
|
|
|
|
`
|
|
|
|
switch docTemplateFilePath {
|
|
|
|
case "testStep.md":
|
|
|
|
return ioutil.NopCloser(strings.NewReader(meta1)), nil
|
|
|
|
default:
|
|
|
|
return ioutil.NopCloser(strings.NewReader("")), fmt.Errorf("Wrong Path: %v", docTemplateFilePath)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-14 14:59:31 +02:00
|
|
|
var stepData config.StepData = config.StepData{
|
|
|
|
Spec: config.StepSpec{
|
|
|
|
Inputs: config.StepInputs{
|
|
|
|
Parameters: []config.StepParameters{
|
2019-11-14 16:09:12 +02:00
|
|
|
{Name: "param0", Scope: []string{"GENERAL"}, Type: "string", Default: "default0",
|
|
|
|
Conditions: []config.Condition{
|
|
|
|
{Params: []config.Param{
|
|
|
|
{"name0a", "val0a"},
|
|
|
|
{"name0b", "val0b"},
|
|
|
|
},
|
|
|
|
}},
|
|
|
|
},
|
|
|
|
{Name: "param1", Scope: []string{"GENERAL"}, Type: "string", Default: "default1",
|
|
|
|
Conditions: []config.Condition{
|
|
|
|
{Params: []config.Param{
|
|
|
|
{"name1a", "val1a"},
|
|
|
|
},
|
|
|
|
}},
|
|
|
|
},
|
|
|
|
{Name: "param1", Scope: []string{"GENERAL"}, Type: "string", Default: "default1",
|
|
|
|
Conditions: []config.Condition{
|
|
|
|
{Params: []config.Param{
|
|
|
|
{"name1b", "val1b"},
|
|
|
|
},
|
|
|
|
}},
|
|
|
|
},
|
2019-11-14 14:59:31 +02:00
|
|
|
},
|
|
|
|
Resources: []config.StepResources{
|
|
|
|
{Name: "resource0", Type: "stash", Description: "val0"},
|
|
|
|
{Name: "resource1", Type: "stash", Description: "val1"},
|
|
|
|
{Name: "resource2", Type: "stash", Description: "val2"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Containers: []config.Container{
|
|
|
|
{Name: "container0", Image: "image", WorkingDir: "workingdir", Shell: "shell",
|
|
|
|
EnvVars: []config.EnvVar{
|
|
|
|
{"envar.name0", "envar.value0"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{Name: "container1", Image: "image", WorkingDir: "workingdir",
|
|
|
|
EnvVars: []config.EnvVar{
|
|
|
|
{"envar.name1", "envar.value1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{Name: "container2a", Command: []string{"command"}, ImagePullPolicy: "pullpolicy", Image: "image", WorkingDir: "workingdir",
|
|
|
|
EnvVars: []config.EnvVar{
|
|
|
|
{"envar.name2a", "envar.value2a"}},
|
|
|
|
Conditions: []config.Condition{
|
|
|
|
{Params: []config.Param{
|
2019-11-20 15:36:07 +02:00
|
|
|
{"param_name2a", "param_value2a"},
|
2019-11-14 14:59:31 +02:00
|
|
|
}},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{Name: "container2b", Image: "image", WorkingDir: "workingdir",
|
|
|
|
EnvVars: []config.EnvVar{
|
|
|
|
{"envar.name2b", "envar.value2b"},
|
|
|
|
},
|
|
|
|
Conditions: []config.Condition{
|
|
|
|
{Params: []config.Param{
|
|
|
|
{"param.name2b", "param.value2b"},
|
|
|
|
}},
|
|
|
|
},
|
2019-11-20 10:05:10 +02:00
|
|
|
//VolumeMounts: []config.VolumeMount{
|
|
|
|
// {"mp.2b", "mn.2b"},
|
|
|
|
//},
|
|
|
|
Options: []config.Option{
|
|
|
|
{"option.name2b", "option.value2b"},
|
2019-11-18 12:14:45 +02:00
|
|
|
},
|
2019-11-14 14:59:31 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
Sidecars: []config.Container{
|
|
|
|
{Name: "sidecar0", Command: []string{"command"}, ImagePullPolicy: "pullpolicy", Image: "image", WorkingDir: "workingdir", ReadyCommand: "readycommand",
|
|
|
|
EnvVars: []config.EnvVar{
|
|
|
|
{"envar.name3", "envar.value3"}},
|
|
|
|
Conditions: []config.Condition{
|
|
|
|
{Params: []config.Param{
|
|
|
|
{"param.name0", "param.value0"},
|
|
|
|
}},
|
|
|
|
},
|
2019-11-20 10:05:10 +02:00
|
|
|
//VolumeMounts: []config.VolumeMount{
|
|
|
|
// {"mp.3b", "mn.3b"},
|
|
|
|
//},
|
|
|
|
Options: []config.Option{
|
|
|
|
{"option.name3b", "option.value3b"},
|
2019-11-18 12:14:45 +02:00
|
|
|
},
|
2019-11-14 14:59:31 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2019-11-13 15:43:53 +02:00
|
|
|
var resultDocumentContent string
|
|
|
|
|
|
|
|
func docFileWriterMock(docTemplateFilePath string, data []byte, perm os.FileMode) error {
|
|
|
|
|
|
|
|
resultDocumentContent = string(data)
|
|
|
|
switch docTemplateFilePath {
|
|
|
|
case "testStep.md":
|
|
|
|
return nil
|
|
|
|
default:
|
|
|
|
return fmt.Errorf("Wrong Path: %v", docTemplateFilePath)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestGenerateStepDocumentationSuccess(t *testing.T) {
|
|
|
|
var stepData config.StepData
|
|
|
|
contentMetaData, _ := configMetaDataMock("test.yaml")
|
|
|
|
stepData.ReadPipelineStepData(contentMetaData)
|
|
|
|
|
|
|
|
generateStepDocumentation(stepData, DocuHelperData{true, "", configOpenDocTemplateFileMock, docFileWriterMock})
|
|
|
|
|
|
|
|
t.Run("Docu Generation Success", func(t *testing.T) {
|
|
|
|
assert.Equal(t, expectedResultDocument, resultDocumentContent)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestGenerateStepDocumentationError(t *testing.T) {
|
|
|
|
var stepData config.StepData
|
|
|
|
contentMetaData, _ := configMetaDataMock("test.yaml")
|
|
|
|
stepData.ReadPipelineStepData(contentMetaData)
|
|
|
|
|
|
|
|
err := generateStepDocumentation(stepData, DocuHelperData{true, "Dummy", configOpenDocTemplateFileMock, docFileWriterMock})
|
|
|
|
|
|
|
|
t.Run("Docu Generation Success", func(t *testing.T) {
|
|
|
|
assert.Error(t, err, fmt.Sprintf("Error occured: %v\n", err))
|
|
|
|
})
|
|
|
|
}
|
2019-11-14 14:59:31 +02:00
|
|
|
|
|
|
|
func TestReadAndAdjustTemplate(t *testing.T) {
|
|
|
|
|
|
|
|
t.Run("Success Case", func(t *testing.T) {
|
|
|
|
|
|
|
|
tmpl, _ := configOpenDocTemplateFileMock("testStep.md")
|
|
|
|
content := readAndAdjustTemplate(tmpl)
|
|
|
|
|
|
|
|
cases := []struct {
|
|
|
|
x, y string
|
|
|
|
}{
|
|
|
|
{"{{docGenStepName .}}", "${docGenStepName}"},
|
|
|
|
{"{{docGenConfiguration .}}", "${docGenConfiguration}"},
|
|
|
|
{"{{docGenParameters .}}", "${docGenParameters}"},
|
|
|
|
{"{{docGenDescription .}}", "${docGenDescription}"},
|
|
|
|
{"", "${docJenkinsPluginDependencies}"},
|
|
|
|
}
|
|
|
|
for _, c := range cases {
|
|
|
|
if len(c.x) > 0 {
|
|
|
|
assert.Contains(t, content, c.x)
|
|
|
|
}
|
|
|
|
if len(c.y) > 0 {
|
|
|
|
assert.NotContains(t, content, c.y)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-11-20 12:29:13 +02:00
|
|
|
func TestAddDefaultContainerContent(t *testing.T) {
|
2019-11-14 14:59:31 +02:00
|
|
|
|
|
|
|
t.Run("Success Case", func(t *testing.T) {
|
|
|
|
|
|
|
|
var m map[string]string = make(map[string]string)
|
2019-11-20 12:29:13 +02:00
|
|
|
addDefaultContainerContent(&stepData, m)
|
2019-11-14 14:59:31 +02:00
|
|
|
|
|
|
|
cases := []struct {
|
|
|
|
x, want string
|
|
|
|
}{
|
|
|
|
{"containerCommand", "command"},
|
2019-11-18 12:14:45 +02:00
|
|
|
{"containerName", "container0, container1 <br>container2a <br>container2b <br>"},
|
2019-11-14 14:59:31 +02:00
|
|
|
{"containerShell", "shell"},
|
2019-11-20 15:36:07 +02:00
|
|
|
{"dockerEnvVars", "envar.name0=envar.value0, envar.name1=envar.value1 <br>param_name2a=param_value2a:\\[envar.name2a=envar.value2a\\] <br>param.name2b=param.value2b:\\[envar.name2b=envar.value2b\\]"},
|
|
|
|
{"dockerImage", "image, image <br>param_name2a=param_value2a:image <br>param.name2b=param.value2b:image"},
|
2019-11-14 14:59:31 +02:00
|
|
|
{"dockerName", "container0, container1 <br>container2a <br>container2b <br>"},
|
|
|
|
{"dockerPullImage", "true"},
|
2019-11-20 11:50:23 +02:00
|
|
|
{"dockerOptions", "option.name2b option.value2b"},
|
2019-11-20 15:36:07 +02:00
|
|
|
{"dockerWorkspace", "workingdir, workingdir <br>param_name2a=param_value2a:workingdir <br>param.name2b=param.value2b:workingdir"},
|
2019-11-14 14:59:31 +02:00
|
|
|
}
|
2019-11-20 11:50:23 +02:00
|
|
|
assert.Equal(t, len(cases), len(m))
|
2019-11-14 14:59:31 +02:00
|
|
|
for _, c := range cases {
|
|
|
|
assert.Contains(t, m, c.x)
|
|
|
|
assert.True(t, len(m[c.x]) > 0)
|
|
|
|
assert.True(t, strings.Contains(m[c.x], c.want), fmt.Sprintf("%v:%v", c.x, m[c.x]))
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2019-11-20 12:29:13 +02:00
|
|
|
func TestAddDefaultSidecarContent(t *testing.T) {
|
2019-11-14 14:59:31 +02:00
|
|
|
|
|
|
|
t.Run("Success Case", func(t *testing.T) {
|
|
|
|
|
|
|
|
var m map[string]string = make(map[string]string)
|
2019-11-20 12:29:13 +02:00
|
|
|
addDefaultSidecarContent(&stepData, m)
|
2019-11-14 14:59:31 +02:00
|
|
|
|
|
|
|
cases := []struct {
|
|
|
|
x, want string
|
|
|
|
}{
|
|
|
|
{"sidecarCommand", "command"},
|
|
|
|
{"sidecarEnvVars", "envar.name3=envar.value3"},
|
|
|
|
{"sidecarImage", "image"},
|
|
|
|
{"sidecarName", "sidecar0"},
|
|
|
|
{"sidecarPullImage", "true"},
|
|
|
|
{"sidecarReadyCommand", "readycommand"},
|
2019-11-20 11:50:23 +02:00
|
|
|
{"sidecarOptions", "option.name3b option.value3b"},
|
2019-11-14 14:59:31 +02:00
|
|
|
{"sidecarWorkspace", "workingdir"},
|
|
|
|
}
|
2019-11-20 11:50:23 +02:00
|
|
|
assert.Equal(t, len(cases), len(m))
|
2019-11-14 14:59:31 +02:00
|
|
|
for _, c := range cases {
|
|
|
|
assert.Contains(t, m, c.x)
|
|
|
|
assert.True(t, len(m[c.x]) > 0)
|
|
|
|
assert.Equal(t, c.want, m[c.x], fmt.Sprintf("%v:%v", c.x, m[c.x]))
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestAddStashContent(t *testing.T) {
|
|
|
|
|
|
|
|
t.Run("Success Case", func(t *testing.T) {
|
|
|
|
|
|
|
|
var m map[string]string = make(map[string]string)
|
|
|
|
addStashContent(&stepData, m)
|
|
|
|
|
|
|
|
cases := []struct {
|
|
|
|
x, want string
|
|
|
|
}{
|
|
|
|
{"stashContent", "resource0, resource1, resource2"},
|
|
|
|
}
|
2019-11-20 11:50:23 +02:00
|
|
|
assert.Equal(t, len(cases), len(m))
|
2019-11-14 14:59:31 +02:00
|
|
|
for _, c := range cases {
|
|
|
|
assert.Contains(t, m, c.x)
|
|
|
|
assert.True(t, len(m[c.x]) > 0)
|
|
|
|
assert.True(t, strings.Contains(m[c.x], c.want), fmt.Sprintf("%v:%v", c.x, m[c.x]))
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestGetDocuContextDefaults(t *testing.T) {
|
|
|
|
|
|
|
|
t.Run("Success Case", func(t *testing.T) {
|
|
|
|
|
|
|
|
m := getDocuContextDefaults(&stepData)
|
|
|
|
|
|
|
|
cases := []struct {
|
|
|
|
x, want string
|
|
|
|
}{
|
|
|
|
{"stashContent", "resource0, resource1, resource2"},
|
|
|
|
{"sidecarCommand", "command"},
|
|
|
|
{"sidecarEnvVars", "envar.name3=envar.value3"},
|
|
|
|
{"sidecarImage", "image"},
|
|
|
|
{"sidecarName", "sidecar0"},
|
|
|
|
{"sidecarPullImage", "true"},
|
|
|
|
{"sidecarReadyCommand", "readycommand"},
|
2019-11-20 11:50:23 +02:00
|
|
|
{"sidecarOptions", "option.name3b option.value3b"},
|
2019-11-14 14:59:31 +02:00
|
|
|
{"sidecarWorkspace", "workingdir"},
|
|
|
|
{"containerCommand", "command"},
|
2019-11-18 12:14:45 +02:00
|
|
|
{"containerName", "container0, container1 <br>container2a <br>container2b <br>"},
|
2019-11-14 14:59:31 +02:00
|
|
|
{"containerShell", "shell"},
|
2019-11-20 15:36:07 +02:00
|
|
|
{"dockerEnvVars", "envar.name0=envar.value0, envar.name1=envar.value1 <br>param_name2a=param_value2a:\\[envar.name2a=envar.value2a\\] <br>param.name2b=param.value2b:\\[envar.name2b=envar.value2b\\]"},
|
|
|
|
{"dockerImage", "image, image <br>param_name2a=param_value2a:image <br>param.name2b=param.value2b:image"},
|
2019-11-14 14:59:31 +02:00
|
|
|
{"dockerName", "container0, container1 <br>container2a <br>container2b <br>"},
|
|
|
|
{"dockerPullImage", "true"},
|
2019-11-20 11:50:23 +02:00
|
|
|
{"dockerOptions", "option.name2b option.value2b"},
|
2019-11-20 15:36:07 +02:00
|
|
|
{"dockerWorkspace", "workingdir, workingdir <br>param_name2a=param_value2a:workingdir <br>param.name2b=param.value2b:workingdir"},
|
2019-11-14 14:59:31 +02:00
|
|
|
}
|
2019-11-20 11:50:23 +02:00
|
|
|
assert.Equal(t, len(cases), len(m))
|
2019-11-14 14:59:31 +02:00
|
|
|
for _, c := range cases {
|
|
|
|
assert.Contains(t, m, c.x)
|
|
|
|
assert.True(t, len(m[c.x]) > 0)
|
|
|
|
assert.True(t, strings.Contains(m[c.x], c.want), fmt.Sprintf("%v:%v", c.x, m[c.x]))
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2019-11-14 16:09:12 +02:00
|
|
|
|
|
|
|
func TestAddNewParameterWithCondition(t *testing.T) {
|
|
|
|
|
|
|
|
t.Run("Success Case", func(t *testing.T) {
|
|
|
|
|
|
|
|
var m map[string]string = make(map[string]string)
|
|
|
|
|
|
|
|
cases := []struct {
|
|
|
|
x, want string
|
|
|
|
i int
|
|
|
|
}{
|
|
|
|
{"param0", "name0a=val0a:default0 name0b=val0b:default0", 0},
|
|
|
|
{"param1", "name1a=val1a:default1", 1},
|
|
|
|
}
|
|
|
|
for _, c := range cases {
|
|
|
|
|
|
|
|
addNewParameterWithCondition(stepData.Spec.Inputs.Parameters[c.i], m)
|
|
|
|
assert.Contains(t, m, c.x)
|
|
|
|
assert.True(t, len(m[c.x]) > 0)
|
|
|
|
assert.True(t, strings.Contains(m[c.x], c.want), fmt.Sprintf("%v", m[c.x]))
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestAddExistingParameterWithCondition(t *testing.T) {
|
|
|
|
|
|
|
|
t.Run("Success Case", func(t *testing.T) {
|
|
|
|
|
|
|
|
var m map[string]string = make(map[string]string)
|
|
|
|
addNewParameterWithCondition(stepData.Spec.Inputs.Parameters[1], m)
|
|
|
|
|
|
|
|
cases := []struct {
|
|
|
|
x, want string
|
|
|
|
}{
|
|
|
|
{"param1", "name1a=val1a:default1 <br> name1b=val1b:default1"},
|
|
|
|
}
|
|
|
|
for _, c := range cases {
|
|
|
|
|
|
|
|
addExistingParameterWithCondition(stepData.Spec.Inputs.Parameters[2], m)
|
|
|
|
assert.Contains(t, m, c.x)
|
|
|
|
assert.True(t, len(m[c.x]) > 0)
|
|
|
|
assert.True(t, strings.Contains(m[c.x], c.want), fmt.Sprintf("%v", m[c.x]))
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|