Skip to content

Commit

Permalink
refactor: mv params parse and valid part to pkg package that client a…
Browse files Browse the repository at this point in the history
…nd daemon can both use

Signed-off-by: Michael Wan <zirenwan@gmail.com>
  • Loading branch information
HusterWan committed Apr 3, 2018
1 parent 85d808d commit 4054dc3
Show file tree
Hide file tree
Showing 17 changed files with 770 additions and 394 deletions.
209 changes: 26 additions & 183 deletions cli/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,10 @@ package main

import (
"fmt"
"net"
"strconv"
"strings"

"github.com/alibaba/pouch/apis/types"
"github.com/alibaba/pouch/pkg/runconfig"
"github.com/docker/go-connections/nat"
"github.com/alibaba/pouch/pkg/opts"

units "github.com/docker/go-units"
strfmt "github.com/go-openapi/strfmt"
Expand Down Expand Up @@ -97,101 +94,62 @@ func (c *container) config() (*types.ContainerCreateConfig, error) {
return nil, err
}

deviceMappings, err := parseDeviceMappings(c.devices)
deviceMappings, err := opts.ParseDeviceMappings(c.devices)
if err != nil {
return nil, err
}

restartPolicy, err := parseRestartPolicy(c.restartPolicy)
restartPolicy, err := opts.ParseRestartPolicy(c.restartPolicy)
if err != nil {
return nil, err
}

if err := opts.VerifyRestartPolicy(restartPolicy); err != nil {
return nil, err
}

sysctls, err := parseSysctls(c.sysctls)
if err != nil {
return nil, err
}

diskQuota, err := parseDiskQuota(c.diskQuota)
diskQuota, err := opts.ParseDiskQuota(c.diskQuota)
if err != nil {
return nil, err
}

if err := validateOOMScore(c.oomScoreAdj); err != nil {
if err := opts.VerifyDiskQuota(diskQuota); err != nil {
return nil, err
}

var networkMode string
if len(c.networks) == 0 {
networkMode = "bridge"
}
networkingConfig := &types.NetworkingConfig{
EndpointsConfig: map[string]*types.EndpointSettings{},
if err := validateOOMScore(c.oomScoreAdj); err != nil {
return nil, err
}
for _, network := range c.networks {
name, parameter, mode, err := parseNetwork(network)
if err != nil {
return nil, err
}

if networkMode == "" || mode == "mode" {
networkMode = name
}
networkingConfig, networkMode, err := opts.ParseNetworks(c.networks)
if err != nil {
return nil, err
}

if name == "container" {
networkMode = fmt.Sprintf("%s:%s", name, parameter)
} else if ipaddr := net.ParseIP(parameter); ipaddr != nil {
networkingConfig.EndpointsConfig[name] = &types.EndpointSettings{
IPAddress: parameter,
IPAMConfig: &types.EndpointIPAMConfig{
IPV4Address: parameter,
},
}
}
if err := opts.VerifyNetworks(networkingConfig); err != nil {
return nil, err
}

// parse port binding
tmpPorts, tmpPortBindings, err := nat.ParsePortSpecs(c.ports)
portBindings, err := opts.ParsePortBinding(c.ports)
if err != nil {
return nil, err
}
// translate ports and portbingings
ports := map[string]interface{}{}
for n, p := range tmpPorts {
ports[string(n)] = p
}
portBindings := make(types.PortMap)
for n, pbs := range tmpPortBindings {
portBindings[string(n)] = []types.PortBinding{}
for _, tmpPb := range pbs {
pb := types.PortBinding{HostIP: tmpPb.HostIP, HostPort: tmpPb.HostPort}
portBindings[string(n)] = append(portBindings[string(n)], pb)
}
}

for _, e := range c.expose {
if strings.Contains(e, ":") {
return nil, fmt.Errorf("invalid port format for --expose: %s", e)
}
// FIXME(ziren): do we need verify portBinding ???
if err := opts.VerifyPortBinding(portBindings); err != nil {
return nil, err
}

//support two formats for expose, original format <portnum>/[<proto>] or <startport-endport>/[<proto>]
proto, port := nat.SplitProtoPort(e)
//parse the start and end port and create a sequence of ports to expose
//if expose a port, the start and end port are the same
start, end, err := nat.ParsePortRange(port)
if err != nil {
return nil, fmt.Errorf("invalid range format for --expose: %s, error: %s", e, err)
}
for i := start; i <= end; i++ {
p, err := nat.NewPort(proto, strconv.FormatUint(i, 10))
if err != nil {
return nil, err
}
if _, exists := ports[string(p)]; !exists {
ports[string(p)] = struct{}{}
}
}
ports, err := opts.ParseExposedPorts(c.ports, c.expose)
if err != nil {
return nil, err
}

config := &types.ContainerCreateConfig{
ContainerConfig: types.ContainerConfig{
Tty: c.tty,
Expand Down Expand Up @@ -301,29 +259,6 @@ func parseLabel(label string) ([]string, error) {
return fields, nil
}

func parseDeviceMappings(devices []string) ([]*types.DeviceMapping, error) {
results := []*types.DeviceMapping{}
for _, device := range devices {
deviceMapping, err := parseDevice(device)
if err != nil {
return nil, err
}
results = append(results, deviceMapping)
}
return results, nil
}

func parseDevice(device string) (*types.DeviceMapping, error) {
deviceMapping, err := runconfig.ParseDevice(device)
if err != nil {
return nil, fmt.Errorf("parse devices error: %s", err)
}
if !runconfig.ValidDeviceMode(deviceMapping.CgroupPermissions) {
return nil, fmt.Errorf("%s invalid device mode: %s", device, deviceMapping.CgroupPermissions)
}
return deviceMapping, nil
}

func parseMemory(memory string) (int64, error) {
if memory == "" {
return 0, nil
Expand Down Expand Up @@ -361,98 +296,6 @@ func parseIntelRdt(intelRdtL3Cbm string) (string, error) {
return intelRdtL3Cbm, nil
}

func parseRestartPolicy(restartPolicy string) (*types.RestartPolicy, error) {
policy := &types.RestartPolicy{}

if restartPolicy == "" {
policy.Name = "no"
return policy, nil
}

fields := strings.Split(restartPolicy, ":")
policy.Name = fields[0]

switch policy.Name {
case "always", "unless-stopped", "no":
case "on-failure":
if len(fields) > 2 {
return nil, fmt.Errorf("invalid restart policy: %s", restartPolicy)
}
if len(fields) == 2 {
n, err := strconv.Atoi(fields[1])
if err != nil {
return nil, fmt.Errorf("invalid restart policy: %v", err)
}
policy.MaximumRetryCount = int64(n)
}
default:
return nil, fmt.Errorf("invalid restart policy: %s", restartPolicy)
}

return policy, nil
}

// network format as below:
// [network]:[ip_address], such as: mynetwork:172.17.0.2 or mynetwork(ip alloc by ipam) or 172.17.0.2(default network is bridge)
// [network_mode]:[parameter], such as: host(use host network) or container:containerID(use exist container network)
// [network_mode]:[parameter]:mode, such as: mynetwork:172.17.0.2:mode(if the container has multi-networks, the network is the default network mode)
func parseNetwork(network string) (string, string, string, error) {
var (
name string
parameter string
mode string
)
if network == "" {
return "", "", "", fmt.Errorf("invalid network: cannot be empty")
}
arr := strings.Split(network, ":")
switch len(arr) {
case 1:
if ipaddr := net.ParseIP(arr[0]); ipaddr != nil {
parameter = arr[0]
} else {
name = arr[0]
}
case 2:
name = arr[0]
if name == "container" {
parameter = arr[1]
} else if ipaddr := net.ParseIP(arr[1]); ipaddr != nil {
parameter = arr[1]
} else {
mode = arr[1]
}
default:
name = arr[0]
parameter = arr[1]
mode = arr[2]
}

return name, parameter, mode, nil
}

func parseDiskQuota(quotas []string) (map[string]string, error) {
var quotaMaps = make(map[string]string)

for _, quota := range quotas {
if quota == "" {
return nil, fmt.Errorf("invalid format for disk quota: %s", quota)
}

parts := strings.Split(quota, "=")
switch len(parts) {
case 1:
quotaMaps["/"] = parts[0]
case 2:
quotaMaps[parts[0]] = parts[1]
default:
return nil, fmt.Errorf("invalid format for disk quota: %s", quota)
}
}

return quotaMaps, nil
}

// validateOOMScore validates oom score
func validateOOMScore(score int64) error {
if score < -1000 || score > 1000 {
Expand Down
Loading

0 comments on commit 4054dc3

Please sign in to comment.