Skip to content

Commit

Permalink
[Ajat/Albert] move s3 and cloudfront package into aws package and ref…
Browse files Browse the repository at this point in the history
…actor storage.baseUrl to storage.baseURL
  • Loading branch information
albertus.raharja authored and ajatprabha committed Jul 1, 2019
1 parent 404b35f commit 7567fa9
Show file tree
Hide file tree
Showing 40 changed files with 1,298 additions and 32 deletions.
10 changes: 1 addition & 9 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,8 @@ FROM golang:alpine AS builder
ENV GO111MODULE=on
WORKDIR /app
COPY . .
RUN apk update && apk add --no-cache git openssh-client
RUN git config --global url."git@***REMOVED***:".insteadOf "https://***REMOVED***/"
ARG SSH_PRIVATE_KEY
RUN mkdir /root/.ssh/
RUN echo "${SSH_PRIVATE_KEY}" > /root/.ssh/id_rsa
RUN chmod 400 /root/.ssh/id_rsa
RUN touch /root/.ssh/known_hosts
RUN ssh-keyscan ***REMOVED*** >> /root/.ssh/known_hosts
RUN apk update && apk add --no-cache git
RUN GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o darkroom cmd/darkroom/main.go
RUN rm /root/.ssh/id_rsa

FROM alpine
RUN apk update && apk add --no-cache ca-certificates
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
[![coverage report](https://***REMOVED***/darkroom/core/badges/master/coverage.svg)](https://***REMOVED***/darkroom/core/commits/master)

#### About
This project combines the darkroom [storage backend](https://***REMOVED***/darkroom/storage) and the [image processor](https://***REMOVED***/darkroom/processor) and acts as an `Image Proxy` on your image source.
This project combines the darkroom [storage backend](pkg/storage) and the [image processor](pkg/processor) and acts as an `Image Proxy` on your image source.
You may implement your own `Storage` and `Processor` interfaces to gain custom functionality while still keeping other Darkroom Server functionality.

#### Installation
Expand Down Expand Up @@ -40,7 +40,7 @@ SOURCE_HYSTRIX_ERRORPERCENTTHRESHOLD=25
```
Build the docker image and run it with the config created.
```bash
docker build --build-arg SSH_PRIVATE_KEY="$(cat ~/.ssh/id_rsa)" -t ${USER}/darkroom:latest .
docker build -t ${USER}/darkroom:latest .
docker run -p 80:3000 --env-file ./config.env ${USER}/darkroom:latest
```

Expand Down
14 changes: 8 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,23 @@ go 1.12

require (
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5
github.com/aws/aws-sdk-go v1.20.0 // indirect
github.com/anthonynsimon/bild v0.10.0
github.com/aws/aws-sdk-go v1.20.0
github.com/axw/gocov v0.0.0-20170322000131-3a69a0d2a4ef // indirect
github.com/gojektech/heimdall v5.0.2+incompatible
github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c // indirect
github.com/gorilla/mux v1.7.2
github.com/pkg/errors v0.8.1
github.com/sirupsen/logrus v1.4.2
github.com/smartystreets/assertions v1.0.0 // indirect
github.com/spf13/viper v1.4.0
github.com/stretchr/objx v0.2.0 // indirect
github.com/stretchr/testify v1.3.0
github.com/urfave/cli v1.20.0
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 // indirect
golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56 // indirect
golang.org/x/lint v0.0.0-20190409202823-959b441ac422 // indirect
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980 // indirect
golang.org/x/sys v0.0.0-20190614084037-d442b75600c5 // indirect
golang.org/x/tools v0.0.0-20190613204242-ed0dc450797f // indirect
***REMOVED***/darkroom/processor v0.0.0-20190612103256-1f5dcc37d42e
***REMOVED***/darkroom/storage v0.0.0-20190613152558-7fe54b92b0d4
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f // indirect
golang.org/x/text v0.3.2 // indirect
golang.org/x/tools v0.0.0-20190617190820-da514acc4774 // indirect
)
5 changes: 5 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422 h1:QzoH/1pFpZguR8NrRHLcO6jKqfv2zpuSqZLgdm7ZmjI=
Expand Down Expand Up @@ -174,6 +175,8 @@ golang.org/x/sys v0.0.0-20190613124609-5ed2794edfdc h1:x+/QxSNkVFAC+v4pL1f6mZr1z
golang.org/x/sys v0.0.0-20190613124609-5ed2794edfdc/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190614084037-d442b75600c5 h1:tQrtnaPeNyfkuD2UMixVD6lAa7WngkIFvtWcdzNeq80=
golang.org/x/sys v0.0.0-20190614084037-d442b75600c5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f h1:25KHgbfyiSm6vwQLbM3zZIe1v9p/3ea4Rz+nnM5K/i4=
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
Expand All @@ -187,6 +190,8 @@ golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3
golang.org/x/tools v0.0.0-20190603231351-8aaa1484dc10/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190613204242-ed0dc450797f h1:+zypR5600WBcnJgA2nzZAsBlM8cArEGa8dhhiNE4u3w=
golang.org/x/tools v0.0.0-20190613204242-ed0dc450797f/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190617190820-da514acc4774 h1:CQVOmarCBFzTx0kbOU0ru54Cvot8SdSrNYjZPhQl+gk=
golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
Expand Down
2 changes: 1 addition & 1 deletion internal/handler/image_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/suite"
"***REMOVED***/darkroom/core/pkg/service"
"***REMOVED***/darkroom/storage"
"***REMOVED***/darkroom/core/pkg/storage"
)

type ImageHandlerTestSuite struct {
Expand Down
2 changes: 1 addition & 1 deletion pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package config

import (
"github.com/afex/hystrix-go/hystrix"
"***REMOVED***/darkroom/storage"
"***REMOVED***/darkroom/core/pkg/storage"
"sync"
)

Expand Down
2 changes: 1 addition & 1 deletion pkg/config/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package config

import (
"***REMOVED***/darkroom/core/pkg/regex"
"***REMOVED***/darkroom/storage"
"***REMOVED***/darkroom/core/pkg/storage"
)

type loggerConfig struct {
Expand Down
25 changes: 25 additions & 0 deletions pkg/processor/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Image Processor for Darkroom

#### About
This module holds the logic to process images. It is used by the Darkroom [Application Server](https://***REMOVED***/darkroom/core).
You may implement the `Processor` interface to gain custom functionality while still keeping other Darkroom functionality.

#### Interface
```go
type Processor interface {
Crop(input []byte, width, height int, point CropPoint) ([]byte, error)
Resize(input []byte, width, height int) ([]byte, error)
Watermark(base []byte, overlay []byte, opacity uint8) ([]byte, error)
GrayScale(input []byte) ([]byte, error)
}
```
Any `struct` implementing the above interface can be used with Darkroom.

#### Example

```go
bp := NewBildProcessor()
img, _ := ioutil.ReadFile("test.png")
output, err := bp.Resize(img, 500, 500)
_, _ := ioutil.WriteFile("output.png", output, 0644)
```
15 changes: 15 additions & 0 deletions pkg/processor/constants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package processor

type CropPoint int

const (
CropTopLeft CropPoint = 1
CropTop CropPoint = 2
CropTopRight CropPoint = 3
CropLeft CropPoint = 4
CropCenter CropPoint = 5
CropRight CropPoint = 6
CropBottomLeft CropPoint = 7
CropBottom CropPoint = 8
CropBottomRight CropPoint = 9
)
9 changes: 9 additions & 0 deletions pkg/processor/interface.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package processor

// Processor interface for performing operations on image
type Processor interface {
Crop(input []byte, width, height int, point CropPoint) ([]byte, error)
Resize(input []byte, width, height int) ([]byte, error)
Watermark(base []byte, overlay []byte, opacity uint8) ([]byte, error)
GrayScale(input []byte) ([]byte, error)
}
Binary file added pkg/processor/native/overlay.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
115 changes: 115 additions & 0 deletions pkg/processor/native/processor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package native

import (
"bytes"
"github.com/anthonynsimon/bild/clone"
"github.com/anthonynsimon/bild/effect"
"github.com/anthonynsimon/bild/transform"
"image"
"image/color"
"image/draw"
"image/jpeg"
"image/png"
"***REMOVED***/darkroom/core/pkg/processor"
)

const (
pngType = "png"
jpgType = "jpeg"
)

// BildProcessor uses bild library to process images using native Golang image.Image interface
type BildProcessor struct {
}

func (bp *BildProcessor) Crop(input []byte, width, height int, point processor.CropPoint) ([]byte, error) {
img, f, err := image.Decode(bytes.NewReader(input))
if err != nil {
return nil, err
}

w, h := getResizeWidthAndHeightForCrop(width, height, img.Bounds().Dx(), img.Bounds().Dy())

img = transform.Resize(img, w, h, transform.Linear)
x0, y0 := getStartingPointForCrop(w, h, width, height, point)
rect := image.Rect(x0, y0, width+x0, height+y0)
img = (clone.AsRGBA(img)).SubImage(rect)

return bp.encode(img, f)
}

func (bp *BildProcessor) Resize(input []byte, width, height int) ([]byte, error) {
img, f, err := image.Decode(bytes.NewReader(input))
if err != nil {
return nil, err
}

initW := img.Bounds().Dx()
initH := img.Bounds().Dy()

w, h := getResizeWidthAndHeight(width, height, initW, initH)
if w != initW || h != initH {
img = transform.Resize(img, w, h, transform.Linear)
}

return bp.encode(img, f)
}

func (bp *BildProcessor) Watermark(base []byte, overlay []byte, opacity uint8) ([]byte, error) {
baseImg, f, err := image.Decode(bytes.NewReader(base))
if err != nil {
return nil, err
}
overlayImg, _, err := image.Decode(bytes.NewReader(overlay))
if err != nil {
return nil, err
}

ratio := float64(overlayImg.Bounds().Dy()) / float64(overlayImg.Bounds().Dx())
dWidth := float64(baseImg.Bounds().Dx()) / 2.0

// Resizing overlay image according to base image
overlayImg = transform.Resize(overlayImg, int(dWidth), int(dWidth*ratio), transform.Linear)

// Anchor point for overlaying
x := (baseImg.Bounds().Dx() - overlayImg.Bounds().Dx()) / 2
y := (baseImg.Bounds().Dy() - overlayImg.Bounds().Dy()) / 2
offset := image.Pt(int(x), int(y))

// Mask image (that is just a solid light gray image)
mask := image.NewUniform(color.Alpha{A: opacity})

// Performing overlay
draw.DrawMask(baseImg.(draw.Image), overlayImg.Bounds().Add(offset), overlayImg, image.ZP, mask, image.ZP, draw.Over)

return bp.encode(baseImg, f)
}

func (bp *BildProcessor) GrayScale(input []byte) ([]byte, error) {
img, f, err := image.Decode(bytes.NewReader(input))
if err != nil {
return nil, err
}

img = effect.Grayscale(img)
return bp.encode(img, f)
}

func (bp *BildProcessor) encode(img image.Image, format string) ([]byte, error) {
if format == pngType && isOpaque(img) {
format = jpgType
}
buff := &bytes.Buffer{}
var err error
if format == pngType {
enc := png.Encoder{CompressionLevel: png.BestCompression}
err = enc.Encode(buff, img)
} else {
err = jpeg.Encode(buff, img, nil)
}
return buff.Bytes(), err
}

func NewBildProcessor() *BildProcessor {
return &BildProcessor{}
}
91 changes: 91 additions & 0 deletions pkg/processor/native/processor_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package native

import (
"bytes"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
"image"
"io/ioutil"
"***REMOVED***/darkroom/core/pkg/processor"
"testing"
)

type BildProcessorSuite struct {
suite.Suite
srcData []byte
watermarkData []byte
badData []byte
processor processor.Processor
}

func (s *BildProcessorSuite) SetupSuite() {
s.processor = NewBildProcessor()
s.srcData, _ = ioutil.ReadFile("test.png")
s.watermarkData, _ = ioutil.ReadFile("overlay.png")
s.badData = []byte("badImage.ext")
}

func TestNewBildProcessor(t *testing.T) {
suite.Run(t, new(BildProcessorSuite))
}

func (s *BildProcessorSuite) TestBildProcessor_Resize() {
output, err := s.processor.Resize(s.srcData, 500, 500)

assert.NotNil(s.T(), output)
assert.Nil(s.T(), err)

img, _, _ := image.Decode(bytes.NewReader(output))
assert.Equal(s.T(), 500, img.Bounds().Dx())
assert.Equal(s.T(), 375, img.Bounds().Dy())
}

func (s *BildProcessorSuite) TestBildProcessor_Crop() {
output, err := s.processor.Crop(s.srcData, 500, 500, processor.CropCenter)

assert.NotNil(s.T(), output)
assert.Nil(s.T(), err)

img, _, _ := image.Decode(bytes.NewReader(output))
assert.Equal(s.T(), 500, img.Bounds().Dx())
assert.Equal(s.T(), 500, img.Bounds().Dy())
}

func (s *BildProcessorSuite) TestBildProcessor_Grayscale() {
output, err := s.processor.GrayScale(s.srcData)

assert.NotNil(s.T(), output)
assert.Nil(s.T(), err)
assert.NotEqual(s.T(), s.srcData, output)
}

func (s *BildProcessorSuite) TestBildProcessor_Watermark() {
output, err := s.processor.Watermark(s.srcData, s.watermarkData, 200)

assert.NotNil(s.T(), output)
assert.Nil(s.T(), err)

assert.NotEqual(s.T(), s.srcData, output)
}

func (s *BildProcessorSuite) TestBildProcessorWithBadInput() {
output, err := s.processor.Crop(s.badData, 0, 0, processor.CropCenter)
assert.NotNil(s.T(), err)
assert.Nil(s.T(), output)

output, err = s.processor.Resize(s.badData, 0, 0)
assert.NotNil(s.T(), err)
assert.Nil(s.T(), output)

output, err = s.processor.GrayScale(s.badData)
assert.NotNil(s.T(), err)
assert.Nil(s.T(), output)

output, err = s.processor.Watermark(s.badData, s.watermarkData, 255)
assert.NotNil(s.T(), err)
assert.Nil(s.T(), output)

output, err = s.processor.Watermark(s.srcData, s.badData, 255)
assert.NotNil(s.T(), err)
assert.Nil(s.T(), output)
}
Binary file added pkg/processor/native/test.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 7567fa9

Please sign in to comment.