Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enabling using another container's network stack on build process #5088

Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions cmd/skaffold/app/cmd/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ func runContext(opts config.SkaffoldOptions) (*runcontext.RunContext, *latest.Sk
return nil, nil, fmt.Errorf("getting run context: %w", err)
}

if err := validation.ProcessWithRunContext(config, runCtx); err != nil {
return nil, nil, fmt.Errorf("invalid skaffold config: %w", err)
}

return runCtx, config, nil
}

Expand Down
5 changes: 4 additions & 1 deletion cmd/skaffold/app/cmd/runner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,11 @@ func TestCreateNewRunner(t *testing.T) {
for _, test := range tests {
testutil.Run(t, test.description, func(t *testutil.T) {
t.Override(&docker.NewAPIClient, func(docker.Config) (docker.LocalDaemon, error) {
return nil, nil
return docker.NewLocalDaemon(&testutil.FakeAPIClient{
ErrVersion: true,
}, nil, false, nil), nil
})

t.Override(&update.GetLatestAndCurrentVersion, func() (semver.Version, semver.Version, error) {
return semver.Version{}, semver.Version{}, nil
})
Expand Down
5 changes: 3 additions & 2 deletions docs/content/en/schemas/v2beta11.json
Original file line number Diff line number Diff line change
Expand Up @@ -992,11 +992,12 @@
},
"network": {
"type": "string",
"description": "passed through to docker and overrides the network configuration of docker builder. If unset, use whatever is configured in the underlying docker daemon. Valid modes are `host`: use the host's networking stack. `bridge`: use the bridged network configuration. `none`: no networking in the container.",
"x-intellij-html-description": "passed through to docker and overrides the network configuration of docker builder. If unset, use whatever is configured in the underlying docker daemon. Valid modes are <code>host</code>: use the host's networking stack. <code>bridge</code>: use the bridged network configuration. <code>none</code>: no networking in the container.",
"description": "passed through to docker and overrides the network configuration of docker builder. If unset, use whatever is configured in the underlying docker daemon. Valid modes are `host`: use the host's networking stack. `bridge`: use the bridged network configuration. `container:<name|id>`: reuse another container's network stack. `none`: no networking in the container.",
"x-intellij-html-description": "passed through to docker and overrides the network configuration of docker builder. If unset, use whatever is configured in the underlying docker daemon. Valid modes are <code>host</code>: use the host's networking stack. <code>bridge</code>: use the bridged network configuration. <code>container:&lt;name|id&gt;</code>: reuse another container's network stack. <code>none</code>: no networking in the container.",
"enum": [
"host",
"bridge",
"container:<name|id>",
"none"
]
},
Expand Down
5 changes: 5 additions & 0 deletions examples/getting-started/skaffold.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ kind: Config
build:
artifacts:
- image: skaffold-example
context: .
docker:
network: "container:alpine"
local:
push: false
deploy:
kubectl:
manifests:
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ require (
github.com/go-git/go-git/v5 v5.0.0
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e
github.com/golang/mock v1.4.4
github.com/golang/protobuf v1.4.3
github.com/google/go-cmp v0.5.2
github.com/google/go-containerregistry v0.1.4
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,7 @@ github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFU
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
Expand Down
1 change: 1 addition & 0 deletions pkg/skaffold/schema/latest/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -1115,6 +1115,7 @@ type DockerArtifact struct {
// is configured in the underlying docker daemon. Valid modes are
// `host`: use the host's networking stack.
// `bridge`: use the bridged network configuration.
// `container:<name|id>`: reuse another container's network stack.
// `none`: no networking in the container.
NetworkMode string `yaml:"network,omitempty"`

Expand Down
72 changes: 71 additions & 1 deletion pkg/skaffold/schema/validation/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,18 @@ limitations under the License.
package validation

import (
"context"
"fmt"
"reflect"
"regexp"
"strings"
"time"

"github.com/docker/docker/api/types"

"github.com/GoogleContainerTools/skaffold/pkg/skaffold/build/misc"
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/docker"
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/runner/runcontext"
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest"
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/util"
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/yamltags"
Expand Down Expand Up @@ -60,6 +65,22 @@ func Process(config *latest.SkaffoldConfig) error {
return fmt.Errorf(strings.Join(messages, " | "))
}

// ProcessWithRunContext checks if the Skaffold pipeline is valid when a RunContext is required.
// It returns all encountered errors as a concatenated string.
func ProcessWithRunContext(config *latest.SkaffoldConfig, runCtx *runcontext.RunContext) error {
var errs []error
errs = append(errs, validateDockerNetworkContainerExists(config.Build.Artifacts, runCtx)...)

if len(errs) == 0 {
return nil
}
var messages []string
for _, err := range errs {
messages = append(messages, err.Error())
}
return fmt.Errorf(strings.Join(messages, " | "))
}

// validateTaggingPolicy checks that the tagging policy is valid in combination with other options.
func validateTaggingPolicy(bc latest.BuildConfig) (errs []error) {
if bc.LocalBuild != nil {
Expand Down Expand Up @@ -179,7 +200,7 @@ func validateUniqueDependencyAliases(artifacts []*latest.Artifact) (errs []error
return
}

// validateDockerNetworkMode makes sure that networkMode is one of `bridge`, `none`, or `host` if set.
// validateDockerNetworkMode makes sure that networkMode is one of `bridge`, `none`, `container:<name|id>`, or `host` if set.
func validateDockerNetworkMode(artifacts []*latest.Artifact) (errs []error) {
for _, a := range artifacts {
if a.DockerArtifact == nil || a.DockerArtifact.NetworkMode == "" {
Expand All @@ -189,11 +210,60 @@ func validateDockerNetworkMode(artifacts []*latest.Artifact) (errs []error) {
if mode == "none" || mode == "bridge" || mode == "host" {
continue
}
containerRegExp := regexp.MustCompile("^container:[a-zA-Z0-9][a-zA-Z0-9_.-]*$")
zedfmario marked this conversation as resolved.
Show resolved Hide resolved
if containerRegExp.MatchString(mode) {
continue
}

errs = append(errs, fmt.Errorf("artifact %s has invalid networkMode '%s'", a.ImageName, mode))
}
return
}

// Validates that a Docker Container with a Network Mode "container:<id|name>" points to an actually running container
func validateDockerNetworkContainerExists(artifacts []*latest.Artifact, runCtx docker.Config) []error {
var errs []error
apiClient, err := docker.NewAPIClient(runCtx)
if err != nil {
errs = append(errs, err)
return errs
}

client := apiClient.RawClient()
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(5*time.Second))
zedfmario marked this conversation as resolved.
Show resolved Hide resolved
defer cancel()

for _, a := range artifacts {
if a.DockerArtifact == nil || a.DockerArtifact.NetworkMode == "" {
continue
}
mode := strings.ToLower(a.DockerArtifact.NetworkMode)
prefix := "container:"
if strings.HasPrefix(mode, prefix) {
id := strings.TrimPrefix(mode, prefix)
containers, err := client.ContainerList(ctx, types.ContainerListOptions{})
if err != nil {
errs = append(errs, fmt.Errorf("retrieving docker containers list: %s", err.Error()))
return errs
}
for _, c := range containers {
// Comparing ID seeking for <id>
if c.ID == id {
return errs
}
for _, name := range c.Names {
// c.Names come in form "/<name>"
if name == "/"+id {
return errs
}
}
}
errs = append(errs, fmt.Errorf("container '%s' not found. Required by image '%s' for docker network stack sharing", id, a.ImageName))
}
}
return errs
}

// validateCustomDependencies makes sure that dependencies.ignore is only used in conjunction with dependencies.paths
func validateCustomDependencies(artifacts []*latest.Artifact) (errs []error) {
for _, a := range artifacts {
Expand Down
Loading