Skip to content

Commit

Permalink
Merge pull request #89 from fubarhouse/isue/88
Browse files Browse the repository at this point in the history
#88: Open up Docker Network API to user/config
  • Loading branch information
fubarhouse committed Jan 10, 2020
2 parents ea45506 + f82a10f commit c25ba9a
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 60 deletions.
41 changes: 39 additions & 2 deletions service/interface/interface.go
Expand Up @@ -40,6 +40,21 @@ type Service struct {
NetworkConfig network.NetworkingConfig
}

// Network is a struct containing the configuration of a single Docker network
// including some extra fields so that Pygmy knows how to interact with the
// desired outcome.
type Network struct {
// Name is the name of the network, it is independent of the map key which
// will be used to configure pygmy but this field should match the map key.
Name string `yaml:"name"`
// Containers is a []string which indicates the names of the containers
// that need to be connected to this network.
Containers []string `yaml:"containers"`
// Config is the actual Network configuration for the Docker Network.
// It is the Network creation configuration as provided by the Docker API.
Config types.NetworkCreate `yaml:"config"`
}

func (Service *Service) Setup() error {
if Service.Config.Image == "" {
return nil
Expand Down Expand Up @@ -398,19 +413,41 @@ func DockerRemove(id string) error {
return nil
}

func DockerNetworkCreate(name string) error {
// DockerNetworkCreate is an abstraction layer on top of the Docker API call
// which will create a Docker network using a specified configuration.
func DockerNetworkCreate(name string, config types.NetworkCreate) error {
ctx := context.Background()
cli, err := client.NewEnvClient()
if err != nil {
fmt.Println(err)
}
_, err = cli.NetworkCreate(ctx, name, types.NetworkCreate{})
_, err = cli.NetworkCreate(ctx, name, config)
if err != nil {
fmt.Println(err)
}
return nil
}

// DockerNetworkGet will use the Docker API to retrieve a Docker network
// which has a given name.
func DockerNetworkGet(name string) (types.NetworkResource, error) {
ctx := context.Background()
cli, err := client.NewEnvClient()
if err != nil {
return types.NetworkResource{}, err
}
networks, err := cli.NetworkList(ctx, types.NetworkListOptions{})
if err != nil {
return types.NetworkResource{}, err
}
for _, network := range networks {
if network.Name == name {
return network, nil
}
}
return types.NetworkResource{}, nil
}

func DockerNetworkConnect(network string, containerName string) error {
ctx := context.Background()
cli, err := client.NewEnvClient()
Expand Down
3 changes: 2 additions & 1 deletion service/library/library.go
Expand Up @@ -3,6 +3,7 @@ package library

import (
"fmt"

model "github.com/fubarhouse/pygmy-go/service/interface"
"github.com/fubarhouse/pygmy-go/service/resolv"
"github.com/imdario/mergo"
Expand All @@ -24,7 +25,7 @@ type Config struct {
SortedServices []string

// Networks is for network configuration
Networks map[string][]string `yaml:"networks"`
Networks map[string]model.Network `yaml:"networks"`

// NoDefaults will prevent default configuration items.
Defaults bool
Expand Down
41 changes: 41 additions & 0 deletions service/library/network.go
@@ -0,0 +1,41 @@
package library

import (
"context"
"errors"
"fmt"

"github.com/docker/docker/api/types"
"github.com/docker/docker/client"
"github.com/fubarhouse/pygmy-go/service/interface"
)

// NetworkCreate is part of a centralised abstraction of the Docker API
// and will create a Docker network with a specified configuration.
func NetworkCreate(c Config, name string) error {
return model.DockerNetworkCreate(name, c.Networks[name].Config)
}

// NetworkConnect is part of a centralised abstraction of the Docker API
// and will connect a created container to a docker network with a
// specified name.
func NetworkConnect(c Config, name string, containerName string) error {
return model.DockerNetworkConnect(name, containerName)
}

// NetworkStatus will check the state of a Docker network to test if it has
// been created, and will return false if the network can not be found.
func NetworkStatus(network string) (bool, error) {
ctx := context.Background()
cli, err := client.NewEnvClient()
if err != nil {
return false, err
}
networkResources, err := cli.NetworkList(ctx, types.NetworkListOptions{})
for _, Network := range networkResources {
if Network.Name == network {
return true, nil
}
}
return false, errors.New(fmt.Sprintf("network %v not found\n", network))
}
22 changes: 13 additions & 9 deletions service/library/setup.go
Expand Up @@ -2,29 +2,25 @@ package library

import (
"fmt"
"runtime"
"sort"
"strings"

"github.com/fubarhouse/pygmy-go/service/dnsmasq"
"github.com/fubarhouse/pygmy-go/service/haproxy"
model "github.com/fubarhouse/pygmy-go/service/interface"
"github.com/fubarhouse/pygmy-go/service/mailhog"
"github.com/fubarhouse/pygmy-go/service/network"
"github.com/fubarhouse/pygmy-go/service/resolv"
"github.com/fubarhouse/pygmy-go/service/ssh/agent"
"github.com/fubarhouse/pygmy-go/service/ssh/key"
"github.com/spf13/viper"
"runtime"
"sort"
"strings"
)

func Setup(c *Config) {

viper.SetDefault("defaults", true)

viper.SetDefault("networks", map[string][]string{
"amazeeio-network": []string{
"amazeeio-haproxy",
},
})

var ResolvMacOS = resolv.Resolv{
Data: "# Generated by amazeeio pygmy\nnameserver 127.0.0.1\nport 6053\n",
File: "docker.amazee.io",
Expand Down Expand Up @@ -85,6 +81,14 @@ func Setup(c *Config) {
c.Services["mailhog.docker.amazee.io"] = getService(mailhog.NewDefaultPorts(), c.Services["mailhog.docker.amazee.io"])
}

// If networks are not provided, we should provide defaults.
// Defaults will be provided if nothing is found in configuration
// (is completely absent).
// TODO: Make this mergable like container configurations are.
viper.SetDefault("networks", map[string]model.Network{
"amazeeio-network": network.New(),
})

}

// It is because of interdependent containers we introduce a weighting system.
Expand Down
19 changes: 9 additions & 10 deletions service/library/status.go
Expand Up @@ -6,7 +6,6 @@ import (

"github.com/fubarhouse/pygmy-go/service/haproxy_connector"
model "github.com/fubarhouse/pygmy-go/service/interface"
"github.com/fubarhouse/pygmy-go/service/network"
"github.com/fubarhouse/pygmy-go/service/resolv"
"github.com/fubarhouse/pygmy-go/service/test_url"
)
Expand Down Expand Up @@ -55,21 +54,21 @@ func Status(c Config) {
}
}

for Network, Containers := range c.Networks {
netStat, _ := network.Status(Network)
for _, Network := range c.Networks {
netStat, _ := NetworkStatus(Network.Name)
if netStat {
for _, Container := range Containers {
if s, _ := haproxy_connector.Connected(Container, Network); s {
fmt.Printf("[*] %v is connected to network %v\n", Container, Network)
for _, Container := range Network.Containers {
if s, _ := haproxy_connector.Connected(Container, Network.Name); s {
fmt.Printf("[*] %v is connected to network %v\n", Container, Network.Name)
} else {
fmt.Printf("[ ] %v is not connected to network %v\n", Container, Network)
fmt.Printf("[ ] %v is not connected to network %v\n", Container, Network.Name)
}
}
}
if _, e := network.Status(Network); e == nil {
fmt.Printf("[*] %v network has been created\n", Network)
if _, e := NetworkStatus(Network.Name); e == nil {
fmt.Printf("[*] %v network has been created\n", Network.Name)
} else {
fmt.Printf("[ ] %v network has not been created\n", Network)
fmt.Printf("[ ] %v network has not been created\n", Network.Name)
}
}

Expand Down
23 changes: 11 additions & 12 deletions service/library/up.go
@@ -1,12 +1,11 @@
package library

import (
"os"
"fmt"
"os"

"github.com/fubarhouse/pygmy-go/service/haproxy_connector"
model "github.com/fubarhouse/pygmy-go/service/interface"
"github.com/fubarhouse/pygmy-go/service/network"
"github.com/fubarhouse/pygmy-go/service/resolv"
"github.com/fubarhouse/pygmy-go/service/test_url"
)
Expand Down Expand Up @@ -50,21 +49,21 @@ func Up(c Config) {
}
}

for Network, Containers := range c.Networks {
netStat, _ := network.Status(Network)
for _, Network := range c.Networks {
netStat, _ := NetworkStatus(Network.Name)
if !netStat {
network.Create(Network)
NetworkCreate(c, Network.Name)
}
for _, Container := range Containers {
if s, _ := haproxy_connector.Connected(Container, Network); !s {
haproxy_connector.Connect(Container, Network)
if s, _ := haproxy_connector.Connected(Container, Network); s {
fmt.Printf("Successfully connected %v to %v\n", Container, Network)
for _, Container := range Network.Containers {
if s, _ := haproxy_connector.Connected(Container, Network.Name); !s {
haproxy_connector.Connect(Container, Network.Name)
if s, _ := haproxy_connector.Connected(Container, Network.Name); s {
fmt.Printf("Successfully connected %v to %v\n", Container, Network.Name)
} else {
fmt.Printf("Could not connect %v to %v\n", Container, Network)
fmt.Printf("Could not connect %v to %v\n", Container, Network.Name)
}
} else {
fmt.Printf("Already connected %v to %v\n", Container, Network)
fmt.Printf("Already connected %v to %v\n", Container, Network.Name)
}
}
}
Expand Down
44 changes: 18 additions & 26 deletions service/network/network.go
@@ -1,34 +1,26 @@
package network

import (
"context"
"errors"
"fmt"

"github.com/docker/docker/api/types"
"github.com/docker/docker/client"
"github.com/fubarhouse/pygmy-go/service/interface"
"github.com/docker/docker/api/types/network"
model "github.com/fubarhouse/pygmy-go/service/interface"
)

func Create(network string) error {
return model.DockerNetworkCreate(network)
}

func Connect(containerName string, network string) error {
return model.DockerNetworkConnect(network, containerName)
}

func Status(network string) (bool, error) {
ctx := context.Background()
cli, err := client.NewEnvClient()
if err != nil {
return false, err
}
networkResources, err := cli.NetworkList(ctx, types.NetworkListOptions{})
for _, Network := range networkResources {
if Network.Name == network {
return true, nil
}
// New will generate the defaults for the Docker network.
// If configuration is provided this will not be used at all.
func New() model.Network {
return model.Network{
Name: "amazeeio-network",
Containers: []string{"amazeeio-haproxy"},
Config: types.NetworkCreate{
IPAM: &network.IPAM{
Config: []network.IPAMConfig{
{
Subnet: "10.99.99.0/24",
Gateway: "10.99.99.1",
},
},
},
},
}
return false, errors.New(fmt.Sprintf("network %v not found\n", network))
}

0 comments on commit c25ba9a

Please sign in to comment.