From 4c26b942ee07869a4000e8abe217ea1095dc7682 Mon Sep 17 00:00:00 2001 From: tiloKo <70266685+tiloKo@users.noreply.github.com> Date: Tue, 26 Mar 2024 10:39:51 +0100 Subject: [PATCH 01/15] new step abapAddonAssemblyKitCheck --- cmd/abapAddonAssemblyKitCheck.go | 80 +++++ cmd/abapAddonAssemblyKitCheck_generated.go | 296 ++++++++++++++++++ ...bapAddonAssemblyKitCheck_generated_test.go | 20 ++ cmd/abapAddonAssemblyKitCheck_test.go | 52 +++ cmd/metadata_generated.go | 1 + .../metadata/abapAddonAssemblyKitCheck.yaml | 102 ++++++ 6 files changed, 551 insertions(+) create mode 100644 cmd/abapAddonAssemblyKitCheck.go create mode 100644 cmd/abapAddonAssemblyKitCheck_generated.go create mode 100644 cmd/abapAddonAssemblyKitCheck_generated_test.go create mode 100644 cmd/abapAddonAssemblyKitCheck_test.go create mode 100644 resources/metadata/abapAddonAssemblyKitCheck.yaml diff --git a/cmd/abapAddonAssemblyKitCheck.go b/cmd/abapAddonAssemblyKitCheck.go new file mode 100644 index 0000000000..37122b0d7b --- /dev/null +++ b/cmd/abapAddonAssemblyKitCheck.go @@ -0,0 +1,80 @@ +package cmd + +import ( + "github.com/SAP/jenkins-library/pkg/command" + piperhttp "github.com/SAP/jenkins-library/pkg/http" + "github.com/SAP/jenkins-library/pkg/log" + "github.com/SAP/jenkins-library/pkg/telemetry" +) + +type abapAddonAssemblyKitCheckUtils interface { + command.ExecRunner + piperhttp.Sender +} + +type abapAddonAssemblyKitCheckUtilsBundle struct { + *command.Command + *piperhttp.Client +} + +func newAbapAddonAssemblyKitCheckUtils() abapAddonAssemblyKitCheckUtils { + utils := abapAddonAssemblyKitCheckUtilsBundle{ + Command: &command.Command{}, + } + // Reroute command output to logging framework + utils.Stdout(log.Writer()) + utils.Stderr(log.Writer()) + return &utils +} + +func abapAddonAssemblyKitCheck(config abapAddonAssemblyKitCheckOptions, telemetryData *telemetry.CustomData, commonPipelineEnvironment *abapAddonAssemblyKitCheckCommonPipelineEnvironment) { + utils := newAbapAddonAssemblyKitCheckUtils() + + err := runAbapAddonAssemblyKitCheck(&config, telemetryData, utils, commonPipelineEnvironment) + if err != nil { + log.Entry().WithError(err).Fatal("step execution failed") + } +} + +func runAbapAddonAssemblyKitCheck(config *abapAddonAssemblyKitCheckOptions, telemetryData *telemetry.CustomData, utils abapAddonAssemblyKitCheckUtils, commonPipelineEnvironment *abapAddonAssemblyKitCheckCommonPipelineEnvironment) error { + + // log.Entry().WithField("LogField", "Log field content").Info("This is just a demo for a simple step.") + // // Example of calling methods from external dependencies directly on utils: + // exists, err := utils.FileExists("file.txt") + // if err != nil { + // // It is good practice to set an error category. + // // Most likely you want to do this at the place where enough context is known. + // log.SetErrorCategory(log.ErrorConfiguration) + // // Always wrap non-descriptive errors to enrich them with context for when they appear in the log: + // return fmt.Errorf("failed to check for important file: %w", err) + // } + // if !exists { + // log.SetErrorCategory(log.ErrorConfiguration) + // return fmt.Errorf("cannot run without important file") + // } + + return nil +} + +type ProductVersionHeader struct { + ProductName string + SemanticProductVersion string `json:"SemProductVersion"` + ProductVersion string + Spslevel string + PatchLevel string + Vendor string + VendorType string + Content []ProductVersionContent +} + +type ProductVersionContent struct { + ProductName string + SemanticProductVersion string `json:"SemProductVersion"` + SoftwareComponentName string `json:"ScName"` + SemanticSoftwareComponentVersion string `json:"SemScVersion"` + SoftwareComponentVersion string `json:"ScVersion"` + SpLevel string + PatchLevel string + Vendor string + VendorType string +} diff --git a/cmd/abapAddonAssemblyKitCheck_generated.go b/cmd/abapAddonAssemblyKitCheck_generated.go new file mode 100644 index 0000000000..1027325870 --- /dev/null +++ b/cmd/abapAddonAssemblyKitCheck_generated.go @@ -0,0 +1,296 @@ +// Code generated by piper's step-generator. DO NOT EDIT. + +package cmd + +import ( + "fmt" + "os" + "path/filepath" + "time" + + "github.com/SAP/jenkins-library/pkg/config" + "github.com/SAP/jenkins-library/pkg/log" + "github.com/SAP/jenkins-library/pkg/piperenv" + "github.com/SAP/jenkins-library/pkg/splunk" + "github.com/SAP/jenkins-library/pkg/telemetry" + "github.com/SAP/jenkins-library/pkg/validation" + "github.com/spf13/cobra" +) + +type abapAddonAssemblyKitCheckOptions struct { + AbapAddonAssemblyKitCertificateFile string `json:"abapAddonAssemblyKitCertificateFile,omitempty"` + AbapAddonAssemblyKitCertificatePass string `json:"abapAddonAssemblyKitCertificatePass,omitempty"` + AbapAddonAssemblyKitEndpoint string `json:"abapAddonAssemblyKitEndpoint,omitempty"` + Username string `json:"username,omitempty"` + Password string `json:"password,omitempty"` + AddonDescriptorFileName string `json:"addonDescriptorFileName,omitempty"` + AddonDescriptor string `json:"addonDescriptor,omitempty"` +} + +type abapAddonAssemblyKitCheckCommonPipelineEnvironment struct { + abap struct { + addonDescriptor string + } +} + +func (p *abapAddonAssemblyKitCheckCommonPipelineEnvironment) persist(path, resourceName string) { + content := []struct { + category string + name string + value interface{} + }{ + {category: "abap", name: "addonDescriptor", value: p.abap.addonDescriptor}, + } + + 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 { + log.Entry().Error("failed to persist Piper environment") + } +} + +// AbapAddonAssemblyKitCheckCommand This step calls AAKaaS to check the validity of the Addon Product Modelling. +func AbapAddonAssemblyKitCheckCommand() *cobra.Command { + const STEP_NAME = "abapAddonAssemblyKitCheck" + + metadata := abapAddonAssemblyKitCheckMetadata() + var stepConfig abapAddonAssemblyKitCheckOptions + var startTime time.Time + var commonPipelineEnvironment abapAddonAssemblyKitCheckCommonPipelineEnvironment + var logCollector *log.CollectorHook + var splunkClient *splunk.Splunk + telemetryClient := &telemetry.Telemetry{} + + var createAbapAddonAssemblyKitCheckCmd = &cobra.Command{ + Use: STEP_NAME, + Short: "This step calls AAKaaS to check the validity of the Addon Product Modelling.", + Long: `This step does the following: + +
+For logon to AAKaaS you can either provide a credential with basic authorization (username and password) or two secret text credentials containing the technical s-users certificate (see note [2805811](https://me.sap.com/notes/2805811) for download) as base64 encoded string and the password to decrypt the file +
+For Terminology refer to the [Scenario Description](https://www.project-piper.io/scenarios/abapEnvironmentAddons/).`, + PreRunE: func(cmd *cobra.Command, _ []string) error { + startTime = time.Now() + log.SetStepName(STEP_NAME) + log.SetVerbose(GeneralConfig.Verbose) + + GeneralConfig.GitHubAccessTokens = ResolveAccessTokens(GeneralConfig.GitHubTokens) + + path, _ := os.Getwd() + fatalHook := &log.FatalHook{CorrelationID: GeneralConfig.CorrelationID, Path: path} + log.RegisterHook(fatalHook) + + err := PrepareConfig(cmd, &metadata, STEP_NAME, &stepConfig, config.OpenPiperFile) + if err != nil { + log.SetErrorCategory(log.ErrorConfiguration) + return err + } + log.RegisterSecret(stepConfig.AbapAddonAssemblyKitCertificateFile) + log.RegisterSecret(stepConfig.AbapAddonAssemblyKitCertificatePass) + log.RegisterSecret(stepConfig.Username) + log.RegisterSecret(stepConfig.Password) + + if len(GeneralConfig.HookConfig.SentryConfig.Dsn) > 0 { + sentryHook := log.NewSentryHook(GeneralConfig.HookConfig.SentryConfig.Dsn, GeneralConfig.CorrelationID) + log.RegisterHook(&sentryHook) + } + + if len(GeneralConfig.HookConfig.SplunkConfig.Dsn) > 0 || len(GeneralConfig.HookConfig.SplunkConfig.ProdCriblEndpoint) > 0 { + splunkClient = &splunk.Splunk{} + logCollector = &log.CollectorHook{CorrelationID: GeneralConfig.CorrelationID} + log.RegisterHook(logCollector) + } + + if err = log.RegisterANSHookIfConfigured(GeneralConfig.CorrelationID); err != nil { + log.Entry().WithError(err).Warn("failed to set up SAP Alert Notification Service log hook") + } + + validation, err := validation.New(validation.WithJSONNamesForStructFields(), validation.WithPredefinedErrorMessages()) + if err != nil { + return err + } + if err = validation.ValidateStruct(stepConfig); err != nil { + log.SetErrorCategory(log.ErrorConfiguration) + return err + } + + return nil + }, + Run: func(_ *cobra.Command, _ []string) { + stepTelemetryData := telemetry.CustomData{} + stepTelemetryData.ErrorCode = "1" + handler := func() { + commonPipelineEnvironment.persist(GeneralConfig.EnvRootPath, "commonPipelineEnvironment") + config.RemoveVaultSecretFiles() + stepTelemetryData.Duration = fmt.Sprintf("%v", time.Since(startTime).Milliseconds()) + stepTelemetryData.ErrorCategory = log.GetErrorCategory().String() + stepTelemetryData.PiperCommitHash = GitCommit + telemetryClient.SetData(&stepTelemetryData) + telemetryClient.Send() + if len(GeneralConfig.HookConfig.SplunkConfig.Dsn) > 0 { + splunkClient.Initialize(GeneralConfig.CorrelationID, + GeneralConfig.HookConfig.SplunkConfig.Dsn, + GeneralConfig.HookConfig.SplunkConfig.Token, + GeneralConfig.HookConfig.SplunkConfig.Index, + GeneralConfig.HookConfig.SplunkConfig.SendLogs) + splunkClient.Send(telemetryClient.GetData(), logCollector) + } + if len(GeneralConfig.HookConfig.SplunkConfig.ProdCriblEndpoint) > 0 { + splunkClient.Initialize(GeneralConfig.CorrelationID, + GeneralConfig.HookConfig.SplunkConfig.ProdCriblEndpoint, + GeneralConfig.HookConfig.SplunkConfig.ProdCriblToken, + GeneralConfig.HookConfig.SplunkConfig.ProdCriblIndex, + GeneralConfig.HookConfig.SplunkConfig.SendLogs) + splunkClient.Send(telemetryClient.GetData(), logCollector) + } + } + log.DeferExitHandler(handler) + defer handler() + telemetryClient.Initialize(GeneralConfig.NoTelemetry, STEP_NAME, GeneralConfig.HookConfig.PendoConfig.Token) + abapAddonAssemblyKitCheck(stepConfig, &stepTelemetryData, &commonPipelineEnvironment) + stepTelemetryData.ErrorCode = "0" + log.Entry().Info("SUCCESS") + }, + } + + addAbapAddonAssemblyKitCheckFlags(createAbapAddonAssemblyKitCheckCmd, &stepConfig) + return createAbapAddonAssemblyKitCheckCmd +} + +func addAbapAddonAssemblyKitCheckFlags(cmd *cobra.Command, stepConfig *abapAddonAssemblyKitCheckOptions) { + cmd.Flags().StringVar(&stepConfig.AbapAddonAssemblyKitCertificateFile, "abapAddonAssemblyKitCertificateFile", os.Getenv("PIPER_abapAddonAssemblyKitCertificateFile"), "base64 encoded certificate pfx file (PKCS12 format) see note [2805811](https://me.sap.com/notes/2805811)") + cmd.Flags().StringVar(&stepConfig.AbapAddonAssemblyKitCertificatePass, "abapAddonAssemblyKitCertificatePass", os.Getenv("PIPER_abapAddonAssemblyKitCertificatePass"), "password to decrypt the certificate file") + cmd.Flags().StringVar(&stepConfig.AbapAddonAssemblyKitEndpoint, "abapAddonAssemblyKitEndpoint", `https://apps.support.sap.com`, "Base URL to the Addon Assembly Kit as a Service (AAKaaS) system") + cmd.Flags().StringVar(&stepConfig.Username, "username", os.Getenv("PIPER_username"), "User for the Addon Assembly Kit as a Service (AAKaaS) system") + cmd.Flags().StringVar(&stepConfig.Password, "password", os.Getenv("PIPER_password"), "Password for the Addon Assembly Kit as a Service (AAKaaS) system") + cmd.Flags().StringVar(&stepConfig.AddonDescriptorFileName, "addonDescriptorFileName", `addon.yml`, "File name of the YAML file which describes the Product Version and corresponding Software Component Versions") + cmd.Flags().StringVar(&stepConfig.AddonDescriptor, "addonDescriptor", os.Getenv("PIPER_addonDescriptor"), "Structure in the commonPipelineEnvironment containing information about the Product Version and corresponding Software Component Versions") + + cmd.MarkFlagRequired("abapAddonAssemblyKitEndpoint") + cmd.MarkFlagRequired("addonDescriptorFileName") +} + +// retrieve step metadata +func abapAddonAssemblyKitCheckMetadata() config.StepData { + var theMetaData = config.StepData{ + Metadata: config.StepMetadata{ + Name: "abapAddonAssemblyKitCheck", + Aliases: []config.Alias{}, + Description: "This step calls AAKaaS to check the validity of the Addon Product Modelling.", + }, + Spec: config.StepSpec{ + Inputs: config.StepInputs{ + Secrets: []config.StepSecrets{ + {Name: "abapAddonAssemblyKitCredentialsId", Description: "CredentialsId stored in Jenkins for the Addon Assembly Kit as a Service (AAKaaS) system", Type: "jenkins"}, + {Name: "abapAddonAssemblyKitCertificateFileCredentialsId", Description: "Jenkins secret text credential ID containing the base64 encoded certificate pfx file (PKCS12 format) see note [2805811](https://me.sap.com/notes/2805811)", Type: "jenkins"}, + {Name: "abapAddonAssemblyKitCertificatePassCredentialsId", Description: "Jenkins secret text credential ID containing the password to decrypt the certificate file stored in abapAddonAssemblyKitCertificateFileCredentialsId", Type: "jenkins"}, + }, + Parameters: []config.StepParameters{ + { + Name: "abapAddonAssemblyKitCertificateFile", + ResourceRef: []config.ResourceReference{ + { + Name: "abapAddonAssemblyKitCertificateFileCredentialsId", + Param: "abapAddonAssemblyKitCertificateFile", + Type: "secret", + }, + }, + Scope: []string{"PARAMETERS"}, + Type: "string", + Mandatory: false, + Aliases: []config.Alias{}, + Default: os.Getenv("PIPER_abapAddonAssemblyKitCertificateFile"), + }, + { + Name: "abapAddonAssemblyKitCertificatePass", + ResourceRef: []config.ResourceReference{ + { + Name: "abapAddonAssemblyKitCertificatePassCredentialsId", + Param: "abapAddonAssemblyKitCertificatePass", + Type: "secret", + }, + }, + Scope: []string{"PARAMETERS"}, + Type: "string", + Mandatory: false, + Aliases: []config.Alias{}, + Default: os.Getenv("PIPER_abapAddonAssemblyKitCertificatePass"), + }, + { + Name: "abapAddonAssemblyKitEndpoint", + ResourceRef: []config.ResourceReference{}, + Scope: []string{"PARAMETERS", "STAGES", "STEPS", "GENERAL"}, + Type: "string", + Mandatory: true, + Aliases: []config.Alias{}, + Default: `https://apps.support.sap.com`, + }, + { + Name: "username", + ResourceRef: []config.ResourceReference{}, + Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, + Type: "string", + Mandatory: false, + Aliases: []config.Alias{}, + Default: os.Getenv("PIPER_username"), + }, + { + Name: "password", + ResourceRef: []config.ResourceReference{}, + Scope: []string{"PARAMETERS"}, + Type: "string", + Mandatory: false, + Aliases: []config.Alias{}, + Default: os.Getenv("PIPER_password"), + }, + { + Name: "addonDescriptorFileName", + ResourceRef: []config.ResourceReference{}, + Scope: []string{"PARAMETERS", "STAGES", "STEPS", "GENERAL"}, + Type: "string", + Mandatory: true, + Aliases: []config.Alias{}, + Default: `addon.yml`, + }, + { + Name: "addonDescriptor", + ResourceRef: []config.ResourceReference{ + { + Name: "commonPipelineEnvironment", + Param: "abap/addonDescriptor", + }, + }, + Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, + Type: "string", + Mandatory: false, + Aliases: []config.Alias{}, + Default: os.Getenv("PIPER_addonDescriptor"), + }, + }, + }, + Outputs: config.StepOutputs{ + Resources: []config.StepResources{ + { + Name: "commonPipelineEnvironment", + Type: "piperEnvironment", + Parameters: []map[string]interface{}{ + {"name": "abap/addonDescriptor"}, + }, + }, + }, + }, + }, + } + return theMetaData +} diff --git a/cmd/abapAddonAssemblyKitCheck_generated_test.go b/cmd/abapAddonAssemblyKitCheck_generated_test.go new file mode 100644 index 0000000000..0cbf7de791 --- /dev/null +++ b/cmd/abapAddonAssemblyKitCheck_generated_test.go @@ -0,0 +1,20 @@ +//go:build unit +// +build unit + +package cmd + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestAbapAddonAssemblyKitCheckCommand(t *testing.T) { + t.Parallel() + + testCmd := AbapAddonAssemblyKitCheckCommand() + + // only high level testing performed - details are tested in step generation procedure + assert.Equal(t, "abapAddonAssemblyKitCheck", testCmd.Use, "command name incorrect") + +} diff --git a/cmd/abapAddonAssemblyKitCheck_test.go b/cmd/abapAddonAssemblyKitCheck_test.go new file mode 100644 index 0000000000..90ad05caae --- /dev/null +++ b/cmd/abapAddonAssemblyKitCheck_test.go @@ -0,0 +1,52 @@ +package cmd + +import ( + "testing" + + "github.com/SAP/jenkins-library/pkg/mock" + "github.com/stretchr/testify/assert" +) + +type abapAddonAssemblyKitCheckMockUtils struct { + *mock.ExecMockRunner + *mock.HttpClientMock +} + +func newAbapAddonAssemblyKitCheckTestsUtils() abapAddonAssemblyKitCheckUtils { + utils := abapAddonAssemblyKitCheckMockUtils{ + ExecMockRunner: &mock.ExecMockRunner{}, + } + return utils +} + +func TestRunAbapAddonAssemblyKitCheck(t *testing.T) { + t.Parallel() + + t.Run("happy path", func(t *testing.T) { + t.Parallel() + // init + config := abapAddonAssemblyKitCheckOptions{} + + utils := newAbapAddonAssemblyKitCheckTestsUtils() + + // test + err := runAbapAddonAssemblyKitCheck(&config, nil, utils, nil) + + // assert + assert.NoError(t, err) + }) + + t.Run("error path", func(t *testing.T) { + t.Parallel() + // init + config := abapAddonAssemblyKitCheckOptions{} + + utils := newAbapAddonAssemblyKitCheckTestsUtils() + + // test + err := runAbapAddonAssemblyKitCheck(&config, nil, utils, nil) + + // assert + assert.EqualError(t, err, "cannot run without important file") + }) +} diff --git a/cmd/metadata_generated.go b/cmd/metadata_generated.go index 21360f54dd..d39526eb13 100644 --- a/cmd/metadata_generated.go +++ b/cmd/metadata_generated.go @@ -7,6 +7,7 @@ import "github.com/SAP/jenkins-library/pkg/config" // GetStepMetadata return a map with all the step metadata mapped to their stepName func GetAllStepMetadata() map[string]config.StepData { return map[string]config.StepData{ + "abapAddonAssemblyKitCheck": abapAddonAssemblyKitCheckMetadata(), "abapAddonAssemblyKitCheckCVs": abapAddonAssemblyKitCheckCVsMetadata(), "abapAddonAssemblyKitCheckPV": abapAddonAssemblyKitCheckPVMetadata(), "abapAddonAssemblyKitCreateTargetVector": abapAddonAssemblyKitCreateTargetVectorMetadata(), diff --git a/resources/metadata/abapAddonAssemblyKitCheck.yaml b/resources/metadata/abapAddonAssemblyKitCheck.yaml new file mode 100644 index 0000000000..13b087e82b --- /dev/null +++ b/resources/metadata/abapAddonAssemblyKitCheck.yaml @@ -0,0 +1,102 @@ +metadata: + name: abapAddonAssemblyKitCheck + description: This step calls AAKaaS to check the validity of the Addon Product Modelling. + longDescription: | + This step does the following: + +
+ For logon to AAKaaS you can either provide a credential with basic authorization (username and password) or two secret text credentials containing the technical s-users certificate (see note [2805811](https://me.sap.com/notes/2805811) for download) as base64 encoded string and the password to decrypt the file +
+ For Terminology refer to the [Scenario Description](https://www.project-piper.io/scenarios/abapEnvironmentAddons/). +spec: + inputs: + secrets: + - name: abapAddonAssemblyKitCredentialsId + description: CredentialsId stored in Jenkins for the Addon Assembly Kit as a Service (AAKaaS) system + type: jenkins + - name: abapAddonAssemblyKitCertificateFileCredentialsId + description: Jenkins secret text credential ID containing the base64 encoded certificate pfx file (PKCS12 format) see note [2805811](https://me.sap.com/notes/2805811) + type: jenkins + - name: abapAddonAssemblyKitCertificatePassCredentialsId + description: Jenkins secret text credential ID containing the password to decrypt the certificate file stored in abapAddonAssemblyKitCertificateFileCredentialsId + type: jenkins + params: + - name: abapAddonAssemblyKitCertificateFile + type: string + description: base64 encoded certificate pfx file (PKCS12 format) see note [2805811](https://me.sap.com/notes/2805811) + scope: + - PARAMETERS + mandatory: false + secret: true + resourceRef: + - name: abapAddonAssemblyKitCertificateFileCredentialsId + type: secret + param: abapAddonAssemblyKitCertificateFile + - name: abapAddonAssemblyKitCertificatePass + type: string + description: password to decrypt the certificate file + scope: + - PARAMETERS + mandatory: false + secret: true + resourceRef: + - name: abapAddonAssemblyKitCertificatePassCredentialsId + type: secret + param: abapAddonAssemblyKitCertificatePass + - name: abapAddonAssemblyKitEndpoint + type: string + description: Base URL to the Addon Assembly Kit as a Service (AAKaaS) system + scope: + - PARAMETERS + - STAGES + - STEPS + - GENERAL + mandatory: true + default: https://apps.support.sap.com + - name: username + type: string + description: User for the Addon Assembly Kit as a Service (AAKaaS) system + scope: + - PARAMETERS + - STAGES + - STEPS + mandatory: false + secret: true + - name: password + type: string + description: Password for the Addon Assembly Kit as a Service (AAKaaS) system + scope: + - PARAMETERS + mandatory: false + secret: true + - name: addonDescriptorFileName + type: string + description: File name of the YAML file which describes the Product Version and corresponding Software Component Versions + mandatory: true + default: addon.yml + scope: + - PARAMETERS + - STAGES + - STEPS + - GENERAL + - name: addonDescriptor + type: string + description: Structure in the commonPipelineEnvironment containing information about the Product Version and corresponding Software Component Versions + mandatory: false + scope: + - PARAMETERS + - STAGES + - STEPS + resourceRef: + - name: commonPipelineEnvironment + param: abap/addonDescriptor + outputs: + resources: + - name: commonPipelineEnvironment + type: piperEnvironment + params: + - name: abap/addonDescriptor From 04db344c409c0641e06463139db2df23d097cb8a Mon Sep 17 00:00:00 2001 From: tiloKo <70266685+tiloKo@users.noreply.github.com> Date: Tue, 26 Mar 2024 16:10:42 +0100 Subject: [PATCH 02/15] build pv header from addon descriptor --- cmd/abapAddonAssemblyKitCheck.go | 91 ++++++++++++++++++++------- cmd/abapAddonAssemblyKitCheck_test.go | 56 ++++++++--------- 2 files changed, 94 insertions(+), 53 deletions(-) diff --git a/cmd/abapAddonAssemblyKitCheck.go b/cmd/abapAddonAssemblyKitCheck.go index 37122b0d7b..6aafb7423c 100644 --- a/cmd/abapAddonAssemblyKitCheck.go +++ b/cmd/abapAddonAssemblyKitCheck.go @@ -1,42 +1,48 @@ package cmd import ( - "github.com/SAP/jenkins-library/pkg/command" - piperhttp "github.com/SAP/jenkins-library/pkg/http" + "github.com/SAP/jenkins-library/pkg/abap/aakaas" + abapbuild "github.com/SAP/jenkins-library/pkg/abap/build" + "github.com/SAP/jenkins-library/pkg/abaputils" "github.com/SAP/jenkins-library/pkg/log" "github.com/SAP/jenkins-library/pkg/telemetry" + "github.com/pkg/errors" ) -type abapAddonAssemblyKitCheckUtils interface { - command.ExecRunner - piperhttp.Sender -} +func abapAddonAssemblyKitCheck(config abapAddonAssemblyKitCheckOptions, telemetryData *telemetry.CustomData, commonPipelineEnvironment *abapAddonAssemblyKitCheckCommonPipelineEnvironment) { + utils := aakaas.NewAakBundle() -type abapAddonAssemblyKitCheckUtilsBundle struct { - *command.Command - *piperhttp.Client + err := runAbapAddonAssemblyKitCheck(&config, telemetryData, utils, commonPipelineEnvironment) + if err != nil { + log.Entry().WithError(err).Fatal("step execution failed") + } } -func newAbapAddonAssemblyKitCheckUtils() abapAddonAssemblyKitCheckUtils { - utils := abapAddonAssemblyKitCheckUtilsBundle{ - Command: &command.Command{}, +func runAbapAddonAssemblyKitCheck(config *abapAddonAssemblyKitCheckOptions, telemetryData *telemetry.CustomData, utils aakaas.AakUtils, commonPipelineEnvironment *abapAddonAssemblyKitCheckCommonPipelineEnvironment) error { + + log.Entry().Info("╔═══════════════════════════╗") + log.Entry().Info("║ abapAddonAssemblyKitCheck ║") + log.Entry().Info("╚═══════════════════════════╝") + + conn := new(abapbuild.Connector) + if err := conn.InitAAKaaS(config.AbapAddonAssemblyKitEndpoint, config.Username, config.Password, utils, "", config.AbapAddonAssemblyKitCertificateFile, config.AbapAddonAssemblyKitCertificatePass); err != nil { + return err } - // Reroute command output to logging framework - utils.Stdout(log.Writer()) - utils.Stderr(log.Writer()) - return &utils -} -func abapAddonAssemblyKitCheck(config abapAddonAssemblyKitCheckOptions, telemetryData *telemetry.CustomData, commonPipelineEnvironment *abapAddonAssemblyKitCheckCommonPipelineEnvironment) { - utils := newAbapAddonAssemblyKitCheckUtils() + log.Entry().Infof("Reading addonDescriptor (aka addon.yml) file: %s", config.AddonDescriptorFileName) + addonDescriptor, err := utils.ReadAddonDescriptor(config.AddonDescriptorFileName) + if err != nil { + return err + } - err := runAbapAddonAssemblyKitCheck(&config, telemetryData, utils, commonPipelineEnvironment) + pvh, err := NewProductVersionHeader(&addonDescriptor, conn) if err != nil { - log.Entry().WithError(err).Fatal("step execution failed") + return err } -} -func runAbapAddonAssemblyKitCheck(config *abapAddonAssemblyKitCheckOptions, telemetryData *telemetry.CustomData, utils abapAddonAssemblyKitCheckUtils, commonPipelineEnvironment *abapAddonAssemblyKitCheckCommonPipelineEnvironment) error { + if err := pvh.check(); err != nil { + return err + } // log.Entry().WithField("LogField", "Log field content").Info("This is just a demo for a simple step.") // // Example of calling methods from external dependencies directly on utils: @@ -64,7 +70,7 @@ type ProductVersionHeader struct { PatchLevel string Vendor string VendorType string - Content []ProductVersionContent + Content []ProductVersionContent //maybe some struct in between see TargetVector??? } type ProductVersionContent struct { @@ -78,3 +84,40 @@ type ProductVersionContent struct { Vendor string VendorType string } + +func NewProductVersionHeader(addonDescriptor *abaputils.AddonDescriptor, conn *abapbuild.Connector) (*ProductVersionHeader, error) { + productVersion := new(aakaas.ProductVersion) + if err := productVersion.ConstructProductversion(*addonDescriptor, *conn); err != nil { + return nil, err + } + pvh := ProductVersionHeader{ + ProductName: productVersion.Name, + SemanticProductVersion: productVersion.Version, + Content: []ProductVersionContent{}, + } + + for _, repo := range addonDescriptor.Repositories { + componentVersion := new(aakaas.ComponentVersion) + if err := componentVersion.ConstructComponentVersion(repo, *conn); err != nil { + return nil, err + } + pvc := ProductVersionContent{ + ProductName: pvh.ProductName, + SemanticProductVersion: pvh.ProductName, + SoftwareComponentName: componentVersion.Name, + SemanticSoftwareComponentVersion: componentVersion.Version, + } + pvh.Content = append(pvh.Content, pvc) + } + + if len(pvh.Content) == 0 { + return nil, errors.New("addonDescriptor must contain at least one software component repository") + } + + return &pvh, nil +} + +func (pv *ProductVersionHeader) check() error { + + return nil +} diff --git a/cmd/abapAddonAssemblyKitCheck_test.go b/cmd/abapAddonAssemblyKitCheck_test.go index 90ad05caae..d196794b26 100644 --- a/cmd/abapAddonAssemblyKitCheck_test.go +++ b/cmd/abapAddonAssemblyKitCheck_test.go @@ -2,51 +2,49 @@ package cmd import ( "testing" - - "github.com/SAP/jenkins-library/pkg/mock" - "github.com/stretchr/testify/assert" + // "github.com/stretchr/testify/assert" ) -type abapAddonAssemblyKitCheckMockUtils struct { - *mock.ExecMockRunner - *mock.HttpClientMock -} +// type abapAddonAssemblyKitCheckMockUtils struct { +// *mock.ExecMockRunner +// *mock.HttpClientMock +// } -func newAbapAddonAssemblyKitCheckTestsUtils() abapAddonAssemblyKitCheckUtils { - utils := abapAddonAssemblyKitCheckMockUtils{ - ExecMockRunner: &mock.ExecMockRunner{}, - } - return utils -} +// func newAbapAddonAssemblyKitCheckTestsUtils() abapAddonAssemblyKitCheckUtils { +// utils := abapAddonAssemblyKitCheckMockUtils{ +// ExecMockRunner: &mock.ExecMockRunner{}, +// } +// return utils +// } func TestRunAbapAddonAssemblyKitCheck(t *testing.T) { t.Parallel() t.Run("happy path", func(t *testing.T) { - t.Parallel() - // init - config := abapAddonAssemblyKitCheckOptions{} + // t.Parallel() + // // init + // config := abapAddonAssemblyKitCheckOptions{} - utils := newAbapAddonAssemblyKitCheckTestsUtils() + // utils := newAbapAddonAssemblyKitCheckTestsUtils() - // test - err := runAbapAddonAssemblyKitCheck(&config, nil, utils, nil) + // // test + // err := runAbapAddonAssemblyKitCheck(&config, nil, utils, nil) - // assert - assert.NoError(t, err) + // // assert + // assert.NoError(t, err) }) t.Run("error path", func(t *testing.T) { - t.Parallel() - // init - config := abapAddonAssemblyKitCheckOptions{} + // t.Parallel() + // // init + // config := abapAddonAssemblyKitCheckOptions{} - utils := newAbapAddonAssemblyKitCheckTestsUtils() + // utils := newAbapAddonAssemblyKitCheckTestsUtils() - // test - err := runAbapAddonAssemblyKitCheck(&config, nil, utils, nil) + // // test + // err := runAbapAddonAssemblyKitCheck(&config, nil, utils, nil) - // assert - assert.EqualError(t, err, "cannot run without important file") + // // assert + // assert.EqualError(t, err, "cannot run without important file") }) } From fb61ee0560ff20fd9c71021669494c90799e92d4 Mon Sep 17 00:00:00 2001 From: tiloKo <70266685+tiloKo@users.noreply.github.com> Date: Fri, 5 Apr 2024 11:37:57 +0200 Subject: [PATCH 03/15] more functions --- cmd/abapAddonAssemblyKitCheck.go | 99 ++++++++++++++++++++++++++------ 1 file changed, 83 insertions(+), 16 deletions(-) diff --git a/cmd/abapAddonAssemblyKitCheck.go b/cmd/abapAddonAssemblyKitCheck.go index 6aafb7423c..a106f13a28 100644 --- a/cmd/abapAddonAssemblyKitCheck.go +++ b/cmd/abapAddonAssemblyKitCheck.go @@ -1,10 +1,13 @@ package cmd import ( + "encoding/json" + "github.com/SAP/jenkins-library/pkg/abap/aakaas" abapbuild "github.com/SAP/jenkins-library/pkg/abap/build" "github.com/SAP/jenkins-library/pkg/abaputils" "github.com/SAP/jenkins-library/pkg/log" + "github.com/SAP/jenkins-library/pkg/piperutils" "github.com/SAP/jenkins-library/pkg/telemetry" "github.com/pkg/errors" ) @@ -40,28 +43,28 @@ func runAbapAddonAssemblyKitCheck(config *abapAddonAssemblyKitCheckOptions, tele return err } - if err := pvh.check(); err != nil { + if err := pvh.checkAndResolveVersion(conn); err != nil { return err } + pvh.SyncAddonDescriptorVersionFields(&addonDescriptor) + + commonPipelineEnvironment.abap.addonDescriptor = string(addonDescriptor.AsJSON()) - // log.Entry().WithField("LogField", "Log field content").Info("This is just a demo for a simple step.") - // // Example of calling methods from external dependencies directly on utils: - // exists, err := utils.FileExists("file.txt") - // if err != nil { - // // It is good practice to set an error category. - // // Most likely you want to do this at the place where enough context is known. - // log.SetErrorCategory(log.ErrorConfiguration) - // // Always wrap non-descriptive errors to enrich them with context for when they appear in the log: - // return fmt.Errorf("failed to check for important file: %w", err) - // } - // if !exists { - // log.SetErrorCategory(log.ErrorConfiguration) - // return fmt.Errorf("cannot run without important file") - // } + publishAddonYaml(config, utils) return nil } +func publishAddonYaml(config *abapAddonAssemblyKitCheckOptions, utils aakaas.AakUtils) { + var filesToPublish []piperutils.Path + log.Entry().Infof("Add %s to be published", config.AddonDescriptorFileName) + filesToPublish = append(filesToPublish, piperutils.Path{Target: config.AddonDescriptorFileName, Name: "AddonDescriptor", Mandatory: true}) + log.Entry().Infof("Publishing %v files", len(filesToPublish)) + if err := piperutils.PersistReportsAndLinks("abapAddonAssemblyKitCheckPV", "", utils, filesToPublish, nil); err != nil { + log.Entry().WithError(err).Error("failed to persist report information") + } +} + type ProductVersionHeader struct { ProductName string SemanticProductVersion string `json:"SemProductVersion"` @@ -117,7 +120,71 @@ func NewProductVersionHeader(addonDescriptor *abaputils.AddonDescriptor, conn *a return &pvh, nil } -func (pv *ProductVersionHeader) check() error { +func (pv *ProductVersionHeader) checkAndResolveVersion(conn *abapbuild.Connector) error { + requestJson, err := json.Marshal(pv) + if err != nil { + return err + } + appendum := "/odata/aas_ocs_package/ProductVersionHeaderSet" + responseBody, err := conn.Post(appendum, string(requestJson)) + if err != nil { + return errors.Wrap(err, "Checking Product Modeling in AAkaaS failed") + } + var resultPv ProductVersionHeader //wrapper struct needed??? + if err := json.Unmarshal(responseBody, &resultPv); err != nil { + return errors.Wrap(err, "Unexpected AAKaaS response for checking Product Modeling "+string(responseBody)) + } + + pv.ProductVersion = resultPv.ProductVersion + pv.Spslevel = resultPv.Spslevel + pv.PatchLevel = resultPv.PatchLevel + + //transfer resolved version fields (and others) + for pvc_index, pvc := range pv.Content { + foundPvc := ProductVersionContent{} + for _, resultPvc := range resultPv.Content { + if pvc.SoftwareComponentName == resultPvc.SoftwareComponentName && foundPvc.SoftwareComponentName == "" { + foundPvc = resultPvc + } else if pvc.SoftwareComponentName == resultPvc.SoftwareComponentName { + return errors.New("Software Component Name must be unique in the ProductVersionContent") + } + } + if foundPvc.SoftwareComponentName == "" { + return errors.New("Software Component Name not found in the ProductVersionContent") + } + pv.Content[pvc_index].PatchLevel = foundPvc.PatchLevel + pv.Content[pvc_index].SpLevel = foundPvc.SpLevel + pv.Content[pvc_index].SoftwareComponentVersion = foundPvc.SoftwareComponentVersion + } + + return nil +} + +func (pv *ProductVersionHeader) SyncAddonDescriptorVersionFields(addonDescriptor *abaputils.AddonDescriptor) error { + addonDescriptor.AddonVersion = pv.ProductVersion + addonDescriptor.AddonSpsLevel = pv.Spslevel + addonDescriptor.AddonPatchLevel = pv.PatchLevel + + //in NewPvh function pvh was build up 1:1 based on addonDescriptor + //in checkAndResolve pvh was synced from AAKaaS reply assuming it does not contain more content than before(if it does it is ignored) + //anyway we are defenisve once more + for repo_index, repo := range addonDescriptor.Repositories { + foundPvc := ProductVersionContent{} + for _, pvc := range pv.Content { + if pvc.SoftwareComponentName == repo.Name && foundPvc.SoftwareComponentName == "" { + foundPvc = pvc + } else if pvc.SoftwareComponentName == repo.Name { + return errors.New("Software Component Name must be unique in addon descriptor(aka addon.yml)") + } + } + if foundPvc.SoftwareComponentName == "" { + return errors.New("ProductVersionContent & addon descriptor (aka addon.yml) out of sync") + } + + addonDescriptor.Repositories[repo_index].PatchLevel = foundPvc.PatchLevel + addonDescriptor.Repositories[repo_index].SpLevel = foundPvc.SpLevel + addonDescriptor.Repositories[repo_index].Version = foundPvc.SoftwareComponentVersion + } return nil } From ad621673fbe6e25d5c98862d0443d85acd5f5818 Mon Sep 17 00:00:00 2001 From: tiloKo <70266685+tiloKo@users.noreply.github.com> Date: Mon, 15 Apr 2024 15:25:53 +0200 Subject: [PATCH 04/15] happy path unit test --- cmd/abapAddonAssemblyKitCheck.go | 68 ++++++++++++++++++++++----- cmd/abapAddonAssemblyKitCheck_test.go | 59 +++++++++++++---------- pkg/abap/aakaas/aakUtils_mock.go | 7 ++- pkg/abap/aakaas/testData.go | 38 +++++++++++++++ 4 files changed, 134 insertions(+), 38 deletions(-) diff --git a/cmd/abapAddonAssemblyKitCheck.go b/cmd/abapAddonAssemblyKitCheck.go index a106f13a28..89b189c82d 100644 --- a/cmd/abapAddonAssemblyKitCheck.go +++ b/cmd/abapAddonAssemblyKitCheck.go @@ -37,24 +37,55 @@ func runAbapAddonAssemblyKitCheck(config *abapAddonAssemblyKitCheckOptions, tele if err != nil { return err } - + log.Entry().Info("Building Product Modeling (and Resolving potential wildcards)") pvh, err := NewProductVersionHeader(&addonDescriptor, conn) if err != nil { return err } + printProductVersionHeader(*pvh) + log.Entry().Info("Tranfering Product Modeling to AAKaaS to be checked...") if err := pvh.checkAndResolveVersion(conn); err != nil { return err } + log.Entry().Info("... success!") pvh.SyncAddonDescriptorVersionFields(&addonDescriptor) - + log.Entry().Info("Resolved Version Fields:") + printAddonDescriptorVersionFields(addonDescriptor) + log.Entry().Info("Transfering addonDescriptor to commonPipelineEnvironment for usage by following steps of the pipeline") commonPipelineEnvironment.abap.addonDescriptor = string(addonDescriptor.AsJSON()) publishAddonYaml(config, utils) - return nil } +func printProductVersionHeader(pvh ProductVersionHeader) { + logLine30 := "──────────────────────────────" + log.Entry().Infof("┌─%-30v─┬─%-30v─┐", logLine30, logLine30) + log.Entry().Infof("│ %-30v │ %-30v │", "Product Name", pvh.ProductName) + log.Entry().Infof("│ %-30v │ %-30v │", "Product Version", pvh.SemanticProductVersion) + log.Entry().Infof("├─%-30v─┼─%-30v─┤", logLine30, logLine30) + log.Entry().Infof("│ %-30v │ %-30v │", "Software Component Name", "Software Component Version") + log.Entry().Infof("├─%-30v─┼─%-30v─┤", logLine30, logLine30) + for _, pvc := range pvh.Content { + log.Entry().Infof("│ %-30v │ %-30v │", pvc.SoftwareComponentName, pvc.SemanticSoftwareComponentVersion) + } + log.Entry().Infof("└─%-30v─┴─%-30v─┘", logLine30, logLine30) +} + +func printAddonDescriptorVersionFields(addonDescriptor abaputils.AddonDescriptor) { + logLine30 := "──────────────────────────────" + logLine4 := "────" + log.Entry().Infof("┌─%-30v─┬─%-4v─┬─%-4v─┬─%-4v─┐", logLine30, logLine4, logLine4, logLine4) + log.Entry().Infof("│ %-30v │ %-4v │ %-4v │ %-4v │", "Name", "Vers", "SP", "Pat.") + log.Entry().Infof("├─%-30v─┼─%-4v─┼─%-4v─┼─%-4v─┤", logLine30, logLine4, logLine4, logLine4) + log.Entry().Infof("│ %-30v │ %-4v │ %-4v │ %-4v │", addonDescriptor.AddonProduct, addonDescriptor.AddonVersion, addonDescriptor.AddonSpsLevel, addonDescriptor.AddonPatchLevel) + for _, repo := range addonDescriptor.Repositories { + log.Entry().Infof("│ %-30v │ %-4v │ %-4v │ %-4v │", repo.Name, repo.Version, repo.SpLevel, repo.PatchLevel) + } + log.Entry().Infof("└─%-30v─┴─%-4v─┴─%-4v─┴─%-4v─┘", logLine30, logLine4, logLine4, logLine4) +} + func publishAddonYaml(config *abapAddonAssemblyKitCheckOptions, utils aakaas.AakUtils) { var filesToPublish []piperutils.Path log.Entry().Infof("Add %s to be published", config.AddonDescriptorFileName) @@ -65,6 +96,10 @@ func publishAddonYaml(config *abapAddonAssemblyKitCheckOptions, utils aakaas.Aak } } +type jsonProductVersionHeader struct { + Pvh *ProductVersionHeader `json:"d"` +} + type ProductVersionHeader struct { ProductName string SemanticProductVersion string `json:"SemProductVersion"` @@ -73,7 +108,12 @@ type ProductVersionHeader struct { PatchLevel string Vendor string VendorType string - Content []ProductVersionContent //maybe some struct in between see TargetVector??? + Content []ProductVersionContent `json:"-"` //for developer access + JsonContent ProductVersionContents `json:"Content"` //for json (Un)Marshaling +} + +type ProductVersionContents struct { + Content []ProductVersionContent `json:"results"` } type ProductVersionContent struct { @@ -106,7 +146,7 @@ func NewProductVersionHeader(addonDescriptor *abaputils.AddonDescriptor, conn *a } pvc := ProductVersionContent{ ProductName: pvh.ProductName, - SemanticProductVersion: pvh.ProductName, + SemanticProductVersion: pvh.SemanticProductVersion, SoftwareComponentName: componentVersion.Name, SemanticSoftwareComponentVersion: componentVersion.Version, } @@ -121,28 +161,32 @@ func NewProductVersionHeader(addonDescriptor *abaputils.AddonDescriptor, conn *a } func (pv *ProductVersionHeader) checkAndResolveVersion(conn *abapbuild.Connector) error { + pv.JsonContent = ProductVersionContents{ + Content: pv.Content, + } requestJson, err := json.Marshal(pv) if err != nil { return err } + appendum := "/odata/aas_ocs_package/ProductVersionHeaderSet" responseBody, err := conn.Post(appendum, string(requestJson)) if err != nil { return errors.Wrap(err, "Checking Product Modeling in AAkaaS failed") } - var resultPv ProductVersionHeader //wrapper struct needed??? + + var resultPv jsonProductVersionHeader if err := json.Unmarshal(responseBody, &resultPv); err != nil { return errors.Wrap(err, "Unexpected AAKaaS response for checking Product Modeling "+string(responseBody)) } - pv.ProductVersion = resultPv.ProductVersion - pv.Spslevel = resultPv.Spslevel - pv.PatchLevel = resultPv.PatchLevel + pv.ProductVersion = resultPv.Pvh.ProductVersion + pv.Spslevel = resultPv.Pvh.Spslevel + pv.PatchLevel = resultPv.Pvh.PatchLevel - //transfer resolved version fields (and others) for pvc_index, pvc := range pv.Content { foundPvc := ProductVersionContent{} - for _, resultPvc := range resultPv.Content { + for _, resultPvc := range resultPv.Pvh.JsonContent.Content { if pvc.SoftwareComponentName == resultPvc.SoftwareComponentName && foundPvc.SoftwareComponentName == "" { foundPvc = resultPvc } else if pvc.SoftwareComponentName == resultPvc.SoftwareComponentName { @@ -157,6 +201,7 @@ func (pv *ProductVersionHeader) checkAndResolveVersion(conn *abapbuild.Connector pv.Content[pvc_index].SoftwareComponentVersion = foundPvc.SoftwareComponentVersion } + pv.JsonContent = ProductVersionContents{} return nil } @@ -167,7 +212,6 @@ func (pv *ProductVersionHeader) SyncAddonDescriptorVersionFields(addonDescriptor //in NewPvh function pvh was build up 1:1 based on addonDescriptor //in checkAndResolve pvh was synced from AAKaaS reply assuming it does not contain more content than before(if it does it is ignored) - //anyway we are defenisve once more for repo_index, repo := range addonDescriptor.Repositories { foundPvc := ProductVersionContent{} for _, pvc := range pv.Content { diff --git a/cmd/abapAddonAssemblyKitCheck_test.go b/cmd/abapAddonAssemblyKitCheck_test.go index d196794b26..15e303c571 100644 --- a/cmd/abapAddonAssemblyKitCheck_test.go +++ b/cmd/abapAddonAssemblyKitCheck_test.go @@ -1,37 +1,46 @@ +//go:build unit +// +build unit + package cmd import ( "testing" - // "github.com/stretchr/testify/assert" -) -// type abapAddonAssemblyKitCheckMockUtils struct { -// *mock.ExecMockRunner -// *mock.HttpClientMock -// } - -// func newAbapAddonAssemblyKitCheckTestsUtils() abapAddonAssemblyKitCheckUtils { -// utils := abapAddonAssemblyKitCheckMockUtils{ -// ExecMockRunner: &mock.ExecMockRunner{}, -// } -// return utils -// } + "github.com/SAP/jenkins-library/pkg/abap/aakaas" + "github.com/SAP/jenkins-library/pkg/abaputils" + "github.com/stretchr/testify/assert" +) func TestRunAbapAddonAssemblyKitCheck(t *testing.T) { - t.Parallel() + var config abapAddonAssemblyKitCheckOptions + var cpe abapAddonAssemblyKitCheckCommonPipelineEnvironment + bundle := aakaas.NewAakBundleMock() + utils := bundle.GetUtils() + config.Username = "dummyUser" + config.Password = "dummyPassword" t.Run("happy path", func(t *testing.T) { - // t.Parallel() - // // init - // config := abapAddonAssemblyKitCheckOptions{} - - // utils := newAbapAddonAssemblyKitCheckTestsUtils() - - // // test - // err := runAbapAddonAssemblyKitCheck(&config, nil, utils, nil) - - // // assert - // assert.NoError(t, err) + config.AddonDescriptorFileName = "addon.yml.mock" + bundle.SetBody(aakaas.ResponseCheck) + bundle.MockAddonDescriptor = abaputils.AddonDescriptor{ + AddonProduct: "/DRNMSPC/PRD01", + AddonVersionYAML: "2.0.0", + Repositories: []abaputils.Repository{ + { + Name: "/DRNMSPC/COMP01", + VersionYAML: "2.0.0", + }, + { + Name: "/DRNMSPC/COMP02", + VersionYAML: "1.0.0", + }, + }, + } + + err := runAbapAddonAssemblyKitCheck(&config, nil, utils, &cpe) + + assert.NoError(t, err) + assert.EqualError(t, err, "dummy - get logoutput") }) t.Run("error path", func(t *testing.T) { diff --git a/pkg/abap/aakaas/aakUtils_mock.go b/pkg/abap/aakaas/aakUtils_mock.go index 307771ef4a..5e4de0a8f0 100644 --- a/pkg/abap/aakaas/aakUtils_mock.go +++ b/pkg/abap/aakaas/aakUtils_mock.go @@ -17,7 +17,8 @@ type AakBundleMock struct { *mock.ExecMockRunner *abaputils.ClientMock *mock.FilesMock - maxRuntime time.Duration + maxRuntime time.Duration + MockAddonDescriptor abaputils.AddonDescriptor } func NewAakBundleMock() *AakBundleMock { @@ -99,6 +100,10 @@ func (bundle *AakBundleMock) ReadAddonDescriptor(FileName string) (abaputils.Add { err = errors.New("error in ReadAddonDescriptor") } + case "addon.yml.mock": + { + return bundle.MockAddonDescriptor, nil + } } return addonDescriptor, err } diff --git a/pkg/abap/aakaas/testData.go b/pkg/abap/aakaas/testData.go index 3a0b10dbe4..adc64a167a 100644 --- a/pkg/abap/aakaas/testData.go +++ b/pkg/abap/aakaas/testData.go @@ -34,6 +34,44 @@ var ResponseCheckCVs = `{ } }` +var ResponseCheck = `{ + "d": { + "ProductName": "/DRNMSPC/PRD01", + "SemProductVersion": "2.0.0", + "ProductVersion": "0002", + "SpsLevel": "0000", + "PatchLevel": "0000", + "Vendor": "", + "VendorType": "", + "Content": { + "results": [ + { + "ProductName": "/DRNMSPC/PRD01", + "SemProductVersion": "2.0.0", + "ScName": "/DRNMSPC/COMP01", + "SemScVersion": "2.0.0", + "ScVersion": "0002", + "SpLevel": "0000", + "PatchLevel": "0000", + "Vendor": "", + "VendorType": "" + }, + { + "ProductName": "/DRNMSPC/PRD01", + "SemProductVersion": "2.0.0", + "ScName": "/DRNMSPC/COMP02", + "SemScVersion": "1.0.0", + "ScVersion": "0001", + "SpLevel": "0000", + "PatchLevel": "0000", + "Vendor": "", + "VendorType": "" + } + ] + } + } +}` + var emptyResultBody = `{ "d": { "results": [] From e00606ba0176cc5878bef054a1569d7eb6cd123b Mon Sep 17 00:00:00 2001 From: tiloKo <70266685+tiloKo@users.noreply.github.com> Date: Mon, 15 Apr 2024 15:41:15 +0200 Subject: [PATCH 05/15] one unhappy path --- cmd/abapAddonAssemblyKitCheck_test.go | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/cmd/abapAddonAssemblyKitCheck_test.go b/cmd/abapAddonAssemblyKitCheck_test.go index 15e303c571..a9b2f41fbe 100644 --- a/cmd/abapAddonAssemblyKitCheck_test.go +++ b/cmd/abapAddonAssemblyKitCheck_test.go @@ -40,20 +40,21 @@ func TestRunAbapAddonAssemblyKitCheck(t *testing.T) { err := runAbapAddonAssemblyKitCheck(&config, nil, utils, &cpe) assert.NoError(t, err) - assert.EqualError(t, err, "dummy - get logoutput") }) t.Run("error path", func(t *testing.T) { - // t.Parallel() - // // init - // config := abapAddonAssemblyKitCheckOptions{} - - // utils := newAbapAddonAssemblyKitCheckTestsUtils() + config.AddonDescriptorFileName = "addon.yml.mock" + bundle.SetBody(aakaas.ResponseCheck) + bundle.MockAddonDescriptor = abaputils.AddonDescriptor{ + AddonProduct: "/DRNMSPC/PRD01", + AddonVersionYAML: "2.0.0", + Repositories: []abaputils.Repository{ + //no repos should fail during pvh creation... + }, + } - // // test - // err := runAbapAddonAssemblyKitCheck(&config, nil, utils, nil) + err := runAbapAddonAssemblyKitCheck(&config, nil, utils, &cpe) - // // assert - // assert.EqualError(t, err, "cannot run without important file") + assert.EqualError(t, err, "addonDescriptor must contain at least one software component repository") }) } From 679a29641718b5f9401477c8264c25da286be0ec Mon Sep 17 00:00:00 2001 From: tiloKo <70266685+tiloKo@users.noreply.github.com> Date: Mon, 15 Apr 2024 15:56:14 +0200 Subject: [PATCH 06/15] fix trailing space yaml --- resources/metadata/abapAddonAssemblyKitCheck.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/metadata/abapAddonAssemblyKitCheck.yaml b/resources/metadata/abapAddonAssemblyKitCheck.yaml index 13b087e82b..dfa6eb90f2 100644 --- a/resources/metadata/abapAddonAssemblyKitCheck.yaml +++ b/resources/metadata/abapAddonAssemblyKitCheck.yaml @@ -3,7 +3,7 @@ metadata: description: This step calls AAKaaS to check the validity of the Addon Product Modelling. longDescription: | This step does the following: -