resolve conflict with PR #1160
This commit is contained in:
		
							parent
							
								
									f720c817c7
								
							
						
					
					
						commit
						e8323441ab
					
				|  | @ -230,23 +230,40 @@ func ResolveCrossStageCommands(cmds []instructions.Command, stageNameToIdx map[s | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // resolveStagesArgs resolves all the args from list of stages
 | ||||||
|  | func resolveStagesArgs(stages []instructions.Stage, args []string) error { | ||||||
|  | 	for i, s := range stages { | ||||||
|  | 		resolvedBaseName, err := util.ResolveEnvironmentReplacement(s.BaseName, args, false) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return errors.Wrap(err, fmt.Sprintf("resolving base name %s", s.BaseName)) | ||||||
|  | 		} | ||||||
|  | 		if s.BaseName != resolvedBaseName { | ||||||
|  | 			stages[i].BaseName = resolvedBaseName | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func MakeKanikoStages(opts *config.KanikoOptions, stages []instructions.Stage, metaArgs []instructions.ArgCommand) ([]config.KanikoStage, error) { | func MakeKanikoStages(opts *config.KanikoOptions, stages []instructions.Stage, metaArgs []instructions.ArgCommand) ([]config.KanikoStage, error) { | ||||||
| 	targetStage, err := targetStage(stages, opts.Target) | 	targetStage, err := targetStage(stages, opts.Target) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, errors.Wrap(err, "Error finding target stage") | 		return nil, errors.Wrap(err, "Error finding target stage") | ||||||
| 	} | 	} | ||||||
|  | 	args := unifyArgs(metaArgs, opts.BuildArgs) | ||||||
|  | 	if err := resolveStagesArgs(stages, args); err != nil { | ||||||
|  | 		return nil, errors.Wrap(err, "resolving args") | ||||||
|  | 	} | ||||||
| 	var kanikoStages []config.KanikoStage | 	var kanikoStages []config.KanikoStage | ||||||
| 	for index, stage := range stages { | 	for index, stage := range stages { | ||||||
| 		resolvedBaseName, err := util.ResolveEnvironmentReplacement(stage.BaseName, opts.BuildArgs, false) | 		if len(stage.Name) > 0 { | ||||||
| 		if err != nil { |  | ||||||
| 			return nil, errors.Wrap(err, "resolving base name") |  | ||||||
| 		} |  | ||||||
| 		stage.Name = resolvedBaseName |  | ||||||
| 			logrus.Infof("Resolved base name %s to %s", stage.BaseName, stage.Name) | 			logrus.Infof("Resolved base name %s to %s", stage.BaseName, stage.Name) | ||||||
|  | 		} | ||||||
|  | 		baseImageIndex := baseImageIndex(index, stages) | ||||||
|  | 
 | ||||||
| 		kanikoStages = append(kanikoStages, config.KanikoStage{ | 		kanikoStages = append(kanikoStages, config.KanikoStage{ | ||||||
| 			Stage:                  stage, | 			Stage:                  stage, | ||||||
| 			BaseImageIndex:         baseImageIndex(index, stages), | 			BaseImageIndex:         baseImageIndex, | ||||||
| 			BaseImageStoredLocally: (baseImageIndex(index, stages) != -1), | 			BaseImageStoredLocally: (baseImageIndex != -1), | ||||||
| 			SaveStage:              saveStage(index, stages), | 			SaveStage:              saveStage(index, stages), | ||||||
| 			Final:                  index == targetStage, | 			Final:                  index == targetStage, | ||||||
| 			MetaArgs:               metaArgs, | 			MetaArgs:               metaArgs, | ||||||
|  | @ -273,3 +290,26 @@ func GetOnBuildInstructions(config *v1.Config, stageNameToIdx map[string]string) | ||||||
| 	ResolveCrossStageCommands(cmds, stageNameToIdx) | 	ResolveCrossStageCommands(cmds, stageNameToIdx) | ||||||
| 	return cmds, nil | 	return cmds, nil | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | // unifyArgs returns the unified args between metaArgs and --build-arg
 | ||||||
|  | // by default --build-arg overrides metaArgs except when --build-arg is empty
 | ||||||
|  | func unifyArgs(metaArgs []instructions.ArgCommand, buildArgs []string) []string { | ||||||
|  | 	argsMap := make(map[string]string) | ||||||
|  | 	for _, a := range metaArgs { | ||||||
|  | 		if a.Value != nil { | ||||||
|  | 			argsMap[a.Key] = *a.Value | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	splitter := "=" | ||||||
|  | 	for _, a := range buildArgs { | ||||||
|  | 		s := strings.Split(a, splitter) | ||||||
|  | 		if len(s) > 1 && s[1] != "" { | ||||||
|  | 			argsMap[s[0]] = s[1] | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	var args []string | ||||||
|  | 	for k, v := range argsMap { | ||||||
|  | 		args = append(args, fmt.Sprintf("%s=%s", k, v)) | ||||||
|  | 	} | ||||||
|  | 	return args | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -17,6 +17,7 @@ limitations under the License. | ||||||
| package dockerfile | package dockerfile | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
|  | 	"fmt" | ||||||
| 	"io/ioutil" | 	"io/ioutil" | ||||||
| 	"os" | 	"os" | ||||||
| 	"reflect" | 	"reflect" | ||||||
|  | @ -427,3 +428,72 @@ func Test_baseImageIndex(t *testing.T) { | ||||||
| 		}) | 		}) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func Test_ResolveStagesArgs(t *testing.T) { | ||||||
|  | 	dockerfile := ` | ||||||
|  | 	ARG IMAGE="ubuntu:16.04" | ||||||
|  | 	ARG LAST_STAGE_VARIANT | ||||||
|  | 	FROM ${IMAGE} as base | ||||||
|  | 	RUN echo hi > /hi | ||||||
|  | 	FROM base AS base-dev | ||||||
|  | 	RUN echo dev >> /hi | ||||||
|  | 	FROM base AS base-prod | ||||||
|  | 	RUN echo prod >> /hi | ||||||
|  | 	FROM base-${LAST_STAGE_VARIANT} | ||||||
|  | 	RUN cat /hi | ||||||
|  | 	` | ||||||
|  | 
 | ||||||
|  | 	buildArgLastVariants := []string{"dev", "prod"} | ||||||
|  | 	buildArgImages := []string{"alpine:3.11", ""} | ||||||
|  | 	var expectedImage string | ||||||
|  | 
 | ||||||
|  | 	for _, buildArgLastVariant := range buildArgLastVariants { | ||||||
|  | 		for _, buildArgImage := range buildArgImages { | ||||||
|  | 			if buildArgImage != "" { | ||||||
|  | 				expectedImage = buildArgImage | ||||||
|  | 			} else { | ||||||
|  | 				expectedImage = "ubuntu:16.04" | ||||||
|  | 			} | ||||||
|  | 			buildArgs := []string{fmt.Sprintf("IMAGE=%s", buildArgImage), fmt.Sprintf("LAST_STAGE_VARIANT=%s", buildArgLastVariant)} | ||||||
|  | 
 | ||||||
|  | 			stages, metaArgs, err := Parse([]byte(dockerfile)) | ||||||
|  | 			if err != nil { | ||||||
|  | 				t.Fatal(err) | ||||||
|  | 			} | ||||||
|  | 			stagesLen := len(stages) | ||||||
|  | 
 | ||||||
|  | 			args := unifyArgs(metaArgs, buildArgs) | ||||||
|  | 			if err := resolveStagesArgs(stages, args); err != nil { | ||||||
|  | 				t.Fatalf("fail to resolves args %v: %v", buildArgs, err) | ||||||
|  | 			} | ||||||
|  | 			tests := []struct { | ||||||
|  | 				name               string | ||||||
|  | 				actualSourceCode   string | ||||||
|  | 				actualBaseName     string | ||||||
|  | 				expectedSourceCode string | ||||||
|  | 				expectedBaseName   string | ||||||
|  | 			}{ | ||||||
|  | 				{ | ||||||
|  | 					name:               "Test_BuildArg_From_First_Stage", | ||||||
|  | 					actualSourceCode:   stages[0].SourceCode, | ||||||
|  | 					actualBaseName:     stages[0].BaseName, | ||||||
|  | 					expectedSourceCode: "FROM ${IMAGE} as base", | ||||||
|  | 					expectedBaseName:   expectedImage, | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					name:               "Test_BuildArg_From_Last_Stage", | ||||||
|  | 					actualSourceCode:   stages[stagesLen-1].SourceCode, | ||||||
|  | 					actualBaseName:     stages[stagesLen-1].BaseName, | ||||||
|  | 					expectedSourceCode: "FROM base-${LAST_STAGE_VARIANT}", | ||||||
|  | 					expectedBaseName:   fmt.Sprintf("base-%s", buildArgLastVariant), | ||||||
|  | 				}, | ||||||
|  | 			} | ||||||
|  | 			for _, test := range tests { | ||||||
|  | 				t.Run(test.name, func(t *testing.T) { | ||||||
|  | 					testutil.CheckDeepEqual(t, test.expectedSourceCode, test.actualSourceCode) | ||||||
|  | 					testutil.CheckDeepEqual(t, test.expectedBaseName, test.actualBaseName) | ||||||
|  | 				}) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue