build,config: add support for --unsetannotation
Just like `--unsetlabel` add support for `--unsetannotation`. Closes: https://github.com/containers/buildah/issues/6183 Signed-off-by: flouthoc <flouthoc.git@gmail.com>
This commit is contained in:
parent
b8d8cc375f
commit
83acf720d9
|
@ -49,6 +49,7 @@ type configResults struct {
|
|||
volume []string
|
||||
workingDir string
|
||||
unsetLabels []string
|
||||
unsetAnnotations []string
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
@ -102,6 +103,7 @@ func init() {
|
|||
flags.StringSliceVarP(&opts.volume, "volume", "v", []string{}, "add default `volume` path to be created for containers based on image (default [])")
|
||||
flags.StringVar(&opts.workingDir, "workingdir", "", "set working `directory` for containers based on image")
|
||||
flags.StringSliceVar(&opts.unsetLabels, "unsetlabel", nil, "remove image configuration label")
|
||||
flags.StringSliceVar(&opts.unsetAnnotations, "unsetannotation", nil, "remove image configuration annotation")
|
||||
|
||||
rootCmd.AddCommand(configCommand)
|
||||
}
|
||||
|
@ -309,6 +311,10 @@ func updateConfig(builder *buildah.Builder, c *cobra.Command, iopts configResult
|
|||
for _, key := range iopts.unsetLabels {
|
||||
builder.UnsetLabel(key)
|
||||
}
|
||||
// unset annotation if any
|
||||
for _, key := range iopts.unsetAnnotations {
|
||||
builder.UnsetAnnotation(key)
|
||||
}
|
||||
if c.Flag("workingdir").Changed {
|
||||
builder.SetWorkDir(iopts.workingDir)
|
||||
conditionallyAddHistory(builder, c, "/bin/sh -c #(nop) WORKDIR %s", iopts.workingDir)
|
||||
|
|
|
@ -340,6 +340,8 @@ type BuildOptions struct {
|
|||
UnsetEnvs []string
|
||||
// UnsetLabels is a list of labels to not add to final image from base image.
|
||||
UnsetLabels []string
|
||||
// UnsetAnnotations is a list of annotations to not add to final image from base image.
|
||||
UnsetAnnotations []string
|
||||
// Envs is a list of environment variables to set in the final image.
|
||||
Envs []string
|
||||
// OSFeatures specifies operating system features the image requires.
|
||||
|
|
|
@ -1045,6 +1045,10 @@ include:
|
|||
"sigpending": maximum number of pending signals (ulimit -i)
|
||||
"stack": maximum stack size (ulimit -s)
|
||||
|
||||
**--unsetannotation** *annotation*
|
||||
|
||||
Unset the image annotation, causing the annotation not to be inherited from the base image.
|
||||
|
||||
**--unsetenv** *env*
|
||||
|
||||
Unset environment variables from the final image.
|
||||
|
|
|
@ -231,6 +231,10 @@ Note: this setting is not present in the OCIv1 image format, so it is discarded
|
|||
|
||||
Set default *stop signal* for container. This signal will be sent when container is stopped, default is SIGINT.
|
||||
|
||||
**--unsetannotation** *annotation*
|
||||
|
||||
Unset the image annotation, causing the annotation not to be inherited from the base image.
|
||||
|
||||
**--unsetlabel** *label*
|
||||
|
||||
Unset the image label, causing the label not to be inherited from the base image.
|
||||
|
|
|
@ -151,6 +151,7 @@ type Executor struct {
|
|||
logPrefix string
|
||||
unsetEnvs []string
|
||||
unsetLabels []string
|
||||
unsetAnnotations []string
|
||||
processLabel string // Shares processLabel of first stage container with containers of other stages in same build
|
||||
mountLabel string // Shares mountLabel of first stage container with containers of other stages in same build
|
||||
buildOutputs []string // Specifies instructions for any custom build output
|
||||
|
@ -319,6 +320,7 @@ func newExecutor(logger *logrus.Logger, logPrefix string, store storage.Store, o
|
|||
logPrefix: logPrefix,
|
||||
unsetEnvs: slices.Clone(options.UnsetEnvs),
|
||||
unsetLabels: slices.Clone(options.UnsetLabels),
|
||||
unsetAnnotations: slices.Clone(options.UnsetAnnotations),
|
||||
buildOutputs: buildOutputs,
|
||||
osVersion: options.OSVersion,
|
||||
osFeatures: slices.Clone(options.OSFeatures),
|
||||
|
@ -331,6 +333,11 @@ func newExecutor(logger *logrus.Logger, logPrefix string, store storage.Store, o
|
|||
compatScratchConfig: options.CompatScratchConfig,
|
||||
noPivotRoot: options.NoPivotRoot,
|
||||
}
|
||||
// sort unsetAnnotations because we will later write these
|
||||
// values to the history of the image therefore we want to
|
||||
// make sure that order is always consistent.
|
||||
slices.Sort(exec.unsetAnnotations)
|
||||
|
||||
if exec.err == nil {
|
||||
exec.err = os.Stderr
|
||||
}
|
||||
|
|
|
@ -1284,7 +1284,7 @@ func (s *StageExecutor) Execute(ctx context.Context, base string) (imgID string,
|
|||
|
||||
if len(children) == 0 {
|
||||
// There are no steps.
|
||||
if s.builder.FromImageID == "" || s.executor.squash || s.executor.confidentialWorkload.Convert || len(s.executor.labels) > 0 || len(s.executor.annotations) > 0 || len(s.executor.unsetEnvs) > 0 || len(s.executor.unsetLabels) > 0 || len(s.executor.sbomScanOptions) > 0 {
|
||||
if s.builder.FromImageID == "" || s.executor.squash || s.executor.confidentialWorkload.Convert || len(s.executor.labels) > 0 || len(s.executor.annotations) > 0 || len(s.executor.unsetEnvs) > 0 || len(s.executor.unsetLabels) > 0 || len(s.executor.sbomScanOptions) > 0 || len(s.executor.unsetAnnotations) > 0 {
|
||||
// We either don't have a base image, or we need to
|
||||
// transform the contents of the base image, or we need
|
||||
// to make some changes to just the config blob. Whichever
|
||||
|
@ -1293,7 +1293,7 @@ func (s *StageExecutor) Execute(ctx context.Context, base string) (imgID string,
|
|||
// No base image means there's nothing to put in a
|
||||
// layer, so don't create one.
|
||||
emptyLayer := (s.builder.FromImageID == "")
|
||||
createdBy, err := s.getCreatedBy(nil, "")
|
||||
createdBy, err := s.getCreatedBy(nil, "", lastStage)
|
||||
if err != nil {
|
||||
return "", nil, false, fmt.Errorf("unable to get createdBy for the node: %w", err)
|
||||
}
|
||||
|
@ -1444,7 +1444,7 @@ func (s *StageExecutor) Execute(ctx context.Context, base string) (imgID string,
|
|||
if s.executor.timestamp != nil {
|
||||
timestamp = *s.executor.timestamp
|
||||
}
|
||||
createdBy, err := s.getCreatedBy(node, addedContentSummary)
|
||||
createdBy, err := s.getCreatedBy(node, addedContentSummary, false)
|
||||
if err != nil {
|
||||
return "", nil, false, fmt.Errorf("unable to get createdBy for the node: %w", err)
|
||||
}
|
||||
|
@ -1458,7 +1458,7 @@ func (s *StageExecutor) Execute(ctx context.Context, base string) (imgID string,
|
|||
// stage.
|
||||
if lastStage || imageIsUsedLater {
|
||||
logCommit(s.output, i)
|
||||
createdBy, err := s.getCreatedBy(node, addedContentSummary)
|
||||
createdBy, err := s.getCreatedBy(node, addedContentSummary, lastStage && lastInstruction)
|
||||
if err != nil {
|
||||
return "", nil, false, fmt.Errorf("unable to get createdBy for the node: %w", err)
|
||||
}
|
||||
|
@ -1533,7 +1533,7 @@ func (s *StageExecutor) Execute(ctx context.Context, base string) (imgID string,
|
|||
// cacheKey since it will be used either while pulling or pushing the
|
||||
// cache images.
|
||||
if needsCacheKey {
|
||||
cacheKey, err = s.generateCacheKey(ctx, node, addedContentSummary, s.stepRequiresLayer(step))
|
||||
cacheKey, err = s.generateCacheKey(ctx, node, addedContentSummary, s.stepRequiresLayer(step), lastInstruction && lastStage)
|
||||
if err != nil {
|
||||
return "", nil, false, fmt.Errorf("failed while generating cache key: %w", err)
|
||||
}
|
||||
|
@ -1561,13 +1561,13 @@ func (s *StageExecutor) Execute(ctx context.Context, base string) (imgID string,
|
|||
addedContentSummary = s.getContentSummaryAfterAddingContent()
|
||||
// regenerate cache key with updated content summary
|
||||
if needsCacheKey {
|
||||
cacheKey, err = s.generateCacheKey(ctx, node, addedContentSummary, s.stepRequiresLayer(step))
|
||||
cacheKey, err = s.generateCacheKey(ctx, node, addedContentSummary, s.stepRequiresLayer(step), lastInstruction && lastStage)
|
||||
if err != nil {
|
||||
return "", nil, false, fmt.Errorf("failed while generating cache key: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
cacheID, err = s.intermediateImageExists(ctx, node, addedContentSummary, s.stepRequiresLayer(step))
|
||||
cacheID, err = s.intermediateImageExists(ctx, node, addedContentSummary, s.stepRequiresLayer(step), lastInstruction && lastStage)
|
||||
if err != nil {
|
||||
return "", nil, false, fmt.Errorf("checking if cached image exists from a previous build: %w", err)
|
||||
}
|
||||
|
@ -1579,7 +1579,7 @@ func (s *StageExecutor) Execute(ctx context.Context, base string) (imgID string,
|
|||
// is ignored and will be automatically logged for --log-level debug
|
||||
if ref, id, err := s.pullCache(ctx, cacheKey); ref != nil && id != "" && err == nil {
|
||||
logCachePulled(cacheKey, ref)
|
||||
cacheID, err = s.intermediateImageExists(ctx, node, addedContentSummary, s.stepRequiresLayer(step))
|
||||
cacheID, err = s.intermediateImageExists(ctx, node, addedContentSummary, s.stepRequiresLayer(step), lastInstruction && lastStage)
|
||||
if err != nil {
|
||||
return "", nil, false, fmt.Errorf("checking if cached image exists from a previous build: %w", err)
|
||||
}
|
||||
|
@ -1611,7 +1611,7 @@ func (s *StageExecutor) Execute(ctx context.Context, base string) (imgID string,
|
|||
addedContentSummary = s.getContentSummaryAfterAddingContent()
|
||||
// regenerate cache key with updated content summary
|
||||
if needsCacheKey {
|
||||
cacheKey, err = s.generateCacheKey(ctx, node, addedContentSummary, s.stepRequiresLayer(step))
|
||||
cacheKey, err = s.generateCacheKey(ctx, node, addedContentSummary, s.stepRequiresLayer(step), lastInstruction && lastStage)
|
||||
if err != nil {
|
||||
return "", nil, false, fmt.Errorf("failed while generating cache key: %w", err)
|
||||
}
|
||||
|
@ -1620,7 +1620,7 @@ func (s *StageExecutor) Execute(ctx context.Context, base string) (imgID string,
|
|||
// Check if there's already an image based on our parent that
|
||||
// has the same change that we just made.
|
||||
if checkForLayers && !avoidLookingCache {
|
||||
cacheID, err = s.intermediateImageExists(ctx, node, addedContentSummary, s.stepRequiresLayer(step))
|
||||
cacheID, err = s.intermediateImageExists(ctx, node, addedContentSummary, s.stepRequiresLayer(step), lastInstruction && lastStage)
|
||||
if err != nil {
|
||||
return "", nil, false, fmt.Errorf("checking if cached image exists from a previous build: %w", err)
|
||||
}
|
||||
|
@ -1633,7 +1633,7 @@ func (s *StageExecutor) Execute(ctx context.Context, base string) (imgID string,
|
|||
// is ignored and will be automatically logged for --log-level debug
|
||||
if ref, id, err := s.pullCache(ctx, cacheKey); ref != nil && id != "" && err == nil {
|
||||
logCachePulled(cacheKey, ref)
|
||||
cacheID, err = s.intermediateImageExists(ctx, node, addedContentSummary, s.stepRequiresLayer(step))
|
||||
cacheID, err = s.intermediateImageExists(ctx, node, addedContentSummary, s.stepRequiresLayer(step), lastInstruction && lastStage)
|
||||
if err != nil {
|
||||
return "", nil, false, fmt.Errorf("checking if cached image exists from a previous build: %w", err)
|
||||
}
|
||||
|
@ -1683,7 +1683,7 @@ func (s *StageExecutor) Execute(ctx context.Context, base string) (imgID string,
|
|||
// We're not going to find any more cache hits, so we
|
||||
// can stop looking for them.
|
||||
checkForLayers = false
|
||||
createdBy, err := s.getCreatedBy(node, addedContentSummary)
|
||||
createdBy, err := s.getCreatedBy(node, addedContentSummary, lastStage && lastInstruction)
|
||||
if err != nil {
|
||||
return "", nil, false, fmt.Errorf("unable to get createdBy for the node: %w", err)
|
||||
}
|
||||
|
@ -1725,7 +1725,7 @@ func (s *StageExecutor) Execute(ctx context.Context, base string) (imgID string,
|
|||
|
||||
if lastInstruction && lastStage {
|
||||
if s.executor.squash || s.executor.confidentialWorkload.Convert || len(s.executor.sbomScanOptions) != 0 {
|
||||
createdBy, err := s.getCreatedBy(node, addedContentSummary)
|
||||
createdBy, err := s.getCreatedBy(node, addedContentSummary, lastStage && lastInstruction)
|
||||
if err != nil {
|
||||
return "", nil, false, fmt.Errorf("unable to get createdBy for the node: %w", err)
|
||||
}
|
||||
|
@ -1826,7 +1826,7 @@ func historyEntriesEqual(base, derived v1.History) bool {
|
|||
// that we're comparing.
|
||||
// Used to verify whether a cache of the intermediate image exists and whether
|
||||
// to run the build again.
|
||||
func (s *StageExecutor) historyAndDiffIDsMatch(baseHistory []v1.History, baseDiffIDs []digest.Digest, child *parser.Node, history []v1.History, diffIDs []digest.Digest, addedContentSummary string, buildAddsLayer bool) (bool, error) {
|
||||
func (s *StageExecutor) historyAndDiffIDsMatch(baseHistory []v1.History, baseDiffIDs []digest.Digest, child *parser.Node, history []v1.History, diffIDs []digest.Digest, addedContentSummary string, buildAddsLayer bool, lastInstruction bool) (bool, error) {
|
||||
// our history should be as long as the base's, plus one entry for what
|
||||
// we're doing
|
||||
if len(history) != len(baseHistory)+1 {
|
||||
|
@ -1865,7 +1865,7 @@ func (s *StageExecutor) historyAndDiffIDsMatch(baseHistory []v1.History, baseDif
|
|||
return false, nil
|
||||
}
|
||||
}
|
||||
createdBy, err := s.getCreatedBy(child, addedContentSummary)
|
||||
createdBy, err := s.getCreatedBy(child, addedContentSummary, lastInstruction)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("unable to get createdBy for the node: %w", err)
|
||||
}
|
||||
|
@ -1875,15 +1875,25 @@ func (s *StageExecutor) historyAndDiffIDsMatch(baseHistory []v1.History, baseDif
|
|||
// getCreatedBy returns the command the image at node will be created by. If
|
||||
// the passed-in CompositeDigester is not nil, it is assumed to have the digest
|
||||
// information for the content if the node is ADD or COPY.
|
||||
func (s *StageExecutor) getCreatedBy(node *parser.Node, addedContentSummary string) (string, error) {
|
||||
//
|
||||
// This function acts differently if getCreatedBy is invoked by LastStep. For instances
|
||||
// certain instructions like `removing annotations` does not makes sense for every step
|
||||
// but only makes sense if the step is last step of a build.
|
||||
func (s *StageExecutor) getCreatedBy(node *parser.Node, addedContentSummary string, isLastStep bool) (string, error) {
|
||||
if node == nil {
|
||||
return "/bin/sh", nil
|
||||
}
|
||||
inheritLabels := ""
|
||||
unsetAnnotations := ""
|
||||
// If --inherit-label was manually set to false then update history.
|
||||
if s.executor.inheritLabels == types.OptionalBoolFalse {
|
||||
inheritLabels = "|inheritLabels=false"
|
||||
}
|
||||
if isLastStep {
|
||||
for _, annotation := range s.executor.unsetAnnotations {
|
||||
unsetAnnotations += "|unsetAnnotation=" + annotation
|
||||
}
|
||||
}
|
||||
switch strings.ToUpper(node.Value) {
|
||||
case "ARG":
|
||||
for _, variable := range strings.Fields(node.Original) {
|
||||
|
@ -1892,7 +1902,7 @@ func (s *StageExecutor) getCreatedBy(node *parser.Node, addedContentSummary stri
|
|||
}
|
||||
}
|
||||
buildArgs := s.getBuildArgsKey()
|
||||
return "/bin/sh -c #(nop) ARG " + buildArgs + inheritLabels, nil
|
||||
return "/bin/sh -c #(nop) ARG " + buildArgs + inheritLabels + unsetAnnotations, nil
|
||||
case "RUN":
|
||||
shArg := ""
|
||||
buildArgs := s.getBuildArgsResolvedForRun()
|
||||
|
@ -1972,16 +1982,16 @@ func (s *StageExecutor) getCreatedBy(node *parser.Node, addedContentSummary stri
|
|||
if buildArgs != "" {
|
||||
result = result + "|" + strconv.Itoa(len(strings.Split(buildArgs, " "))) + " " + buildArgs + " "
|
||||
}
|
||||
result = result + "/bin/sh -c " + shArg + heredoc + appendCheckSum + inheritLabels
|
||||
result = result + "/bin/sh -c " + shArg + heredoc + appendCheckSum + inheritLabels + unsetAnnotations
|
||||
return result, nil
|
||||
case "ADD", "COPY":
|
||||
destination := node
|
||||
for destination.Next != nil {
|
||||
destination = destination.Next
|
||||
}
|
||||
return "/bin/sh -c #(nop) " + strings.ToUpper(node.Value) + " " + addedContentSummary + " in " + destination.Value + " " + inheritLabels, nil
|
||||
return "/bin/sh -c #(nop) " + strings.ToUpper(node.Value) + " " + addedContentSummary + " in " + destination.Value + " " + inheritLabels + " " + unsetAnnotations, nil
|
||||
default:
|
||||
return "/bin/sh -c #(nop) " + node.Original + inheritLabels, nil
|
||||
return "/bin/sh -c #(nop) " + node.Original + inheritLabels + unsetAnnotations, nil
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2115,7 +2125,7 @@ func (s *StageExecutor) tagExistingImage(ctx context.Context, cacheID, output st
|
|||
// generated CacheKey is further used by buildah to lock and decide
|
||||
// tag for the intermediate image which can be pushed and pulled to/from
|
||||
// the remote repository.
|
||||
func (s *StageExecutor) generateCacheKey(ctx context.Context, currNode *parser.Node, addedContentDigest string, buildAddsLayer bool) (string, error) {
|
||||
func (s *StageExecutor) generateCacheKey(ctx context.Context, currNode *parser.Node, addedContentDigest string, buildAddsLayer bool, lastInstruction bool) (string, error) {
|
||||
hash := sha256.New()
|
||||
var baseHistory []v1.History
|
||||
var diffIDs []digest.Digest
|
||||
|
@ -2130,7 +2140,7 @@ func (s *StageExecutor) generateCacheKey(ctx context.Context, currNode *parser.N
|
|||
fmt.Fprintln(hash, diffIDs[i].String())
|
||||
}
|
||||
}
|
||||
createdBy, err := s.getCreatedBy(currNode, addedContentDigest)
|
||||
createdBy, err := s.getCreatedBy(currNode, addedContentDigest, lastInstruction)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -2248,7 +2258,7 @@ func (s *StageExecutor) pullCache(ctx context.Context, cacheKey string) (referen
|
|||
// intermediateImageExists returns image ID if an intermediate image of currNode exists in the image store from a previous build.
|
||||
// It verifies this by checking the parent of the top layer of the image and the history.
|
||||
// If more than one image matches as potiential candidates then priority is given to the most recently built image.
|
||||
func (s *StageExecutor) intermediateImageExists(ctx context.Context, currNode *parser.Node, addedContentDigest string, buildAddsLayer bool) (string, error) {
|
||||
func (s *StageExecutor) intermediateImageExists(ctx context.Context, currNode *parser.Node, addedContentDigest string, buildAddsLayer bool, lastInstruction bool) (string, error) {
|
||||
cacheCandidates := []storage.Image{}
|
||||
// Get the list of images available in the image store
|
||||
images, err := s.executor.store.Images()
|
||||
|
@ -2315,7 +2325,7 @@ func (s *StageExecutor) intermediateImageExists(ctx context.Context, currNode *p
|
|||
continue
|
||||
}
|
||||
// children + currNode is the point of the Dockerfile we are currently at.
|
||||
foundMatch, err := s.historyAndDiffIDsMatch(baseHistory, baseDiffIDs, currNode, history, diffIDs, addedContentDigest, buildAddsLayer)
|
||||
foundMatch, err := s.historyAndDiffIDsMatch(baseHistory, baseDiffIDs, currNode, history, diffIDs, addedContentDigest, buildAddsLayer, lastInstruction)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -2431,6 +2441,11 @@ func (s *StageExecutor) commit(ctx context.Context, createdBy string, emptyLayer
|
|||
annotationk, annotationv, _ := strings.Cut(annotationSpec, "=")
|
||||
s.builder.SetAnnotation(annotationk, annotationv)
|
||||
}
|
||||
if finalInstruction {
|
||||
for _, key := range s.executor.unsetAnnotations {
|
||||
s.builder.UnsetAnnotation(key)
|
||||
}
|
||||
}
|
||||
if imageRef != nil {
|
||||
logName := transports.ImageName(imageRef)
|
||||
logrus.Debugf("COMMIT %q", logName)
|
||||
|
|
|
@ -419,6 +419,7 @@ func GenBuildOptions(c *cobra.Command, inputArgs []string, iopts BuildOptions) (
|
|||
TransientMounts: iopts.Volumes,
|
||||
UnsetEnvs: iopts.UnsetEnvs,
|
||||
UnsetLabels: iopts.UnsetLabels,
|
||||
UnsetAnnotations: iopts.UnsetAnnotations,
|
||||
}
|
||||
if iopts.RetryDelay != "" {
|
||||
options.PullPushRetryDelay, err = time.ParseDuration(iopts.RetryDelay)
|
||||
|
|
|
@ -116,6 +116,7 @@ type BudResults struct {
|
|||
RusageLogFile string
|
||||
UnsetEnvs []string
|
||||
UnsetLabels []string
|
||||
UnsetAnnotations []string
|
||||
Envs []string
|
||||
OSFeatures []string
|
||||
OSVersion string
|
||||
|
@ -314,6 +315,7 @@ newer: only pull base and SBOM scanner images when newer images exist on the r
|
|||
fs.String("variant", "", "override the `variant` of the specified image")
|
||||
fs.StringSliceVar(&flags.UnsetEnvs, "unsetenv", nil, "unset environment variable from final image")
|
||||
fs.StringSliceVar(&flags.UnsetLabels, "unsetlabel", nil, "unset label when inheriting labels from base image")
|
||||
fs.StringSliceVar(&flags.UnsetAnnotations, "unsetannotation", nil, "unset annotation when inheriting annotation from base image")
|
||||
return fs
|
||||
}
|
||||
|
||||
|
@ -368,6 +370,7 @@ func GetBudFlagsCompletions() commonComp.FlagCompletions {
|
|||
flagCompletion["timestamp"] = commonComp.AutocompleteNone
|
||||
flagCompletion["unsetenv"] = commonComp.AutocompleteNone
|
||||
flagCompletion["unsetlabel"] = commonComp.AutocompleteNone
|
||||
flagCompletion["unsetannotation"] = commonComp.AutocompleteNone
|
||||
flagCompletion["variant"] = commonComp.AutocompleteNone
|
||||
return flagCompletion
|
||||
}
|
||||
|
|
|
@ -2670,6 +2670,104 @@ _EOF
|
|||
expect_output "$want_output"
|
||||
}
|
||||
|
||||
@test "bud and test --unsetannotation" {
|
||||
base=registry.fedoraproject.org/fedora-minimal
|
||||
_prefetch $base
|
||||
target=exp
|
||||
|
||||
run_buildah --version
|
||||
local -a output_fields=($output)
|
||||
buildah_version=${output_fields[2]}
|
||||
|
||||
buildah inspect --format '{{ .ImageAnnotations }}' $base
|
||||
not_want_output='map[]'
|
||||
assert "$output" != "$not_want_output" "expected some annotations to be set in base image $base"
|
||||
|
||||
annotations=$(buildah inspect --format '{{ range $key, $value := .ImageAnnotations }}{{ $key }} {{end}}' $base)
|
||||
annotationflags="--annotation hello=world"
|
||||
for annotation in $annotations; do
|
||||
if test $annotation != io.buildah.version ; then
|
||||
annotationflags="$annotationflags --unsetannotation $annotation"
|
||||
fi
|
||||
done
|
||||
|
||||
run_buildah build $WITH_POLICY_JSON $annotationflags -t $target --from $base $BUDFILES/base-with-labels
|
||||
|
||||
# no annotations should be inherited from base image
|
||||
# and `hello=world` which we just added using cli flag
|
||||
want_output='map["hello":"world"]'
|
||||
run_buildah inspect --format '{{printf "%q" .ImageAnnotations}}' $target
|
||||
expect_output "$want_output"
|
||||
}
|
||||
|
||||
@test "bud and test --unsetannotation with --layers" {
|
||||
base=registry.fedoraproject.org/fedora-minimal
|
||||
_prefetch $base
|
||||
target=exp
|
||||
|
||||
run_buildah --version
|
||||
local -a output_fields=($output)
|
||||
buildah_version=${output_fields[2]}
|
||||
|
||||
buildah inspect --format '{{ .ImageAnnotations }}' $base
|
||||
not_want_output='map[]'
|
||||
assert "$output" != "$not_want_output" "expected some annotations to be set in base image $base"
|
||||
|
||||
## Build without removing annotations
|
||||
run_buildah build $WITH_POLICY_JSON --layers --iidfile ${TEST_SCRATCH_DIR}/iid1 -t $target --from $base $BUDFILES/base-with-labels
|
||||
## Second build must use cache
|
||||
run_buildah build $WITH_POLICY_JSON --layers --iidfile ${TEST_SCRATCH_DIR}/iid2 -t $target --from $base $BUDFILES/base-with-labels
|
||||
## Must use cache
|
||||
expect_output --substring " Using cache"
|
||||
cmp ${TEST_SCRATCH_DIR}/iid1 ${TEST_SCRATCH_DIR}/iid2
|
||||
|
||||
annotations=$(buildah inspect --format '{{ range $key, $value := .ImageAnnotations }}{{ $key }} {{end}}' $base)
|
||||
annotationflags="--annotation hello=world"
|
||||
for annotation in $annotations; do
|
||||
if test $annotation != io.buildah.version ; then
|
||||
annotationflags="$annotationflags --unsetannotation $annotation"
|
||||
fi
|
||||
done
|
||||
|
||||
## Since we are unsetting something, this should not use previous image present in the cache.
|
||||
run_buildah build $WITH_POLICY_JSON --layers $annotationflags -t $target --from $base $BUDFILES/base-with-labels
|
||||
## should not contain `Using Cache`
|
||||
#assert "$output" !~ "Using cache"
|
||||
|
||||
# no annotations should be inherited from base image
|
||||
# and `hello=world` which we just added using cli flag
|
||||
want_output='map["hello":"world"]'
|
||||
run_buildah inspect --format '{{printf "%q" .ImageAnnotations}}' $target
|
||||
expect_output "$want_output"
|
||||
}
|
||||
|
||||
@test "bud and test --unsetannotation with only base image" {
|
||||
base=registry.fedoraproject.org/fedora-minimal
|
||||
_prefetch $base
|
||||
target=exp
|
||||
|
||||
run_buildah --version
|
||||
local -a output_fields=($output)
|
||||
buildah_version=${output_fields[2]}
|
||||
|
||||
buildah inspect --format '{{ .ImageAnnotations }}' $base
|
||||
not_want_output='map[]'
|
||||
assert "$output" != "$not_want_output" "expected some annotations to be set in base image $base"
|
||||
|
||||
annotations=$(buildah inspect --format '{{ range $key, $value := .ImageAnnotations }}{{ $key }} {{end}}' $base)
|
||||
annotationflags="--annotation hello=world"
|
||||
for annotation in $annotations; do
|
||||
if test $annotation != io.buildah.version ; then
|
||||
annotationflags="$annotationflags --unsetannotation $annotation"
|
||||
fi
|
||||
done
|
||||
|
||||
run_buildah build $WITH_POLICY_JSON $annotationflags -t $target --from $base $BUDFILES/only-base
|
||||
want_output='map["hello":"world"]'
|
||||
run_buildah inspect --format '{{printf "%q" .ImageAnnotations}}' $target
|
||||
expect_output "$want_output"
|
||||
}
|
||||
|
||||
@test "bud and test inherit-labels" {
|
||||
base=registry.fedoraproject.org/fedora-minimal
|
||||
_prefetch $base
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
FROM registry.fedoraproject.org/fedora-minimal
|
|
@ -96,6 +96,21 @@ function check_matrix() {
|
|||
assert "$output" == "" "name label should be removed"
|
||||
}
|
||||
|
||||
@test "config --unsetannotation" {
|
||||
base=registry.fedoraproject.org/fedora-minimal
|
||||
_prefetch $base
|
||||
run_buildah from --quiet --pull=false $WITH_POLICY_JSON $base
|
||||
cid=$output
|
||||
run_buildah commit $WITH_POLICY_JSON $cid with-name-annotation
|
||||
run_buildah config --unsetannotation org.opencontainers.image.base.name $cid
|
||||
run_buildah commit $WITH_POLICY_JSON $cid without-name-annotation
|
||||
|
||||
run_buildah inspect --format '{{ index .ImageAnnotations "org.opencontainers.image.base.name"}}' with-name-annotation
|
||||
assert "$output" != "" "annotation should be set in base image"
|
||||
run_buildah inspect --format '{{ index .ImageAnnotations "org.opencontainers.image.base.name"}}' without-name-annotation
|
||||
assert "$output" == "" "name annotation should be removed"
|
||||
}
|
||||
|
||||
@test "config set empty entrypoint doesn't wipe cmd" {
|
||||
run_buildah from $WITH_POLICY_JSON scratch
|
||||
cid=$output
|
||||
|
|
Loading…
Reference in New Issue