Skip to content

Commit

Permalink
Merge branch 'dev' into refactoring/service/simplify-status
Browse files Browse the repository at this point in the history
  • Loading branch information
ilgooz authored Apr 17, 2019
2 parents a09f146 + 7e9a258 commit 35ac4f9
Show file tree
Hide file tree
Showing 13 changed files with 221 additions and 392 deletions.
73 changes: 41 additions & 32 deletions api/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ import (
"net/http"
"os"
"path/filepath"
"sync"

"github.com/docker/docker/pkg/archive"
"github.com/mesg-foundation/core/service"
"github.com/mesg-foundation/core/service/importer"
"github.com/mesg-foundation/core/utils/dirhash"
"github.com/mesg-foundation/core/x/xgit"
"github.com/mesg-foundation/core/x/xos"
"github.com/mr-tron/base58"
uuid "github.com/satori/go.uuid"
)

Expand Down Expand Up @@ -151,22 +153,11 @@ func (d *serviceDeployer) processPath(path string) (string, error) {
return path, nil
}

// deploy deploys a service in path.
func (d *serviceDeployer) deploy(path string) (*service.Service, *importer.ValidationError, error) {
var (
statuses = make(chan service.DeployStatus)
wg sync.WaitGroup
)

wg.Add(1)
go func() {
defer wg.Done()
d.forwardDeployStatuses(statuses)
}()

s, err := service.New(path, d.api.container, statuses, d.env)
wg.Wait()
// deploy deploys a service in contextDir.
func (d *serviceDeployer) deploy(contextDir string) (*service.Service, *importer.ValidationError, error) {
s := &service.Service{}

def, err := importer.From(contextDir)
validationErr, err := d.assertValidationError(err)
if err != nil {
return nil, nil, err
Expand All @@ -175,6 +166,40 @@ func (d *serviceDeployer) deploy(path string) (*service.Service, *importer.Valid
return nil, validationErr, nil
}

dh := dirhash.New(contextDir)
envbytes := []byte(xos.EnvMapToString(d.env))
hash, err := dh.Sum(envbytes)
if err != nil {
return nil, nil, err
}
s.Hash = base58.Encode(hash)

injectDefinition(s, def)

if err := s.ValidateConfigurationEnv(d.env); err != nil {
return nil, nil, err
}

// replace default env with new one.
defenv := xos.EnvSliceToMap(s.Configuration.Env)
s.Configuration.Env = xos.EnvMapToSlice(xos.EnvMergeMaps(defenv, d.env))

d.sendStatus("Building Docker image...", Running)

imageHash, err := d.api.container.Build(contextDir)
if err != nil {
return nil, nil, err
}

d.sendStatus("Image built with success", DonePositive)

s.Configuration.Image = imageHash
// TODO: the following test should be moved in New function
if s.Sid == "" {
// make sure that sid doesn't have the same length with id.
s.Sid = "_" + s.Hash
}

return s, nil, d.api.db.Save(s)
}

Expand All @@ -199,22 +224,6 @@ func (d *serviceDeployer) closeStatus() {
}
}

// forwardStatuses forwards status messages.
func (d *serviceDeployer) forwardDeployStatuses(statuses chan service.DeployStatus) {
for status := range statuses {
var t StatusType
switch status.Type {
case service.DRunning:
t = Running
case service.DDonePositive:
t = DonePositive
case service.DDoneNegative:
t = DoneNegative
}
d.sendStatus(status.Message, t)
}
}

func (d *serviceDeployer) assertValidationError(err error) (*importer.ValidationError, error) {
if err == nil {
return nil, nil
Expand Down
75 changes: 73 additions & 2 deletions api/deploy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,23 @@ import (
"sync"
"testing"

"github.com/mesg-foundation/core/service"
"github.com/mesg-foundation/core/service/importer"
"github.com/mesg-foundation/core/x/xdocker/xarchive"
"github.com/mesg-foundation/core/x/xos"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
)

func TestDeployService(t *testing.T) {
var (
path = filepath.Join("..", "service-test", "task")
hash = "1"
a, at = newTesting(t)
)
defer at.close()

at.containerMock.On("Build", mock.Anything).Once().Return("1", nil)
at.containerMock.On("Build", mock.Anything).Once().Return(hash, nil)

statuses := make(chan DeployStatus)
var wg sync.WaitGroup
Expand All @@ -30,9 +33,12 @@ func TestDeployService(t *testing.T) {
archive, err := xarchive.GzippedTar(path, nil)
require.NoError(t, err)

_, validationError, err := a.DeployService(archive, nil, DeployServiceStatusOption(statuses))
s, validationError, err := a.DeployService(archive, nil, DeployServiceStatusOption(statuses))
require.Nil(t, validationError)
require.NoError(t, err)
require.Equal(t, "service", s.Configuration.Key)
require.Equal(t, hash, s.Configuration.Image)
require.Len(t, s.Configuration.Env, 0)
}()

require.Equal(t, DeployStatus{
Expand All @@ -54,6 +60,71 @@ func TestDeployService(t *testing.T) {
at.containerMock.AssertExpectations(t)
}

func TestDeployWithDefaultEnv(t *testing.T) {
var (
path = filepath.Join("..", "service-test", "env")
hash = "1"
env = []string{"A=1", "B=2"}
a, at = newTesting(t)
)
defer at.close()

at.containerMock.On("Build", mock.Anything).Once().Return(hash, nil)

archive, err := xarchive.GzippedTar(path, nil)
require.NoError(t, err)

s, validationError, err := a.DeployService(archive, nil)
require.Nil(t, validationError)
require.NoError(t, err)
require.Equal(t, "service", s.Configuration.Key)
require.Equal(t, hash, s.Configuration.Image)
require.Equal(t, env, s.Configuration.Env)

at.containerMock.AssertExpectations(t)
}

func TestDeployWithOverwrittenEnv(t *testing.T) {
var (
path = filepath.Join("..", "service-test", "env")
hash = "1"
env = []string{"A=3", "B=4"}
a, at = newTesting(t)
)
defer at.close()

at.containerMock.On("Build", mock.Anything).Once().Return(hash, nil)

archive, err := xarchive.GzippedTar(path, nil)
require.NoError(t, err)

s, validationError, err := a.DeployService(archive, xos.EnvSliceToMap(env))
require.Nil(t, validationError)
require.NoError(t, err)
require.Equal(t, "service", s.Configuration.Key)
require.Equal(t, hash, s.Configuration.Image)
require.Equal(t, env, s.Configuration.Env)

at.containerMock.AssertExpectations(t)
}

func TestDeployWitNotDefinedEnv(t *testing.T) {
var (
path = filepath.Join("..", "service-test", "task")
a, at = newTesting(t)
)
defer at.close()

archive, err := xarchive.GzippedTar(path, nil)
require.NoError(t, err)

_, validationError, err := a.DeployService(archive, xos.EnvSliceToMap([]string{"A=1", "B=2"}))
require.Nil(t, validationError)
require.Equal(t, service.ErrNotDefinedEnv{[]string{"A", "B"}}, err)

at.containerMock.AssertExpectations(t)
}

func TestDeployInvalidService(t *testing.T) {
var (
path = filepath.Join("..", "service-test", "invalid")
Expand Down
55 changes: 28 additions & 27 deletions service/inject_definition.go → api/inject_definition.go
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
package service
package api

import (
"sort"

"github.com/mesg-foundation/core/service"
"github.com/mesg-foundation/core/service/importer"
"github.com/mesg-foundation/core/x/xstrings"
)

// injectDefinition applies service definition to Service type.
func (s *Service) injectDefinition(def *importer.ServiceDefinition) {
func injectDefinition(s *service.Service, def *importer.ServiceDefinition) {
s.Name = def.Name
s.Sid = def.Sid
s.Description = def.Description
s.Repository = def.Repository
s.Events = s.defEventsToService(def.Events)
s.Tasks = s.defTasksToService(def.Tasks)
s.Dependencies = s.defDependenciesToService(def.Dependencies)
s.Events = defEventsToService(def.Events)
s.Tasks = defTasksToService(def.Tasks)
s.Dependencies = defDependenciesToService(def.Dependencies)

s.Configuration = &Dependency{
Key: MainServiceKey,
s.Configuration = &service.Dependency{
Key: service.MainServiceKey,
}
if def.Configuration != nil {
s.Configuration.Command = def.Configuration.Command
Expand All @@ -30,10 +31,10 @@ func (s *Service) injectDefinition(def *importer.ServiceDefinition) {
}
}

func (s *Service) defTasksToService(tasks map[string]*importer.Task) []*Task {
func defTasksToService(tasks map[string]*importer.Task) []*service.Task {
var (
keys []string
ts = make([]*Task, len(tasks))
ts = make([]*service.Task, len(tasks))
)

for key := range tasks {
Expand All @@ -43,21 +44,21 @@ func (s *Service) defTasksToService(tasks map[string]*importer.Task) []*Task {

for key, task := range tasks {
i := xstrings.SliceIndex(keys, key)
ts[i] = &Task{
ts[i] = &service.Task{
Key: key,
Name: task.Name,
Description: task.Description,
Inputs: s.defParametersToService(task.Inputs),
Outputs: s.defOutputsToService(task.Outputs),
Inputs: defParametersToService(task.Inputs),
Outputs: defOutputsToService(task.Outputs),
}
}
return ts
}

func (s *Service) defOutputsToService(outputs map[string]*importer.Output) []*Output {
func defOutputsToService(outputs map[string]*importer.Output) []*service.Output {
var (
keys []string
ots = make([]*Output, len(outputs))
ots = make([]*service.Output, len(outputs))
)

for key := range outputs {
Expand All @@ -67,20 +68,20 @@ func (s *Service) defOutputsToService(outputs map[string]*importer.Output) []*Ou

for key, output := range outputs {
i := xstrings.SliceIndex(keys, key)
ots[i] = &Output{
ots[i] = &service.Output{
Key: key,
Name: output.Name,
Description: output.Description,
Data: s.defParametersToService(output.Data),
Data: defParametersToService(output.Data),
}
}
return ots
}

func (s *Service) defEventsToService(events map[string]*importer.Event) []*Event {
func defEventsToService(events map[string]*importer.Event) []*service.Event {
var (
keys []string
es = make([]*Event, len(events))
es = make([]*service.Event, len(events))
)

for key := range events {
Expand All @@ -90,20 +91,20 @@ func (s *Service) defEventsToService(events map[string]*importer.Event) []*Event

for key, event := range events {
i := xstrings.SliceIndex(keys, key)
es[i] = &Event{
es[i] = &service.Event{
Key: key,
Name: event.Name,
Description: event.Description,
Data: s.defParametersToService(event.Data),
Data: defParametersToService(event.Data),
}
}
return es
}

func (s *Service) defDependenciesToService(dependencies map[string]*importer.Dependency) []*Dependency {
func defDependenciesToService(dependencies map[string]*importer.Dependency) []*service.Dependency {
var (
keys []string
deps = make([]*Dependency, len(dependencies))
deps = make([]*service.Dependency, len(dependencies))
)

for key := range dependencies {
Expand All @@ -113,7 +114,7 @@ func (s *Service) defDependenciesToService(dependencies map[string]*importer.Dep

for key, dep := range dependencies {
i := xstrings.SliceIndex(keys, key)
deps[i] = &Dependency{
deps[i] = &service.Dependency{
Key: key,
Image: dep.Image,
Volumes: dep.Volumes,
Expand All @@ -127,10 +128,10 @@ func (s *Service) defDependenciesToService(dependencies map[string]*importer.Dep
return deps
}

func (s *Service) defParametersToService(params map[string]*importer.Parameter) []*Parameter {
func defParametersToService(params map[string]*importer.Parameter) []*service.Parameter {
var (
keys []string
ps = make([]*Parameter, len(params))
ps = make([]*service.Parameter, len(params))
)

for key := range params {
Expand All @@ -140,14 +141,14 @@ func (s *Service) defParametersToService(params map[string]*importer.Parameter)

for key, param := range params {
i := xstrings.SliceIndex(keys, key)
ps[i] = &Parameter{
ps[i] = &service.Parameter{
Key: key,
Name: param.Name,
Description: param.Description,
Type: param.Type,
Optional: param.Optional,
Repeated: param.Repeated,
Object: s.defParametersToService(param.Object),
Object: defParametersToService(param.Object),
}
}
return ps
Expand Down
Loading

0 comments on commit 35ac4f9

Please sign in to comment.