mirror of
https://github.com/SAP/jenkins-library.git
synced 2025-01-04 04:07:16 +02:00
Persisted pipeline environment for golang library (#1091)
* Use commonPipelineEnvironment in go binary * Update groovy part incl. tests * Rework structure and naming * Support influx resources in steps * Update tests and some cleanups * Add correct defer handling * Address PR feedback * Fix test * Update resources.go Co-authored-by: Sven Merk <33895725+nevskrem@users.noreply.github.com>
This commit is contained in:
parent
e5db600cf4
commit
a46b57e6b4
@ -4,6 +4,7 @@
|
||||
|
||||
1. [Getting started](#getting-started)
|
||||
1. [Build the project](#build-the-project_)
|
||||
1. [Generating step framework](#generating-step-framework)
|
||||
1. [Logging](#logging)
|
||||
1. [Error handling](#error-handling)
|
||||
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/SAP/jenkins-library/pkg/config"
|
||||
"github.com/SAP/jenkins-library/pkg/log"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@ -20,11 +21,11 @@ type detectExecuteScanOptions struct {
|
||||
}
|
||||
|
||||
var myDetectExecuteScanOptions detectExecuteScanOptions
|
||||
var detectExecuteScanStepConfigJSON string
|
||||
|
||||
// DetectExecuteScanCommand Executes Synopsis Detect scan
|
||||
func DetectExecuteScanCommand() *cobra.Command {
|
||||
metadata := detectExecuteScanMetadata()
|
||||
|
||||
var createDetectExecuteScanCmd = &cobra.Command{
|
||||
Use: "detectExecuteScan",
|
||||
Short: "Executes Synopsis Detect scan",
|
||||
@ -35,6 +36,7 @@ func DetectExecuteScanCommand() *cobra.Command {
|
||||
return PrepareConfig(cmd, &metadata, "detectExecuteScan", &myDetectExecuteScanOptions, config.OpenPiperFile)
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
|
||||
return detectExecuteScan(myDetectExecuteScanOptions)
|
||||
},
|
||||
}
|
||||
@ -65,60 +67,68 @@ func detectExecuteScanMetadata() config.StepData {
|
||||
Inputs: config.StepInputs{
|
||||
Parameters: []config.StepParameters{
|
||||
{
|
||||
Name: "apiToken",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{{Name: "detect/apiToken"}},
|
||||
Name: "apiToken",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{{Name: "detect/apiToken"}},
|
||||
},
|
||||
{
|
||||
Name: "codeLocation",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
Name: "codeLocation",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "projectName",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{{Name: "detect/projectName"}},
|
||||
Name: "projectName",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{{Name: "detect/projectName"}},
|
||||
},
|
||||
{
|
||||
Name: "projectVersion",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{{Name: "detect/projectVersion"}},
|
||||
Name: "projectVersion",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{{Name: "detect/projectVersion"}},
|
||||
},
|
||||
{
|
||||
Name: "scanners",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "[]string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{{Name: "detect/scanners"}},
|
||||
Name: "scanners",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "[]string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{{Name: "detect/scanners"}},
|
||||
},
|
||||
{
|
||||
Name: "scanPaths",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "[]string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{{Name: "detect/scanPaths"}},
|
||||
Name: "scanPaths",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "[]string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{{Name: "detect/scanPaths"}},
|
||||
},
|
||||
{
|
||||
Name: "scanProperties",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "[]string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{{Name: "detect/scanProperties"}},
|
||||
Name: "scanProperties",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "[]string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{{Name: "detect/scanProperties"}},
|
||||
},
|
||||
{
|
||||
Name: "serverUrl",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{{Name: "detect/serverUrl"}},
|
||||
Name: "serverUrl",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{{Name: "detect/serverUrl"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -54,6 +54,8 @@ func generateConfig() error {
|
||||
return errors.Wrap(err, "metadata: read failed")
|
||||
}
|
||||
|
||||
resourceParams := metadata.GetResourceParameters(GeneralConfig.EnvRootPath, "commonPipelineEnvironment")
|
||||
|
||||
var customConfig io.ReadCloser
|
||||
{
|
||||
exists, e := piperutils.FileExists(GeneralConfig.CustomConfig)
|
||||
@ -91,7 +93,7 @@ func generateConfig() error {
|
||||
params = metadata.Spec.Inputs.Parameters
|
||||
}
|
||||
|
||||
stepConfig, err = myConfig.GetStepConfig(flags, GeneralConfig.ParametersJSON, customConfig, defaultConfig, paramFilter, params, GeneralConfig.StageName, metadata.Metadata.Name)
|
||||
stepConfig, err = myConfig.GetStepConfig(flags, GeneralConfig.ParametersJSON, customConfig, defaultConfig, paramFilter, params, resourceParams, GeneralConfig.StageName, metadata.Metadata.Name)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "getting step config failed")
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/SAP/jenkins-library/pkg/config"
|
||||
"github.com/SAP/jenkins-library/pkg/log"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@ -23,11 +24,11 @@ type githubCreatePullRequestOptions struct {
|
||||
}
|
||||
|
||||
var myGithubCreatePullRequestOptions githubCreatePullRequestOptions
|
||||
var githubCreatePullRequestStepConfigJSON string
|
||||
|
||||
// GithubCreatePullRequestCommand Create a pull request on GitHub
|
||||
func GithubCreatePullRequestCommand() *cobra.Command {
|
||||
metadata := githubCreatePullRequestMetadata()
|
||||
|
||||
var createGithubCreatePullRequestCmd = &cobra.Command{
|
||||
Use: "githubCreatePullRequest",
|
||||
Short: "Create a pull request on GitHub",
|
||||
@ -40,6 +41,7 @@ It can for example be used for GitOps scenarios or for scenarios where you want
|
||||
return PrepareConfig(cmd, &metadata, "githubCreatePullRequest", &myGithubCreatePullRequestOptions, config.OpenPiperFile)
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
|
||||
return githubCreatePullRequest(myGithubCreatePullRequestOptions)
|
||||
},
|
||||
}
|
||||
@ -79,81 +81,92 @@ func githubCreatePullRequestMetadata() config.StepData {
|
||||
Inputs: config.StepInputs{
|
||||
Parameters: []config.StepParameters{
|
||||
{
|
||||
Name: "assignees",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "[]string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
Name: "assignees",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "[]string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "base",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{},
|
||||
Name: "base",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "body",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{},
|
||||
Name: "body",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "apiUrl",
|
||||
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{{Name: "githubApiUrl"}},
|
||||
Name: "apiUrl",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{{Name: "githubApiUrl"}},
|
||||
},
|
||||
{
|
||||
Name: "head",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{},
|
||||
Name: "head",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "owner",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{{Name: "githubOrg"}},
|
||||
Name: "owner",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{{Name: "githubOrg"}},
|
||||
},
|
||||
{
|
||||
Name: "repository",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{{Name: "githubRepo"}},
|
||||
Name: "repository",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{{Name: "githubRepo"}},
|
||||
},
|
||||
{
|
||||
Name: "serverUrl",
|
||||
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{{Name: "githubServerUrl"}},
|
||||
Name: "serverUrl",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{{Name: "githubServerUrl"}},
|
||||
},
|
||||
{
|
||||
Name: "title",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{},
|
||||
Name: "title",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "token",
|
||||
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{{Name: "githubToken"}},
|
||||
Name: "token",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{{Name: "githubToken"}},
|
||||
},
|
||||
{
|
||||
Name: "labels",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "[]string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
Name: "labels",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "[]string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -5,32 +5,33 @@ import (
|
||||
|
||||
"github.com/SAP/jenkins-library/pkg/config"
|
||||
"github.com/SAP/jenkins-library/pkg/log"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
type githubPublishReleaseOptions struct {
|
||||
AddClosedIssues bool `json:"addClosedIssues,omitempty"`
|
||||
AddDeltaToLastRelease bool `json:"addDeltaToLastRelease,omitempty"`
|
||||
APIURL string `json:"apiUrl,omitempty"`
|
||||
AssetPath string `json:"assetPath,omitempty"`
|
||||
Commitish string `json:"commitish,omitempty"`
|
||||
ExcludeLabels []string `json:"excludeLabels,omitempty"`
|
||||
APIURL string `json:"apiUrl,omitempty"`
|
||||
Labels []string `json:"labels,omitempty"`
|
||||
Owner string `json:"owner,omitempty"`
|
||||
ReleaseBodyHeader string `json:"releaseBodyHeader,omitempty"`
|
||||
Repository string `json:"repository,omitempty"`
|
||||
ServerURL string `json:"serverUrl,omitempty"`
|
||||
Token string `json:"token,omitempty"`
|
||||
UploadURL string `json:"uploadUrl,omitempty"`
|
||||
Labels []string `json:"labels,omitempty"`
|
||||
ReleaseBodyHeader string `json:"releaseBodyHeader,omitempty"`
|
||||
Version string `json:"version,omitempty"`
|
||||
}
|
||||
|
||||
var myGithubPublishReleaseOptions githubPublishReleaseOptions
|
||||
var githubPublishReleaseStepConfigJSON string
|
||||
|
||||
// GithubPublishReleaseCommand Publish a release in GitHub
|
||||
func GithubPublishReleaseCommand() *cobra.Command {
|
||||
metadata := githubPublishReleaseMetadata()
|
||||
|
||||
var createGithubPublishReleaseCmd = &cobra.Command{
|
||||
Use: "githubPublishRelease",
|
||||
Short: "Publish a release in GitHub",
|
||||
@ -50,6 +51,7 @@ The result looks like
|
||||
return PrepareConfig(cmd, &metadata, "githubPublishRelease", &myGithubPublishReleaseOptions, config.OpenPiperFile)
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
|
||||
return githubPublishRelease(myGithubPublishReleaseOptions)
|
||||
},
|
||||
}
|
||||
@ -61,17 +63,17 @@ The result looks like
|
||||
func addGithubPublishReleaseFlags(cmd *cobra.Command) {
|
||||
cmd.Flags().BoolVar(&myGithubPublishReleaseOptions.AddClosedIssues, "addClosedIssues", false, "If set to `true`, closed issues and merged pull-requests since the last release will added below the `releaseBodyHeader`")
|
||||
cmd.Flags().BoolVar(&myGithubPublishReleaseOptions.AddDeltaToLastRelease, "addDeltaToLastRelease", false, "If set to `true`, a link will be added to the relese information that brings up all commits since the last release.")
|
||||
cmd.Flags().StringVar(&myGithubPublishReleaseOptions.APIURL, "apiUrl", "https://api.github.com", "Set the GitHub API url.")
|
||||
cmd.Flags().StringVar(&myGithubPublishReleaseOptions.AssetPath, "assetPath", os.Getenv("PIPER_assetPath"), "Path to a release asset which should be uploaded to the list of release assets.")
|
||||
cmd.Flags().StringVar(&myGithubPublishReleaseOptions.Commitish, "commitish", "master", "Target git commitish for the release")
|
||||
cmd.Flags().StringSliceVar(&myGithubPublishReleaseOptions.ExcludeLabels, "excludeLabels", []string{}, "Allows to exclude issues with dedicated list of labels.")
|
||||
cmd.Flags().StringVar(&myGithubPublishReleaseOptions.APIURL, "apiUrl", "https://api.github.com", "Set the GitHub API url.")
|
||||
cmd.Flags().StringSliceVar(&myGithubPublishReleaseOptions.Labels, "labels", []string{}, "Labels to include in issue search.")
|
||||
cmd.Flags().StringVar(&myGithubPublishReleaseOptions.Owner, "owner", os.Getenv("PIPER_owner"), "Set the GitHub organization.")
|
||||
cmd.Flags().StringVar(&myGithubPublishReleaseOptions.ReleaseBodyHeader, "releaseBodyHeader", os.Getenv("PIPER_releaseBodyHeader"), "Content which will appear for the release.")
|
||||
cmd.Flags().StringVar(&myGithubPublishReleaseOptions.Repository, "repository", os.Getenv("PIPER_repository"), "Set the GitHub repository.")
|
||||
cmd.Flags().StringVar(&myGithubPublishReleaseOptions.ServerURL, "serverUrl", "https://github.com", "GitHub server url for end-user access.")
|
||||
cmd.Flags().StringVar(&myGithubPublishReleaseOptions.Token, "token", os.Getenv("PIPER_token"), "GitHub personal access token as per https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line")
|
||||
cmd.Flags().StringVar(&myGithubPublishReleaseOptions.UploadURL, "uploadUrl", "https://uploads.github.com", "Set the GitHub API url.")
|
||||
cmd.Flags().StringSliceVar(&myGithubPublishReleaseOptions.Labels, "labels", []string{}, "Labels to include in issue search.")
|
||||
cmd.Flags().StringVar(&myGithubPublishReleaseOptions.ReleaseBodyHeader, "releaseBodyHeader", os.Getenv("PIPER_releaseBodyHeader"), "Content which will appear for the release.")
|
||||
cmd.Flags().StringVar(&myGithubPublishReleaseOptions.Version, "version", os.Getenv("PIPER_version"), "Define the version number which will be written as tag as well as release name.")
|
||||
|
||||
cmd.MarkFlagRequired("apiUrl")
|
||||
@ -90,102 +92,116 @@ func githubPublishReleaseMetadata() config.StepData {
|
||||
Inputs: config.StepInputs{
|
||||
Parameters: []config.StepParameters{
|
||||
{
|
||||
Name: "addClosedIssues",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "bool",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
Name: "addClosedIssues",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "bool",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "addDeltaToLastRelease",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "bool",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
Name: "addDeltaToLastRelease",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "bool",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "assetPath",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
Name: "apiUrl",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{{Name: "githubApiUrl"}},
|
||||
},
|
||||
{
|
||||
Name: "commitish",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
Name: "assetPath",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "excludeLabels",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "[]string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
Name: "commitish",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "apiUrl",
|
||||
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{{Name: "githubApiUrl"}},
|
||||
Name: "excludeLabels",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "[]string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "owner",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{{Name: "githubOrg"}},
|
||||
Name: "labels",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "[]string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "repository",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{{Name: "githubRepo"}},
|
||||
Name: "owner",
|
||||
ResourceRef: []config.ResourceReference{{Name: "commonPipelineEnvironment", Param: "github/owner"}},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{{Name: "githubOrg"}},
|
||||
},
|
||||
{
|
||||
Name: "serverUrl",
|
||||
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{{Name: "githubServerUrl"}},
|
||||
Name: "releaseBodyHeader",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "token",
|
||||
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{{Name: "githubToken"}},
|
||||
Name: "repository",
|
||||
ResourceRef: []config.ResourceReference{{Name: "commonPipelineEnvironment", Param: "github/repository"}},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{{Name: "githubRepo"}},
|
||||
},
|
||||
{
|
||||
Name: "uploadUrl",
|
||||
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{{Name: "githubUploadUrl"}},
|
||||
Name: "serverUrl",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{{Name: "githubServerUrl"}},
|
||||
},
|
||||
{
|
||||
Name: "labels",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "[]string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
Name: "token",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{{Name: "githubToken"}},
|
||||
},
|
||||
{
|
||||
Name: "releaseBodyHeader",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
Name: "uploadUrl",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{{Name: "githubUploadUrl"}},
|
||||
},
|
||||
{
|
||||
Name: "version",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{},
|
||||
Name: "version",
|
||||
ResourceRef: []config.ResourceReference{{Name: "commonPipelineEnvironment", Param: "artifactVersion"}},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -3,6 +3,7 @@ package cmd
|
||||
import (
|
||||
"github.com/SAP/jenkins-library/pkg/config"
|
||||
"github.com/SAP/jenkins-library/pkg/log"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@ -13,11 +14,11 @@ type karmaExecuteTestsOptions struct {
|
||||
}
|
||||
|
||||
var myKarmaExecuteTestsOptions karmaExecuteTestsOptions
|
||||
var karmaExecuteTestsStepConfigJSON string
|
||||
|
||||
// KarmaExecuteTestsCommand Executes the Karma test runner
|
||||
func KarmaExecuteTestsCommand() *cobra.Command {
|
||||
metadata := karmaExecuteTestsMetadata()
|
||||
|
||||
var createKarmaExecuteTestsCmd = &cobra.Command{
|
||||
Use: "karmaExecuteTests",
|
||||
Short: "Executes the Karma test runner",
|
||||
@ -38,6 +39,7 @@ In the Docker network, the containers can be referenced by the values provided i
|
||||
return PrepareConfig(cmd, &metadata, "karmaExecuteTests", &myKarmaExecuteTestsOptions, config.OpenPiperFile)
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
|
||||
return karmaExecuteTests(myKarmaExecuteTestsOptions)
|
||||
},
|
||||
}
|
||||
@ -63,25 +65,28 @@ func karmaExecuteTestsMetadata() config.StepData {
|
||||
Inputs: config.StepInputs{
|
||||
Parameters: []config.StepParameters{
|
||||
{
|
||||
Name: "installCommand",
|
||||
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{},
|
||||
Name: "installCommand",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "modulePath",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{},
|
||||
Name: "modulePath",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "runCommand",
|
||||
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{},
|
||||
Name: "runCommand",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -18,6 +18,7 @@ type GeneralConfigOptions struct {
|
||||
CustomConfig string
|
||||
DefaultConfig []string //ordered list of Piper default configurations. Can be filePath or ENV containing JSON in format 'ENV:MY_ENV_VAR'
|
||||
ParametersJSON string
|
||||
EnvRootPath string
|
||||
StageName string
|
||||
StepConfigJSON string
|
||||
StepMetadata string //metadata to be considered, can be filePath or ENV containing JSON in format 'ENV:MY_ENV_VAR'
|
||||
@ -61,6 +62,7 @@ func addRootFlags(rootCmd *cobra.Command) {
|
||||
rootCmd.PersistentFlags().StringVar(&GeneralConfig.CustomConfig, "customConfig", ".pipeline/config.yml", "Path to the pipeline configuration file")
|
||||
rootCmd.PersistentFlags().StringSliceVar(&GeneralConfig.DefaultConfig, "defaultConfig", []string{".pipeline/defaults.yaml"}, "Default configurations, passed as path to yaml file")
|
||||
rootCmd.PersistentFlags().StringVar(&GeneralConfig.ParametersJSON, "parametersJSON", os.Getenv("PIPER_parametersJSON"), "Parameters to be considered in JSON format")
|
||||
rootCmd.PersistentFlags().StringVar(&GeneralConfig.EnvRootPath, "envRootPath", ".pipeline", "Root path to Piper pipeline shared environments")
|
||||
rootCmd.PersistentFlags().StringVar(&GeneralConfig.StageName, "stageName", os.Getenv("STAGE_NAME"), "Name of the stage for which configuration should be included")
|
||||
rootCmd.PersistentFlags().StringVar(&GeneralConfig.StepConfigJSON, "stepConfigJSON", os.Getenv("PIPER_stepConfigJSON"), "Step configuration in JSON format")
|
||||
rootCmd.PersistentFlags().BoolVarP(&GeneralConfig.Verbose, "verbose", "v", false, "verbose output")
|
||||
@ -71,6 +73,7 @@ func addRootFlags(rootCmd *cobra.Command) {
|
||||
func PrepareConfig(cmd *cobra.Command, metadata *config.StepData, stepName string, options interface{}, openFile func(s string) (io.ReadCloser, error)) error {
|
||||
|
||||
filters := metadata.GetParameterFilters()
|
||||
resourceParams := metadata.GetResourceParameters(GeneralConfig.EnvRootPath, "commonPipelineEnvironment")
|
||||
|
||||
flagValues := config.AvailableFlagValues(cmd, &filters)
|
||||
|
||||
@ -108,7 +111,7 @@ func PrepareConfig(cmd *cobra.Command, metadata *config.StepData, stepName strin
|
||||
defaultConfig = append(defaultConfig, fc)
|
||||
}
|
||||
|
||||
stepConfig, err = myConfig.GetStepConfig(flagValues, GeneralConfig.ParametersJSON, customConfig, defaultConfig, filters, metadata.Spec.Inputs.Parameters, GeneralConfig.StageName, stepName)
|
||||
stepConfig, err = myConfig.GetStepConfig(flagValues, GeneralConfig.ParametersJSON, customConfig, defaultConfig, filters, metadata.Spec.Inputs.Parameters, resourceParams, GeneralConfig.StageName, stepName)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "retrieving step configuration failed")
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package cmd
|
||||
import (
|
||||
"github.com/SAP/jenkins-library/pkg/config"
|
||||
"github.com/SAP/jenkins-library/pkg/log"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@ -10,11 +11,11 @@ type versionOptions struct {
|
||||
}
|
||||
|
||||
var myVersionOptions versionOptions
|
||||
var versionStepConfigJSON string
|
||||
|
||||
// VersionCommand Returns the version of the piper binary
|
||||
func VersionCommand() *cobra.Command {
|
||||
metadata := versionMetadata()
|
||||
|
||||
var createVersionCmd = &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "Returns the version of the piper binary",
|
||||
@ -25,6 +26,7 @@ func VersionCommand() *cobra.Command {
|
||||
return PrepareConfig(cmd, &metadata, "version", &myVersionOptions, config.OpenPiperFile)
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
|
||||
return version(myVersionOptions)
|
||||
},
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/SAP/jenkins-library/pkg/config"
|
||||
"github.com/SAP/jenkins-library/pkg/log"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@ -25,11 +26,11 @@ type xsDeployOptions struct {
|
||||
}
|
||||
|
||||
var myXsDeployOptions xsDeployOptions
|
||||
var xsDeployStepConfigJSON string
|
||||
|
||||
// XsDeployCommand Performs xs deployment
|
||||
func XsDeployCommand() *cobra.Command {
|
||||
metadata := xsDeployMetadata()
|
||||
|
||||
var createXsDeployCmd = &cobra.Command{
|
||||
Use: "xsDeploy",
|
||||
Short: "Performs xs deployment",
|
||||
@ -40,6 +41,7 @@ func XsDeployCommand() *cobra.Command {
|
||||
return PrepareConfig(cmd, &metadata, "xsDeploy", &myXsDeployOptions, config.OpenPiperFile)
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
|
||||
return xsDeploy(myXsDeployOptions)
|
||||
},
|
||||
}
|
||||
@ -80,95 +82,108 @@ func xsDeployMetadata() config.StepData {
|
||||
Inputs: config.StepInputs{
|
||||
Parameters: []config.StepParameters{
|
||||
{
|
||||
Name: "deployOpts",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
Name: "deployOpts",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "operationIdLogPattern",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{{Name: "deployIdLogPattern"}},
|
||||
Name: "operationIdLogPattern",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{{Name: "deployIdLogPattern"}},
|
||||
},
|
||||
{
|
||||
Name: "mtaPath",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{},
|
||||
Name: "mtaPath",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "action",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
Name: "action",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "mode",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{},
|
||||
Name: "mode",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "operationId",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
Name: "operationId",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "apiUrl",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{},
|
||||
Name: "apiUrl",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "user",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{},
|
||||
Name: "user",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "password",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{},
|
||||
Name: "password",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "org",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{},
|
||||
Name: "org",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "space",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{},
|
||||
Name: "space",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "loginOpts",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{},
|
||||
Name: "loginOpts",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "xsSessionFile",
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
Name: "xsSessionFile",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -82,7 +82,7 @@ func getDeepAliasValue(configMap map[string]interface{}, key string) interface{}
|
||||
}
|
||||
|
||||
// GetStepConfig provides merged step configuration using defaults, config, if available
|
||||
func (c *Config) GetStepConfig(flagValues map[string]interface{}, paramJSON string, configuration io.ReadCloser, defaults []io.ReadCloser, filters StepFilters, parameters []StepParameters, stageName, stepName string) (StepConfig, error) {
|
||||
func (c *Config) GetStepConfig(flagValues map[string]interface{}, paramJSON string, configuration io.ReadCloser, defaults []io.ReadCloser, filters StepFilters, parameters []StepParameters, envParameters map[string]interface{}, stageName, stepName string) (StepConfig, error) {
|
||||
var stepConfig StepConfig
|
||||
var d PipelineDefaults
|
||||
|
||||
@ -126,6 +126,9 @@ func (c *Config) GetStepConfig(flagValues map[string]interface{}, paramJSON stri
|
||||
stepConfig.mixIn(def.Steps[stepName], filters.Steps)
|
||||
}
|
||||
|
||||
// merge parameters provided by Piper environment
|
||||
stepConfig.mixIn(envParameters, filters.All)
|
||||
|
||||
// read config & merge - general -> steps -> stages
|
||||
stepConfig.mixIn(c.General, filters.General)
|
||||
stepConfig.mixIn(c.Steps[stepName], filters.Steps)
|
||||
|
@ -5,9 +5,12 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/SAP/jenkins-library/pkg/piperenv"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@ -145,9 +148,26 @@ steps:
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "pe1",
|
||||
Scope: []string{"STEPS"},
|
||||
ResourceRef: []ResourceReference{{Name: "commonPipelineEnvironment", Param: "test_pe1"}},
|
||||
},
|
||||
}
|
||||
|
||||
stepConfig, err := c.GetStepConfig(flags, paramJSON, myConfig, defaults, filters, parameterMetadata, "stage1", "step1")
|
||||
stepMeta := StepData{Spec: StepSpec{Inputs: StepInputs{Parameters: parameterMetadata}}}
|
||||
|
||||
dir, err := ioutil.TempDir("", "")
|
||||
if err != nil {
|
||||
t.Fatal("Failed to create temporary directory")
|
||||
}
|
||||
|
||||
// clean up tmp dir
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
piperenv.SetParameter(filepath.Join(dir, "commonPipelineEnvironment"), "test_pe1", "pe1_val")
|
||||
|
||||
stepConfig, err := c.GetStepConfig(flags, paramJSON, myConfig, defaults, filters, parameterMetadata, stepMeta.GetResourceParameters(dir, "commonPipelineEnvironment"), "stage1", "step1")
|
||||
|
||||
assert.Equal(t, nil, err, "error occured but none expected")
|
||||
|
||||
@ -163,7 +183,9 @@ steps:
|
||||
"p7": "p7_flag",
|
||||
"pd1": "pd1_dependent_default",
|
||||
"pd2": "pd2_metadata_default",
|
||||
"pe1": "pe1_val",
|
||||
}
|
||||
|
||||
for k, v := range expected {
|
||||
t.Run(k, func(t *testing.T) {
|
||||
if stepConfig.Config[k] != v {
|
||||
@ -191,7 +213,7 @@ steps:
|
||||
|
||||
c.openFile = customDefaultsOpenFileMock
|
||||
|
||||
stepConfig, err := c.GetStepConfig(nil, "", ioutil.NopCloser(strings.NewReader(testConfDefaults)), nil, StepFilters{General: []string{"p0"}}, nil, "stage1", "step1")
|
||||
stepConfig, err := c.GetStepConfig(nil, "", ioutil.NopCloser(strings.NewReader(testConfDefaults)), nil, StepFilters{General: []string{"p0"}}, nil, nil, "stage1", "step1")
|
||||
|
||||
assert.NoError(t, err, "Error occured but no error expected")
|
||||
assert.Equal(t, "p0_custom_default", stepConfig.Config["p0"])
|
||||
@ -204,7 +226,7 @@ steps:
|
||||
stepParams := []StepParameters{StepParameters{Name: "p0", Scope: []string{"GENERAL"}, Type: "string", Default: "p0_step_default", Aliases: []Alias{{Name: "p0_alias"}}}}
|
||||
testConf := "general:\n p1: p1_conf"
|
||||
|
||||
stepConfig, err := c.GetStepConfig(nil, "", ioutil.NopCloser(strings.NewReader(testConf)), nil, StepFilters{General: []string{"p0", "p1"}}, stepParams, "stage1", "step1")
|
||||
stepConfig, err := c.GetStepConfig(nil, "", ioutil.NopCloser(strings.NewReader(testConf)), nil, StepFilters{General: []string{"p0", "p1"}}, stepParams, nil, "stage1", "step1")
|
||||
|
||||
assert.NoError(t, err, "Error occured but no error expected")
|
||||
assert.Equal(t, "p0_step_default", stepConfig.Config["p0"])
|
||||
@ -214,7 +236,7 @@ steps:
|
||||
t.Run("Failure case config", func(t *testing.T) {
|
||||
var c Config
|
||||
myConfig := ioutil.NopCloser(strings.NewReader("invalid config"))
|
||||
_, err := c.GetStepConfig(nil, "", myConfig, nil, StepFilters{}, []StepParameters{}, "stage1", "step1")
|
||||
_, err := c.GetStepConfig(nil, "", myConfig, nil, StepFilters{}, []StepParameters{}, nil, "stage1", "step1")
|
||||
assert.EqualError(t, err, "failed to parse custom pipeline configuration: error unmarshalling \"invalid config\": error unmarshaling JSON: json: cannot unmarshal string into Go value of type config.Config", "default error expected")
|
||||
})
|
||||
|
||||
@ -222,7 +244,7 @@ steps:
|
||||
var c Config
|
||||
myConfig := ioutil.NopCloser(strings.NewReader(""))
|
||||
myDefaults := []io.ReadCloser{ioutil.NopCloser(strings.NewReader("invalid defaults"))}
|
||||
_, err := c.GetStepConfig(nil, "", myConfig, myDefaults, StepFilters{}, []StepParameters{}, "stage1", "step1")
|
||||
_, err := c.GetStepConfig(nil, "", myConfig, myDefaults, StepFilters{}, []StepParameters{}, nil, "stage1", "step1")
|
||||
assert.EqualError(t, err, "failed to parse pipeline default configuration: error unmarshalling \"invalid defaults\": error unmarshaling JSON: json: cannot unmarshal string into Go value of type config.Config", "default error expected")
|
||||
})
|
||||
|
||||
|
7
pkg/config/resources.go
Normal file
7
pkg/config/resources.go
Normal file
@ -0,0 +1,7 @@
|
||||
package config
|
||||
|
||||
// InfluxField is the constant for an Influx field
|
||||
const InfluxField = "field"
|
||||
|
||||
// InfluxTag is the constant for an Influx field
|
||||
const InfluxTag = "tag"
|
@ -5,6 +5,9 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/SAP/jenkins-library/pkg/piperenv"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
"github.com/pkg/errors"
|
||||
@ -25,8 +28,8 @@ type StepMetadata struct {
|
||||
|
||||
// StepSpec defines the spec details for a step, like step inputs, containers, sidecars, ...
|
||||
type StepSpec struct {
|
||||
Inputs StepInputs `json:"inputs"`
|
||||
// Outputs string `json:"description,omitempty"`
|
||||
Inputs StepInputs `json:"inputs,omitempty"`
|
||||
Outputs StepOutputs `json:"outputs,omitempty"`
|
||||
Containers []Container `json:"containers,omitempty"`
|
||||
Sidecars []Container `json:"sidecars,omitempty"`
|
||||
}
|
||||
@ -40,15 +43,22 @@ type StepInputs struct {
|
||||
|
||||
// StepParameters defines the parameters for a step
|
||||
type StepParameters struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
LongDescription string `json:"longDescription,omitempty"`
|
||||
Scope []string `json:"scope"`
|
||||
Type string `json:"type"`
|
||||
Mandatory bool `json:"mandatory,omitempty"`
|
||||
Default interface{} `json:"default,omitempty"`
|
||||
Aliases []Alias `json:"aliases,omitempty"`
|
||||
Conditions []Condition `json:"conditions,omitempty"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
LongDescription string `json:"longDescription,omitempty"`
|
||||
ResourceRef []ResourceReference `json:"resourceRef,omitempty"`
|
||||
Scope []string `json:"scope"`
|
||||
Type string `json:"type"`
|
||||
Mandatory bool `json:"mandatory,omitempty"`
|
||||
Default interface{} `json:"default,omitempty"`
|
||||
Aliases []Alias `json:"aliases,omitempty"`
|
||||
Conditions []Condition `json:"conditions,omitempty"`
|
||||
}
|
||||
|
||||
// ResourceReference defines the parameters of a resource reference
|
||||
type ResourceReference struct {
|
||||
Name string `json:"name"`
|
||||
Param string `json:"param"`
|
||||
}
|
||||
|
||||
// Alias defines a step input parameter alias
|
||||
@ -59,10 +69,11 @@ type Alias struct {
|
||||
|
||||
// StepResources defines the resources to be provided by the step context, e.g. Jenkins pipeline
|
||||
type StepResources struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
Conditions []Condition `json:"conditions,omitempty"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
Parameters []map[string]interface{} `json:"params,omitempty"`
|
||||
Conditions []Condition `json:"conditions,omitempty"`
|
||||
}
|
||||
|
||||
// StepSecrets defines the secrets to be provided by the step context, e.g. Jenkins pipeline
|
||||
@ -72,10 +83,10 @@ type StepSecrets struct {
|
||||
Type string `json:"type,omitempty"`
|
||||
}
|
||||
|
||||
// StepOutputs defines the outputs of a step
|
||||
//type StepOutputs struct {
|
||||
// Name string `json:"name"`
|
||||
//}
|
||||
// StepOutputs defines the outputs of a step step, typically one or multiple resources
|
||||
type StepOutputs struct {
|
||||
Resources []StepResources `json:"resources,omitempty"`
|
||||
}
|
||||
|
||||
// Container defines an execution container
|
||||
type Container struct {
|
||||
@ -318,6 +329,23 @@ func (m *StepData) GetContextDefaults(stepName string) (io.ReadCloser, error) {
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// GetResourceParameters retrieves parameters from a named pipeline resource with a defined path
|
||||
func (m *StepData) GetResourceParameters(path, name string) map[string]interface{} {
|
||||
resourceParams := map[string]interface{}{}
|
||||
|
||||
for _, param := range m.Spec.Inputs.Parameters {
|
||||
for _, res := range param.ResourceRef {
|
||||
if res.Name == name {
|
||||
if val := piperenv.GetParameter(filepath.Join(path, name), res.Param); len(val) > 0 {
|
||||
resourceParams[param.Name] = val
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return resourceParams
|
||||
}
|
||||
|
||||
func envVarsAsStringSlice(envVars []EnvVar) []string {
|
||||
e := []string{}
|
||||
for _, v := range envVars {
|
||||
|
@ -4,6 +4,8 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@ -442,3 +444,62 @@ func TestGetContextDefaults(t *testing.T) {
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetResourceParameters(t *testing.T) {
|
||||
tt := []struct {
|
||||
in StepData
|
||||
expected map[string]interface{}
|
||||
}{
|
||||
{
|
||||
in: StepData{Spec: StepSpec{Inputs: StepInputs{}}},
|
||||
expected: map[string]interface{}{},
|
||||
},
|
||||
{
|
||||
in: StepData{
|
||||
Spec: StepSpec{Inputs: StepInputs{Parameters: []StepParameters{
|
||||
{Name: "param1"},
|
||||
{Name: "param2"},
|
||||
}}}},
|
||||
expected: map[string]interface{}{},
|
||||
},
|
||||
{
|
||||
in: StepData{
|
||||
Spec: StepSpec{Inputs: StepInputs{Parameters: []StepParameters{
|
||||
{Name: "param1", ResourceRef: []ResourceReference{}},
|
||||
{Name: "param2", ResourceRef: []ResourceReference{}},
|
||||
}}}},
|
||||
expected: map[string]interface{}{},
|
||||
},
|
||||
{
|
||||
in: StepData{
|
||||
Spec: StepSpec{Inputs: StepInputs{Parameters: []StepParameters{
|
||||
{Name: "param1", ResourceRef: []ResourceReference{{Name: "notAvailable", Param: "envparam1"}}},
|
||||
{Name: "param2", ResourceRef: []ResourceReference{{Name: "commonPipelineEnvironment", Param: "envparam2"}}},
|
||||
}}}},
|
||||
expected: map[string]interface{}{"param2": "val2"},
|
||||
},
|
||||
}
|
||||
|
||||
dir, err := ioutil.TempDir("", "")
|
||||
if err != nil {
|
||||
t.Fatal("Failed to create temporary directory")
|
||||
}
|
||||
// clean up tmp dir
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
cpeDir := filepath.Join(dir, "commonPipelineEnvironment")
|
||||
err = os.MkdirAll(cpeDir, 0700)
|
||||
if err != nil {
|
||||
t.Fatal("Failed to create sub directory")
|
||||
}
|
||||
|
||||
ioutil.WriteFile(filepath.Join(cpeDir, "envparam1"), []byte("val1"), 0700)
|
||||
ioutil.WriteFile(filepath.Join(cpeDir, "envparam2"), []byte("val2"), 0700)
|
||||
|
||||
for run, test := range tt {
|
||||
t.Run(fmt.Sprintf("Run %v", run), func(t *testing.T) {
|
||||
got := test.in.GetResourceParameters(dir, "commonPipelineEnvironment")
|
||||
assert.Equal(t, test.expected, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"text/template"
|
||||
|
||||
"github.com/SAP/jenkins-library/pkg/config"
|
||||
"github.com/SAP/jenkins-library/pkg/piperutils"
|
||||
)
|
||||
|
||||
type stepInfo struct {
|
||||
@ -21,6 +22,7 @@ type stepInfo struct {
|
||||
Long string
|
||||
Metadata []config.StepParameters
|
||||
OSImport bool
|
||||
OutputResources []map[string]string
|
||||
Short string
|
||||
StepFunc string
|
||||
StepName string
|
||||
@ -30,11 +32,14 @@ type stepInfo struct {
|
||||
const stepGoTemplate = `package cmd
|
||||
|
||||
import (
|
||||
{{if .OSImport}}"os"{{end}}
|
||||
{{ if .OSImport }}"os"{{ end }}
|
||||
{{ if .OutputResources }}"fmt"{{ end }}
|
||||
{{ if .OutputResources }}"path/filepath"{{ end }}
|
||||
|
||||
{{if .ExportPrefix}}{{ .ExportPrefix }} "github.com/SAP/jenkins-library/cmd"{{end}}
|
||||
{{ if .ExportPrefix}}{{ .ExportPrefix }} "github.com/SAP/jenkins-library/cmd"{{ end -}}
|
||||
"github.com/SAP/jenkins-library/pkg/config"
|
||||
"github.com/SAP/jenkins-library/pkg/log"
|
||||
{{ if .OutputResources }}"github.com/SAP/jenkins-library/pkg/piperenv"{{ end }}
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@ -43,12 +48,18 @@ type {{ .StepName }}Options struct {
|
||||
{{ $value.Name | golangName }} {{ $value.Type }} ` + "`json:\"{{$value.Name}},omitempty\"`" + `{{end}}
|
||||
}
|
||||
|
||||
{{ range $notused, $oRes := .OutputResources }}
|
||||
{{ index $oRes "def"}}
|
||||
{{ end }}
|
||||
|
||||
var my{{ .StepName | title}}Options {{.StepName}}Options
|
||||
var {{ .StepName }}StepConfigJSON string
|
||||
|
||||
// {{.CobraCmdFuncName}} {{.Short}}
|
||||
func {{.CobraCmdFuncName}}() *cobra.Command {
|
||||
metadata := {{ .StepName }}Metadata()
|
||||
{{- range $notused, $oRes := .OutputResources }}
|
||||
var {{ index $oRes "name" }} {{ index $oRes "objectname" }}{{ end }}
|
||||
|
||||
var {{.CreateCmdVar}} = &cobra.Command{
|
||||
Use: "{{.StepName}}",
|
||||
Short: "{{.Short}}",
|
||||
@ -59,7 +70,15 @@ func {{.CobraCmdFuncName}}() *cobra.Command {
|
||||
return {{if .ExportPrefix}}{{ .ExportPrefix }}.{{end}}PrepareConfig(cmd, &metadata, "{{ .StepName }}", &my{{ .StepName | title}}Options, config.OpenPiperFile)
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return {{.StepName}}(my{{ .StepName | title }}Options)
|
||||
{{ if .OutputResources -}}
|
||||
handler := func() {
|
||||
{{- range $notused, $oRes := .OutputResources }}
|
||||
{{ index $oRes "name" }}.persist(GeneralConfig.EnvRootPath, "{{ index $oRes "name" }}"){{ end }}
|
||||
}
|
||||
log.DeferExitHandler(handler)
|
||||
defer handler()
|
||||
{{- end }}
|
||||
return {{.StepName}}(my{{ .StepName | title }}Options{{ range $notused, $oRes := .OutputResources}}, &{{ index $oRes "name" }}{{ end }})
|
||||
},
|
||||
}
|
||||
|
||||
@ -84,6 +103,7 @@ func {{ .StepName }}Metadata() config.StepData {
|
||||
{{- range $key, $value := .Metadata }}
|
||||
{
|
||||
Name: "{{ $value.Name }}",
|
||||
ResourceRef: []config.ResourceReference{{ "{" }}{{ range $notused, $ref := $value.ResourceRef }}{{ "{" }}Name: "{{ $ref.Name }}", Param: "{{ $ref.Param }}"{{ "}" }},{{ end }}{{ "}" }},
|
||||
Scope: []string{{ "{" }}{{ range $notused, $scope := $value.Scope }}"{{ $scope }}",{{ end }}{{ "}" }},
|
||||
Type: "{{ $value.Type }}",
|
||||
Mandatory: {{ $value.Mandatory }},
|
||||
@ -116,6 +136,17 @@ func Test{{.CobraCmdFuncName}}(t *testing.T) {
|
||||
}
|
||||
`
|
||||
|
||||
const stepGoImplementationTemplate = `package cmd
|
||||
import (
|
||||
"github.com/SAP/jenkins-library/pkg/log"
|
||||
)
|
||||
|
||||
func {{.StepName}}(config {{ .StepName }}Options{{ range $notused, $oRes := .OutputResources}}, {{ index $oRes "name" }} *{{ index $oRes "objectname" }} {{ end }}) error {
|
||||
log.Entry().WithField("customKey", "customValue").Info("This is how you write a log message with a custom field ...")
|
||||
return nil
|
||||
}
|
||||
`
|
||||
|
||||
// ProcessMetaFiles generates step coding based on step configuration provided in yaml files
|
||||
func ProcessMetaFiles(metadataFiles []string, stepHelperData StepHelperData, docuHelperData DocuHelperData) error {
|
||||
for key := range metadataFiles {
|
||||
@ -141,7 +172,8 @@ func ProcessMetaFiles(metadataFiles []string, stepHelperData StepHelperData, doc
|
||||
osImport, err = setDefaultParameters(&stepData)
|
||||
checkError(err)
|
||||
|
||||
myStepInfo := getStepInfo(&stepData, osImport, stepHelperData.ExportPrefix)
|
||||
myStepInfo, err := getStepInfo(&stepData, osImport, stepHelperData.ExportPrefix)
|
||||
checkError(err)
|
||||
|
||||
step := stepTemplate(myStepInfo)
|
||||
err = stepHelperData.WriteFile(fmt.Sprintf("cmd/%v_generated.go", stepData.Metadata.Name), step, 0644)
|
||||
@ -150,6 +182,13 @@ func ProcessMetaFiles(metadataFiles []string, stepHelperData StepHelperData, doc
|
||||
test := stepTestTemplate(myStepInfo)
|
||||
err = stepHelperData.WriteFile(fmt.Sprintf("cmd/%v_generated_test.go", stepData.Metadata.Name), test, 0644)
|
||||
checkError(err)
|
||||
|
||||
exists, _ := piperutils.FileExists(fmt.Sprintf("cmd/%v.go", stepData.Metadata.Name))
|
||||
if !exists {
|
||||
impl := stepImplementation(myStepInfo)
|
||||
err = stepHelperData.WriteFile(fmt.Sprintf("cmd/%v.go", stepData.Metadata.Name), impl, 0644)
|
||||
checkError(err)
|
||||
}
|
||||
} else {
|
||||
err = generateStepDocumentation(stepData, docuHelperData)
|
||||
if err != nil {
|
||||
@ -209,18 +248,91 @@ func setDefaultParameters(stepData *config.StepData) (bool, error) {
|
||||
return osImportRequired, nil
|
||||
}
|
||||
|
||||
func getStepInfo(stepData *config.StepData, osImport bool, exportPrefix string) stepInfo {
|
||||
func getStepInfo(stepData *config.StepData, osImport bool, exportPrefix string) (stepInfo, error) {
|
||||
oRes, err := getOutputResourceDetails(stepData)
|
||||
|
||||
return stepInfo{
|
||||
StepName: stepData.Metadata.Name,
|
||||
CobraCmdFuncName: fmt.Sprintf("%vCommand", strings.Title(stepData.Metadata.Name)),
|
||||
CreateCmdVar: fmt.Sprintf("create%vCmd", strings.Title(stepData.Metadata.Name)),
|
||||
Short: stepData.Metadata.Description,
|
||||
Long: stepData.Metadata.LongDescription,
|
||||
Metadata: stepData.Spec.Inputs.Parameters,
|
||||
FlagsFunc: fmt.Sprintf("add%vFlags", strings.Title(stepData.Metadata.Name)),
|
||||
OSImport: osImport,
|
||||
ExportPrefix: exportPrefix,
|
||||
StepName: stepData.Metadata.Name,
|
||||
CobraCmdFuncName: fmt.Sprintf("%vCommand", strings.Title(stepData.Metadata.Name)),
|
||||
CreateCmdVar: fmt.Sprintf("create%vCmd", strings.Title(stepData.Metadata.Name)),
|
||||
Short: stepData.Metadata.Description,
|
||||
Long: stepData.Metadata.LongDescription,
|
||||
Metadata: stepData.Spec.Inputs.Parameters,
|
||||
FlagsFunc: fmt.Sprintf("add%vFlags", strings.Title(stepData.Metadata.Name)),
|
||||
OSImport: osImport,
|
||||
OutputResources: oRes,
|
||||
ExportPrefix: exportPrefix,
|
||||
},
|
||||
err
|
||||
}
|
||||
|
||||
func getOutputResourceDetails(stepData *config.StepData) ([]map[string]string, error) {
|
||||
outputResources := []map[string]string{}
|
||||
|
||||
for _, res := range stepData.Spec.Outputs.Resources {
|
||||
currentResource := map[string]string{}
|
||||
currentResource["name"] = res.Name
|
||||
|
||||
switch res.Type {
|
||||
case "piperEnvironment":
|
||||
var envResource PiperEnvironmentResource
|
||||
envResource.Name = res.Name
|
||||
envResource.StepName = stepData.Metadata.Name
|
||||
for _, param := range res.Parameters {
|
||||
paramSections := strings.Split(fmt.Sprintf("%v", param["name"]), "/")
|
||||
category := ""
|
||||
name := paramSections[0]
|
||||
if len(paramSections) > 1 {
|
||||
name = strings.Join(paramSections[1:], "_")
|
||||
category = paramSections[0]
|
||||
if !contains(envResource.Categories, category) {
|
||||
envResource.Categories = append(envResource.Categories, category)
|
||||
}
|
||||
}
|
||||
envParam := PiperEnvironmentParameter{Category: category, Name: name}
|
||||
envResource.Parameters = append(envResource.Parameters, envParam)
|
||||
}
|
||||
def, err := envResource.StructString()
|
||||
if err != nil {
|
||||
return outputResources, err
|
||||
}
|
||||
currentResource["def"] = def
|
||||
currentResource["objectname"] = envResource.StructName()
|
||||
outputResources = append(outputResources, currentResource)
|
||||
case "influx":
|
||||
var influxResource InfluxResource
|
||||
influxResource.Name = res.Name
|
||||
influxResource.StepName = stepData.Metadata.Name
|
||||
for _, measurement := range res.Parameters {
|
||||
influxMeasurement := InfluxMeasurement{Name: fmt.Sprintf("%v", measurement["name"])}
|
||||
if fields, ok := measurement["fields"].([]interface{}); ok {
|
||||
for _, field := range fields {
|
||||
if fieldParams, ok := field.(map[string]interface{}); ok {
|
||||
influxMeasurement.Fields = append(influxMeasurement.Fields, InfluxMetric{Name: fmt.Sprintf("%v", fieldParams["name"])})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if tags, ok := measurement["tags"].([]interface{}); ok {
|
||||
for _, tag := range tags {
|
||||
if tagParams, ok := tag.(map[string]interface{}); ok {
|
||||
influxMeasurement.Tags = append(influxMeasurement.Tags, InfluxMetric{Name: fmt.Sprintf("%v", tagParams["name"])})
|
||||
}
|
||||
}
|
||||
}
|
||||
influxResource.Measurements = append(influxResource.Measurements, influxMeasurement)
|
||||
}
|
||||
def, err := influxResource.StructString()
|
||||
if err != nil {
|
||||
return outputResources, err
|
||||
}
|
||||
currentResource["def"] = def
|
||||
currentResource["objectname"] = influxResource.StructName()
|
||||
outputResources = append(outputResources, currentResource)
|
||||
}
|
||||
}
|
||||
|
||||
return outputResources, nil
|
||||
}
|
||||
|
||||
// MetadataFiles provides a list of all step metadata files
|
||||
@ -244,7 +356,7 @@ func stepTemplate(myStepInfo stepInfo) []byte {
|
||||
|
||||
funcMap := template.FuncMap{
|
||||
"flagType": flagType,
|
||||
"golangName": golangName,
|
||||
"golangName": golangNameTitle,
|
||||
"title": strings.Title,
|
||||
"longName": longName,
|
||||
}
|
||||
@ -263,7 +375,7 @@ func stepTestTemplate(myStepInfo stepInfo) []byte {
|
||||
|
||||
funcMap := template.FuncMap{
|
||||
"flagType": flagType,
|
||||
"golangName": golangName,
|
||||
"golangName": golangNameTitle,
|
||||
"title": strings.Title,
|
||||
}
|
||||
|
||||
@ -277,6 +389,22 @@ func stepTestTemplate(myStepInfo stepInfo) []byte {
|
||||
return generatedCode.Bytes()
|
||||
}
|
||||
|
||||
func stepImplementation(myStepInfo stepInfo) []byte {
|
||||
|
||||
funcMap := template.FuncMap{
|
||||
"title": strings.Title,
|
||||
}
|
||||
|
||||
tmpl, err := template.New("impl").Funcs(funcMap).Parse(stepGoImplementationTemplate)
|
||||
checkError(err)
|
||||
|
||||
var generatedCode bytes.Buffer
|
||||
err = tmpl.Execute(&generatedCode, myStepInfo)
|
||||
checkError(err)
|
||||
|
||||
return generatedCode.Bytes()
|
||||
}
|
||||
|
||||
func longName(long string) string {
|
||||
l := strings.ReplaceAll(long, "`", "` + \"`\" + `")
|
||||
l = strings.TrimSpace(l)
|
||||
@ -290,7 +418,11 @@ func golangName(name string) string {
|
||||
properName = strings.Replace(properName, "Id", "ID", -1)
|
||||
properName = strings.Replace(properName, "Json", "JSON", -1)
|
||||
properName = strings.Replace(properName, "json", "JSON", -1)
|
||||
return strings.Title(properName)
|
||||
return properName
|
||||
}
|
||||
|
||||
func golangNameTitle(name string) string {
|
||||
return strings.Title(golangName(name))
|
||||
}
|
||||
|
||||
func flagType(paramType string) string {
|
||||
|
@ -20,6 +20,22 @@ func configOpenFileMock(name string) (io.ReadCloser, error) {
|
||||
longDescription: |
|
||||
Long Test description
|
||||
spec:
|
||||
outputs:
|
||||
resources:
|
||||
- name: commonPipelineEnvironment
|
||||
type: piperEnvironment
|
||||
params:
|
||||
- name: artifactVersion
|
||||
- name: git/commitId
|
||||
- name: git/branch
|
||||
- name: influxTest
|
||||
type: influx
|
||||
params:
|
||||
- name: m1
|
||||
fields:
|
||||
- name: f1
|
||||
tags:
|
||||
- name: t1
|
||||
inputs:
|
||||
params:
|
||||
- name: param0
|
||||
@ -75,6 +91,7 @@ func TestProcessMetaFiles(t *testing.T) {
|
||||
t.Fatalf("failed reading %v", goldenFilePath)
|
||||
}
|
||||
assert.Equal(t, expected, files["cmd/testStep_generated.go"])
|
||||
t.Log(string(files["cmd/testStep_generated.go"]))
|
||||
})
|
||||
|
||||
t.Run("test code", func(t *testing.T) {
|
||||
@ -176,7 +193,9 @@ func TestGetStepInfo(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
myStepInfo := getStepInfo(&stepData, true, "")
|
||||
myStepInfo, err := getStepInfo(&stepData, true, "")
|
||||
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, "testStep", myStepInfo.StepName, "StepName incorrect")
|
||||
assert.Equal(t, "TestStepCommand", myStepInfo.CobraCmdFuncName, "CobraCmdFuncName incorrect")
|
||||
@ -203,7 +222,7 @@ func TestLongName(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGolangName(t *testing.T) {
|
||||
func TestGolangNameTitle(t *testing.T) {
|
||||
tt := []struct {
|
||||
input string
|
||||
expected string
|
||||
@ -217,7 +236,7 @@ func TestGolangName(t *testing.T) {
|
||||
}
|
||||
|
||||
for k, v := range tt {
|
||||
assert.Equal(t, v.expected, golangName(v.input), fmt.Sprintf("wrong golang name for run %v", k))
|
||||
assert.Equal(t, v.expected, golangNameTitle(v.input), fmt.Sprintf("wrong golang name for run %v", k))
|
||||
}
|
||||
}
|
||||
|
||||
|
191
pkg/generator/helper/resources.go
Normal file
191
pkg/generator/helper/resources.go
Normal file
@ -0,0 +1,191 @@
|
||||
package helper
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
// PiperEnvironmentResource defines a piper environement resource which stores data across multiple pipeline steps
|
||||
type PiperEnvironmentResource struct {
|
||||
Name string
|
||||
StepName string
|
||||
Parameters []PiperEnvironmentParameter
|
||||
Categories []string
|
||||
}
|
||||
|
||||
// PiperEnvironmentParameter defines a parameter within the Piper environment
|
||||
type PiperEnvironmentParameter struct {
|
||||
Category string
|
||||
Name string
|
||||
}
|
||||
|
||||
const piperEnvStructTemplate = `type {{ .StepName }}{{ .Name | title}} struct {
|
||||
{{ range $notused, $param := .Parameters }}
|
||||
{{- if not $param.Category}}{{ $param.Name | golangName }} string{{ end }}
|
||||
{{- end }}
|
||||
{{- range $notused, $category := .Categories }}
|
||||
{{ $category }} struct {
|
||||
{{- range $notused, $param := $.Parameters }}
|
||||
{{- if eq $category $param.Category }}
|
||||
{{ $param.Name | golangName }} string
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
}
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
func (p *{{ .StepName }}{{ .Name | title}}) persist(path, resourceName string) {
|
||||
content := []struct{
|
||||
category string
|
||||
name string
|
||||
value string
|
||||
}{
|
||||
{{- range $notused, $param := .Parameters }}
|
||||
{{- if not $param.Category}}
|
||||
{category: "", name: "{{ $param.Name }}", value: p.{{ $param.Name | golangName}}},
|
||||
{{- else }}
|
||||
{category: "{{ $param.Category }}", name: "{{ $param.Name }}", value: p.{{ $param.Category }}.{{ $param.Name | golangName}}},
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
errCount := 0
|
||||
for _, param := range content {
|
||||
err := piperenv.SetResourceParameter(path, resourceName, filepath.Join(param.category, param.name), param.value)
|
||||
if err != nil {
|
||||
log.Entry().WithError(err).Error("Error persisting piper environment.")
|
||||
errCount++
|
||||
}
|
||||
}
|
||||
if errCount > 0 {
|
||||
os.Exit(1)
|
||||
}
|
||||
}`
|
||||
|
||||
// StructName returns the name of the influx resource struct
|
||||
func (p *PiperEnvironmentResource) StructName() string {
|
||||
return fmt.Sprintf("%v%v", p.StepName, strings.Title(p.Name))
|
||||
}
|
||||
|
||||
// StructString returns the golang coding for the struct definition of the InfluxResource
|
||||
func (p *PiperEnvironmentResource) StructString() (string, error) {
|
||||
funcMap := template.FuncMap{
|
||||
"title": strings.Title,
|
||||
"golangName": golangName,
|
||||
}
|
||||
|
||||
tmpl, err := template.New("resources").Funcs(funcMap).Parse(piperEnvStructTemplate)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var generatedCode bytes.Buffer
|
||||
err = tmpl.Execute(&generatedCode, &p)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(generatedCode.Bytes()), nil
|
||||
}
|
||||
|
||||
// InfluxResource defines an Influx resouece that holds measurement information for a pipeline run
|
||||
type InfluxResource struct {
|
||||
Name string
|
||||
StepName string
|
||||
Measurements []InfluxMeasurement
|
||||
}
|
||||
|
||||
// InfluxMeasurement defines a measurement for Influx reporting which is defined via a step resource
|
||||
type InfluxMeasurement struct {
|
||||
Name string
|
||||
Fields []InfluxMetric
|
||||
Tags []InfluxMetric
|
||||
}
|
||||
|
||||
// InfluxMetric defines a metric (column) in an influx measurement
|
||||
type InfluxMetric struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
// InfluxMetricContent defines the content of an Inflx metric
|
||||
type InfluxMetricContent struct {
|
||||
Measurement string
|
||||
ValType string
|
||||
Name string
|
||||
Value *string
|
||||
}
|
||||
|
||||
const influxStructTemplate = `type {{ .StepName }}{{ .Name | title}} struct {
|
||||
{{- range $notused, $measurement := .Measurements }}
|
||||
{{ $measurement.Name }} struct {
|
||||
fields struct {
|
||||
{{- range $notused, $field := $measurement.Fields }}
|
||||
{{ $field.Name | golangName }} string
|
||||
{{- end }}
|
||||
}
|
||||
tags struct {
|
||||
{{- range $notused, $tag := $measurement.Tags }}
|
||||
{{ $tag.Name | golangName }} string
|
||||
{{- end }}
|
||||
}
|
||||
}
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
func (i *{{ .StepName }}{{ .Name | title}}) persist(path, resourceName string) {
|
||||
measurementContent := []struct{
|
||||
measurement string
|
||||
valType string
|
||||
name string
|
||||
value string
|
||||
}{
|
||||
{{- range $notused, $measurement := .Measurements }}
|
||||
{{- range $notused, $field := $measurement.Fields }}
|
||||
{valType: config.InfluxField, measurement: "{{ $measurement.Name }}" , name: "{{ $field.Name }}", value: i.{{ $measurement.Name }}.fields.{{ $field.Name | golangName }}},
|
||||
{{- end }}
|
||||
{{- range $notused, $tag := $measurement.Tags }}
|
||||
{valType: config.InfluxTag, measurement: "{{ $measurement.Name }}" , name: "{{ $tag.Name }}", value: i.{{ $measurement.Name }}.tags.{{ $tag.Name | golangName }}},
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
errCount := 0
|
||||
for _, metric := range measurementContent {
|
||||
err := piperenv.SetResourceParameter(path, resourceName, filepath.Join(metric.measurement, fmt.Sprintf("%vs", metric.valType), metric.name), metric.value)
|
||||
if err != nil {
|
||||
log.Entry().WithError(err).Error("Error persisting influx environment.")
|
||||
errCount++
|
||||
}
|
||||
}
|
||||
if errCount > 0 {
|
||||
os.Exit(1)
|
||||
}
|
||||
}`
|
||||
|
||||
// StructString returns the golang coding for the struct definition of the InfluxResource
|
||||
func (i *InfluxResource) StructString() (string, error) {
|
||||
funcMap := template.FuncMap{
|
||||
"title": strings.Title,
|
||||
"golangName": golangName,
|
||||
}
|
||||
|
||||
tmpl, err := template.New("resources").Funcs(funcMap).Parse(influxStructTemplate)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var generatedCode bytes.Buffer
|
||||
err = tmpl.Execute(&generatedCode, &i)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(generatedCode.Bytes()), nil
|
||||
}
|
||||
|
||||
// StructName returns the name of the influx resource struct
|
||||
func (i *InfluxResource) StructName() string {
|
||||
return fmt.Sprintf("%v%v", i.StepName, strings.Title(i.Name))
|
||||
}
|
94
pkg/generator/helper/resources_test.go
Normal file
94
pkg/generator/helper/resources_test.go
Normal file
@ -0,0 +1,94 @@
|
||||
package helper
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestStructString(t *testing.T) {
|
||||
tt := []struct {
|
||||
in InfluxResource
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
in: InfluxResource{
|
||||
Name: "TestInflux",
|
||||
StepName: "TestStep",
|
||||
Measurements: []InfluxMeasurement{
|
||||
{
|
||||
Name: "m1",
|
||||
Fields: []InfluxMetric{{Name: "field1_1"}, {Name: "field1_2"}},
|
||||
Tags: []InfluxMetric{{Name: "tag1_1"}, {Name: "tag1_2"}},
|
||||
},
|
||||
{
|
||||
Name: "m2",
|
||||
Fields: []InfluxMetric{{Name: "field2_1"}, {Name: "field2_2"}},
|
||||
Tags: []InfluxMetric{{Name: "tag2_1"}, {Name: "tag2_2"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: `type TestStepTestInflux struct {
|
||||
m1 struct {
|
||||
fields struct {
|
||||
field1_1 string
|
||||
field1_2 string
|
||||
}
|
||||
tags struct {
|
||||
tag1_1 string
|
||||
tag1_2 string
|
||||
}
|
||||
}
|
||||
m2 struct {
|
||||
fields struct {
|
||||
field2_1 string
|
||||
field2_2 string
|
||||
}
|
||||
tags struct {
|
||||
tag2_1 string
|
||||
tag2_2 string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (i *TestStepTestInflux) persist(path, resourceName string) {
|
||||
measurementContent := []struct{
|
||||
measurement string
|
||||
valType string
|
||||
name string
|
||||
value string
|
||||
}{
|
||||
{valType: config.InfluxField, measurement: "m1" , name: "field1_1", value: i.m1.fields.field1_1},
|
||||
{valType: config.InfluxField, measurement: "m1" , name: "field1_2", value: i.m1.fields.field1_2},
|
||||
{valType: config.InfluxTag, measurement: "m1" , name: "tag1_1", value: i.m1.tags.tag1_1},
|
||||
{valType: config.InfluxTag, measurement: "m1" , name: "tag1_2", value: i.m1.tags.tag1_2},
|
||||
{valType: config.InfluxField, measurement: "m2" , name: "field2_1", value: i.m2.fields.field2_1},
|
||||
{valType: config.InfluxField, measurement: "m2" , name: "field2_2", value: i.m2.fields.field2_2},
|
||||
{valType: config.InfluxTag, measurement: "m2" , name: "tag2_1", value: i.m2.tags.tag2_1},
|
||||
{valType: config.InfluxTag, measurement: "m2" , name: "tag2_2", value: i.m2.tags.tag2_2},
|
||||
}
|
||||
|
||||
errCount := 0
|
||||
for _, metric := range measurementContent {
|
||||
err := piperenv.SetResourceParameter(path, resourceName, filepath.Join(metric.measurement, fmt.Sprintf("%vs", metric.valType), metric.name), metric.value)
|
||||
if err != nil {
|
||||
log.Entry().WithError(err).Error("Error persisting influx environment.")
|
||||
errCount++
|
||||
}
|
||||
}
|
||||
if errCount > 0 {
|
||||
os.Exit(1)
|
||||
}
|
||||
}`,
|
||||
},
|
||||
}
|
||||
|
||||
for run, test := range tt {
|
||||
t.Run(fmt.Sprintf("Run %v", run), func(t *testing.T) {
|
||||
got, err := test.in.StructString()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, test.expected, got)
|
||||
})
|
||||
|
||||
}
|
||||
}
|
@ -2,10 +2,12 @@ package cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
|
||||
"github.com/SAP/jenkins-library/pkg/config"
|
||||
"github.com/SAP/jenkins-library/pkg/log"
|
||||
"github.com/SAP/jenkins-library/pkg/piperenv"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@ -15,12 +17,83 @@ type testStepOptions struct {
|
||||
Param2 string `json:"param2,omitempty"`
|
||||
}
|
||||
|
||||
|
||||
type testStepCommonPipelineEnvironment struct {
|
||||
artifactVersion string
|
||||
git struct {
|
||||
commitID string
|
||||
branch string
|
||||
}
|
||||
}
|
||||
|
||||
func (p *testStepCommonPipelineEnvironment) persist(path, resourceName string) {
|
||||
content := []struct{
|
||||
category string
|
||||
name string
|
||||
value string
|
||||
}{
|
||||
{category: "", name: "artifactVersion", value: p.artifactVersion},
|
||||
{category: "git", name: "commitId", value: p.git.commitID},
|
||||
{category: "git", name: "branch", value: p.git.branch},
|
||||
}
|
||||
|
||||
errCount := 0
|
||||
for _, param := range content {
|
||||
err := piperenv.SetResourceParameter(path, resourceName, filepath.Join(param.category, param.name), param.value)
|
||||
if err != nil {
|
||||
log.Entry().WithError(err).Error("Error persisting piper environment.")
|
||||
errCount++
|
||||
}
|
||||
}
|
||||
if errCount > 0 {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
type testStepInfluxTest struct {
|
||||
m1 struct {
|
||||
fields struct {
|
||||
f1 string
|
||||
}
|
||||
tags struct {
|
||||
t1 string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (i *testStepInfluxTest) persist(path, resourceName string) {
|
||||
measurementContent := []struct{
|
||||
measurement string
|
||||
valType string
|
||||
name string
|
||||
value string
|
||||
}{
|
||||
{valType: config.InfluxField, measurement: "m1" , name: "f1", value: i.m1.fields.f1},
|
||||
{valType: config.InfluxTag, measurement: "m1" , name: "t1", value: i.m1.tags.t1},
|
||||
}
|
||||
|
||||
errCount := 0
|
||||
for _, metric := range measurementContent {
|
||||
err := piperenv.SetResourceParameter(path, resourceName, filepath.Join(metric.measurement, fmt.Sprintf("%vs", metric.valType), metric.name), metric.value)
|
||||
if err != nil {
|
||||
log.Entry().WithError(err).Error("Error persisting influx environment.")
|
||||
errCount++
|
||||
}
|
||||
}
|
||||
if errCount > 0 {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var myTestStepOptions testStepOptions
|
||||
var testStepStepConfigJSON string
|
||||
|
||||
// TestStepCommand Test description
|
||||
func TestStepCommand() *cobra.Command {
|
||||
metadata := testStepMetadata()
|
||||
var commonPipelineEnvironment testStepCommonPipelineEnvironment
|
||||
var influxTest testStepInfluxTest
|
||||
|
||||
var createTestStepCmd = &cobra.Command{
|
||||
Use: "testStep",
|
||||
Short: "Test description",
|
||||
@ -31,7 +104,13 @@ func TestStepCommand() *cobra.Command {
|
||||
return PrepareConfig(cmd, &metadata, "testStep", &myTestStepOptions, config.OpenPiperFile)
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return testStep(myTestStepOptions)
|
||||
handler := func() {
|
||||
commonPipelineEnvironment.persist(GeneralConfig.EnvRootPath, "commonPipelineEnvironment")
|
||||
influxTest.persist(GeneralConfig.EnvRootPath, "influxTest")
|
||||
}
|
||||
log.DeferExitHandler(handler)
|
||||
defer handler()
|
||||
return testStep(myTestStepOptions, &commonPipelineEnvironment, &influxTest)
|
||||
},
|
||||
}
|
||||
|
||||
@ -56,6 +135,7 @@ func testStepMetadata() config.StepData {
|
||||
Parameters: []config.StepParameters{
|
||||
{
|
||||
Name: "param0",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"GENERAL","PARAMETERS",},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
@ -63,6 +143,7 @@ func testStepMetadata() config.StepData {
|
||||
},
|
||||
{
|
||||
Name: "param1",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS",},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
@ -70,6 +151,7 @@ func testStepMetadata() config.StepData {
|
||||
},
|
||||
{
|
||||
Name: "param2",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS",},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
|
@ -28,3 +28,8 @@ func SetVerbose(verbose bool) {
|
||||
func SetStepName(stepName string) {
|
||||
logger = Entry().WithField("stepName", stepName)
|
||||
}
|
||||
|
||||
// DeferExitHandler registers a logrus exit handler to allow cleanup activities.
|
||||
func DeferExitHandler(handler func()) {
|
||||
logrus.DeferExitHandler(handler)
|
||||
}
|
||||
|
62
pkg/piperenv/environment.go
Normal file
62
pkg/piperenv/environment.go
Normal file
@ -0,0 +1,62 @@
|
||||
package piperenv
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/SAP/jenkins-library/pkg/log"
|
||||
)
|
||||
|
||||
// This file contains functions used to read/write pipeline environment data from/to disk.
|
||||
// The content of a written file is the value. For the custom parameters this could for example also be a JSON representation of a more complex value.
|
||||
|
||||
// SetResourceParameter sets a resource parameter in the environment stored in the file system
|
||||
func SetResourceParameter(path, resourceName, paramName, value string) error {
|
||||
paramPath := filepath.Join(path, resourceName, paramName)
|
||||
return writeToDisk(paramPath, []byte(value))
|
||||
}
|
||||
|
||||
// GetResourceParameter reads a resource parameter from the environment stored in the file system
|
||||
func GetResourceParameter(path, resourceName, paramName string) string {
|
||||
paramPath := filepath.Join(path, resourceName, paramName)
|
||||
return readFromDisk(paramPath)
|
||||
}
|
||||
|
||||
// SetParameter sets any parameter in the pipeline environment or another environment stored in the file system
|
||||
func SetParameter(path, name, value string) error {
|
||||
paramPath := filepath.Join(path, name)
|
||||
return writeToDisk(paramPath, []byte(value))
|
||||
}
|
||||
|
||||
// GetParameter reads any parameter from the pipeline environment or another environment stored in the file system
|
||||
func GetParameter(path, name string) string {
|
||||
paramPath := filepath.Join(path, name)
|
||||
return readFromDisk(paramPath)
|
||||
}
|
||||
|
||||
func writeToDisk(filename string, data []byte) error {
|
||||
|
||||
if _, err := os.Stat(filepath.Dir(filename)); os.IsNotExist(err) {
|
||||
log.Entry().Debugf("Creating directory: %v", filepath.Dir(filename))
|
||||
os.MkdirAll(filepath.Dir(filename), 0700)
|
||||
}
|
||||
|
||||
//ToDo: make sure to not overwrite file but rather add another file? Create error if already existing?
|
||||
if len(data) > 0 {
|
||||
log.Entry().Debugf("Writing file to disk: %v", filename)
|
||||
return ioutil.WriteFile(filename, data, 0700)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func readFromDisk(filename string) string {
|
||||
//ToDo: if multiple files exist, read from latest file
|
||||
log.Entry().Debugf("Reading file from disk: %v", filename)
|
||||
v, err := ioutil.ReadFile(filename)
|
||||
val := string(v)
|
||||
if err != nil {
|
||||
val = ""
|
||||
}
|
||||
return val
|
||||
}
|
51
pkg/piperenv/environment_test.go
Normal file
51
pkg/piperenv/environment_test.go
Normal file
@ -0,0 +1,51 @@
|
||||
package piperenv
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestSetResourceParameter(t *testing.T) {
|
||||
dir, err := ioutil.TempDir("", "")
|
||||
if err != nil {
|
||||
t.Fatal("Failed to create temporary directory")
|
||||
}
|
||||
|
||||
// clean up tmp dir
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
err = SetResourceParameter(dir, "testRes", "testParam", "testVal")
|
||||
|
||||
assert.NoError(t, err, "Error occured but none expected")
|
||||
assert.Equal(t, "testVal", GetResourceParameter(dir, "testRes", "testParam"))
|
||||
}
|
||||
|
||||
func TestSetParameter(t *testing.T) {
|
||||
dir, err := ioutil.TempDir("", "")
|
||||
if err != nil {
|
||||
t.Fatal("Failed to create temporary directory")
|
||||
}
|
||||
|
||||
// clean up tmp dir
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
err = SetParameter(dir, "testParam", "testVal")
|
||||
|
||||
assert.NoError(t, err, "Error occured but none expected")
|
||||
assert.Equal(t, "testVal", GetParameter(dir, "testParam"))
|
||||
}
|
||||
|
||||
func TestReadFromDisk(t *testing.T) {
|
||||
dir, err := ioutil.TempDir("", "")
|
||||
if err != nil {
|
||||
t.Fatal("Failed to create temporary directory")
|
||||
}
|
||||
|
||||
// clean up tmp dir
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
assert.Equal(t, "", GetParameter(dir, "testParamNotExistingYet"))
|
||||
}
|
@ -15,134 +15,147 @@ metadata:
|
||||
spec:
|
||||
inputs:
|
||||
secrets:
|
||||
- name: githubTokenCredentialsId
|
||||
description: Jenkins 'Secret text' credentials ID containing token to authenticate to GitHub.
|
||||
type: jenkins
|
||||
- name: githubTokenCredentialsId
|
||||
description: Jenkins 'Secret text' credentials ID containing token to authenticate to GitHub.
|
||||
type: jenkins
|
||||
resources:
|
||||
- name: commonPipelineEnvironment
|
||||
resourceSpec:
|
||||
type: piperEnvironment
|
||||
params:
|
||||
- name: addClosedIssues
|
||||
description: 'If set to `true`, closed issues and merged pull-requests since the last release will added below the `releaseBodyHeader`'
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
type: bool
|
||||
default: false
|
||||
- name: addDeltaToLastRelease
|
||||
description: 'If set to `true`, a link will be added to the relese information that brings up all commits since the last release.'
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
type: bool
|
||||
default: false
|
||||
- name: assetPath
|
||||
description: Path to a release asset which should be uploaded to the list of release assets.
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
type: string
|
||||
- name: commitish
|
||||
description: 'Target git commitish for the release'
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
type: string
|
||||
default: "master"
|
||||
- name: excludeLabels
|
||||
description: 'Allows to exclude issues with dedicated list of labels.'
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
type: '[]string'
|
||||
- name: apiUrl
|
||||
aliases:
|
||||
- name: githubApiUrl
|
||||
description: Set the GitHub API url.
|
||||
scope:
|
||||
- GENERAL
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
type: string
|
||||
default: https://api.github.com
|
||||
mandatory: true
|
||||
- name: owner
|
||||
aliases:
|
||||
- name: githubOrg
|
||||
description: 'Set the GitHub organization.'
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
type: string
|
||||
mandatory: true
|
||||
- name: repository
|
||||
aliases:
|
||||
- name: githubRepo
|
||||
description: 'Set the GitHub repository.'
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
type: string
|
||||
mandatory: true
|
||||
- name: serverUrl
|
||||
aliases:
|
||||
- name: githubServerUrl
|
||||
description: 'GitHub server url for end-user access.'
|
||||
scope:
|
||||
- GENERAL
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
type: string
|
||||
default: https://github.com
|
||||
mandatory: true
|
||||
- name: token
|
||||
aliases:
|
||||
- name: githubToken
|
||||
description: 'GitHub personal access token as per https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line'
|
||||
scope:
|
||||
- GENERAL
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
type: string
|
||||
mandatory: true
|
||||
- name: uploadUrl
|
||||
aliases:
|
||||
- name: githubUploadUrl
|
||||
description: Set the GitHub API url.
|
||||
scope:
|
||||
- GENERAL
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
type: string
|
||||
default: https://uploads.github.com
|
||||
mandatory: true
|
||||
- name: labels
|
||||
description: 'Labels to include in issue search.'
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
type: '[]string'
|
||||
- name: releaseBodyHeader
|
||||
description: Content which will appear for the release.
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
type: string
|
||||
- name: version
|
||||
description: 'Define the version number which will be written as tag as well as release name.'
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
type: string
|
||||
mandatory: true
|
||||
- name: addClosedIssues
|
||||
description: 'If set to `true`, closed issues and merged pull-requests since the last release will added below the `releaseBodyHeader`'
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
type: bool
|
||||
default: false
|
||||
- name: addDeltaToLastRelease
|
||||
description: 'If set to `true`, a link will be added to the relese information that brings up all commits since the last release.'
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
type: bool
|
||||
default: false
|
||||
- name: apiUrl
|
||||
aliases:
|
||||
- name: githubApiUrl
|
||||
description: Set the GitHub API url.
|
||||
scope:
|
||||
- GENERAL
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
type: string
|
||||
default: https://api.github.com
|
||||
mandatory: true
|
||||
- name: assetPath
|
||||
description: Path to a release asset which should be uploaded to the list of release assets.
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
type: string
|
||||
- name: commitish
|
||||
description: 'Target git commitish for the release'
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
type: string
|
||||
default: "master"
|
||||
- name: excludeLabels
|
||||
description: 'Allows to exclude issues with dedicated list of labels.'
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
type: '[]string'
|
||||
- name: labels
|
||||
description: 'Labels to include in issue search.'
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
type: '[]string'
|
||||
- name: owner
|
||||
aliases:
|
||||
- name: githubOrg
|
||||
description: 'Set the GitHub organization.'
|
||||
resourceRef:
|
||||
- name: commonPipelineEnvironment
|
||||
param: github/owner
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
type: string
|
||||
mandatory: true
|
||||
- name: releaseBodyHeader
|
||||
description: Content which will appear for the release.
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
type: string
|
||||
- name: repository
|
||||
aliases:
|
||||
- name: githubRepo
|
||||
description: 'Set the GitHub repository.'
|
||||
resourceRef:
|
||||
- name: commonPipelineEnvironment
|
||||
param: github/repository
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
type: string
|
||||
mandatory: true
|
||||
- name: serverUrl
|
||||
aliases:
|
||||
- name: githubServerUrl
|
||||
description: 'GitHub server url for end-user access.'
|
||||
scope:
|
||||
- GENERAL
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
type: string
|
||||
default: https://github.com
|
||||
mandatory: true
|
||||
- name: token
|
||||
aliases:
|
||||
- name: githubToken
|
||||
description: 'GitHub personal access token as per https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line'
|
||||
scope:
|
||||
- GENERAL
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
type: string
|
||||
mandatory: true
|
||||
- name: uploadUrl
|
||||
aliases:
|
||||
- name: githubUploadUrl
|
||||
description: Set the GitHub API url.
|
||||
scope:
|
||||
- GENERAL
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
type: string
|
||||
default: https://uploads.github.com
|
||||
mandatory: true
|
||||
- name: version
|
||||
description: 'Define the version number which will be written as tag as well as release name.'
|
||||
resourceRef:
|
||||
- name: commonPipelineEnvironment
|
||||
param: artifactVersion
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
type: string
|
||||
mandatory: true
|
||||
|
@ -2,20 +2,27 @@ import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.rules.RuleChain
|
||||
import util.BasePiperTest
|
||||
import util.JenkinsFileExistsRule
|
||||
import util.JenkinsWriteFileRule
|
||||
import util.JenkinsReadYamlRule
|
||||
import util.Rules
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is
|
||||
import static org.hamcrest.Matchers.contains
|
||||
import static org.hamcrest.Matchers.hasItem
|
||||
import static org.junit.Assert.assertThat
|
||||
|
||||
class CommonPipelineEnvironmentTest extends BasePiperTest {
|
||||
|
||||
private JenkinsWriteFileRule writeFileRule = new JenkinsWriteFileRule(this)
|
||||
private JenkinsFileExistsRule fileExistsRule = new JenkinsFileExistsRule(this, [])
|
||||
|
||||
@Rule
|
||||
public RuleChain rules = Rules
|
||||
.getCommonRules(this)
|
||||
.around(new JenkinsReadYamlRule(this)
|
||||
)
|
||||
.around(new JenkinsReadYamlRule(this))
|
||||
.around(writeFileRule)
|
||||
.around(fileExistsRule)
|
||||
|
||||
@Test
|
||||
void testCustomValueList() {
|
||||
@ -34,4 +41,14 @@ class CommonPipelineEnvironmentTest extends BasePiperTest {
|
||||
assertThat(nullScript.commonPipelineEnvironment.getValue('myList').key1, is('val1'))
|
||||
assertThat(nullScript.commonPipelineEnvironment.getValue('myList').key2, is('val2'))
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWritetoDisk() {
|
||||
nullScript.commonPipelineEnvironment.artifactVersion = '1.0.0'
|
||||
nullScript.commonPipelineEnvironment.setValue('custom1', 'customVal1')
|
||||
nullScript.commonPipelineEnvironment.writeToDisk(nullScript)
|
||||
|
||||
assertThat(writeFileRule.files['.pipeline/commonPipelineEnvironment/artifactVersion'], is('1.0.0'))
|
||||
assertThat(writeFileRule.files['.pipeline/commonPipelineEnvironment/custom/custom1'], is('customVal1'))
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import org.junit.rules.ExpectedException
|
||||
import org.junit.rules.RuleChain
|
||||
import util.BasePiperTest
|
||||
import util.JenkinsCredentialsRule
|
||||
import util.JenkinsFileExistsRule
|
||||
import util.JenkinsLoggingRule
|
||||
import util.JenkinsReadJsonRule
|
||||
import util.JenkinsReadYamlRule
|
||||
@ -23,6 +24,7 @@ class GithubPublishReleaseTest extends BasePiperTest {
|
||||
private JenkinsShellCallRule shellCallRule = new JenkinsShellCallRule(this)
|
||||
private JenkinsStepRule stepRule = new JenkinsStepRule(this)
|
||||
private JenkinsWriteFileRule writeFileRule = new JenkinsWriteFileRule(this)
|
||||
private JenkinsFileExistsRule fileExistsRule = new JenkinsFileExistsRule(this, [])
|
||||
|
||||
private List withEnvArgs = []
|
||||
|
||||
@ -35,6 +37,7 @@ class GithubPublishReleaseTest extends BasePiperTest {
|
||||
.around(shellCallRule)
|
||||
.around(stepRule)
|
||||
.around(writeFileRule)
|
||||
.around(fileExistsRule)
|
||||
|
||||
@Before
|
||||
void init() {
|
||||
@ -58,26 +61,6 @@ class GithubPublishReleaseTest extends BasePiperTest {
|
||||
// asserts
|
||||
assertThat(writeFileRule.files['metadata/githubrelease.yaml'], containsString('name: githubPublishRelease'))
|
||||
assertThat(withEnvArgs[0], allOf(startsWith('PIPER_parametersJSON'), containsString('"testParam":"This is test content"')))
|
||||
assertThat(withEnvArgs[1], is('PIPER_owner='))
|
||||
assertThat(withEnvArgs[2], is('PIPER_repository='))
|
||||
assertThat(withEnvArgs[3], is('PIPER_version='))
|
||||
assertThat(shellCallRule.shell[1], is('./piper githubPublishRelease --token thisIsATestToken'))
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGithubPublishReleaseWithEnv() {
|
||||
|
||||
nullScript.commonPipelineEnvironment.setArtifactVersion('1.0.0')
|
||||
nullScript.commonPipelineEnvironment.setGithubOrg('TestOrg')
|
||||
nullScript.commonPipelineEnvironment.setGithubRepo('TestRepo')
|
||||
|
||||
stepRule.step.githubPublishRelease(
|
||||
juStabUtils: utils,
|
||||
script: nullScript
|
||||
)
|
||||
// asserts
|
||||
assertThat(withEnvArgs[1], is('PIPER_owner=TestOrg'))
|
||||
assertThat(withEnvArgs[2], is('PIPER_repository=TestRepo'))
|
||||
assertThat(withEnvArgs[3], is('PIPER_version=1.0.0'))
|
||||
}
|
||||
}
|
||||
|
@ -40,13 +40,13 @@ class JenkinsFileExistsRule implements TestRule {
|
||||
void evaluate() throws Throwable {
|
||||
|
||||
testInstance.helper.registerAllowedMethod('fileExists', [String.class], {s ->
|
||||
queriedFiles.add(s)
|
||||
return s in existingFiles
|
||||
queriedFiles.add(s.toString())
|
||||
return s.toString() in existingFiles
|
||||
})
|
||||
|
||||
testInstance.helper.registerAllowedMethod('fileExists', [Map.class], {m ->
|
||||
queriedFiles.add(m.file)
|
||||
return m.file in existingFiles}
|
||||
queriedFiles.add(m.file.toString())
|
||||
return m.file.toString() in existingFiles}
|
||||
)
|
||||
|
||||
base.evaluate()
|
||||
|
@ -144,8 +144,74 @@ class commonPipelineEnvironment implements Serializable {
|
||||
config = ConfigurationMerger.merge(configuration.get('stages')?.get(stageName) ?: [:], null, config)
|
||||
return config
|
||||
}
|
||||
|
||||
void writeToDisk(script) {
|
||||
|
||||
def files = [
|
||||
[filename: '.pipeline/commonPipelineEnvironment/artifactVersion', content: artifactVersion],
|
||||
[filename: '.pipeline/commonPipelineEnvironment/github/owner', content: githubOrg],
|
||||
[filename: '.pipeline/commonPipelineEnvironment/github/repository', content: githubRepo],
|
||||
[filename: '.pipeline/commonPipelineEnvironment/git/branch', content: gitBranch],
|
||||
[filename: '.pipeline/commonPipelineEnvironment/git/commitId', content: gitCommitId],
|
||||
[filename: '.pipeline/commonPipelineEnvironment/git/commitMessage', content: gitCommitMessage],
|
||||
]
|
||||
|
||||
files.each({f ->
|
||||
if (f.content && !script.fileExists(f.filename)) {
|
||||
script.writeFile file: f.filename, text: f.content
|
||||
}
|
||||
})
|
||||
|
||||
valueMap.each({key, value ->
|
||||
def fileName = ".pipeline/commonPipelineEnvironment/custom/${key}"
|
||||
if (value && !script.fileExists(fileName)) {
|
||||
//ToDo: check for value type and act accordingly?
|
||||
script.writeFile file: fileName, text: value
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
void readFromDisk() {
|
||||
def file = '.pipeline/commonPipelineEnvironment/artifactVersion'
|
||||
if (fileExists(file)) {
|
||||
artifactVersion = readFile(file)
|
||||
}
|
||||
|
||||
file = '.pipeline/commonPipelineEnvironment/github/owner'
|
||||
if (fileExists(file)) {
|
||||
githubOrg = readFile(file)
|
||||
}
|
||||
|
||||
file = '.pipeline/commonPipelineEnvironment/github/repository'
|
||||
if (fileExists(file)) {
|
||||
githubRepo = readFile(file)
|
||||
}
|
||||
|
||||
file = '.pipeline/commonPipelineEnvironment/git/branch'
|
||||
if (fileExists(file)) {
|
||||
gitBranch = readFile(file)
|
||||
}
|
||||
|
||||
file = '.pipeline/commonPipelineEnvironment/git/commitId'
|
||||
if (fileExists(file)) {
|
||||
gitCommitId = readFile(file)
|
||||
}
|
||||
|
||||
file = '.pipeline/commonPipelineEnvironment/git/commitMessage'
|
||||
if (fileExists(file)) {
|
||||
gitCommitMessage = readFile(file)
|
||||
}
|
||||
|
||||
def customValues = findFiles(glob: '.pipeline/commonPipelineEnvironment/custom/*')
|
||||
|
||||
customValues.each({f ->
|
||||
def fileName = f.getName()
|
||||
def param = fileName.split('/')[fileName.split('\\/').size()-1]
|
||||
valueMap[param] = readFile(f.getPath())
|
||||
})
|
||||
}
|
||||
|
||||
List getCustomDefaults() {
|
||||
DefaultValueCache.getInstance().getCustomDefaults()
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -23,14 +23,12 @@ void call(Map parameters = [:]) {
|
||||
|
||||
new PiperGoUtils(this, utils).unstashPiperBin()
|
||||
utils.unstash('pipelineConfigAndTests')
|
||||
script.commonPipelineEnvironment.writeToDisk(script)
|
||||
|
||||
writeFile(file: METADATA_FILE, text: libraryResource(METADATA_FILE))
|
||||
|
||||
withEnv([
|
||||
"PIPER_parametersJSON=${groovy.json.JsonOutput.toJson(parameters)}",
|
||||
"PIPER_owner=${script.commonPipelineEnvironment.getGithubOrg()?:''}",
|
||||
"PIPER_repository=${script.commonPipelineEnvironment.getGithubRepo()?:''}",
|
||||
"PIPER_version=${script.commonPipelineEnvironment.getArtifactVersion()?:''}"
|
||||
]) {
|
||||
// get context configuration
|
||||
config = readJSON (text: sh(returnStdout: true, script: "./piper getConfig --contextConfig --stepMetadata '${METADATA_FILE}'"))
|
||||
|
Loading…
Reference in New Issue
Block a user