Merge pull request #514 from technolo-g/Issue_499_Automate_golint_pr

Issue #500 Run golint on codebase
This commit is contained in:
Victor Vieux 2015-03-30 12:14:15 -07:00
commit b655cbb7c5
39 changed files with 164 additions and 73 deletions

View File

@ -22,6 +22,7 @@ import (
"github.com/samalba/dockerclient" "github.com/samalba/dockerclient"
) )
// APIVERSION is exported
const APIVERSION = "1.16" const APIVERSION = "1.16"
type context struct { type context struct {
@ -55,14 +56,14 @@ func getInfo(c *context, w http.ResponseWriter, r *http.Request) {
func getVersion(c *context, w http.ResponseWriter, r *http.Request) { func getVersion(c *context, w http.ResponseWriter, r *http.Request) {
version := struct { version := struct {
Version string Version string
ApiVersion string APIVersion string
GoVersion string GoVersion string
GitCommit string GitCommit string
Os string Os string
Arch string Arch string
}{ }{
Version: "swarm/" + version.VERSION, Version: "swarm/" + version.VERSION,
ApiVersion: APIVERSION, APIVersion: APIVERSION,
GoVersion: runtime.Version(), GoVersion: runtime.Version(),
GitCommit: version.GITCOMMIT, GitCommit: version.GITCOMMIT,
Os: runtime.GOOS, Os: runtime.GOOS,
@ -316,7 +317,7 @@ func postContainersExec(c *context, w http.ResponseWriter, r *http.Request) {
return return
} }
id := struct{ Id string }{} id := struct{ ID string }{}
if err := json.Unmarshal(data, &id); err != nil { if err := json.Unmarshal(data, &id); err != nil {
httpError(w, err.Error(), http.StatusInternalServerError) httpError(w, err.Error(), http.StatusInternalServerError)
@ -324,7 +325,7 @@ func postContainersExec(c *context, w http.ResponseWriter, r *http.Request) {
} }
// add execID to the container, so the later exec/start will work // add execID to the container, so the later exec/start will work
container.Info.ExecIDs = append(container.Info.ExecIDs, id.Id) container.Info.ExecIDs = append(container.Info.ExecIDs, id.ID)
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
w.Write(data) w.Write(data)

View File

@ -15,6 +15,7 @@ type eventsHandler struct {
cs map[string]chan struct{} cs map[string]chan struct{}
} }
// NewEventsHandler is exported
func NewEventsHandler() *eventsHandler { func NewEventsHandler() *eventsHandler {
return &eventsHandler{ return &eventsHandler{
ws: make(map[string]io.Writer), ws: make(map[string]io.Writer),

View File

@ -8,6 +8,7 @@ import (
"github.com/docker/docker/pkg/ioutils" "github.com/docker/docker/pkg/ioutils"
) )
// WriteFlusher is exported
type WriteFlusher struct { type WriteFlusher struct {
sync.Mutex sync.Mutex
w io.Writer w io.Writer
@ -29,6 +30,7 @@ func (wf *WriteFlusher) Flush() {
wf.flusher.Flush() wf.flusher.Flush()
} }
// NewWriteFlusher is exported
func NewWriteFlusher(w io.Writer) *WriteFlusher { func NewWriteFlusher(w io.Writer) *WriteFlusher {
var flusher http.Flusher var flusher http.Flusher
if f, ok := w.(http.Flusher); ok { if f, ok := w.(http.Flusher); ok {

View File

@ -11,6 +11,7 @@ import (
"github.com/docker/swarm/cluster" "github.com/docker/swarm/cluster"
) )
// DefaultDockerPort is exported
const DefaultDockerPort = ":2375" const DefaultDockerPort = ":2375"
func newListener(proto, addr string, tlsConfig *tls.Config) (net.Listener, error) { func newListener(proto, addr string, tlsConfig *tls.Config) (net.Listener, error) {
@ -28,6 +29,7 @@ func newListener(proto, addr string, tlsConfig *tls.Config) (net.Listener, error
return l, nil return l, nil
} }
// ListenAndServe is exported
func ListenAndServe(c cluster.Cluster, hosts []string, enableCors bool, tlsConfig *tls.Config, eventsHandler *eventsHandler) error { func ListenAndServe(c cluster.Cluster, hosts []string, enableCors bool, tlsConfig *tls.Config, eventsHandler *eventsHandler) error {
context := &context{ context := &context{
cluster: c, cluster: c,

View File

@ -4,6 +4,7 @@ import (
"github.com/samalba/dockerclient" "github.com/samalba/dockerclient"
) )
// ContainerSorter is exported
type ContainerSorter []*dockerclient.Container type ContainerSorter []*dockerclient.Container
func (s ContainerSorter) Len() int { func (s ContainerSorter) Len() int {

View File

@ -2,6 +2,7 @@ package cluster
import "github.com/samalba/dockerclient" import "github.com/samalba/dockerclient"
// Cluster is exported
type Cluster interface { type Cluster interface {
// Create a container // Create a container
CreateContainer(config *dockerclient.ContainerConfig, name string) (*Container, error) CreateContainer(config *dockerclient.ContainerConfig, name string) (*Container, error)
@ -12,8 +13,8 @@ type Cluster interface {
// Return all images // Return all images
Images() []*Image Images() []*Image
// Return one image matching `IdOrName` // Return one image matching `IDOrName`
Image(IdOrName string) *Image Image(IDOrName string) *Image
// Remove an image from the cluster // Remove an image from the cluster
RemoveImage(image *Image) ([]*dockerclient.ImageDelete, error) RemoveImage(image *Image) ([]*dockerclient.ImageDelete, error)
@ -21,8 +22,8 @@ type Cluster interface {
// Return all containers // Return all containers
Containers() []*Container Containers() []*Container
// Return container the matching `IdOrName` // Return container the matching `IDOrName`
Container(IdOrName string) *Container Container(IDOrName string) *Container
// Pull images // Pull images
// `callback` can be called multiple time // `callback` can be called multiple time

View File

@ -2,6 +2,7 @@ package cluster
import "github.com/samalba/dockerclient" import "github.com/samalba/dockerclient"
// Container is exported
type Container struct { type Container struct {
dockerclient.Container dockerclient.Container

View File

@ -2,11 +2,13 @@ package cluster
import "github.com/samalba/dockerclient" import "github.com/samalba/dockerclient"
// Event is exported
type Event struct { type Event struct {
dockerclient.Event dockerclient.Event
Node Node Node Node
} }
// EventHandler is exported
type EventHandler interface { type EventHandler interface {
Handle(*Event) error Handle(*Event) error
} }

View File

@ -6,20 +6,22 @@ import (
"github.com/samalba/dockerclient" "github.com/samalba/dockerclient"
) )
// Image is exported
type Image struct { type Image struct {
dockerclient.Image dockerclient.Image
Node Node Node Node
} }
func (image *Image) Match(IdOrName string) bool { // Match is exported
size := len(IdOrName) func (image *Image) Match(IDOrName string) bool {
size := len(IDOrName)
if image.Id == IdOrName || (size > 2 && strings.HasPrefix(image.Id, IdOrName)) { if image.Id == IDOrName || (size > 2 && strings.HasPrefix(image.Id, IDOrName)) {
return true return true
} }
for _, repoTag := range image.RepoTags { for _, repoTag := range image.RepoTags {
if repoTag == IdOrName || (size > 2 && strings.HasPrefix(repoTag, IdOrName)) { if repoTag == IDOrName || (size > 2 && strings.HasPrefix(repoTag, IDOrName)) {
return true return true
} }
} }

View File

@ -2,6 +2,7 @@ package cluster
import "fmt" import "fmt"
// Node is exported
type Node interface { type Node interface {
ID() string ID() string
Name() string Name() string
@ -10,9 +11,9 @@ type Node interface {
Addr() string //to know where to connect with the proxy Addr() string //to know where to connect with the proxy
Images() []*Image //used by the API Images() []*Image //used by the API
Image(IdOrName string) *Image //used by the filters Image(IDOrName string) *Image //used by the filters
Containers() []*Container //used by the filters Containers() []*Container //used by the filters
Container(IdOrName string) *Container //used by the filters Container(IDOrName string) *Container //used by the filters
TotalCpus() int64 //used by the strategy TotalCpus() int64 //used by the strategy
UsedCpus() int64 //used by the strategy UsedCpus() int64 //used by the strategy
@ -24,6 +25,7 @@ type Node interface {
IsHealthy() bool IsHealthy() bool
} }
// SerializeNode is exported
func SerializeNode(node Node) string { func SerializeNode(node Node) string {
return fmt.Sprintf("{%q:%q,%q:%q,%q:%q,%q:%q}", return fmt.Sprintf("{%q:%q,%q:%q,%q:%q,%q:%q}",
"Name", node.Name(), "Name", node.Name(),

View File

@ -2,6 +2,7 @@ package cluster
import "crypto/tls" import "crypto/tls"
// Options is exported
type Options struct { type Options struct {
TLSConfig *tls.Config TLSConfig *tls.Config
OvercommitRatio float64 OvercommitRatio float64

View File

@ -13,6 +13,7 @@ import (
"github.com/samalba/dockerclient" "github.com/samalba/dockerclient"
) )
// Cluster is exported
type Cluster struct { type Cluster struct {
sync.RWMutex sync.RWMutex
@ -23,6 +24,7 @@ type Cluster struct {
store *state.Store store *state.Store
} }
// NewCluster is exported
func NewCluster(scheduler *scheduler.Scheduler, store *state.Store, eventhandler cluster.EventHandler, options *cluster.Options) cluster.Cluster { func NewCluster(scheduler *scheduler.Scheduler, store *state.Store, eventhandler cluster.EventHandler, options *cluster.Options) cluster.Cluster {
log.WithFields(log.Fields{"name": "swarm"}).Debug("Initializing cluster") log.WithFields(log.Fields{"name": "swarm"}).Debug("Initializing cluster")
@ -54,7 +56,7 @@ func NewCluster(scheduler *scheduler.Scheduler, store *state.Store, eventhandler
return cluster return cluster
} }
// callback for the events // Handle callbacks for the events
func (c *Cluster) Handle(e *cluster.Event) error { func (c *Cluster) Handle(e *cluster.Event) error {
if err := c.eventHandler.Handle(e); err != nil { if err := c.eventHandler.Handle(e); err != nil {
log.Error(err) log.Error(err)
@ -62,7 +64,7 @@ func (c *Cluster) Handle(e *cluster.Event) error {
return nil return nil
} }
// Schedule a brand new container into the cluster. // CreateContainer aka schedule a brand new container into the cluster.
func (c *Cluster) CreateContainer(config *dockerclient.ContainerConfig, name string) (*cluster.Container, error) { func (c *Cluster) CreateContainer(config *dockerclient.ContainerConfig, name string) (*cluster.Container, error) {
c.RLock() c.RLock()
@ -108,8 +110,8 @@ retry:
return nil, nil return nil, nil
} }
// Remove a container from the cluster. Containers should always be destroyed // RemoveContainer aka Remove a container from the cluster. Containers should
// through the scheduler to guarantee atomicity. // always be destroyed through the scheduler to guarantee atomicity.
func (c *Cluster) RemoveContainer(container *cluster.Container, force bool) error { func (c *Cluster) RemoveContainer(container *cluster.Container, force bool) error {
c.Lock() c.Lock()
defer c.Unlock() defer c.Unlock()
@ -186,17 +188,17 @@ func (c *Cluster) Images() []*cluster.Image {
return out return out
} }
// Image returns an image with IdOrName in the cluster // Image returns an image with IDOrName in the cluster
func (c *Cluster) Image(IdOrName string) *cluster.Image { func (c *Cluster) Image(IDOrName string) *cluster.Image {
// Abort immediately if the name is empty. // Abort immediately if the name is empty.
if len(IdOrName) == 0 { if len(IDOrName) == 0 {
return nil return nil
} }
c.RLock() c.RLock()
defer c.RUnlock() defer c.RUnlock()
for _, n := range c.nodes { for _, n := range c.nodes {
if image := n.Image(IdOrName); image != nil { if image := n.Image(IDOrName); image != nil {
return image return image
} }
} }
@ -214,6 +216,7 @@ func (c *Cluster) RemoveImage(image *cluster.Image) ([]*dockerclient.ImageDelete
return nil, nil return nil, nil
} }
// Pull is exported
func (c *Cluster) Pull(name string, callback func(what, status string)) { func (c *Cluster) Pull(name string, callback func(what, status string)) {
size := len(c.nodes) size := len(c.nodes)
done := make(chan bool, size) done := make(chan bool, size)
@ -251,17 +254,17 @@ func (c *Cluster) Containers() []*cluster.Container {
return out return out
} }
// Container returns the container with IdOrName in the cluster // Container returns the container with IDOrName in the cluster
func (c *Cluster) Container(IdOrName string) *cluster.Container { func (c *Cluster) Container(IDOrName string) *cluster.Container {
// Abort immediately if the name is empty. // Abort immediately if the name is empty.
if len(IdOrName) == 0 { if len(IDOrName) == 0 {
return nil return nil
} }
c.RLock() c.RLock()
defer c.RUnlock() defer c.RUnlock()
for _, n := range c.nodes { for _, n := range c.nodes {
if container := n.Container(IdOrName); container != nil { if container := n.Container(IDOrName); container != nil {
return container return container
} }
} }
@ -282,6 +285,7 @@ func (c *Cluster) listNodes() []cluster.Node {
return out return out
} }
// Info is exported
func (c *Cluster) Info() [][2]string { func (c *Cluster) Info() [][2]string {
info := [][2]string{{"\bNodes", fmt.Sprintf("%d", len(c.nodes))}} info := [][2]string{{"\bNodes", fmt.Sprintf("%d", len(c.nodes))}}

View File

@ -22,6 +22,7 @@ const (
requestTimeout = 10 * time.Second requestTimeout = 10 * time.Second
) )
// NewNode is exported
func NewNode(addr string, overcommitRatio float64) *node { func NewNode(addr string, overcommitRatio float64) *node {
e := &node{ e := &node{
addr: addr, addr: addr,
@ -144,7 +145,7 @@ func (n *node) updateSpecs() error {
// Older versions of Docker don't expose the ID field and are not supported // Older versions of Docker don't expose the ID field and are not supported
// by Swarm. Catch the error ASAP and refuse to connect. // by Swarm. Catch the error ASAP and refuse to connect.
if len(info.ID) == 0 { if len(info.ID) == 0 {
return fmt.Errorf("node %s is running an unsupported version of Docker Engine. Please upgrade.", n.addr) return fmt.Errorf("node %s is running an unsupported version of Docker Engine. Please upgrade", n.addr)
} }
n.id = info.ID n.id = info.ID
n.name = info.Name n.name = info.Name
@ -327,7 +328,7 @@ func (n *node) emitEvent(event string) {
// Return the sum of memory reserved by containers. // Return the sum of memory reserved by containers.
func (n *node) UsedMemory() int64 { func (n *node) UsedMemory() int64 {
var r int64 = 0 var r int64
n.RLock() n.RLock()
for _, c := range n.containers { for _, c := range n.containers {
r += c.Info.Config.Memory r += c.Info.Config.Memory
@ -338,7 +339,7 @@ func (n *node) UsedMemory() int64 {
// Return the sum of CPUs reserved by containers. // Return the sum of CPUs reserved by containers.
func (n *node) UsedCpus() int64 { func (n *node) UsedCpus() int64 {
var r int64 = 0 var r int64
n.RLock() n.RLock()
for _, c := range n.containers { for _, c := range n.containers {
r += c.Info.Config.CpuShares r += c.Info.Config.CpuShares
@ -437,10 +438,10 @@ func (n *node) Containers() []*cluster.Container {
return containers return containers
} }
// Container returns the container with IdOrName in the node. // Container returns the container with IDOrName in the node.
func (n *node) Container(IdOrName string) *cluster.Container { func (n *node) Container(IDOrName string) *cluster.Container {
// Abort immediately if the name is empty. // Abort immediately if the name is empty.
if len(IdOrName) == 0 { if len(IDOrName) == 0 {
return nil return nil
} }
@ -449,13 +450,13 @@ func (n *node) Container(IdOrName string) *cluster.Container {
for _, container := range n.Containers() { for _, container := range n.Containers() {
// Match ID prefix. // Match ID prefix.
if strings.HasPrefix(container.Id, IdOrName) { if strings.HasPrefix(container.Id, IDOrName) {
return container return container
} }
// Match name, /name or engine/name. // Match name, /name or engine/name.
for _, name := range container.Names { for _, name := range container.Names {
if name == IdOrName || name == "/"+IdOrName || container.Node.ID()+name == IdOrName || container.Node.Name()+name == IdOrName { if name == IDOrName || name == "/"+IDOrName || container.Node.ID()+name == IDOrName || container.Node.Name()+name == IDOrName {
return container return container
} }
} }
@ -476,13 +477,13 @@ func (n *node) Images() []*cluster.Image {
return images return images
} }
// Image returns the image with IdOrName in the node // Image returns the image with IDOrName in the node
func (n *node) Image(IdOrName string) *cluster.Image { func (n *node) Image(IDOrName string) *cluster.Image {
n.RLock() n.RLock()
defer n.RUnlock() defer n.RUnlock()
for _, image := range n.images { for _, image := range n.images {
if image.Match(IdOrName) { if image.Match(IDOrName) {
return image return image
} }
} }

View File

@ -11,6 +11,7 @@ import (
consul "github.com/hashicorp/consul/api" consul "github.com/hashicorp/consul/api"
) )
// ConsulDiscoveryService is exported
type ConsulDiscoveryService struct { type ConsulDiscoveryService struct {
heartbeat time.Duration heartbeat time.Duration
client *consul.Client client *consul.Client
@ -22,6 +23,7 @@ func init() {
discovery.Register("consul", &ConsulDiscoveryService{}) discovery.Register("consul", &ConsulDiscoveryService{})
} }
// Initialize is exported
func (s *ConsulDiscoveryService) Initialize(uris string, heartbeat int) error { func (s *ConsulDiscoveryService) Initialize(uris string, heartbeat int) error {
parts := strings.SplitN(uris, "/", 2) parts := strings.SplitN(uris, "/", 2)
if len(parts) < 2 { if len(parts) < 2 {
@ -52,6 +54,8 @@ func (s *ConsulDiscoveryService) Initialize(uris string, heartbeat int) error {
s.lastIndex = meta.LastIndex s.lastIndex = meta.LastIndex
return nil return nil
} }
// Fetch is exported
func (s *ConsulDiscoveryService) Fetch() ([]*discovery.Entry, error) { func (s *ConsulDiscoveryService) Fetch() ([]*discovery.Entry, error) {
kv := s.client.KV() kv := s.client.KV()
pairs, _, err := kv.List(s.prefix, nil) pairs, _, err := kv.List(s.prefix, nil)
@ -70,6 +74,7 @@ func (s *ConsulDiscoveryService) Fetch() ([]*discovery.Entry, error) {
return discovery.CreateEntries(addrs) return discovery.CreateEntries(addrs)
} }
// Watch is exported
func (s *ConsulDiscoveryService) Watch(callback discovery.WatchCallback) { func (s *ConsulDiscoveryService) Watch(callback discovery.WatchCallback) {
for _ = range s.waitForChange() { for _ = range s.waitForChange() {
log.WithField("name", "consul").Debug("Discovery watch triggered") log.WithField("name", "consul").Debug("Discovery watch triggered")
@ -80,6 +85,7 @@ func (s *ConsulDiscoveryService) Watch(callback discovery.WatchCallback) {
} }
} }
// Register is exported
func (s *ConsulDiscoveryService) Register(addr string) error { func (s *ConsulDiscoveryService) Register(addr string) error {
kv := s.client.KV() kv := s.client.KV()
p := &consul.KVPair{Key: path.Join(s.prefix, addr), Value: []byte(addr)} p := &consul.KVPair{Key: path.Join(s.prefix, addr), Value: []byte(addr)}

View File

@ -9,11 +9,13 @@ import (
log "github.com/Sirupsen/logrus" log "github.com/Sirupsen/logrus"
) )
// Entry is exported
type Entry struct { type Entry struct {
Host string Host string
Port string Port string
} }
// NewEntry is exported
func NewEntry(url string) (*Entry, error) { func NewEntry(url string) (*Entry, error) {
host, port, err := net.SplitHostPort(url) host, port, err := net.SplitHostPort(url)
if err != nil { if err != nil {
@ -26,8 +28,10 @@ func (m Entry) String() string {
return fmt.Sprintf("%s:%s", m.Host, m.Port) return fmt.Sprintf("%s:%s", m.Host, m.Port)
} }
// WatchCallback is exported
type WatchCallback func(entries []*Entry) type WatchCallback func(entries []*Entry)
// DiscoveryService is exported
type DiscoveryService interface { type DiscoveryService interface {
Initialize(string, int) error Initialize(string, int) error
Fetch() ([]*Entry, error) Fetch() ([]*Entry, error)
@ -36,8 +40,10 @@ type DiscoveryService interface {
} }
var ( var (
discoveries map[string]DiscoveryService discoveries map[string]DiscoveryService
ErrNotSupported = errors.New("discovery service not supported") // ErrNotSupported is exported
ErrNotSupported = errors.New("discovery service not supported")
// ErrNotImplemented is exported
ErrNotImplemented = errors.New("not implemented in this discovery service") ErrNotImplemented = errors.New("not implemented in this discovery service")
) )
@ -45,6 +51,7 @@ func init() {
discoveries = make(map[string]DiscoveryService) discoveries = make(map[string]DiscoveryService)
} }
// Register is exported
func Register(scheme string, d DiscoveryService) error { func Register(scheme string, d DiscoveryService) error {
if _, exists := discoveries[scheme]; exists { if _, exists := discoveries[scheme]; exists {
return fmt.Errorf("scheme already registered %s", scheme) return fmt.Errorf("scheme already registered %s", scheme)
@ -65,6 +72,7 @@ func parse(rawurl string) (string, string) {
return parts[0], parts[1] return parts[0], parts[1]
} }
// New is exported
func New(rawurl string, heartbeat int) (DiscoveryService, error) { func New(rawurl string, heartbeat int) (DiscoveryService, error) {
scheme, uri := parse(rawurl) scheme, uri := parse(rawurl)
@ -77,6 +85,7 @@ func New(rawurl string, heartbeat int) (DiscoveryService, error) {
return nil, ErrNotSupported return nil, ErrNotSupported
} }
// CreateEntries is exported
func CreateEntries(addrs []string) ([]*Entry, error) { func CreateEntries(addrs []string) ([]*Entry, error) {
entries := []*Entry{} entries := []*Entry{}
if addrs == nil { if addrs == nil {

View File

@ -10,6 +10,7 @@ import (
"github.com/docker/swarm/discovery" "github.com/docker/swarm/discovery"
) )
// EtcdDiscoveryService is exported
type EtcdDiscoveryService struct { type EtcdDiscoveryService struct {
ttl uint64 ttl uint64
client *etcd.Client client *etcd.Client
@ -20,6 +21,7 @@ func init() {
discovery.Register("etcd", &EtcdDiscoveryService{}) discovery.Register("etcd", &EtcdDiscoveryService{})
} }
// Initialize is exported
func (s *EtcdDiscoveryService) Initialize(uris string, heartbeat int) error { func (s *EtcdDiscoveryService) Initialize(uris string, heartbeat int) error {
var ( var (
// split here because uris can contain multiples ips // split here because uris can contain multiples ips
@ -51,6 +53,8 @@ func (s *EtcdDiscoveryService) Initialize(uris string, heartbeat int) error {
} }
return nil return nil
} }
// Fetch is exported
func (s *EtcdDiscoveryService) Fetch() ([]*discovery.Entry, error) { func (s *EtcdDiscoveryService) Fetch() ([]*discovery.Entry, error) {
resp, err := s.client.Get(s.path, true, true) resp, err := s.client.Get(s.path, true, true)
if err != nil { if err != nil {
@ -64,6 +68,7 @@ func (s *EtcdDiscoveryService) Fetch() ([]*discovery.Entry, error) {
return discovery.CreateEntries(addrs) return discovery.CreateEntries(addrs)
} }
// Watch is exported
func (s *EtcdDiscoveryService) Watch(callback discovery.WatchCallback) { func (s *EtcdDiscoveryService) Watch(callback discovery.WatchCallback) {
watchChan := make(chan *etcd.Response) watchChan := make(chan *etcd.Response)
go s.client.Watch(s.path, 0, true, watchChan, nil) go s.client.Watch(s.path, 0, true, watchChan, nil)
@ -76,6 +81,7 @@ func (s *EtcdDiscoveryService) Watch(callback discovery.WatchCallback) {
} }
} }
// Register is exported
func (s *EtcdDiscoveryService) Register(addr string) error { func (s *EtcdDiscoveryService) Register(addr string) error {
_, err := s.client.Set(path.Join(s.path, addr), addr, s.ttl) _, err := s.client.Set(path.Join(s.path, addr), addr, s.ttl)
return err return err

View File

@ -8,6 +8,7 @@ import (
"github.com/docker/swarm/discovery" "github.com/docker/swarm/discovery"
) )
// FileDiscoveryService is exported
type FileDiscoveryService struct { type FileDiscoveryService struct {
heartbeat int heartbeat int
path string path string
@ -17,6 +18,7 @@ func init() {
discovery.Register("file", &FileDiscoveryService{}) discovery.Register("file", &FileDiscoveryService{})
} }
// Initialize is exported
func (s *FileDiscoveryService) Initialize(path string, heartbeat int) error { func (s *FileDiscoveryService) Initialize(path string, heartbeat int) error {
s.path = path s.path = path
s.heartbeat = heartbeat s.heartbeat = heartbeat
@ -33,6 +35,7 @@ func parseFileContent(content []byte) []string {
return result return result
} }
// Fetch is exported
func (s *FileDiscoveryService) Fetch() ([]*discovery.Entry, error) { func (s *FileDiscoveryService) Fetch() ([]*discovery.Entry, error) {
fileContent, err := ioutil.ReadFile(s.path) fileContent, err := ioutil.ReadFile(s.path)
if err != nil { if err != nil {
@ -41,6 +44,7 @@ func (s *FileDiscoveryService) Fetch() ([]*discovery.Entry, error) {
return discovery.CreateEntries(parseFileContent(fileContent)) return discovery.CreateEntries(parseFileContent(fileContent))
} }
// Watch is exported
func (s *FileDiscoveryService) Watch(callback discovery.WatchCallback) { func (s *FileDiscoveryService) Watch(callback discovery.WatchCallback) {
for _ = range time.Tick(time.Duration(s.heartbeat) * time.Second) { for _ = range time.Tick(time.Duration(s.heartbeat) * time.Second) {
entries, err := s.Fetch() entries, err := s.Fetch()
@ -50,6 +54,7 @@ func (s *FileDiscoveryService) Watch(callback discovery.WatchCallback) {
} }
} }
// Register is exported
func (s *FileDiscoveryService) Register(addr string) error { func (s *FileDiscoveryService) Register(addr string) error {
return discovery.ErrNotImplemented return discovery.ErrNotImplemented
} }

View File

@ -6,9 +6,7 @@ import (
"strconv" "strconv"
) )
// // Generate takes care of IP generation
// IP generator
//
func Generate(pattern string) []string { func Generate(pattern string) []string {
re, _ := regexp.Compile(`\[(.+):(.+)\]`) re, _ := regexp.Compile(`\[(.+):(.+)\]`)
submatch := re.FindStringSubmatch(pattern) submatch := re.FindStringSubmatch(pattern)

View File

@ -6,6 +6,7 @@ import (
"github.com/docker/swarm/discovery" "github.com/docker/swarm/discovery"
) )
// NodesDiscoveryService is exported
type NodesDiscoveryService struct { type NodesDiscoveryService struct {
entries []*discovery.Entry entries []*discovery.Entry
} }
@ -14,6 +15,7 @@ func init() {
discovery.Register("nodes", &NodesDiscoveryService{}) discovery.Register("nodes", &NodesDiscoveryService{})
} }
// Initialize is exported
func (s *NodesDiscoveryService) Initialize(uris string, _ int) error { func (s *NodesDiscoveryService) Initialize(uris string, _ int) error {
for _, input := range strings.Split(uris, ",") { for _, input := range strings.Split(uris, ",") {
for _, ip := range discovery.Generate(input) { for _, ip := range discovery.Generate(input) {
@ -27,13 +29,17 @@ func (s *NodesDiscoveryService) Initialize(uris string, _ int) error {
return nil return nil
} }
// Fetch is exported
func (s *NodesDiscoveryService) Fetch() ([]*discovery.Entry, error) { func (s *NodesDiscoveryService) Fetch() ([]*discovery.Entry, error) {
return s.entries, nil return s.entries, nil
} }
// Watch is exported
func (s *NodesDiscoveryService) Watch(callback discovery.WatchCallback) { func (s *NodesDiscoveryService) Watch(callback discovery.WatchCallback) {
} }
// Register is exported
func (s *NodesDiscoveryService) Register(addr string) error { func (s *NodesDiscoveryService) Register(addr string) error {
return discovery.ErrNotImplemented return discovery.ErrNotImplemented
} }

View File

@ -12,8 +12,10 @@ import (
"github.com/docker/swarm/discovery" "github.com/docker/swarm/discovery"
) )
const DISCOVERY_URL = "https://discovery-stage.hub.docker.com/v1" // DiscoveryUrl is exported
const DiscoveryURL = "https://discovery-stage.hub.docker.com/v1"
// TokenDiscoveryService is exported
type TokenDiscoveryService struct { type TokenDiscoveryService struct {
heartbeat int heartbeat int
url string url string
@ -24,12 +26,13 @@ func init() {
discovery.Register("token", &TokenDiscoveryService{}) discovery.Register("token", &TokenDiscoveryService{})
} }
// Initialize is exported
func (s *TokenDiscoveryService) Initialize(urltoken string, heartbeat int) error { func (s *TokenDiscoveryService) Initialize(urltoken string, heartbeat int) error {
if i := strings.LastIndex(urltoken, "/"); i != -1 { if i := strings.LastIndex(urltoken, "/"); i != -1 {
s.url = "https://" + urltoken[:i] s.url = "https://" + urltoken[:i]
s.token = urltoken[i+1:] s.token = urltoken[i+1:]
} else { } else {
s.url = DISCOVERY_URL s.url = DiscoveryURL
s.token = urltoken s.token = urltoken
} }
@ -63,6 +66,7 @@ func (s *TokenDiscoveryService) Fetch() ([]*discovery.Entry, error) {
return discovery.CreateEntries(addrs) return discovery.CreateEntries(addrs)
} }
// Watch is exported
func (s *TokenDiscoveryService) Watch(callback discovery.WatchCallback) { func (s *TokenDiscoveryService) Watch(callback discovery.WatchCallback) {
for _ = range time.Tick(time.Duration(s.heartbeat) * time.Second) { for _ = range time.Tick(time.Duration(s.heartbeat) * time.Second) {
entries, err := s.Fetch() entries, err := s.Fetch()
@ -72,7 +76,7 @@ func (s *TokenDiscoveryService) Watch(callback discovery.WatchCallback) {
} }
} }
// RegisterEntry adds a new entry identified by the into the discovery service // Register adds a new entry identified by the into the discovery service
func (s *TokenDiscoveryService) Register(addr string) error { func (s *TokenDiscoveryService) Register(addr string) error {
buf := strings.NewReader(addr) buf := strings.NewReader(addr)

View File

@ -11,7 +11,7 @@ func TestInitialize(t *testing.T) {
err := discovery.Initialize("token", 0) err := discovery.Initialize("token", 0)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, discovery.token, "token") assert.Equal(t, discovery.token, "token")
assert.Equal(t, discovery.url, DISCOVERY_URL) assert.Equal(t, discovery.url, DiscoveryURL)
err = discovery.Initialize("custom/path/token", 0) err = discovery.Initialize("custom/path/token", 0)
assert.NoError(t, err) assert.NoError(t, err)
@ -23,7 +23,7 @@ func TestInitialize(t *testing.T) {
} }
func TestRegister(t *testing.T) { func TestRegister(t *testing.T) {
discovery := &TokenDiscoveryService{token: "TEST_TOKEN", url: DISCOVERY_URL} discovery := &TokenDiscoveryService{token: "TEST_TOKEN", url: DiscoveryURL}
expected := "127.0.0.1:2675" expected := "127.0.0.1:2675"
assert.NoError(t, discovery.Register(expected)) assert.NoError(t, discovery.Register(expected))

View File

@ -11,6 +11,7 @@ import (
"github.com/samuel/go-zookeeper/zk" "github.com/samuel/go-zookeeper/zk"
) )
// ZkDiscoveryService is exported
type ZkDiscoveryService struct { type ZkDiscoveryService struct {
conn *zk.Conn conn *zk.Conn
path []string path []string
@ -39,6 +40,7 @@ func (s *ZkDiscoveryService) createFullpath() error {
return nil return nil
} }
// Initialize is exported
func (s *ZkDiscoveryService) Initialize(uris string, heartbeat int) error { func (s *ZkDiscoveryService) Initialize(uris string, heartbeat int) error {
var ( var (
// split here because uris can contain multiples ips // split here because uris can contain multiples ips
@ -72,6 +74,7 @@ func (s *ZkDiscoveryService) Initialize(uris string, heartbeat int) error {
return nil return nil
} }
// Fetch is exported
func (s *ZkDiscoveryService) Fetch() ([]*discovery.Entry, error) { func (s *ZkDiscoveryService) Fetch() ([]*discovery.Entry, error) {
addrs, _, err := s.conn.Children(s.fullpath()) addrs, _, err := s.conn.Children(s.fullpath())
@ -82,6 +85,7 @@ func (s *ZkDiscoveryService) Fetch() ([]*discovery.Entry, error) {
return discovery.CreateEntries(addrs) return discovery.CreateEntries(addrs)
} }
// Watch is exported
func (s *ZkDiscoveryService) Watch(callback discovery.WatchCallback) { func (s *ZkDiscoveryService) Watch(callback discovery.WatchCallback) {
addrs, _, eventChan, err := s.conn.ChildrenW(s.fullpath()) addrs, _, eventChan, err := s.conn.ChildrenW(s.fullpath())
@ -107,6 +111,7 @@ func (s *ZkDiscoveryService) Watch(callback discovery.WatchCallback) {
} }
// Register is exported
func (s *ZkDiscoveryService) Register(addr string) error { func (s *ZkDiscoveryService) Register(addr string) error {
nodePath := path.Join(s.fullpath(), addr) nodePath := path.Join(s.fullpath(), addr)

View File

@ -54,23 +54,23 @@ var (
Name: "api-enable-cors, cors", Name: "api-enable-cors, cors",
Usage: "enable CORS headers in the remote API", Usage: "enable CORS headers in the remote API",
} }
flTls = cli.BoolFlag{ flTLS = cli.BoolFlag{
Name: "tls", Name: "tls",
Usage: "use TLS; implied by --tlsverify=true", Usage: "use TLS; implied by --tlsverify=true",
} }
flTlsCaCert = cli.StringFlag{ flTLSCaCert = cli.StringFlag{
Name: "tlscacert", Name: "tlscacert",
Usage: "trust only remotes providing a certificate signed by the CA given here", Usage: "trust only remotes providing a certificate signed by the CA given here",
} }
flTlsCert = cli.StringFlag{ flTLSCert = cli.StringFlag{
Name: "tlscert", Name: "tlscert",
Usage: "path to TLS certificate file", Usage: "path to TLS certificate file",
} }
flTlsKey = cli.StringFlag{ flTLSKey = cli.StringFlag{
Name: "tlskey", Name: "tlskey",
Usage: "path to TLS key file", Usage: "path to TLS key file",
} }
flTlsVerify = cli.BoolFlag{ flTLSVerify = cli.BoolFlag{
Name: "tlsverify", Name: "tlsverify",
Usage: "use TLS and verify the remote", Usage: "use TLS and verify the remote",
} }
@ -86,8 +86,9 @@ var (
} }
// hack for go vet // hack for go vet
flFilterValue = cli.StringSlice([]string{"constraint", "affinity", "health", "port", "dependency"}) flFilterValue = cli.StringSlice([]string{"constraint", "affinity", "health", "port", "dependency"})
DEFAULT_FILTER_NUMBER = len(flFilterValue) // DefaultFilterNumber is exported
DefaultFilterNumber = len(flFilterValue)
flFilter = cli.StringSliceFlag{ flFilter = cli.StringSliceFlag{
Name: "filter, f", Name: "filter, f",

View File

@ -108,7 +108,7 @@ func main() {
flStore, flCluster, flStore, flCluster,
flStrategy, flFilter, flStrategy, flFilter,
flHosts, flHeartBeat, flOverCommit, flHosts, flHeartBeat, flOverCommit,
flTls, flTlsCaCert, flTlsCert, flTlsKey, flTlsVerify, flTLS, flTLSCaCert, flTLSCert, flTLSKey, flTLSVerify,
flEnableCors}, flEnableCors},
Action: manage, Action: manage,
}, },

View File

@ -32,7 +32,7 @@ func (h *logHandler) Handle(e *cluster.Event) error {
} }
// Load the TLS certificates/keys and, if verify is true, the CA. // Load the TLS certificates/keys and, if verify is true, the CA.
func loadTlsConfig(ca, cert, key string, verify bool) (*tls.Config, error) { func loadTLSConfig(ca, cert, key string, verify bool) (*tls.Config, error) {
c, err := tls.LoadX509KeyPair(cert, key) c, err := tls.LoadX509KeyPair(cert, key)
if err != nil { if err != nil {
return nil, fmt.Errorf("Couldn't load X509 key pair (%s, %s): %s. Key encrypted?", return nil, fmt.Errorf("Couldn't load X509 key pair (%s, %s): %s. Key encrypted?",
@ -64,7 +64,7 @@ func loadTlsConfig(ca, cert, key string, verify bool) (*tls.Config, error) {
func manage(c *cli.Context) { func manage(c *cli.Context) {
var ( var (
tlsConfig *tls.Config = nil tlsConfig *tls.Config
err error err error
) )
@ -76,7 +76,7 @@ func manage(c *cli.Context) {
if c.Bool("tlsverify") && !c.IsSet("tlscacert") { if c.Bool("tlsverify") && !c.IsSet("tlscacert") {
log.Fatal("--tlscacert must be provided when using --tlsverify") log.Fatal("--tlscacert must be provided when using --tlsverify")
} }
tlsConfig, err = loadTlsConfig( tlsConfig, err = loadTLSConfig(
c.String("tlscacert"), c.String("tlscacert"),
c.String("tlscert"), c.String("tlscert"),
c.String("tlskey"), c.String("tlskey"),
@ -110,7 +110,7 @@ func manage(c *cli.Context) {
// see https://github.com/codegangsta/cli/issues/160 // see https://github.com/codegangsta/cli/issues/160
names := c.StringSlice("filter") names := c.StringSlice("filter")
if c.IsSet("filter") || c.IsSet("f") { if c.IsSet("filter") || c.IsSet("f") {
names = names[DEFAULT_FILTER_NUMBER:] names = names[DefaultFilterNumber:]
} }
fs, err := filter.New(names) fs, err := filter.New(names)
if err != nil { if err != nil {

View File

@ -13,6 +13,7 @@ import (
type AffinityFilter struct { type AffinityFilter struct {
} }
// Filter is exported
func (f *AffinityFilter) Filter(config *dockerclient.ContainerConfig, nodes []cluster.Node) ([]cluster.Node, error) { func (f *AffinityFilter) Filter(config *dockerclient.ContainerConfig, nodes []cluster.Node) ([]cluster.Node, error) {
affinities, err := parseExprs("affinity", config.Env) affinities, err := parseExprs("affinity", config.Env)
if err != nil { if err != nil {

View File

@ -12,6 +12,7 @@ import (
type ConstraintFilter struct { type ConstraintFilter struct {
} }
// Filter is exported
func (f *ConstraintFilter) Filter(config *dockerclient.ContainerConfig, nodes []cluster.Node) ([]cluster.Node, error) { func (f *ConstraintFilter) Filter(config *dockerclient.ContainerConfig, nodes []cluster.Node) ([]cluster.Node, error) {
constraints, err := parseExprs("constraint", config.Env) constraints, err := parseExprs("constraint", config.Env)
if err != nil { if err != nil {

View File

@ -12,6 +12,7 @@ import (
type DependencyFilter struct { type DependencyFilter struct {
} }
// Filter is exported
func (f *DependencyFilter) Filter(config *dockerclient.ContainerConfig, nodes []cluster.Node) ([]cluster.Node, error) { func (f *DependencyFilter) Filter(config *dockerclient.ContainerConfig, nodes []cluster.Node) ([]cluster.Node, error) {
if len(nodes) == 0 { if len(nodes) == 0 {
return nodes, nil return nodes, nil

View File

@ -9,10 +9,13 @@ import (
) )
const ( const (
// EQ is exported
EQ = iota EQ = iota
// NOTEQ is exported
NOTEQ NOTEQ
) )
// OPERATORS is exported
var OPERATORS = []string{"==", "!="} var OPERATORS = []string{"==", "!="}
type expr struct { type expr struct {
@ -109,7 +112,6 @@ func (e *expr) Match(whats ...string) bool {
func isSoft(value string) bool { func isSoft(value string) bool {
if value[0] == '~' { if value[0] == '~' {
return true return true
} else {
return false
} }
return false
} }

View File

@ -8,13 +8,15 @@ import (
"github.com/samalba/dockerclient" "github.com/samalba/dockerclient"
) )
// Filter is exported
type Filter interface { type Filter interface {
// Return a subset of nodes that were accepted by the filtering policy. // Return a subset of nodes that were accepted by the filtering policy.
Filter(*dockerclient.ContainerConfig, []cluster.Node) ([]cluster.Node, error) Filter(*dockerclient.ContainerConfig, []cluster.Node) ([]cluster.Node, error)
} }
var ( var (
filters map[string]Filter filters map[string]Filter
// ErrNotSupported is exported
ErrNotSupported = errors.New("filter not supported") ErrNotSupported = errors.New("filter not supported")
) )
@ -28,6 +30,7 @@ func init() {
} }
} }
// New is exported
func New(names []string) ([]Filter, error) { func New(names []string) ([]Filter, error) {
var selectedFilters []Filter var selectedFilters []Filter
@ -42,7 +45,7 @@ func New(names []string) ([]Filter, error) {
return selectedFilters, nil return selectedFilters, nil
} }
// Apply a set of filters in batch. // ApplyFilters applies a set of filters in batch.
func ApplyFilters(filters []Filter, config *dockerclient.ContainerConfig, nodes []cluster.Node) ([]cluster.Node, error) { func ApplyFilters(filters []Filter, config *dockerclient.ContainerConfig, nodes []cluster.Node) ([]cluster.Node, error) {
var err error var err error

View File

@ -8,6 +8,7 @@ import (
) )
var ( var (
// ErrNoHealthyNodeAvailable is exported
ErrNoHealthyNodeAvailable = errors.New("No healthy node available in the cluster") ErrNoHealthyNodeAvailable = errors.New("No healthy node available in the cluster")
) )
@ -15,6 +16,7 @@ var (
type HealthFilter struct { type HealthFilter struct {
} }
// Filter is exported
func (f *HealthFilter) Filter(_ *dockerclient.ContainerConfig, nodes []cluster.Node) ([]cluster.Node, error) { func (f *HealthFilter) Filter(_ *dockerclient.ContainerConfig, nodes []cluster.Node) ([]cluster.Node, error) {
result := []cluster.Node{} result := []cluster.Node{}
for _, node := range nodes { for _, node := range nodes {

View File

@ -13,6 +13,7 @@ import (
type PortFilter struct { type PortFilter struct {
} }
// Filter is exported
func (p *PortFilter) Filter(config *dockerclient.ContainerConfig, nodes []cluster.Node) ([]cluster.Node, error) { func (p *PortFilter) Filter(config *dockerclient.ContainerConfig, nodes []cluster.Node) ([]cluster.Node, error) {
for _, port := range config.HostConfig.PortBindings { for _, port := range config.HostConfig.PortBindings {
for _, binding := range port { for _, binding := range port {

View File

@ -7,11 +7,13 @@ import (
"github.com/samalba/dockerclient" "github.com/samalba/dockerclient"
) )
// Scheduler is exported
type Scheduler struct { type Scheduler struct {
strategy strategy.PlacementStrategy strategy strategy.PlacementStrategy
filters []filter.Filter filters []filter.Filter
} }
// New is exported
func New(strategy strategy.PlacementStrategy, filters []filter.Filter) *Scheduler { func New(strategy strategy.PlacementStrategy, filters []filter.Filter) *Scheduler {
return &Scheduler{ return &Scheduler{
strategy: strategy, strategy: strategy,
@ -19,7 +21,7 @@ func New(strategy strategy.PlacementStrategy, filters []filter.Filter) *Schedule
} }
} }
// Find a nice home for our container. // SelectNodeForContainer will find a nice home for our container.
func (s *Scheduler) SelectNodeForContainer(nodes []cluster.Node, config *dockerclient.ContainerConfig) (cluster.Node, error) { func (s *Scheduler) SelectNodeForContainer(nodes []cluster.Node, config *dockerclient.ContainerConfig) (cluster.Node, error) {
accepted, err := filter.ApplyFilters(s.filters, config, nodes) accepted, err := filter.ApplyFilters(s.filters, config, nodes)
if err != nil { if err != nil {

View File

@ -7,13 +7,16 @@ import (
"github.com/samalba/dockerclient" "github.com/samalba/dockerclient"
) )
// BinpackPlacementStrategy is exported
type BinpackPlacementStrategy struct { type BinpackPlacementStrategy struct {
} }
// Initialize is exported
func (p *BinpackPlacementStrategy) Initialize() error { func (p *BinpackPlacementStrategy) Initialize() error {
return nil return nil
} }
// PlaceContainer is exported
func (p *BinpackPlacementStrategy) PlaceContainer(config *dockerclient.ContainerConfig, nodes []cluster.Node) (cluster.Node, error) { func (p *BinpackPlacementStrategy) PlaceContainer(config *dockerclient.ContainerConfig, nodes []cluster.Node) (cluster.Node, error) {
weightedNodes, err := weighNodes(config, nodes) weightedNodes, err := weighNodes(config, nodes)
if err != nil { if err != nil {

View File

@ -9,14 +9,16 @@ import (
"github.com/samalba/dockerclient" "github.com/samalba/dockerclient"
) )
// Randomly place the container into the cluster. // RandomPlacementStrategy randomly places the container into the cluster.
type RandomPlacementStrategy struct{} type RandomPlacementStrategy struct{}
// Initialize is exported
func (p *RandomPlacementStrategy) Initialize() error { func (p *RandomPlacementStrategy) Initialize() error {
rand.Seed(time.Now().UTC().UnixNano()) rand.Seed(time.Now().UTC().UnixNano())
return nil return nil
} }
// PlaceContainer is exported
func (p *RandomPlacementStrategy) PlaceContainer(config *dockerclient.ContainerConfig, nodes []cluster.Node) (cluster.Node, error) { func (p *RandomPlacementStrategy) PlaceContainer(config *dockerclient.ContainerConfig, nodes []cluster.Node) (cluster.Node, error) {
if size := len(nodes); size > 0 { if size := len(nodes); size > 0 {
n := rand.Intn(len(nodes)) n := rand.Intn(len(nodes))

View File

@ -7,13 +7,16 @@ import (
"github.com/samalba/dockerclient" "github.com/samalba/dockerclient"
) )
// SpreadPlacementStrategy is exported
type SpreadPlacementStrategy struct { type SpreadPlacementStrategy struct {
} }
// Initialize is exported
func (p *SpreadPlacementStrategy) Initialize() error { func (p *SpreadPlacementStrategy) Initialize() error {
return nil return nil
} }
// PlaceContainer is exported
func (p *SpreadPlacementStrategy) PlaceContainer(config *dockerclient.ContainerConfig, nodes []cluster.Node) (cluster.Node, error) { func (p *SpreadPlacementStrategy) PlaceContainer(config *dockerclient.ContainerConfig, nodes []cluster.Node) (cluster.Node, error) {
weightedNodes, err := weighNodes(config, nodes) weightedNodes, err := weighNodes(config, nodes)
if err != nil { if err != nil {

View File

@ -8,6 +8,7 @@ import (
"github.com/samalba/dockerclient" "github.com/samalba/dockerclient"
) )
// PlacementStrategy is exported
type PlacementStrategy interface { type PlacementStrategy interface {
Initialize() error Initialize() error
// Given a container configuration and a set of nodes, select the target // Given a container configuration and a set of nodes, select the target
@ -16,8 +17,10 @@ type PlacementStrategy interface {
} }
var ( var (
strategies map[string]PlacementStrategy strategies map[string]PlacementStrategy
ErrNotSupported = errors.New("strategy not supported") // ErrNotSupported is exported
ErrNotSupported = errors.New("strategy not supported")
// ErrNoResourcesAvailable is exported
ErrNoResourcesAvailable = errors.New("no resources available to schedule container") ErrNoResourcesAvailable = errors.New("no resources available to schedule container")
) )
@ -30,6 +33,7 @@ func init() {
} }
} }
// New is exported
func New(name string) (PlacementStrategy, error) { func New(name string) (PlacementStrategy, error) {
if strategy, exists := strategies[name]; exists { if strategy, exists := strategies[name]; exists {
log.WithField("name", name).Debugf("Initializing strategy") log.WithField("name", name).Debugf("Initializing strategy")

View File

@ -4,6 +4,7 @@ import (
"github.com/samalba/dockerclient" "github.com/samalba/dockerclient"
) )
// RequestedState is exported
type RequestedState struct { type RequestedState struct {
ID string ID string
Name string Name string

View File

@ -14,12 +14,15 @@ import (
) )
var ( var (
ErrNotFound = errors.New("not found") // ErrNotFound is exported
ErrNotFound = errors.New("not found")
// ErrAlreadyExists is exported
ErrAlreadyExists = errors.New("already exists") ErrAlreadyExists = errors.New("already exists")
ErrInvalidKey = errors.New("invalid key") // ErrInvalidKey is exported
ErrInvalidKey = errors.New("invalid key")
) )
// A simple key<->RequestedState store. // Store is a simple key<->RequestedState store.
type Store struct { type Store struct {
RootDir string RootDir string
values map[string]*RequestedState values map[string]*RequestedState
@ -27,6 +30,7 @@ type Store struct {
sync.RWMutex sync.RWMutex
} }
// NewStore is exported
func NewStore(rootdir string) *Store { func NewStore(rootdir string) *Store {
return &Store{ return &Store{
RootDir: rootdir, RootDir: rootdir,
@ -102,7 +106,7 @@ func (s *Store) load(file string) (*RequestedState, error) {
return value, nil return value, nil
} }
// Retrieves an object from the store keyed by `key`. // Get an object from the store keyed by `key`.
func (s *Store) Get(key string) (*RequestedState, error) { func (s *Store) Get(key string) (*RequestedState, error) {
s.RLock() s.RLock()
defer s.RUnlock() defer s.RUnlock()
@ -113,7 +117,7 @@ func (s *Store) Get(key string) (*RequestedState, error) {
return nil, ErrNotFound return nil, ErrNotFound
} }
// Return all objects of the store. // All objects of the store are returned.
func (s *Store) All() []*RequestedState { func (s *Store) All() []*RequestedState {
s.RLock() s.RLock()
defer s.RUnlock() defer s.RUnlock()
@ -157,7 +161,7 @@ func (s *Store) Add(key string, value *RequestedState) error {
return s.set(key, value) return s.set(key, value)
} }
// Replaces an already existing object from the store. // Replace an already existing object from the store.
func (s *Store) Replace(key string, value *RequestedState) error { func (s *Store) Replace(key string, value *RequestedState) error {
s.Lock() s.Lock()
defer s.Unlock() defer s.Unlock()