feat: use created network to startup container

This commit is contained in:
wencaiwulue
2023-03-21 23:14:47 +08:00
parent 3f7a8f07ee
commit a9c7f8dcb0
3 changed files with 162 additions and 27 deletions

View File

@@ -32,9 +32,9 @@ func CmdDev(f cmdutil.Factory) *cobra.Command {
Env: opts.NewListOpts(nil), Env: opts.NewListOpts(nil),
Volumes: opts.NewListOpts(nil), Volumes: opts.NewListOpts(nil),
ExtraHosts: opts.NewListOpts(nil), ExtraHosts: opts.NewListOpts(nil),
//Aliases: opts.NewListOpts(nil), Aliases: opts.NewListOpts(nil),
NoProxy: false, NoProxy: false,
ExtraCIDR: []string{}, ExtraCIDR: []string{},
} }
var sshConf = &util.SshConfig{} var sshConf = &util.SshConfig{}
cmd := &cobra.Command{ cmd := &cobra.Command{
@@ -164,9 +164,9 @@ Startup your kubernetes workloads in local Docker container with same volume、e
cmd.Flags().Var(&devOptions.NetMode, "network", "Connect a container to a network") cmd.Flags().Var(&devOptions.NetMode, "network", "Connect a container to a network")
cmd.Flags().MarkHidden("net") cmd.Flags().MarkHidden("net")
// We allow for both "--net-alias" and "--network-alias", although the latter is the recommended way. // We allow for both "--net-alias" and "--network-alias", although the latter is the recommended way.
//cmd.Flags().Var(&devOptions.Aliases, "net-alias", "Add network-scoped alias for the container") cmd.Flags().Var(&devOptions.Aliases, "net-alias", "Add network-scoped alias for the container")
//cmd.Flags().Var(&devOptions.Aliases, "network-alias", "Add network-scoped alias for the container") cmd.Flags().Var(&devOptions.Aliases, "network-alias", "Add network-scoped alias for the container")
//cmd.Flags().MarkHidden("net-alias") cmd.Flags().MarkHidden("net-alias")
cmd.Flags().VarP(&devOptions.Volumes, "volume", "v", "Bind mount a volume") cmd.Flags().VarP(&devOptions.Volumes, "volume", "v", "Bind mount a volume")
cmd.Flags().Var(&devOptions.Mounts, "mount", "Attach a filesystem mount to the container") cmd.Flags().Var(&devOptions.Mounts, "mount", "Attach a filesystem mount to the container")
cmd.Flags().Var(&devOptions.Expose, "expose", "Expose a port or a range of ports") cmd.Flags().Var(&devOptions.Expose, "expose", "Expose a port or a range of ports")

View File

@@ -4,6 +4,7 @@ import (
"context" "context"
"fmt" "fmt"
"math/rand" "math/rand"
"net"
"os" "os"
"path/filepath" "path/filepath"
"sort" "sort"
@@ -16,7 +17,9 @@ import (
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
containertypes "github.com/docker/docker/api/types/container" containertypes "github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/mount" "github.com/docker/docker/api/types/mount"
"github.com/docker/docker/api/types/network"
"github.com/docker/docker/client" "github.com/docker/docker/client"
"github.com/docker/docker/errdefs"
"github.com/docker/docker/pkg/archive" "github.com/docker/docker/pkg/archive"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
@@ -27,8 +30,10 @@ import (
"k8s.io/kubectl/pkg/polymorphichelpers" "k8s.io/kubectl/pkg/polymorphichelpers"
"k8s.io/kubectl/pkg/util/podutils" "k8s.io/kubectl/pkg/util/podutils"
"github.com/wencaiwulue/kubevpn/pkg/config"
"github.com/wencaiwulue/kubevpn/pkg/handler" "github.com/wencaiwulue/kubevpn/pkg/handler"
"github.com/wencaiwulue/kubevpn/pkg/mesh" "github.com/wencaiwulue/kubevpn/pkg/mesh"
"github.com/wencaiwulue/kubevpn/pkg/tun"
"github.com/wencaiwulue/kubevpn/pkg/util" "github.com/wencaiwulue/kubevpn/pkg/util"
) )
@@ -45,14 +50,14 @@ type Options struct {
// docker options // docker options
Platform string Platform string
//Pull string // always, missing, never //Pull string // always, missing, never
PublishAll bool PublishAll bool
Entrypoint string Entrypoint string
DockerImage string DockerImage string
Publish opts.ListOpts Publish opts.ListOpts
Expose opts.ListOpts Expose opts.ListOpts
ExtraHosts opts.ListOpts ExtraHosts opts.ListOpts
NetMode opts.NetworkOpt NetMode opts.NetworkOpt
//Aliases opts.ListOpts Aliases opts.ListOpts
Env opts.ListOpts Env opts.ListOpts
Mounts opts.MountOpt Mounts opts.MountOpt
Volumes opts.ListOpts Volumes opts.ListOpts
@@ -146,6 +151,43 @@ func (d Options) Main(ctx context.Context) error {
config.config.Hostname = "" config.config.Hostname = ""
} }
} else { } else {
getInterface, err := tun.GetInterface()
if err != nil {
return err
}
addrs, err := getInterface.Addrs()
if err != nil {
return err
}
cidr, _, err := net.ParseCIDR(addrs[0].String())
if err != nil {
return err
}
create, err := cli.NetworkCreate(ctx, list[0].containerName, types.NetworkCreate{
Driver: "bridge",
Scope: "local",
IPAM: &network.IPAM{
Driver: "",
Options: nil,
Config: []network.IPAMConfig{
{
Subnet: config.CIDR.String(),
Gateway: cidr.String(),
},
},
},
Internal: true,
})
if err != nil {
if errdefs.IsForbidden(err) {
_, _ = cli.NetworkList(ctx, types.NetworkListOptions{})
}
return err
}
list[0].networkingConfig.EndpointsConfig[list[0].containerName] = &network.EndpointSettings{
NetworkID: create.ID,
}
// skip first // skip first
for _, config := range list[1:] { for _, config := range list[1:] {
// remove expose port // remove expose port
@@ -182,24 +224,24 @@ func (r Run) Remove(ctx context.Context) error {
} }
for _, config := range r { for _, config := range r {
//err = cli.NetworkDisconnect(ctx, config.networkName, config.containerName, true) err = cli.NetworkDisconnect(ctx, config.containerName, config.containerName, true)
//if err != nil { if err != nil {
// log.Errorln(err) log.Errorln(err)
//} }
err = cli.ContainerRemove(ctx, config.containerName, types.ContainerRemoveOptions{Force: true}) err = cli.ContainerRemove(ctx, config.containerName, types.ContainerRemoveOptions{Force: true})
if err != nil { if err != nil {
log.Errorln(err) log.Errorln(err)
} }
} }
//for _, config := range r { for _, config := range r {
// _, err = cli.NetworkInspect(ctx, config.networkName, types.NetworkInspectOptions{}) _, err = cli.NetworkInspect(ctx, config.containerName, types.NetworkInspectOptions{})
// if err == nil { if err == nil {
// err = cli.NetworkRemove(ctx, config.networkName) err = cli.NetworkRemove(ctx, config.containerName)
// if err != nil { if err != nil {
// log.Errorln(err) log.Errorln(err)
// } }
// } }
//} }
return nil return nil
} }

View File

@@ -3,13 +3,17 @@ package dev
import ( import (
"fmt" "fmt"
"path/filepath" "path/filepath"
"reflect"
"strconv" "strconv"
"strings" "strings"
"github.com/docker/cli/cli/compose/loader" "github.com/docker/cli/cli/compose/loader"
"github.com/docker/cli/opts" "github.com/docker/cli/opts"
"github.com/docker/docker/api/types/container"
mounttypes "github.com/docker/docker/api/types/mount" mounttypes "github.com/docker/docker/api/types/mount"
"github.com/docker/docker/api/types/network"
"github.com/docker/docker/api/types/strslice" "github.com/docker/docker/api/types/strslice"
"github.com/docker/docker/errdefs"
"github.com/docker/go-connections/nat" "github.com/docker/go-connections/nat"
v12 "github.com/opencontainers/image-spec/specs-go/v1" v12 "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors" "github.com/pkg/errors"
@@ -147,6 +151,11 @@ func fillOptions(r Run, copts Options) error {
} }
config.hostConfig.Binds = binds config.hostConfig.Binds = binds
networkOpts, err := parseNetworkOpts(copts)
if err != nil {
return err
}
config.networkingConfig = &network.NetworkingConfig{EndpointsConfig: networkOpts}
return nil return nil
} }
@@ -171,3 +180,87 @@ func convertToStandardNotation(ports []string) ([]string, error) {
} }
return optsList, nil return optsList, nil
} }
// parseNetworkOpts converts --network advanced options to endpoint-specs, and combines
// them with the old --network-alias and --links. If returns an error if conflicting options
// are found.
//
// this function may return _multiple_ endpoints, which is not currently supported
// by the daemon, but may be in future; it's up to the daemon to produce an error
// in case that is not supported.
func parseNetworkOpts(copts Options) (map[string]*network.EndpointSettings, error) {
var (
endpoints = make(map[string]*network.EndpointSettings, len(copts.NetMode.Value()))
hasUserDefined, hasNonUserDefined bool
)
for i, n := range copts.NetMode.Value() {
n := n
if container.NetworkMode(n.Target).IsUserDefined() {
hasUserDefined = true
} else {
hasNonUserDefined = true
}
if i == 0 {
// The first network corresponds with what was previously the "only"
// network, and what would be used when using the non-advanced syntax
// `--network-alias`, `--link`, `--ip`, `--ip6`, and `--link-local-ip`
// are set on this network, to preserve backward compatibility with
// the non-advanced notation
n.Aliases = copts.Aliases.GetAll()
}
ep, err := parseNetworkAttachmentOpt(n)
if err != nil {
return nil, err
}
if _, ok := endpoints[n.Target]; ok {
return nil, errdefs.InvalidParameter(errors.Errorf("network %q is specified multiple times", n.Target))
}
// For backward compatibility: if no custom options are provided for the network,
// and only a single network is specified, omit the endpoint-configuration
// on the client (the daemon will still create it when creating the container)
if i == 0 && len(copts.NetMode.Value()) == 1 {
if ep == nil || reflect.DeepEqual(*ep, network.EndpointSettings{}) {
continue
}
}
endpoints[n.Target] = ep
}
if hasUserDefined && hasNonUserDefined {
return nil, errdefs.InvalidParameter(errors.New("conflicting options: cannot attach both user-defined and non-user-defined network-modes"))
}
return endpoints, nil
}
func parseNetworkAttachmentOpt(ep opts.NetworkAttachmentOpts) (*network.EndpointSettings, error) {
if strings.TrimSpace(ep.Target) == "" {
return nil, errors.New("no name set for network")
}
if !container.NetworkMode(ep.Target).IsUserDefined() {
if len(ep.Aliases) > 0 {
return nil, errors.New("network-scoped aliases are only supported for user-defined networks")
}
if len(ep.Links) > 0 {
return nil, errors.New("links are only supported for user-defined networks")
}
}
epConfig := &network.EndpointSettings{}
epConfig.Aliases = append(epConfig.Aliases, ep.Aliases...)
if len(ep.DriverOpts) > 0 {
epConfig.DriverOpts = make(map[string]string)
epConfig.DriverOpts = ep.DriverOpts
}
if len(ep.Links) > 0 {
epConfig.Links = ep.Links
}
if ep.IPv4Address != "" || ep.IPv6Address != "" || len(ep.LinkLocalIPs) > 0 {
epConfig.IPAMConfig = &network.EndpointIPAMConfig{
IPv4Address: ep.IPv4Address,
IPv6Address: ep.IPv6Address,
LinkLocalIPs: ep.LinkLocalIPs,
}
}
return epConfig, nil
}