diff --git a/pkg/commands/commands.go b/pkg/commands/commands.go index 6fc2a8c1a6..742fd5ef35 100644 --- a/pkg/commands/commands.go +++ b/pkg/commands/commands.go @@ -38,6 +38,8 @@ func GetCommand(cmd instructions.Command) (DockerCommand, error) { switch c := cmd.(type) { case *instructions.RunCommand: return &RunCommand{cmd: c}, nil + case *instructions.ExposeCommand: + return &ExposeCommand{cmd: c}, nil case *instructions.EnvCommand: return &EnvCommand{cmd: c}, nil } diff --git a/pkg/commands/expose.go b/pkg/commands/expose.go new file mode 100644 index 0000000000..daf4dc7813 --- /dev/null +++ b/pkg/commands/expose.go @@ -0,0 +1,74 @@ +/* +Copyright 2018 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package commands + +import ( + "fmt" + "github.com/containers/image/manifest" + "github.com/docker/docker/builder/dockerfile/instructions" + "github.com/sirupsen/logrus" + "strings" +) + +type ExposeCommand struct { + cmd *instructions.ExposeCommand +} + +func (r *ExposeCommand) ExecuteCommand(config *manifest.Schema2Config) error { + return updateExposedPorts(r.cmd.Ports, config) +} + +func validProtocol(protocol string) bool { + validProtocols := [2]string{"tcp", "udp"} + for _, p := range validProtocols { + if protocol == p { + return true + } + } + return false +} + +func updateExposedPorts(ports []string, config *manifest.Schema2Config) error { + // Grab the currently exposed ports + existingPorts := config.ExposedPorts + + // Add any new ones in + for _, p := range ports { + // Add the default protocol if one isn't specified + if !strings.Contains(p, "/") { + p = p + "/tcp" + } + protocol := strings.Split(p, "/")[1] + if !validProtocol(protocol) { + return fmt.Errorf("Invalid protocol: %s", protocol) + } + logrus.Infof("Adding exposed port: %s", p) + var x struct{} + existingPorts[manifest.Schema2Port(p)] = x + } + config.ExposedPorts = existingPorts + return nil +} + +func (r *ExposeCommand) FilesToSnapshot() []string { + return []string{} +} + +func (r *ExposeCommand) CreatedBy() string { + s := []string{"/bin/sh", "-c"} + return strings.Join(append(s, r.cmd.Ports...), " ") +} diff --git a/pkg/commands/expose_test.go b/pkg/commands/expose_test.go new file mode 100644 index 0000000000..fc7fb2c0e0 --- /dev/null +++ b/pkg/commands/expose_test.go @@ -0,0 +1,61 @@ +/* +Copyright 2018 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package commands + +import ( + "github.com/GoogleCloudPlatform/k8s-container-builder/testutil" + "github.com/containers/image/manifest" + "testing" +) + +func TestUpdateExposedPorts(t *testing.T) { + cfg := &manifest.Schema2Config{ + ExposedPorts: manifest.Schema2PortSet{ + "8080/tcp": {}, + }, + } + + ports := []string{ + "8080", + "8081/tcp", + "8082", + "8083/udp", + } + + expectedPorts := manifest.Schema2PortSet{ + "8080/tcp": {}, + "8081/tcp": {}, + "8082/tcp": {}, + "8083/udp": {}, + } + + err := updateExposedPorts(ports, cfg) + testutil.CheckErrorAndDeepEqual(t, false, err, expectedPorts, cfg.ExposedPorts) +} + +func TestInvalidProtocol(t *testing.T) { + cfg := &manifest.Schema2Config{ + ExposedPorts: manifest.Schema2PortSet{}, + } + + ports := []string{ + "80/garbage", + } + + err := updateExposedPorts(ports, cfg) + testutil.CheckErrorAndDeepEqual(t, true, err, nil, nil) +}