From c14e7e1af7ef97e55804297fa2ed9f5c47275cf8 Mon Sep 17 00:00:00 2001 From: nikhilsbhat Date: Wed, 29 Mar 2023 22:27:57 +0530 Subject: [PATCH] Fix method CreatePipeline --- gocd.go | 2 +- pipeline_config.go | 30 ++++++++++--- pipeline_config_test.go | 22 +++++---- types.go | 98 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 136 insertions(+), 16 deletions(-) diff --git a/gocd.go b/gocd.go index 13521e9..35d6cbc 100644 --- a/gocd.go +++ b/gocd.go @@ -73,7 +73,7 @@ type GoCd interface { CommentOnPipeline(comment PipelineObject) error GetPipelineConfig(name string) (PipelineConfig, error) UpdatePipelineConfig(config PipelineConfig) (PipelineConfig, error) - CreatePipeline(config PipelineConfig) error + CreatePipeline(config PipelineConfig) (PipelineConfig, error) DeletePipeline(name string) error GetScheduledJobs() (ScheduledJobs, error) ExtractTemplatePipeline(pipeline, template string) (PipelineConfig, error) diff --git a/pipeline_config.go b/pipeline_config.go index 7bc9f9c..92dd7bb 100644 --- a/pipeline_config.go +++ b/pipeline_config.go @@ -85,14 +85,19 @@ func (conf *client) UpdatePipelineConfig(config PipelineConfig) (PipelineConfig, return pipelineConfig, nil } -func (conf *client) CreatePipeline(config PipelineConfig) error { +func (conf *client) CreatePipeline(config PipelineConfig) (PipelineConfig, error) { newClient := &client{} if err := copier.CopyWithOption(newClient, conf, copier.Option{IgnoreEmpty: true, DeepCopy: true}); err != nil { - return err + return PipelineConfig{}, err } pipelineName := config.Config["name"].(string) + pipelineConfig := map[string]interface{}{ + "pipeline": config.Config, + "group": config.Group, + } + defaultHeaders := map[string]string{ "Accept": HeaderVersionEleven, "Content-Type": ContentJSON, @@ -108,17 +113,30 @@ func (conf *client) CreatePipeline(config PipelineConfig) error { resp, err := newClient.httpClient.R(). SetHeaders(defaultHeaders). - SetBody(config.Config). + SetBody(pipelineConfig). Post(PipelineConfigEndpoint) if err != nil { - return &errors.APIError{Err: err, Message: fmt.Sprintf("create pipeline config '%s'", pipelineName)} + return PipelineConfig{}, &errors.APIError{Err: err, Message: fmt.Sprintf("create pipeline config '%s'", pipelineName)} } if resp.StatusCode() != http.StatusOK { - return &errors.NonOkError{Code: resp.StatusCode(), Response: resp} + return PipelineConfig{}, &errors.NonOkError{Code: resp.StatusCode(), Response: resp} } - return nil + var pipelineCfg map[string]interface{} + if err = json.Unmarshal(resp.Body(), &pipelineCfg); err != nil { + return PipelineConfig{}, &errors.MarshalError{Err: err} + } + + delete(pipelineCfg, "_links") + delete(pipelineCfg, "origin") + + var cfg PipelineConfig + + cfg.Config = pipelineCfg + cfg.ETAG = resp.Header().Get("ETag") + + return cfg, nil } func (conf *client) DeletePipeline(name string) error { diff --git a/pipeline_config_test.go b/pipeline_config_test.go index 6bc7ee9..90ce06c 100644 --- a/pipeline_config_test.go +++ b/pipeline_config_test.go @@ -487,18 +487,22 @@ func Test_client_CreatePipeline(t *testing.T) { correctPipelineConfigHeader := map[string]string{"Accept": gocd.HeaderVersionEleven} t.Run("should be able to create pipeline configuration successfully", func(t *testing.T) { server := mockServer([]byte(pipelineConfigJSON), http.StatusOK, - correctPipelineConfigHeader, false, nil) + correctPipelineConfigHeader, false, map[string]string{"ETag": "65dbc5f2d5b9c13a2cwxlfkjdlw23654eofixnwe3b3d8a6155d"}) client := gocd.NewClient(server.URL, auth, "info", nil) input := gocd.PipelineConfig{ - Config: map[string]interface{}{"name": "new_pipeline"}, + Group: "new_group", + Config: map[string]interface{}{ + "name": "new_pipeline", + }, ETAG: "65dbc5f2d5b9c13a2ccdlw23654b3b3d8a6155d", PausePipeline: true, } - err := client.CreatePipeline(input) + out, err := client.CreatePipeline(input) assert.NoError(t, err) + assert.Equal(t, "new_group", out.Config["group"].(string)) }) t.Run("should error out while creating pipeline configuration present in GoCD due to wrong headers", func(t *testing.T) { @@ -512,9 +516,9 @@ func Test_client_CreatePipeline(t *testing.T) { ETAG: "65dbc5f2d5b9c13a2ccdlw23654b3b3d8a6155d", } - err := client.CreatePipeline(input) + _, err := client.CreatePipeline(input) assert.EqualError(t, err, "got 404 from GoCD while making POST call for "+server.URL+ - "/api/admin/pipelines/new_pipeline\nwith BODY:\n\n\t

404 Not found

\n\n\n") + "/api/admin/pipelines\nwith BODY:\n\n\t

404 Not found

\n\n\n") }) t.Run("should error out while creating pipeline configuration present in GoCD due to missing headers", func(t *testing.T) { @@ -527,9 +531,9 @@ func Test_client_CreatePipeline(t *testing.T) { ETAG: "65dbc5f2d5b9c13a2ccdlw23654b3b3d8a6155d", } - err := client.CreatePipeline(input) + _, err := client.CreatePipeline(input) assert.EqualError(t, err, "got 404 from GoCD while making POST call for "+server.URL+ - "/api/admin/pipelines/new_pipeline\nwith BODY:\n\n\t

404 Not found

\n\n\n") + "/api/admin/pipelines\nwith BODY:\n\n\t

404 Not found

\n\n\n") }) t.Run("should error out while creating pipeline configuration present in GoCD as server is not reachable", func(t *testing.T) { @@ -543,8 +547,8 @@ func Test_client_CreatePipeline(t *testing.T) { ETAG: "65dbc5f2d5b9c13a2ccdlw23654b3b3d8a6155d", } - err := client.CreatePipeline(input) + _, err := client.CreatePipeline(input) assert.EqualError(t, err, "call made to create pipeline config 'new_pipeline' errored with: Post "+ - "\"http://localhost:8156/go/api/admin/pipelines/new_pipeline\": dial tcp [::1]:8156: connect: connection refused") + "\"http://localhost:8156/go/api/admin/pipelines\": dial tcp [::1]:8156: connect: connection refused") }) } diff --git a/types.go b/types.go index 2325251..bee6f48 100644 --- a/types.go +++ b/types.go @@ -140,6 +140,7 @@ type PipelineConfig struct { Config map[string]interface{} `json:"config,omitempty" yaml:"config,omitempty"` PausePipeline bool `json:"pause_pipeline,omitempty" yaml:"pause_pipeline,omitempty"` PauseReason string `json:"pause_reason,omitempty" yaml:"pause_reason,omitempty"` + Group string `json:"group,omitempty" yaml:"group,omitempty"` ETAG string `json:"etag,omitempty" yaml:"etag,omitempty"` } @@ -552,3 +553,100 @@ type UserRole struct { Name string `json:"name,omitempty" yaml:"name,omitempty"` Type string `json:"type,omitempty" yaml:"type,omitempty"` } + +// type ApprovalConfig struct { +// Type string `json:"type,omitempty" yaml:"type,omitempty"` +// OnlyOnSuccess bool `json:"allow_only_on_success,omitempty" yaml:"allow_only_on_success,omitempty"` +// Authorization AuthorizationConfig `json:"authorization,omitempty" yaml:"authorization,omitempty"` +//} +// +// type TimerConfig struct { +// Spec string `json:"spec,omitempty" yaml:"spec,omitempty"` +// OnlyOnChanges bool `json:"only_on_changes,omitempty" yaml:"only_on_changes,omitempty"` +//} +// +// type EnvironmentVariable struct { +// Name string `json:"name,omitempty" yaml:"name,omitempty"` +// Value string `json:"value,omitempty" yaml:"value,omitempty"` +// EncryptedValue string `json:"encrypted_value,omitempty" yaml:"encrypted_value,omitempty"` +// IsSecure bool `json:"secure,omitempty" yaml:"secure,omitempty"` +//} +// +// type Origin struct { +// Type string `json:"type,omitempty" yaml:"type,omitempty"` +// ID string `json:"id,omitempty" yaml:"id,omitempty"` +//} +// +// type AuthorizationConfig struct { +// Roles []string `json:"roles,omitempty" yaml:"roles,omitempty"` +// Users []string `json:"users,omitempty" yaml:"users,omitempty"` +// } +// +// type TaskConfig struct { +// Type string `json:"type,omitempty" yaml:"type,omitempty"` +// Attributes TaskAttribute `json:"attributes,omitempty" yaml:"attributes,omitempty"` +// } +// +// type TaskAttribute struct { +// RunIf []string `json:"run_if,omitempty" yaml:"run_if,omitempty"` +// Command string `json:"command,omitempty" yaml:"command,omitempty"` +// Args []string `json:"args,omitempty" yaml:"args,omitempty"` +// WorkingDirectory string `json:"working_directory,omitempty" yaml:"working_directory,omitempty"` +// OnCancel struct { +// RunIf []string `json:"run_if,omitempty" yaml:"run_if,omitempty"` +// Command string `json:"command,omitempty" yaml:"command,omitempty"` +// Args []string `json:"args,omitempty" yaml:"args,omitempty"` +// WorkingDirectory string `json:"working_directory,omitempty" yaml:"working_directory,omitempty"` +// } `json:"on_cancel,omitempty" yaml:"on_cancel,omitempty"` +// } +// +// type ArtifactConfig struct { +// } +// +// type JobConfig struct { +// Name string `json:"name,omitempty" yaml:"name,omitempty"` +// RunInstanceCount interface{} `json:"run_instance_count,omitempty" yaml:"run_instance_count,omitempty"` +// Timeout int `json:"timeout,omitempty" yaml:"timeout,omitempty"` +// EnvironmentVariables []EnvironmentVariable `json:"environment_variables,omitempty" yaml:"environment_variables,omitempty"` +// Resources []string `json:"resources,omitempty" yaml:"resources,omitempty"` +// Tasks []TaskConfig `json:"tasks,omitempty" yaml:"tasks,omitempty"` +// Artifacts []struct { +// Type string `json:"type,omitempty" yaml:"type,omitempty"` +// ArtifactID string `json:"artifact_id,omitempty" yaml:"artifact_id,omitempty"` +// StoreID string `json:"store_id,omitempty" yaml:"store_id,omitempty"` +// Configuration []struct { +// Key string `json:"key,omitempty" yaml:"key,omitempty"` +// Value string `json:"value,omitempty" yaml:"value,omitempty"` +// } `json:"configuration,omitempty" yaml:"configuration,omitempty"` +// } `json:"artifacts,omitempty" yaml:"artifacts,omitempty"` +// ElasticProfileID string `json:"elastic_profile_id,omitempty" yaml:"elastic_profile_id,omitempty"` +// } +// +// type Stage struct { +// Name string `json:"name,omitempty" yaml:"name,omitempty"` +// FetchMaterials bool `json:"fetch_materials,omitempty" yaml:"fetch_materials,omitempty"` +// CleanWorkingDirectory bool `json:"clean_working_directory,omitempty" yaml:"clean-working-directory,omitempty"` +// NeverCleanupArtifacts bool `json:"never_cleanup_artifacts,omitempty" yaml:"never_cleanup_artifacts,omitempty"` +// Approval ApprovalConfig `json:"approval,omitempty" yaml:"approval,omitempty"` +// EnvironmentVariables []EnvironmentVariable `json:"environment_variables,omitempty" yaml:"environment_variables,omitempty"` +// Jobs []JobConfig `json:"jobs,omitempty" yaml:"jobs,omitempty"` +// } +// +// type Parameter struct { +// Name string `json:"name,omitempty" yaml:"name,omitempty"` +// Value string `json:"value,omitempty" yaml:"value,omitempty"` +// } +// +// type AutoGenerated struct { +// PipelineGroup string `json:"group,omitempty,omitempty" yaml:"group,omitempty"` +// LabelTemplate string `json:"label_template,omitempty" yaml:"label_template,omitempty"` +// LockBehavior string `json:"lock_behavior,omitempty" yaml:"lock_behavior,omitempty"` +// Name string `json:"name,omitempty" yaml:"name,omitempty"` +// Template string `json:"template,omitempty" yaml:"template,omitempty"` +// Origin Origin `json:"origin,omitempty" yaml:"origin,omitempty"` +// Parameters []Parameter `json:"parameters,omitempty" yaml:"parameters,omitempty"` +// EnvironmentVariables []EnvironmentVariable `json:"environment_variables,omitempty" yaml:"environment_variables,omitempty"` +// Materials []Material `json:"materials,omitempty" yaml:"materials,omitempty"` +// Stages []Stage `json:"stages,omitempty" yaml:"stages,omitempty"` +// Timer TimerConfig `json:"timer,omitempty" yaml:"timer,omitempty"` +// }