Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor-x, closes #373 #386

Merged
merged 14 commits into from Aug 27, 2018
2 changes: 1 addition & 1 deletion .codeclimate.yml
Expand Up @@ -18,4 +18,4 @@ plugins:
checks:
return-statements:
config:
threshold: 6
threshold: 6
4 changes: 2 additions & 2 deletions api/core/listen_event.go
Expand Up @@ -8,7 +8,7 @@ import (
"github.com/mesg-foundation/core/event"
"github.com/mesg-foundation/core/pubsub"
service "github.com/mesg-foundation/core/service"
"github.com/mesg-foundation/core/utils/array"
"github.com/mesg-foundation/core/x/xstrings"
)

// ListenEvent listens for an event from a specific service.
Expand Down Expand Up @@ -56,5 +56,5 @@ func validateEventKey(service *service.Service, eventKey string) error {
}

func isSubscribedEvent(request *ListenEventRequest, e *event.Event) bool {
return array.IncludedIn([]string{"", "*", e.Key}, request.EventFilter)
return xstrings.SliceContains([]string{"", "*", e.Key}, request.EventFilter)
}
8 changes: 4 additions & 4 deletions api/core/listen_result.go
Expand Up @@ -8,7 +8,7 @@ import (
"github.com/mesg-foundation/core/execution"
"github.com/mesg-foundation/core/pubsub"
service "github.com/mesg-foundation/core/service"
"github.com/mesg-foundation/core/utils/array"
"github.com/mesg-foundation/core/x/xstrings"
)

// ListenResult listens for results from a services.
Expand Down Expand Up @@ -87,16 +87,16 @@ func isSubscribed(request *ListenResultRequest, e *execution.Execution) bool {
}

func isSubscribedToTask(request *ListenResultRequest, e *execution.Execution) bool {
return array.IncludedIn([]string{"", "*", e.Task}, request.TaskFilter)
return xstrings.SliceContains([]string{"", "*", e.Task}, request.TaskFilter)
}

func isSubscribedToOutput(request *ListenResultRequest, e *execution.Execution) bool {
return array.IncludedIn([]string{"", "*", e.Output}, request.OutputFilter)
return xstrings.SliceContains([]string{"", "*", e.Output}, request.OutputFilter)
}

