mirror of
https://github.com/GoogleContainerTools/kaniko
synced 2026-10-18 01:05:28 +02:00
WIP
This commit is contained in:
+8
-16
@@ -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)
|
||||
|
||||
@@ -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
@@ -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{}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user