From 98df5d0456920f0ee371b1da899c236d64ab93fd Mon Sep 17 00:00:00 2001 From: Roman Zipp Date: Sat, 15 Jan 2022 14:09:51 +0100 Subject: [PATCH 1/5] Add step struct json tags --- pipelines/step.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pipelines/step.go b/pipelines/step.go index eb186c4..407b514 100644 --- a/pipelines/step.go +++ b/pipelines/step.go @@ -10,8 +10,8 @@ const ( ) type Step struct { - Name string `faker:"name"` - Type StepType `faker:"-"` + Name string `json:"name" faker:"name"` + Type StepType `json:"type" faker:"-"` } func (s Step) Translate() (IExecutableStep, error) { From a4650f6900662bff228119b998de749f3467321c Mon Sep 17 00:00:00 2001 From: Roman Zipp Date: Sat, 15 Jan 2022 14:37:18 +0100 Subject: [PATCH 2/5] Add step options --- config/example.json | 14 ++++++-- pipelines/executable_step.go | 8 +++++ pipelines/executable_step_test.go | 55 +++++++++++++++++++++++++++++++ pipelines/pipeline.go | 2 +- pipelines/step.go | 28 +++++++++------- pipelines/step_test.go | 8 +++-- 6 files changed, 96 insertions(+), 19 deletions(-) create mode 100644 pipelines/executable_step_test.go diff --git a/config/example.json b/config/example.json index a8720a7..072d863 100644 --- a/config/example.json +++ b/config/example.json @@ -6,11 +6,19 @@ "steps": [ { "name": "resize image", - "type": 0 + "type": 0, + "options": { + "width": 1280, + "height": 720, + "upscale": false + } }, { "name": "compress image", - "type": 1 + "type": 1, + "options": { + "quality": 80 + } } ] -} \ No newline at end of file +} diff --git a/pipelines/executable_step.go b/pipelines/executable_step.go index 1ef14b7..371f0b9 100644 --- a/pipelines/executable_step.go +++ b/pipelines/executable_step.go @@ -8,6 +8,11 @@ type IExecutableStep interface { type ResizeImageStep struct { Step + Options struct { + Width int `json:"width"` + Height int `json:"height"` + Upscale bool `json:"upscale"` + } `json:"options"` } func (s ResizeImageStep) Execute() { @@ -18,6 +23,9 @@ func (s ResizeImageStep) Execute() { type CompressImageStep struct { Step + Options struct { + Quality int `json:"quality"` + } `json:"options"` } func (s CompressImageStep) Execute() { diff --git a/pipelines/executable_step_test.go b/pipelines/executable_step_test.go new file mode 100644 index 0000000..f7cddf9 --- /dev/null +++ b/pipelines/executable_step_test.go @@ -0,0 +1,55 @@ +package pipelines + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestDeserializeOptions(t *testing.T) { + const Payload string = `{ + "name": "example pipeline", + "type": 0, + "removeMetadata": false, + "steps": [ + { + "name": "resize image", + "type": 0, + "options": { + "width": 1280, + "height": 720, + "upscale": false + } + } + ] + }` + + t.Run("Image pipeline deserialization is successful", func(t *testing.T) { + values := DeserializePipelines([][]byte{[]byte(Payload)}) + + _, err := values[0].GetSteps()[0].Translate() + + assert.Equal(t, nil, err) + }) +} + +func TestDeserializeMissingOptions(t *testing.T) { + const Payload string = `{ + "name": "example pipeline", + "type": 0, + "removeMetadata": false, + "steps": [ + { + "name": "resize image", + "type": 0 + } + ] + }` + + t.Run("Image pipeline deserialization is successful", func(t *testing.T) { + values := DeserializePipelines([][]byte{[]byte(Payload)}) + + _, err := values[0].GetSteps()[0].Translate() + + assert.EqualError(t, err, "unexpected end of JSON input") + }) +} diff --git a/pipelines/pipeline.go b/pipelines/pipeline.go index 76d6e10..2e243e3 100644 --- a/pipelines/pipeline.go +++ b/pipelines/pipeline.go @@ -30,7 +30,7 @@ type Pipeline struct { Slug string `json:"slug" faker:"word"` Type PipelineType `json:"type" faker:"-"` RemoveMetadata bool `json:"remove_metadata" faker:"-"` - Steps []Step `json:"steps"` + Steps []Step `json:"steps" faker:"-"` } func (p Pipeline) GetName() string { diff --git a/pipelines/step.go b/pipelines/step.go index 407b514..99a95ad 100644 --- a/pipelines/step.go +++ b/pipelines/step.go @@ -1,6 +1,9 @@ package pipelines -import "errors" +import ( + "encoding/json" + "errors" +) type StepType int @@ -10,24 +13,25 @@ const ( ) type Step struct { - Name string `json:"name" faker:"name"` - Type StepType `json:"type" faker:"-"` + Name string `json:"name" faker:"name"` + Type StepType `json:"type" faker:"-"` + Options json.RawMessage `json:"options"` } func (s Step) Translate() (IExecutableStep, error) { - var step IExecutableStep switch s.GetType() { case TypeResizeImageStep: - step = ResizeImageStep{s} - case TypeCompressImageStep: - step = CompressImageStep{s} - } - - if step == nil { - return nil, errors.New("invalid type") + step := ResizeImageStep{} + if err := json.Unmarshal(s.Options, &step.Options); err != nil { + return nil, err + } + + return step, nil + //case TypeCompressImageStep: + // step = CompressImageStep{s} } - return step, nil + return nil, errors.New("invalid type") } func (s Step) GetType() StepType { diff --git a/pipelines/step_test.go b/pipelines/step_test.go index a61eca2..d1c1c4e 100644 --- a/pipelines/step_test.go +++ b/pipelines/step_test.go @@ -13,7 +13,8 @@ func TestTranslateStep(t *testing.T) { "steps": [ { "name": "resize image", - "type": 0 + "type": 0, + "options": {} } ] }` @@ -28,7 +29,7 @@ func TestTranslateStep(t *testing.T) { assert.Equal(t, TypeResizeImageStep, steps[0].GetType()) translated, err := steps[0].Translate() - assert.Equal(t, err, nil) + assert.Equal(t, nil, err) assert.IsType(t, ResizeImageStep{}, translated) }) } @@ -41,7 +42,8 @@ func TestInvalidStepType(t *testing.T) { "steps": [ { "name": "resize image", - "type": 99999 + "type": 99999, + "options": {} } ] }` From 7aca6b1a0dd22329081473980463ce521fcb01ca Mon Sep 17 00:00:00 2001 From: Roman Zipp Date: Sat, 15 Jan 2022 14:39:31 +0100 Subject: [PATCH 3/5] Add image compression step deserialization --- pipelines/executable_step_test.go | 27 ++++++++++++++++++++++++++- pipelines/step.go | 8 ++++++-- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/pipelines/executable_step_test.go b/pipelines/executable_step_test.go index f7cddf9..0a4bb31 100644 --- a/pipelines/executable_step_test.go +++ b/pipelines/executable_step_test.go @@ -5,7 +5,7 @@ import ( "testing" ) -func TestDeserializeOptions(t *testing.T) { +func TestDeserializeOptionsResizeImage(t *testing.T) { const Payload string = `{ "name": "example pipeline", "type": 0, @@ -32,6 +32,31 @@ func TestDeserializeOptions(t *testing.T) { }) } +func TestDeserializeOptionsCompressImage(t *testing.T) { + const Payload string = `{ + "name": "example pipeline", + "type": 0, + "removeMetadata": false, + "steps": [ + { + "name": "compress image", + "type": 1, + "options": { + "quality": 80 + } + } + ] + }` + + t.Run("Image pipeline deserialization is successful", func(t *testing.T) { + values := DeserializePipelines([][]byte{[]byte(Payload)}) + + _, err := values[0].GetSteps()[0].Translate() + + assert.Equal(t, nil, err) + }) +} + func TestDeserializeMissingOptions(t *testing.T) { const Payload string = `{ "name": "example pipeline", diff --git a/pipelines/step.go b/pipelines/step.go index 99a95ad..eaed75c 100644 --- a/pipelines/step.go +++ b/pipelines/step.go @@ -25,10 +25,14 @@ func (s Step) Translate() (IExecutableStep, error) { if err := json.Unmarshal(s.Options, &step.Options); err != nil { return nil, err } + return step, nil + case TypeCompressImageStep: + step := CompressImageStep{} + if err := json.Unmarshal(s.Options, &step.Options); err != nil { + return nil, err + } return step, nil - //case TypeCompressImageStep: - // step = CompressImageStep{s} } return nil, errors.New("invalid type") From d863b7211e3fae4bc1bf2e4fe05578464a7a6b83 Mon Sep 17 00:00:00 2001 From: Roman Zipp Date: Sat, 15 Jan 2022 14:40:50 +0100 Subject: [PATCH 4/5] Rename step executable getter method --- pipelines/executable_step_test.go | 6 +++--- pipelines/step.go | 2 +- pipelines/step_test.go | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pipelines/executable_step_test.go b/pipelines/executable_step_test.go index 0a4bb31..7719951 100644 --- a/pipelines/executable_step_test.go +++ b/pipelines/executable_step_test.go @@ -26,7 +26,7 @@ func TestDeserializeOptionsResizeImage(t *testing.T) { t.Run("Image pipeline deserialization is successful", func(t *testing.T) { values := DeserializePipelines([][]byte{[]byte(Payload)}) - _, err := values[0].GetSteps()[0].Translate() + _, err := values[0].GetSteps()[0].GetExecutable() assert.Equal(t, nil, err) }) @@ -51,7 +51,7 @@ func TestDeserializeOptionsCompressImage(t *testing.T) { t.Run("Image pipeline deserialization is successful", func(t *testing.T) { values := DeserializePipelines([][]byte{[]byte(Payload)}) - _, err := values[0].GetSteps()[0].Translate() + _, err := values[0].GetSteps()[0].GetExecutable() assert.Equal(t, nil, err) }) @@ -73,7 +73,7 @@ func TestDeserializeMissingOptions(t *testing.T) { t.Run("Image pipeline deserialization is successful", func(t *testing.T) { values := DeserializePipelines([][]byte{[]byte(Payload)}) - _, err := values[0].GetSteps()[0].Translate() + _, err := values[0].GetSteps()[0].GetExecutable() assert.EqualError(t, err, "unexpected end of JSON input") }) diff --git a/pipelines/step.go b/pipelines/step.go index eaed75c..aa80da3 100644 --- a/pipelines/step.go +++ b/pipelines/step.go @@ -18,7 +18,7 @@ type Step struct { Options json.RawMessage `json:"options"` } -func (s Step) Translate() (IExecutableStep, error) { +func (s Step) GetExecutable() (IExecutableStep, error) { switch s.GetType() { case TypeResizeImageStep: step := ResizeImageStep{} diff --git a/pipelines/step_test.go b/pipelines/step_test.go index d1c1c4e..f731f5f 100644 --- a/pipelines/step_test.go +++ b/pipelines/step_test.go @@ -28,7 +28,7 @@ func TestTranslateStep(t *testing.T) { assert.Equal(t, "resize image", steps[0].GetName()) assert.Equal(t, TypeResizeImageStep, steps[0].GetType()) - translated, err := steps[0].Translate() + translated, err := steps[0].GetExecutable() assert.Equal(t, nil, err) assert.IsType(t, ResizeImageStep{}, translated) }) @@ -57,7 +57,7 @@ func TestInvalidStepType(t *testing.T) { assert.Equal(t, "resize image", steps[0].GetName()) assert.Equal(t, StepType(99999), steps[0].GetType()) - translated, err := steps[0].Translate() + translated, err := steps[0].GetExecutable() assert.EqualError(t, err, "invalid type") assert.Nil(t, translated) }) From dbcf08b197b6b08352597588611e489f8188f643 Mon Sep 17 00:00:00 2001 From: Roman Zipp Date: Sat, 15 Jan 2022 14:43:29 +0100 Subject: [PATCH 5/5] Handle json encoding errors --- main.go | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/main.go b/main.go index 490b7ee..0b60c73 100644 --- a/main.go +++ b/main.go @@ -18,12 +18,18 @@ type Metadata struct { func PipelineHandler(pipeline pipelines.IPipeline, w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(pipeline) + err := json.NewEncoder(w).Encode(pipeline) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + } } func IndexHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(Metadata{Name, Version}) + err := json.NewEncoder(w).Encode(Metadata{Name, Version}) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + } } func RegisterPipelineRoutes(r *mux.Router, pipelines []pipelines.IPipeline) { @@ -42,5 +48,8 @@ func main() { RegisterPipelineRoutes(r, pipes) - http.ListenAndServe(":8000", r) + err := http.ListenAndServe(":8000", r) + if err != nil { + panic(err) + } }