Review config for cmd/entrypoint after building a stage
As mentioned in #346, if only ENTRYPOINT is set in a stage then any CMD inherited from a parent should be cleared. If both entrypoint and cmd are set then nothing should change. I added a function and unit test to review the config file after building a stage which clears out config.Cmd if ENTRYPOINT was declared but CMD wasn't. I also added an integration test to make sure this works, which should be tested by the preexisting container-diff --metadata test.
This commit is contained in:
		
							parent
							
								
									4dc34343b6
								
							
						
					
					
						commit
						5d2d2829d0
					
				|  | @ -0,0 +1,5 @@ | |||
| FROM scratch AS first | ||||
| CMD ["mycmd"] | ||||
| 
 | ||||
| FROM first | ||||
| ENTRYPOINT ["myentrypoint"] # This should clear out CMD in the config metadata | ||||
|  | @ -145,6 +145,9 @@ func DoBuild(opts *config.KanikoOptions) (v1.Image, error) { | |||
| 				return nil, err | ||||
| 			} | ||||
| 		} | ||||
| 		if err := reviewConfig(stage, &imageConfig.Config); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		sourceImage, err = mutate.Config(sourceImage, imageConfig.Config) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
|  | @ -228,3 +231,24 @@ func resolveOnBuild(stage *config.KanikoStage, config *v1.Config) error { | |||
| 	config.OnBuild = nil | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // reviewConfig makes sure the value of CMD is correct after building the stage
 | ||||
| // If ENTRYPOINT was set in this stage but CMD wasn't, then CMD should be cleared out
 | ||||
| // See Issue #346 for more info
 | ||||
| func reviewConfig(stage config.KanikoStage, config *v1.Config) error { | ||||
| 	entrypoint := false | ||||
| 	cmd := false | ||||
| 
 | ||||
| 	for _, c := range stage.Commands { | ||||
| 		if c.Name() == "cmd" { | ||||
| 			cmd = true | ||||
| 		} | ||||
| 		if c.Name() == "entrypoint" { | ||||
| 			entrypoint = true | ||||
| 		} | ||||
| 	} | ||||
| 	if entrypoint && !cmd { | ||||
| 		config.Cmd = []string{} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,76 @@ | |||
| /* | ||||
| 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 executor | ||||
| 
 | ||||
| import ( | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"github.com/GoogleContainerTools/kaniko/pkg/config" | ||||
| 	"github.com/GoogleContainerTools/kaniko/pkg/dockerfile" | ||||
| 	"github.com/GoogleContainerTools/kaniko/testutil" | ||||
| 	"github.com/google/go-containerregistry/pkg/v1" | ||||
| ) | ||||
| 
 | ||||
| func Test_reviewConfig(t *testing.T) { | ||||
| 	tests := []struct { | ||||
| 		name               string | ||||
| 		dockerfile         string | ||||
| 		originalCmd        []string | ||||
| 		originalEntrypoint []string | ||||
| 		expectedCmd        []string | ||||
| 	}{ | ||||
| 		{ | ||||
| 			name: "entrypoint and cmd declared", | ||||
| 			dockerfile: ` | ||||
| 			FROM scratch | ||||
| 			CMD ["mycmd"] | ||||
| 			ENTRYPOINT ["myentrypoint"]`, | ||||
| 			originalEntrypoint: []string{"myentrypoint"}, | ||||
| 			originalCmd:        []string{"mycmd"}, | ||||
| 			expectedCmd:        []string{"mycmd"}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: "only entrypoint declared", | ||||
| 			dockerfile: ` | ||||
| 			FROM scratch | ||||
| 			ENTRYPOINT ["myentrypoint"]`, | ||||
| 			originalEntrypoint: []string{"myentrypoint"}, | ||||
| 			originalCmd:        []string{"mycmd"}, | ||||
| 			expectedCmd:        []string{}, | ||||
| 		}, | ||||
| 	} | ||||
| 	for _, test := range tests { | ||||
| 		t.Run(test.name, func(t *testing.T) { | ||||
| 			config := &v1.Config{ | ||||
| 				Cmd:        test.originalCmd, | ||||
| 				Entrypoint: test.originalEntrypoint, | ||||
| 			} | ||||
| 			err := reviewConfig(stage(t, test.dockerfile), config) | ||||
| 			testutil.CheckErrorAndDeepEqual(t, false, err, test.expectedCmd, config.Cmd) | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func stage(t *testing.T, d string) config.KanikoStage { | ||||
| 	stages, err := dockerfile.Parse([]byte(d)) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("error parsing dockerfile: %v", err) | ||||
| 	} | ||||
| 	return config.KanikoStage{ | ||||
| 		Stage: stages[0], | ||||
| 	} | ||||
| } | ||||
		Loading…
	
		Reference in New Issue