Large diffs are not rendered by default.

@@ -16,15 +16,55 @@
syntax = "proto3";
package dropship;

service rpcService {
rpc RegisterService (Service) returns (RegisterResponse);
service Management {
rpc MemberAdd (MemberAddRequest) returns (MemberAddResponse) {}
rpc MemberRemove (MemberRemoveRequest) returns (MemberRemoveResponse) {}
}

message Service {
service Deploy {
rpc Watch(stream DeployRequest) returns (stream DeployResponse) {}
rpc Trigger(DeployRequest) returns (stream DeployResponse) {}
}

message Event {
enum EventType {
INFO = 0;
ERROR = 1;
}

EventType type = 1;
string message = 2;
}

message DeployRequest {
string Service = 1;
string Revision = 2;
}

message DeployResponse {
repeated Event events = 1;
}

message Member {
uint64 ID = 1;
string name = 2;
repeated string peerUrls = 3;
}

message MemberAddRequest {
string name = 1;
repeated string peerUrls = 2;
}

message MemberAddResponse {
Member member = 1;
}

message RegisterResponse {
message MemberRemoveRequest {
uint64 ID = 1;
}

message MemberRemoveResponse {
bool success = 1;
string message = 2;
}

@@ -0,0 +1,28 @@
// Copyright (c) 2016 "ChrisMcKenzie"
// This file is part of Dropship.
//
// Dropship is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License v3 as
// published by the Free Software Foundation
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package manager

import (
"fmt"
"net/http"

log "github.com/Sirupsen/logrus"
)

func serveInterface(port int) error {
router := newRouter()
log.Infof("HTTP Server Listening on port %d", port)
return http.ListenAndServe(fmt.Sprintf(":%d", port), router)
}
@@ -15,17 +15,67 @@
package manager

import (
"encoding/json"
"fmt"
"net"

"github.com/ChrisMcKenzie/dropship/dropship"
log "github.com/Sirupsen/logrus"
"github.com/docker/libkv/store"
"golang.org/x/net/context"
"google.golang.org/grpc"
)

type RpcServiceServer struct{}
type ServiceServer struct {
store store.Store
}

func serveRpc(port int) error {
lis, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
grpcServer := grpc.NewServer()
dropship.RegisterRpcServiceServer(grpcServer, &RpcServiceServer{})
// determine whether to use TLS
log.Infof("RPC Server Listening on port %d", port)
return grpcServer.Serve(lis)
}

func (s RpcServiceServer) RegisterService(ctx context.Context, svc *dropship.Service) (*dropship.RegisterResponse, error) {
log.Infof("RegisterService Request Received for %s", svc.Name)
fmt.Println(svc)

// do stuff here
// if service exists then do nothing.
path := fmt.Sprintf(
"%s/services/%s",
DefaultKeyPrefix,
svc.Name,
)

serviceExists, err := s.store.Exists(path)
if err != nil {
return &dropship.RegisterResponse{
Success: false,
}, err
}

fmt.Println(serviceExists)
if !serviceExists {
log.Infof("Registering %s service", svc.Name)

data, err := json.Marshal(Service{
Name: svc.Name,
})

err := s.store.Put(path, []byte(svc.Ip), nil)
if err != nil {
return &dropship.RegisterResponse{
Success: false,
}, err
}
}

return &dropship.RegisterResponse{
Success: true,
@@ -15,29 +15,37 @@
package manager

import (
"fmt"
"net"
"net/http"
"net/url"
"sync"

"github.com/ChrisMcKenzie/dropship/dropship"
log "github.com/Sirupsen/logrus"
"google.golang.org/grpc"
"github.com/docker/libkv/store"
)

func ServeRpc(port int) error {
lis, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
var kvstore store.Store

func Start(storePath string) {
storeUrl, err := url.Parse(storePath)
if err != nil {
log.Fatalf("failed to listen: %v", err)
log.Fatal(err)
return
}

kvstore, err = initStore(storeUrl)
if err != nil {
log.Fatal(err)
}
grpcServer := grpc.NewServer()
dropship.RegisterRpcServiceServer(grpcServer, &RpcServiceServer{})
// determine whether to use TLS
log.Infof("RPC Server Listening on port %d", port)
return grpcServer.Serve(lis)
}

func ServeHttp(port int) error {
router := newRouter()
log.Infof("HTTP Server Listening on port %d", port)
return http.ListenAndServe(fmt.Sprintf(":%d", port), router)
wg := &sync.WaitGroup{}
wg.Add(1)
go func() {
log.Fatal(serveRpc(3000))
wg.Done()
}()
wg.Add(1)
go func() {
log.Fatal(serveInterface(3001))
wg.Done()
}()
wg.Wait()
}
@@ -14,11 +14,51 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package manager

import "net/http"
import (
"encoding/json"
"fmt"
"net/http"
"strings"

log "github.com/Sirupsen/logrus"
)

type Service struct {
Name string `json:"name"`
Href string `json:"href"`
Description string `json:"description"`
LastDeploy string `json:"last_deployed_on"`
Hosts []string `json:"hosts"`
}

func servicesIndex(w http.ResponseWriter, r *http.Request) {
keys, err := kvstore.List(fmt.Sprintf("%s/services/", DefaultKeyPrefix))
if err != nil {
w.WriteHeader(500)
w.Write([]byte(err.Error()))
}

var services []Service
for _, val := range keys {
key := strings.Split(val.Key, "/")
var svc Service
err := json.Unmarshal(val.Value, &svc)
if err != nil {
log.Error(err)
}
svc.Name = key[len(key)-1]
services = append(services, svc)
}

payload, err := json.Marshal(services)
if err != nil {
w.WriteHeader(500)
w.Write([]byte(err.Error()))
return
}

w.WriteHeader(200)
w.Write([]byte("hello, world"))
w.Write(payload)
}

func servicesShow(w http.ResponseWriter, r *http.Request) {
@@ -0,0 +1,42 @@
package manager

import (
"errors"
"net/url"
"strings"
"time"

"github.com/docker/libkv"
"github.com/docker/libkv/store"
"github.com/docker/libkv/store/boltdb"
"github.com/docker/libkv/store/consul"
"github.com/docker/libkv/store/etcd"
"github.com/docker/libkv/store/zookeeper"
)

const (
DefaultKeyPrefix = "dropship"
)

func init() {
consul.Register()
etcd.Register()
zookeeper.Register()
boltdb.Register()
}

func initStore(storeUrl *url.URL) (store.Store, error) {
if storeUrl.Scheme == "" {
return nil, errors.New("unable to determine store type please make sure you have added a scheme (ie. consul:// or etcd://)")
}

hosts := strings.Split(storeUrl.Host, ",")

return libkv.NewStore(
store.Backend(storeUrl.Scheme),
hosts,
&store.Config{
ConnectionTimeout: 10 * time.Second,
},
)
}