func isSubscribedToTags(request *ListenResultRequest, e *execution.Execution) bool {
for _, tag := range request.TagFilters {
if !array.IncludedIn(e.Tags, tag) {
if !xstrings.SliceContains(e.Tags, tag) {
return false
}
}
Expand Down
3 changes: 2 additions & 1 deletion cmd/service/dev.go
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/logrusorgru/aurora"
"github.com/mesg-foundation/core/api/core"
"github.com/mesg-foundation/core/cmd/utils"
"github.com/mesg-foundation/core/x/xsignal"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -43,7 +44,7 @@ func devHandler(cmd *cobra.Command, args []string) {
closeReaders := showLogs(serviceID, "*")
defer closeReaders()

<-utils.WaitForCancel()
<-xsignal.WaitForInterrupt()

utils.ShowSpinnerForFunc(utils.SpinnerOptions{Text: "Deleting test service..."}, func() {
cli().DeleteService(context.Background(), &core.DeleteServiceRequest{ // Delete service. This will automatically stop the service too
Expand Down
2 changes: 1 addition & 1 deletion cmd/service/execute.go
Expand Up @@ -13,7 +13,7 @@ import (
"github.com/mesg-foundation/core/api/core"
"github.com/mesg-foundation/core/cmd/utils"
"github.com/mesg-foundation/core/service"
"github.com/mesg-foundation/core/utils/xpflag"
"github.com/mesg-foundation/core/x/xpflag"
uuid "github.com/satori/go.uuid"
"github.com/spf13/cobra"
survey "gopkg.in/AlecAivazis/survey.v1"
Expand Down
2 changes: 1 addition & 1 deletion cmd/service/execute_test.go
Expand Up @@ -4,7 +4,7 @@ import (
"testing"

"github.com/mesg-foundation/core/service"
"github.com/mesg-foundation/core/utils/xpflag"
"github.com/mesg-foundation/core/x/xpflag"
"github.com/spf13/cobra"
"github.com/stretchr/testify/require"
)
Expand Down
12 changes: 10 additions & 2 deletions cmd/service/init.go
Expand Up @@ -11,6 +11,7 @@ import (

"github.com/logrusorgru/aurora"
"github.com/mesg-foundation/core/cmd/utils"
"github.com/mesg-foundation/core/x/xgit"
"github.com/spf13/cobra"
"gopkg.in/AlecAivazis/survey.v1"
)
Expand Down Expand Up @@ -140,12 +141,19 @@ func getTemplateResult(result string, templates []*templateStruct) (tmpl *templa
}

func downloadTemplate(tmpl *templateStruct) (path string, err error) {
path, err = createTempFolder()
path, err = ioutil.TempDir("", utils.TempDirPrefix)
if err != nil {
return "", err
}

return path, gitClone(tmpl.URL, path, "Downloading template "+tmpl.Name+"...")
message := fmt.Sprintf("Downloading template %s ...", tmpl.Name)
utils.ShowSpinnerForFunc(utils.SpinnerOptions{Text: message}, func() {
err = xgit.Clone(tmpl.URL, path)
})
if err != nil {
return "", err
}
return path, nil
}

func ask(label string, value string, validator survey.Validator) string {
Expand Down
3 changes: 2 additions & 1 deletion cmd/service/logs.go
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/docker/docker/pkg/stdcopy"
"github.com/mesg-foundation/core/api/core"
"github.com/mesg-foundation/core/cmd/utils"
"github.com/mesg-foundation/core/x/xsignal"
"github.com/spf13/cobra"
)

Expand All @@ -28,7 +29,7 @@ func init() {
func logsHandler(cmd *cobra.Command, args []string) {
closeReaders := showLogs(args[0], cmd.Flag("dependency").Value.String())
defer closeReaders()
<-utils.WaitForCancel()
<-xsignal.WaitForInterrupt()
}

func showLogs(serviceID string, dependency string) func() {
Expand Down
88 changes: 69 additions & 19 deletions cmd/service/utils.go
Expand Up @@ -3,20 +3,34 @@ package service
import (
"fmt"
"io/ioutil"
"net/url"
"log"
"os"

"github.com/asaskevich/govalidator"
"github.com/logrusorgru/aurora"
"github.com/mesg-foundation/core/api/core"
"github.com/mesg-foundation/core/cmd/utils"
"github.com/mesg-foundation/core/config"
"github.com/mesg-foundation/core/container"
"github.com/mesg-foundation/core/service"
"github.com/mesg-foundation/core/service/importer"
"github.com/mesg-foundation/core/x/xgit"
"github.com/spf13/viper"
"google.golang.org/grpc"
git "gopkg.in/src-d/go-git.v4"
"gopkg.in/src-d/go-git.v4/plumbing"
)

// TODO(ilgooz): remove this after service package made Newable.
var defaultContainer *container.Container

// TODO(ilgooz): remove this after service package made Newable.
func init() {
c, err := container.New()
if err != nil {
log.Fatal(err)
}
defaultContainer = c
}

func cli() core.CoreClient {
connection, err := grpc.Dial(viper.GetString(config.APIClientTarget), grpc.WithInsecure())
utils.HandleError(err)
Expand All @@ -39,26 +53,62 @@ func handleValidationError(err error) {
}
}

func gitClone(repoURL string, path string, message string) error {
u, err := url.Parse(repoURL)
if err != nil {
return err
// prepareService downloads if needed, create the service, build it and inject configuration
func prepareService(path string) *service.Service {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks to codeclimate, I think this function is not needed here, same for downloadServiceIfNeeded or injectConfigurationInDependencies because they moved to the mesg/deploy @ilgooz can you confirm ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes that is correct. @krhubert can you please check the current version of cmd/service/utils.go in dev branch and compare with yours to see diffs. Thanks a lot.

path, didDownload, err := downloadServiceIfNeeded(path)
utils.HandleError(err)
if didDownload {
defer os.RemoveAll(path)
fmt.Printf("%s Service downloaded with success\n", aurora.Green("✔"))
}
importedService, err := importer.From(path)
handleValidationError(err)
utils.HandleError(err)
imageHash, err := buildDockerImage(path)
utils.HandleError(err)
fmt.Printf("%s Image built with success\n", aurora.Green("✔"))
injectConfigurationInDependencies(importedService, imageHash)
return importedService
}

func downloadServiceIfNeeded(path string) (newPath string, didDownload bool, err error) {
if !govalidator.IsURL(path) {
return path, false, nil
}
if u.Scheme == "" {
u.Scheme = "https"
newPath, err = ioutil.TempDir("", utils.TempDirPrefix)
if err != nil {
return "", false, err
}
options := &git.CloneOptions{}
if u.Fragment != "" {
options.ReferenceName = plumbing.ReferenceName("refs/heads/" + u.Fragment)
u.Fragment = ""
utils.ShowSpinnerForFunc(utils.SpinnerOptions{Text: "Downloading service..."}, func() {
err = xgit.Clone(path, newPath)
})
if err != nil {
return "", false, err
}
options.URL = u.String()
utils.ShowSpinnerForFunc(utils.SpinnerOptions{Text: message}, func() {
_, err = git.PlainClone(path, false, options)
return newPath, true, nil
}

func buildDockerImage(path string) (imageHash string, err error) {
utils.ShowSpinnerForFunc(utils.SpinnerOptions{Text: "Building image..."}, func() {
imageHash, err = defaultContainer.Build(path)
})
return err
return
}

func createTempFolder() (path string, err error) {
return ioutil.TempDir("", "mesg-")
func injectConfigurationInDependencies(s *service.Service, imageHash string) {
config := s.Configuration
if config == nil {
config = &service.Dependency{}
}
dependency := &service.Dependency{
Command: config.Command,
Ports: config.Ports,
Volumes: config.Volumes,
Volumesfrom: config.Volumesfrom,
Image: imageHash,
}
if s.Dependencies == nil {
s.Dependencies = make(map[string]*service.Dependency)
}
s.Dependencies["service"] = dependency
}
75 changes: 75 additions & 0 deletions cmd/service/utils_test.go
@@ -1,8 +1,10 @@
package service

import (
"os"
"testing"

"github.com/mesg-foundation/core/service"
"github.com/stretchr/testify/require"
)

Expand All @@ -11,3 +13,76 @@ func TestDefaultPath(t *testing.T) {
require.Equal(t, defaultPath([]string{"foo"}), "foo")
require.Equal(t, defaultPath([]string{"foo", "bar"}), "foo")
}

func TestBuildDockerImagePathDoNotExist(t *testing.T) {
_, err := buildDockerImage("/doNotExist")
require.NotNil(t, err)
}

func TestDownloadServiceIfNeededAbsolutePath(t *testing.T) {
path := "/users/paul/service-js-function"
newPath, didDownload, err := downloadServiceIfNeeded(path)
require.Nil(t, err)
require.Equal(t, path, newPath)
require.Equal(t, false, didDownload)
}

func TestDownloadServiceIfNeededRelativePath(t *testing.T) {
path := "./service-js-function"
newPath, didDownload, err := downloadServiceIfNeeded(path)
require.Nil(t, err)
require.Equal(t, path, newPath)
require.Equal(t, false, didDownload)
}

func TestDownloadServiceIfNeededUrl(t *testing.T) {
path := "https://github.com/mesg-foundation/awesome.git"
newPath, didDownload, err := downloadServiceIfNeeded(path)
defer os.RemoveAll(newPath)
require.Nil(t, err)
require.NotEqual(t, path, newPath)
require.Equal(t, true, didDownload)
}

func TestInjectConfigurationInDependencies(t *testing.T) {
s := &service.Service{}
injectConfigurationInDependencies(s, "TestInjectConfigurationInDependencies")
require.Equal(t, s.Dependencies["service"].Image, "TestInjectConfigurationInDependencies")
}

func TestInjectConfigurationInDependenciesWithConfig(t *testing.T) {
s := &service.Service{
Configuration: &service.Dependency{
Command: "xxx",
Image: "yyy",
},
}
injectConfigurationInDependencies(s, "TestInjectConfigurationInDependenciesWithConfig")
require.Equal(t, s.Dependencies["service"].Image, "TestInjectConfigurationInDependenciesWithConfig")
require.Equal(t, s.Dependencies["service"].Command, "xxx")
}

func TestInjectConfigurationInDependenciesWithDependency(t *testing.T) {
s := &service.Service{
Dependencies: map[string]*service.Dependency{
"test": {
Image: "xxx",
},
},
}
injectConfigurationInDependencies(s, "TestInjectConfigurationInDependenciesWithDependency")
require.Equal(t, s.Dependencies["service"].Image, "TestInjectConfigurationInDependenciesWithDependency")
require.Equal(t, s.Dependencies["test"].Image, "xxx")
}

func TestInjectConfigurationInDependenciesWithDependencyOverride(t *testing.T) {
s := &service.Service{
Dependencies: map[string]*service.Dependency{
"service": {
Image: "xxx",
},
},
}
injectConfigurationInDependencies(s, "TestInjectConfigurationInDependenciesWithDependencyOverride")
require.Equal(t, s.Dependencies["service"].Image, "TestInjectConfigurationInDependenciesWithDependencyOverride")
}
14 changes: 0 additions & 14 deletions cmd/utils/cancel.go

This file was deleted.

4 changes: 4 additions & 0 deletions cmd/utils/const.go
@@ -0,0 +1,4 @@
package utils

// TempDirPrefix is a prefix for temp dirctories or files.
const TempDirPrefix = "mesg-"
9 changes: 2 additions & 7 deletions core/main.go
@@ -1,14 +1,11 @@
package main

import (
"os"
"os/signal"
"syscall"

"github.com/mesg-foundation/core/api"
"github.com/mesg-foundation/core/config"
"github.com/mesg-foundation/core/logger"
"github.com/mesg-foundation/core/version"
"github.com/mesg-foundation/core/x/xsignal"
"github.com/sirupsen/logrus"
"github.com/spf13/viper"
)
Expand All @@ -27,9 +24,7 @@ func main() {
Network: "unix",
Address: viper.GetString(config.APIServerSocket),
})
abort := make(chan os.Signal, 1)
signal.Notify(abort, syscall.SIGINT, syscall.SIGTERM)
<-abort
<-xsignal.WaitForInterrupt()
}

func startServer(server *api.Server) {
Expand Down