This commit is contained in:
Priya Wadhwa
2018-03-20 17:15:09 -07:00
parent 58e70d8b77
commit cf24231121
6 changed files with 181 additions and 37 deletions
+8 -16
View File
@@ -17,11 +17,9 @@ limitations under the License.
package commands
import (
"bytes"
"github.com/GoogleCloudPlatform/k8s-container-builder/pkg/util"
"github.com/containers/image/manifest"
"github.com/docker/docker/builder/dockerfile/instructions"
"github.com/docker/docker/builder/dockerfile/parser"
"github.com/docker/docker/builder/dockerfile/shell"
"github.com/sirupsen/logrus"
"os"
"strings"
@@ -33,26 +31,20 @@ type EnvCommand struct {
func (e *EnvCommand) ExecuteCommand(config *manifest.Schema2Config) error {
logrus.Info("cmd: ENV")
// The dockerfile/shell package handles processing env values
// It handles escape characters and supports expansion from the config.Env array
// Shlex handles some of the following use cases (these and more are tested in integration tests)
// ""a'b'c"" -> "a'b'c"
// "Rex\ The\ Dog \" -> "Rex The Dog"
// "a\"b" -> "a"b"
envString := envToString(e.cmd)
p, err := parser.Parse(bytes.NewReader([]byte(envString)))
if err != nil {
return err
}
shlex := shell.NewLex(p.EscapeToken)
newEnvs := e.cmd.Env
for index, pair := range newEnvs {
expandedValue, err := shlex.ProcessWord(pair.Value, config.Env)
expandedKey, err := util.ResolveEnvironmentReplacement(envString, pair.Key, config.Env)
if err != nil {
return err
}
expandedValue, err := util.ResolveEnvironmentReplacement(envString, pair.Value, config.Env)
if err != nil {
return err
}
newEnvs[index] = instructions.KeyValuePair{
Key: pair.Key,
Key: expandedKey,
Value: expandedValue,
}
logrus.Infof("Setting environment variable %s=%s", pair.Key, expandedValue)
+37
View File
@@ -71,3 +71,40 @@ func TestEnvToString(t *testing.T) {
actualString := envToString(envCmd)
testutil.CheckErrorAndDeepEqual(t, false, nil, expectedString, actualString)
}
func Test_EnvExecute(t *testing.T) {
cfg := &manifest.Schema2Config{
Env: []string{
"path=/usr/",
"home=/root",
},
}
envCmd := &EnvCommand{
&instructions.EnvCommand{
Env: []instructions.KeyValuePair{
{
Key: "path",
Value: "/some/path",
},
{
Key: "HOME",
Value: "$home",
},
{
Key: "$path",
Value: "$home",
},
},
},
}
expectedEnvs := []string{
"path=/some/path",
"home=/root",
"HOME=/root",
"/usr/=/root",
}
err := envCmd.ExecuteCommand(cfg)
testutil.CheckErrorAndDeepEqual(t, false, err, expectedEnvs, cfg.Env)
}
+23 -16
View File
@@ -18,6 +18,7 @@ package commands
import (
"fmt"
"github.com/GoogleCloudPlatform/k8s-container-builder/pkg/util"
"github.com/containers/image/manifest"
"github.com/docker/docker/builder/dockerfile/instructions"
"github.com/sirupsen/logrus"
@@ -29,25 +30,16 @@ type ExposeCommand struct {
}
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
exposeString := r.exposeToString()
// Add any new ones in
for _, p := range ports {
for _, p := range r.cmd.Ports {
// Resolve any environment variables
p, err := util.ResolveEnvironmentReplacement(exposeString, p, config.Env)
if err != nil {
return err
}
// Add the default protocol if one isn't specified
if !strings.Contains(p, "/") {
p = p + "/tcp"
@@ -64,6 +56,21 @@ func updateExposedPorts(ports []string, config *manifest.Schema2Config) error {
return nil
}
func validProtocol(protocol string) bool {
validProtocols := [2]string{"tcp", "udp"}
for _, p := range validProtocols {
if protocol == p {
return true
}
}
return false
}
func (r *ExposeCommand) exposeToString() string {
expose := []string{"EXPOSE"}
return strings.Join(append(expose, r.cmd.Ports...), " ")
}
func (r *ExposeCommand) FilesToSnapshot() []string {
return []string{}
}
+25 -2
View File
@@ -19,6 +19,7 @@ package commands
import (
"github.com/GoogleCloudPlatform/k8s-container-builder/testutil"
"github.com/containers/image/manifest"
"github.com/docker/docker/builder/dockerfile/instructions"
"testing"
)
@@ -27,6 +28,10 @@ func TestUpdateExposedPorts(t *testing.T) {
ExposedPorts: manifest.Schema2PortSet{
"8080/tcp": {},
},
Env: []string{
"port=udp",
"num=8085",
},
}
ports := []string{
@@ -34,6 +39,15 @@ func TestUpdateExposedPorts(t *testing.T) {
"8081/tcp",
"8082",
"8083/udp",
"8084/$port",
"$num",
"$num/$port",
}
exposeCmd := &ExposeCommand{
&instructions.ExposeCommand{
Ports: ports,
},
}
expectedPorts := manifest.Schema2PortSet{
@@ -41,9 +55,12 @@ func TestUpdateExposedPorts(t *testing.T) {
"8081/tcp": {},
"8082/tcp": {},
"8083/udp": {},
"8084/udp": {},
"8085/tcp": {},
"8085/udp": {},
}
err := updateExposedPorts(ports, cfg)
err := exposeCmd.ExecuteCommand(cfg)
testutil.CheckErrorAndDeepEqual(t, false, err, expectedPorts, cfg.ExposedPorts)
}
@@ -56,6 +73,12 @@ func TestInvalidProtocol(t *testing.T) {
"80/garbage",
}
err := updateExposedPorts(ports, cfg)
exposeCmd := &ExposeCommand{
&instructions.ExposeCommand{
Ports: ports,
},
}
err := exposeCmd.ExecuteCommand(cfg)
testutil.CheckErrorAndDeepEqual(t, true, err, nil, nil)
}
+26 -3
View File
@@ -16,8 +16,31 @@ limitations under the License.
package util
// ResolvEnvironmentReplacement resolves replacing env variables in fp from envs
// Ex: fp = $foo/newdir, envs = [foo=/foodir], then this should return /foodir/newdir
func ResolveEnvironmentReplacement(fp string, envs []string) string {
import (
"bytes"
"github.com/docker/docker/builder/dockerfile/parser"
"github.com/docker/docker/builder/dockerfile/shell"
"path/filepath"
)
// ResolveEnvironmentReplacement resolves replacing env variables in some text from envs
// It takes in a string representation of the command, the value to be resolved, and a list of envs (config.Env)
// Ex: fp = $foo/newdir, envs = [foo=/foodir], then this should return /foodir/newdir
// The dockerfile/shell package handles processing env values
// It handles escape characters and supports expansion from the config.Env array
// Shlex handles some of the following use cases (these and more are tested in integration tests)
// ""a'b'c"" -> "a'b'c"
// "Rex\ The\ Dog \" -> "Rex The Dog"
// "a\"b" -> "a"b"
func ResolveEnvironmentReplacement(command, value string, envs []string) (string, error) {
p, err := parser.Parse(bytes.NewReader([]byte(command)))
if err != nil {
return "", err
}
shlex := shell.NewLex(p.EscapeToken)
processedWord, err := shlex.ProcessWord(value, envs)
if err != nil {
return "", err
}
return filepath.Clean(processedWord), nil
}
+62
View File
@@ -15,3 +15,65 @@ limitations under the License.
*/
package util
import (
"github.com/GoogleCloudPlatform/k8s-container-builder/testutil"
"testing"
)
var testEnvReplacement = []struct {
path string
command string
envs []string
expectedPath string
}{
{
path: "/simple/path",
command: "WORKDIR /simple/path",
envs: []string{
"simple=/path/",
},
expectedPath: "/simple/path",
},
{
path: "${a}/b",
command: "WORKDIR ${a}/b",
envs: []string{
"a=/path/",
"b=/path2/",
},
expectedPath: "/path/b",
},
{
path: "/$a/b",
command: "COPY ${a}/b /c/",
envs: []string{
"a=/path/",
"b=/path2/",
},
expectedPath: "/path/b",
},
{
path: "\\$foo",
command: "COPY \\$foo /quux",
envs: []string{
"foo=/path/",
},
expectedPath: "$foo",
},
{
path: "8080/$protocol",
command: "EXPOSE 8080/$protocol",
envs: []string{
"protocol=udp",
},
expectedPath: "8080/udp",
},
}
func Test_EnvReplacement(t *testing.T) {
for _, test := range testEnvReplacement {
actualPath, err := ResolveEnvironmentReplacement(test.command, test.path, test.envs)
testutil.CheckErrorAndDeepEqual(t, false, err, test.expectedPath, actualPath)
}
}