init
This commit is contained in:
parent
65f2820b3f
commit
d35f12a77e
@ -71,8 +71,18 @@ func CreateCluster(c *cli.Context) error {
|
||||
k3sServerArgs = append(k3sServerArgs, c.StringSlice("server-arg")...)
|
||||
}
|
||||
|
||||
fmt.Println("==========")
|
||||
pm, err := createPortMap(c.StringSlice("publish"))
|
||||
fmt.Printf("pm: %+v \n err: %+v \n", pm, err)
|
||||
for _, x := range *pm {
|
||||
fmt.Printf("x: %+v\n -> Ports: %+v\n", x, x.Ports)
|
||||
}
|
||||
fmt.Println("==========")
|
||||
publishedPorts, err := createPublishedPorts(c.StringSlice("publish"))
|
||||
if (err != nil) {
|
||||
fmt.Printf("pm: %+v \n err: %+v \n", publishedPorts, err)
|
||||
fmt.Println("==========")
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("ERROR: failed to parse the publish parameter.\n%+v", err)
|
||||
}
|
||||
|
||||
|
||||
104
cli/container.go
104
cli/container.go
@ -18,84 +18,8 @@ import (
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/network"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/go-connections/nat"
|
||||
)
|
||||
|
||||
type PublishedPorts struct {
|
||||
ExposedPorts map[nat.Port]struct{}
|
||||
PortBindings map[nat.Port][]nat.PortBinding
|
||||
}
|
||||
|
||||
// The factory function for PublishedPorts
|
||||
func createPublishedPorts(specs []string) (*PublishedPorts, error) {
|
||||
if len(specs) == 0 {
|
||||
var newExposedPorts = make(map[nat.Port]struct{}, 1)
|
||||
var newPortBindings = make(map[nat.Port][]nat.PortBinding, 1)
|
||||
return &PublishedPorts{ExposedPorts: newExposedPorts, PortBindings: newPortBindings}, nil
|
||||
}
|
||||
|
||||
newExposedPorts, newPortBindings, err := nat.ParsePortSpecs(specs)
|
||||
return &PublishedPorts{ExposedPorts: newExposedPorts, PortBindings: newPortBindings}, err
|
||||
}
|
||||
|
||||
// Create a new PublishedPort structure, with all host ports are changed by a fixed 'offset'
|
||||
func (p PublishedPorts) Offset(offset int) (*PublishedPorts) {
|
||||
var newExposedPorts = make(map[nat.Port]struct{}, len(p.ExposedPorts))
|
||||
var newPortBindings = make(map[nat.Port][]nat.PortBinding, len(p.PortBindings))
|
||||
|
||||
for k, v := range p.ExposedPorts {
|
||||
newExposedPorts[k] = v
|
||||
}
|
||||
|
||||
for k, v := range p.PortBindings {
|
||||
bindings := make([]nat.PortBinding, len(v))
|
||||
for i, b := range v {
|
||||
port, _ := nat.ParsePort(b.HostPort)
|
||||
bindings[i].HostIP = b.HostIP
|
||||
bindings[i].HostPort = fmt.Sprintf("%d", port + offset)
|
||||
}
|
||||
newPortBindings[k] = bindings
|
||||
}
|
||||
|
||||
return &PublishedPorts{ExposedPorts: newExposedPorts, PortBindings: newPortBindings}
|
||||
}
|
||||
|
||||
// Create a new PublishedPort struct with one more port, based on 'portSpec'
|
||||
func (p *PublishedPorts) AddPort(portSpec string) (*PublishedPorts, error) {
|
||||
portMappings, err := nat.ParsePortSpec(portSpec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var newExposedPorts = make(map[nat.Port]struct{}, len(p.ExposedPorts) + 1)
|
||||
var newPortBindings = make(map[nat.Port][]nat.PortBinding, len(p.PortBindings) + 1)
|
||||
|
||||
// Populate the new maps
|
||||
for k, v := range p.ExposedPorts {
|
||||
newExposedPorts[k] = v
|
||||
}
|
||||
|
||||
for k, v := range p.PortBindings {
|
||||
newPortBindings[k] = v
|
||||
}
|
||||
|
||||
// Add new ports
|
||||
for _, portMapping := range portMappings {
|
||||
port := portMapping.Port
|
||||
if _, exists := newExposedPorts[port]; !exists {
|
||||
newExposedPorts[port] = struct{}{}
|
||||
}
|
||||
|
||||
bslice, exists := newPortBindings[port];
|
||||
if !exists {
|
||||
bslice = []nat.PortBinding{}
|
||||
}
|
||||
newPortBindings[port] = append(bslice, portMapping.Binding)
|
||||
}
|
||||
|
||||
return &PublishedPorts{ExposedPorts: newExposedPorts, PortBindings: newPortBindings}, nil
|
||||
}
|
||||
|
||||
func startContainer(verbose bool, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, containerName string) (string, error) {
|
||||
ctx := context.Background()
|
||||
|
||||
@ -139,7 +63,7 @@ func startContainer(verbose bool, config *container.Config, hostConfig *containe
|
||||
}
|
||||
|
||||
func createServer(verbose bool, image string, port string, args []string, env []string,
|
||||
name string, volumes []string, pPorts *PublishedPorts) (string, error) {
|
||||
name string, volumes []string, pPorts *PublishedPorts) (string, error) {
|
||||
log.Printf("Creating server using %s...\n", image)
|
||||
|
||||
containerLabels := make(map[string]string)
|
||||
@ -152,13 +76,13 @@ func createServer(verbose bool, image string, port string, args []string, env []
|
||||
|
||||
apiPortSpec := fmt.Sprintf("0.0.0.0:%s:%s/tcp", port, port)
|
||||
serverPublishedPorts, err := pPorts.AddPort(apiPortSpec)
|
||||
if (err != nil) {
|
||||
if err != nil {
|
||||
log.Fatalf("Error: failed to parse API port spec %s \n%+v", apiPortSpec, err)
|
||||
}
|
||||
|
||||
hostConfig := &container.HostConfig{
|
||||
PortBindings: serverPublishedPorts.PortBindings,
|
||||
Privileged: true,
|
||||
Privileged: true,
|
||||
}
|
||||
|
||||
if len(volumes) > 0 && volumes[0] != "" {
|
||||
@ -174,12 +98,12 @@ func createServer(verbose bool, image string, port string, args []string, env []
|
||||
}
|
||||
|
||||
config := &container.Config{
|
||||
Hostname: containerName,
|
||||
Image: image,
|
||||
Cmd: append([]string{"server"}, args...),
|
||||
Hostname: containerName,
|
||||
Image: image,
|
||||
Cmd: append([]string{"server"}, args...),
|
||||
ExposedPorts: serverPublishedPorts.ExposedPorts,
|
||||
Env: env,
|
||||
Labels: containerLabels,
|
||||
Env: env,
|
||||
Labels: containerLabels,
|
||||
}
|
||||
id, err := startContainer(verbose, config, hostConfig, networkingConfig, containerName)
|
||||
if err != nil {
|
||||
@ -191,7 +115,7 @@ func createServer(verbose bool, image string, port string, args []string, env []
|
||||
|
||||
// createWorker creates/starts a k3s agent node that connects to the server
|
||||
func createWorker(verbose bool, image string, args []string, env []string, name string, volumes []string,
|
||||
postfix int, serverPort string, pPorts *PublishedPorts) (string, error) {
|
||||
postfix int, serverPort string, pPorts *PublishedPorts) (string, error) {
|
||||
containerLabels := make(map[string]string)
|
||||
containerLabels["app"] = "k3d"
|
||||
containerLabels["component"] = "worker"
|
||||
@ -210,7 +134,7 @@ func createWorker(verbose bool, image string, args []string, env []string, name
|
||||
"/var/run": "",
|
||||
},
|
||||
PortBindings: workerPublishedPorts.PortBindings,
|
||||
Privileged: true,
|
||||
Privileged: true,
|
||||
}
|
||||
|
||||
if len(volumes) > 0 && volumes[0] != "" {
|
||||
@ -226,10 +150,10 @@ func createWorker(verbose bool, image string, args []string, env []string, name
|
||||
}
|
||||
|
||||
config := &container.Config{
|
||||
Hostname: containerName,
|
||||
Image: image,
|
||||
Env: env,
|
||||
Labels: containerLabels,
|
||||
Hostname: containerName,
|
||||
Image: image,
|
||||
Env: env,
|
||||
Labels: containerLabels,
|
||||
ExposedPorts: workerPublishedPorts.ExposedPorts,
|
||||
}
|
||||
|
||||
|
||||
153
cli/port.go
Normal file
153
cli/port.go
Normal file
@ -0,0 +1,153 @@
|
||||
package run
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/go-connections/nat"
|
||||
)
|
||||
|
||||
// PublishedPorts is a struct used for exposing container ports on the host system
|
||||
type PublishedPorts struct {
|
||||
ExposedPorts map[nat.Port]struct{}
|
||||
PortBindings map[nat.Port][]nat.PortBinding
|
||||
}
|
||||
|
||||
// Portmap maps node roles/names to a set of PublishedPorts
|
||||
type Portmap struct {
|
||||
Node string
|
||||
Ports *PublishedPorts
|
||||
}
|
||||
|
||||
// defaultNodes describes the type of nodes on which a port should be exposed by default
|
||||
const defaultNodes = "all"
|
||||
|
||||
// createPortMap creates a list of portmaps that map nodes (roles or names) to a list of published ports
|
||||
func createPortMap(specs []string) (*[]Portmap, error) {
|
||||
|
||||
if err := validatePortSpecs(specs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nodeToPortSpecMap := make(map[string][]string)
|
||||
|
||||
for _, spec := range specs {
|
||||
nodes, portSpec := extractNodes(spec)
|
||||
|
||||
for _, node := range nodes {
|
||||
nodeToPortSpecMap[node] = append(nodeToPortSpecMap[node], portSpec)
|
||||
}
|
||||
}
|
||||
|
||||
portmaps := []Portmap{}
|
||||
for node, portSpecs := range nodeToPortSpecMap {
|
||||
ports, err := createPublishedPorts(portSpecs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newPortMap := Portmap{
|
||||
Node: node,
|
||||
Ports: ports,
|
||||
}
|
||||
portmaps = append(portmaps, newPortMap)
|
||||
}
|
||||
return &portmaps, nil
|
||||
}
|
||||
|
||||
// The factory function for PublishedPorts
|
||||
func createPublishedPorts(specs []string) (*PublishedPorts, error) {
|
||||
if len(specs) == 0 {
|
||||
var newExposedPorts = make(map[nat.Port]struct{}, 1)
|
||||
var newPortBindings = make(map[nat.Port][]nat.PortBinding, 1)
|
||||
return &PublishedPorts{ExposedPorts: newExposedPorts, PortBindings: newPortBindings}, nil
|
||||
}
|
||||
|
||||
newExposedPorts, newPortBindings, err := nat.ParsePortSpecs(specs)
|
||||
return &PublishedPorts{ExposedPorts: newExposedPorts, PortBindings: newPortBindings}, err
|
||||
}
|
||||
|
||||
// validatePortSpecs matches the provided port specs against a set of rules to enable early exit if something is wrong
|
||||
func validatePortSpecs(specs []string) error {
|
||||
// regex matching (no sophisticated IP/Hostname matching at the moment)
|
||||
regex := regexp.MustCompile(`^(((?P<host>[\w\.]+)?:)?((?P<hostPort>[0-9]{0,6}):)?(?P<containerPort>[0-9]{1,6}))((/(?P<protocol>udp|tcp))?(?P<nodes>(@(?P<node>[\w-]+))*))$`)
|
||||
for _, spec := range specs {
|
||||
if !regex.MatchString(spec) {
|
||||
return fmt.Errorf("[ERROR] Provided port spec [%s] didn't match format specification", spec)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// extractNodes separates the node specification from the actual port specs
|
||||
func extractNodes(spec string) ([]string, string) {
|
||||
// extract nodes
|
||||
nodes := []string{}
|
||||
atSplit := strings.Split(spec, "@")
|
||||
portSpec := atSplit[0]
|
||||
if len(atSplit) > 1 {
|
||||
nodes = atSplit[1:]
|
||||
}
|
||||
if len(nodes) == 0 {
|
||||
nodes = append(nodes, defaultNodes)
|
||||
}
|
||||
return nodes, portSpec
|
||||
}
|
||||
|
||||
// Offset creates a new PublishedPort structure, with all host ports are changed by a fixed 'offset'
|
||||
func (p PublishedPorts) Offset(offset int) *PublishedPorts {
|
||||
var newExposedPorts = make(map[nat.Port]struct{}, len(p.ExposedPorts))
|
||||
var newPortBindings = make(map[nat.Port][]nat.PortBinding, len(p.PortBindings))
|
||||
|
||||
for k, v := range p.ExposedPorts {
|
||||
newExposedPorts[k] = v
|
||||
}
|
||||
|
||||
for k, v := range p.PortBindings {
|
||||
bindings := make([]nat.PortBinding, len(v))
|
||||
for i, b := range v {
|
||||
port, _ := nat.ParsePort(b.HostPort)
|
||||
bindings[i].HostIP = b.HostIP
|
||||
bindings[i].HostPort = fmt.Sprintf("%d", port+offset)
|
||||
}
|
||||
newPortBindings[k] = bindings
|
||||
}
|
||||
|
||||
return &PublishedPorts{ExposedPorts: newExposedPorts, PortBindings: newPortBindings}
|
||||
}
|
||||
|
||||
// AddPort creates a new PublishedPort struct with one more port, based on 'portSpec'
|
||||
func (p *PublishedPorts) AddPort(portSpec string) (*PublishedPorts, error) {
|
||||
portMappings, err := nat.ParsePortSpec(portSpec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var newExposedPorts = make(map[nat.Port]struct{}, len(p.ExposedPorts)+1)
|
||||
var newPortBindings = make(map[nat.Port][]nat.PortBinding, len(p.PortBindings)+1)
|
||||
|
||||
// Populate the new maps
|
||||
for k, v := range p.ExposedPorts {
|
||||
newExposedPorts[k] = v
|
||||
}
|
||||
|
||||
for k, v := range p.PortBindings {
|
||||
newPortBindings[k] = v
|
||||
}
|
||||
|
||||
// Add new ports
|
||||
for _, portMapping := range portMappings {
|
||||
port := portMapping.Port
|
||||
if _, exists := newExposedPorts[port]; !exists {
|
||||
newExposedPorts[port] = struct{}{}
|
||||
}
|
||||
|
||||
bslice, exists := newPortBindings[port]
|
||||
if !exists {
|
||||
bslice = []nat.PortBinding{}
|
||||
}
|
||||
newPortBindings[port] = append(bslice, portMapping.Binding)
|
||||
}
|
||||
|
||||
return &PublishedPorts{ExposedPorts: newExposedPorts, PortBindings: newPortBindings}, nil
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user