mirror of
https://github.com/containers/podman.git
synced 2025-10-19 12:12:36 +08:00
Merge pull request #25452 from ygalblum/quadlet-warning-messages
Quadlet warning messages
This commit is contained in:
@ -631,15 +631,15 @@ func generateUnitsInfoMap(units []*parser.UnitFile) map[string]*quadlet.UnitInfo
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
if err := process(); err != nil {
|
if processErred := process(); processErred {
|
||||||
Logf("%s", err.Error())
|
Logf("processing encountered some errors")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func process() error {
|
func process() bool {
|
||||||
var prevError error
|
var processErred bool
|
||||||
|
|
||||||
prgname := path.Base(os.Args[0])
|
prgname := path.Base(os.Args[0])
|
||||||
isUserFlag = strings.Contains(prgname, "user")
|
isUserFlag = strings.Contains(prgname, "user")
|
||||||
@ -648,7 +648,7 @@ func process() error {
|
|||||||
|
|
||||||
if versionFlag {
|
if versionFlag {
|
||||||
fmt.Printf("%s\n", rawversion.RawVersion)
|
fmt.Printf("%s\n", rawversion.RawVersion)
|
||||||
return prevError
|
return processErred
|
||||||
}
|
}
|
||||||
|
|
||||||
if verboseFlag || dryRunFlag {
|
if verboseFlag || dryRunFlag {
|
||||||
@ -660,15 +660,13 @@ func process() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
reportError := func(err error) {
|
reportError := func(err error) {
|
||||||
if prevError != nil {
|
Logf("%s", err.Error())
|
||||||
err = fmt.Errorf("%s\n%s", prevError, err)
|
processErred = true
|
||||||
}
|
|
||||||
prevError = err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !dryRunFlag && flag.NArg() < 1 {
|
if !dryRunFlag && flag.NArg() < 1 {
|
||||||
reportError(errors.New("missing output directory argument"))
|
reportError(errors.New("missing output directory argument"))
|
||||||
return prevError
|
return processErred
|
||||||
}
|
}
|
||||||
|
|
||||||
var outputPath string
|
var outputPath string
|
||||||
@ -694,7 +692,7 @@ func process() error {
|
|||||||
// containers/podman/issues/17374: exit cleanly but log that we
|
// containers/podman/issues/17374: exit cleanly but log that we
|
||||||
// had nothing to do
|
// had nothing to do
|
||||||
Debugf("No files parsed from %s", sourcePathsMap)
|
Debugf("No files parsed from %s", sourcePathsMap)
|
||||||
return prevError
|
return processErred
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, unit := range units {
|
for _, unit := range units {
|
||||||
@ -707,7 +705,7 @@ func process() error {
|
|||||||
err := os.MkdirAll(outputPath, os.ModePerm)
|
err := os.MkdirAll(outputPath, os.ModePerm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
reportError(err)
|
reportError(err)
|
||||||
return prevError
|
return processErred
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -730,24 +728,24 @@ func process() error {
|
|||||||
|
|
||||||
for _, unit := range units {
|
for _, unit := range units {
|
||||||
var service *parser.UnitFile
|
var service *parser.UnitFile
|
||||||
var err error
|
var warnings, err error
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case strings.HasSuffix(unit.Filename, ".container"):
|
case strings.HasSuffix(unit.Filename, ".container"):
|
||||||
warnIfAmbiguousName(unit, quadlet.ContainerGroup)
|
warnIfAmbiguousName(unit, quadlet.ContainerGroup)
|
||||||
service, err = quadlet.ConvertContainer(unit, isUserFlag, unitsInfoMap)
|
service, warnings, err = quadlet.ConvertContainer(unit, isUserFlag, unitsInfoMap)
|
||||||
case strings.HasSuffix(unit.Filename, ".volume"):
|
case strings.HasSuffix(unit.Filename, ".volume"):
|
||||||
warnIfAmbiguousName(unit, quadlet.VolumeGroup)
|
warnIfAmbiguousName(unit, quadlet.VolumeGroup)
|
||||||
service, err = quadlet.ConvertVolume(unit, unit.Filename, unitsInfoMap, isUserFlag)
|
service, warnings, err = quadlet.ConvertVolume(unit, unit.Filename, unitsInfoMap, isUserFlag)
|
||||||
case strings.HasSuffix(unit.Filename, ".kube"):
|
case strings.HasSuffix(unit.Filename, ".kube"):
|
||||||
service, err = quadlet.ConvertKube(unit, unitsInfoMap, isUserFlag)
|
service, err = quadlet.ConvertKube(unit, unitsInfoMap, isUserFlag)
|
||||||
case strings.HasSuffix(unit.Filename, ".network"):
|
case strings.HasSuffix(unit.Filename, ".network"):
|
||||||
service, err = quadlet.ConvertNetwork(unit, unit.Filename, unitsInfoMap, isUserFlag)
|
service, warnings, err = quadlet.ConvertNetwork(unit, unit.Filename, unitsInfoMap, isUserFlag)
|
||||||
case strings.HasSuffix(unit.Filename, ".image"):
|
case strings.HasSuffix(unit.Filename, ".image"):
|
||||||
warnIfAmbiguousName(unit, quadlet.ImageGroup)
|
warnIfAmbiguousName(unit, quadlet.ImageGroup)
|
||||||
service, err = quadlet.ConvertImage(unit, unitsInfoMap, isUserFlag)
|
service, err = quadlet.ConvertImage(unit, unitsInfoMap, isUserFlag)
|
||||||
case strings.HasSuffix(unit.Filename, ".build"):
|
case strings.HasSuffix(unit.Filename, ".build"):
|
||||||
service, err = quadlet.ConvertBuild(unit, unitsInfoMap, isUserFlag)
|
service, warnings, err = quadlet.ConvertBuild(unit, unitsInfoMap, isUserFlag)
|
||||||
case strings.HasSuffix(unit.Filename, ".pod"):
|
case strings.HasSuffix(unit.Filename, ".pod"):
|
||||||
service, err = quadlet.ConvertPod(unit, unit.Filename, unitsInfoMap, isUserFlag)
|
service, err = quadlet.ConvertPod(unit, unit.Filename, unitsInfoMap, isUserFlag)
|
||||||
default:
|
default:
|
||||||
@ -755,6 +753,10 @@ func process() error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if warnings != nil {
|
||||||
|
Logf("%s", warnings.Error())
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
reportError(fmt.Errorf("converting %q: %w", unit.Filename, err))
|
reportError(fmt.Errorf("converting %q: %w", unit.Filename, err))
|
||||||
continue
|
continue
|
||||||
@ -776,7 +778,7 @@ func process() error {
|
|||||||
}
|
}
|
||||||
enableServiceFile(outputPath, service)
|
enableServiceFile(outputPath, service)
|
||||||
}
|
}
|
||||||
return prevError
|
return processErred
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package parser
|
package parser
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
@ -838,21 +839,26 @@ func (f *UnitFile) LookupLastArgs(groupName string, key string) ([]string, bool)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Look up 'Environment' style key-value keys
|
// Look up 'Environment' style key-value keys
|
||||||
func (f *UnitFile) LookupAllKeyVal(groupName string, key string) map[string]string {
|
func (f *UnitFile) LookupAllKeyVal(groupName string, key string) (map[string]string, error) {
|
||||||
|
var warnings error
|
||||||
res := make(map[string]string)
|
res := make(map[string]string)
|
||||||
allKeyvals := f.LookupAll(groupName, key)
|
allKeyvals := f.LookupAll(groupName, key)
|
||||||
for _, keyvals := range allKeyvals {
|
for _, keyvals := range allKeyvals {
|
||||||
assigns, err := splitString(keyvals, WhitespaceSeparators, SplitRelax|SplitUnquote|SplitCUnescape)
|
assigns, err := splitString(keyvals, WhitespaceSeparators, SplitRelax|SplitUnquote|SplitCUnescape)
|
||||||
if err == nil {
|
if err != nil {
|
||||||
for _, assign := range assigns {
|
warnings = errors.Join(warnings, err)
|
||||||
key, value, found := strings.Cut(assign, "=")
|
continue
|
||||||
if found {
|
}
|
||||||
res[key] = value
|
for _, assign := range assigns {
|
||||||
}
|
key, value, found := strings.Cut(assign, "=")
|
||||||
|
if found {
|
||||||
|
res[key] = value
|
||||||
|
} else {
|
||||||
|
warnings = errors.Join(warnings, fmt.Errorf("separator was not found for %s", assign))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return res
|
return res, warnings
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *UnitFile) Set(groupName string, key string, value string) {
|
func (f *UnitFile) Set(groupName string, key string, value string) {
|
||||||
|
@ -520,10 +520,12 @@ func usernsOpts(kind string, opts []string) string {
|
|||||||
// service file (unit file with Service group) based on the options in the
|
// service file (unit file with Service group) based on the options in the
|
||||||
// Container group.
|
// Container group.
|
||||||
// The original Container group is kept around as X-Container.
|
// The original Container group is kept around as X-Container.
|
||||||
func ConvertContainer(container *parser.UnitFile, isUser bool, unitsInfoMap map[string]*UnitInfo) (*parser.UnitFile, error) {
|
func ConvertContainer(container *parser.UnitFile, isUser bool, unitsInfoMap map[string]*UnitInfo) (*parser.UnitFile, error, error) {
|
||||||
|
var warn, warnings error
|
||||||
|
|
||||||
unitInfo, ok := unitsInfoMap[container.Filename]
|
unitInfo, ok := unitsInfoMap[container.Filename]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("internal error while processing container %s", container.Filename)
|
return nil, warnings, fmt.Errorf("internal error while processing container %s", container.Filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
service := container.Dup()
|
service := container.Dup()
|
||||||
@ -536,7 +538,7 @@ func ConvertContainer(container *parser.UnitFile, isUser bool, unitsInfoMap map[
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := checkForUnknownKeys(container, ContainerGroup, supportedContainerKeys); err != nil {
|
if err := checkForUnknownKeys(container, ContainerGroup, supportedContainerKeys); err != nil {
|
||||||
return nil, err
|
return nil, warnings, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rename old Container group to x-Container so that systemd ignores it
|
// Rename old Container group to x-Container so that systemd ignores it
|
||||||
@ -549,16 +551,16 @@ func ConvertContainer(container *parser.UnitFile, isUser bool, unitsInfoMap map[
|
|||||||
image, _ := container.Lookup(ContainerGroup, KeyImage)
|
image, _ := container.Lookup(ContainerGroup, KeyImage)
|
||||||
rootfs, _ := container.Lookup(ContainerGroup, KeyRootfs)
|
rootfs, _ := container.Lookup(ContainerGroup, KeyRootfs)
|
||||||
if len(image) == 0 && len(rootfs) == 0 {
|
if len(image) == 0 && len(rootfs) == 0 {
|
||||||
return nil, fmt.Errorf("no Image or Rootfs key specified")
|
return nil, warnings, fmt.Errorf("no Image or Rootfs key specified")
|
||||||
}
|
}
|
||||||
if len(image) > 0 && len(rootfs) > 0 {
|
if len(image) > 0 && len(rootfs) > 0 {
|
||||||
return nil, fmt.Errorf("the Image And Rootfs keys conflict can not be specified together")
|
return nil, warnings, fmt.Errorf("the Image And Rootfs keys conflict can not be specified together")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(image) > 0 {
|
if len(image) > 0 {
|
||||||
var err error
|
var err error
|
||||||
if image, err = handleImageSource(image, service, unitsInfoMap); err != nil {
|
if image, err = handleImageSource(image, service, unitsInfoMap); err != nil {
|
||||||
return nil, err
|
return nil, warnings, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -571,7 +573,7 @@ func ConvertContainer(container *parser.UnitFile, isUser bool, unitsInfoMap map[
|
|||||||
killMode, ok := service.Lookup(ServiceGroup, "KillMode")
|
killMode, ok := service.Lookup(ServiceGroup, "KillMode")
|
||||||
if !ok || !(killMode == "mixed" || killMode == "control-group") {
|
if !ok || !(killMode == "mixed" || killMode == "control-group") {
|
||||||
if ok {
|
if ok {
|
||||||
return nil, fmt.Errorf("invalid KillMode '%s'", killMode)
|
return nil, warnings, fmt.Errorf("invalid KillMode '%s'", killMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
// We default to mixed instead of control-group, because it lets conmon do its thing
|
// We default to mixed instead of control-group, because it lets conmon do its thing
|
||||||
@ -579,7 +581,8 @@ func ConvertContainer(container *parser.UnitFile, isUser bool, unitsInfoMap map[
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Read env early so we can override it below
|
// Read env early so we can override it below
|
||||||
podmanEnv := container.LookupAllKeyVal(ContainerGroup, KeyEnvironment)
|
podmanEnv, warn := container.LookupAllKeyVal(ContainerGroup, KeyEnvironment)
|
||||||
|
warnings = errors.Join(warnings, warn)
|
||||||
|
|
||||||
// Need the containers filesystem mounted to start podman
|
// Need the containers filesystem mounted to start podman
|
||||||
service.Add(UnitGroup, "RequiresMountsFor", "%t/containers")
|
service.Add(UnitGroup, "RequiresMountsFor", "%t/containers")
|
||||||
@ -661,12 +664,12 @@ func ConvertContainer(container *parser.UnitFile, isUser bool, unitsInfoMap map[
|
|||||||
lookupAndAddBoolean(container, ContainerGroup, boolKeys, podman)
|
lookupAndAddBoolean(container, ContainerGroup, boolKeys, podman)
|
||||||
|
|
||||||
if err := addNetworks(container, ContainerGroup, service, unitsInfoMap, podman); err != nil {
|
if err := addNetworks(container, ContainerGroup, service, unitsInfoMap, podman); err != nil {
|
||||||
return nil, err
|
return nil, warnings, err
|
||||||
}
|
}
|
||||||
|
|
||||||
serviceType, ok := service.Lookup(ServiceGroup, "Type")
|
serviceType, ok := service.Lookup(ServiceGroup, "Type")
|
||||||
if ok && serviceType != "notify" && serviceType != "oneshot" {
|
if ok && serviceType != "notify" && serviceType != "oneshot" {
|
||||||
return nil, fmt.Errorf("invalid service Type '%s'", serviceType)
|
return nil, warnings, fmt.Errorf("invalid service Type '%s'", serviceType)
|
||||||
}
|
}
|
||||||
|
|
||||||
if serviceType != "oneshot" {
|
if serviceType != "oneshot" {
|
||||||
@ -771,15 +774,15 @@ func ConvertContainer(container *parser.UnitFile, isUser bool, unitsInfoMap map[
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := handleUser(container, ContainerGroup, podman); err != nil {
|
if err := handleUser(container, ContainerGroup, podman); err != nil {
|
||||||
return nil, err
|
return nil, warnings, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := handleUserMappings(container, ContainerGroup, podman, true); err != nil {
|
if err := handleUserMappings(container, ContainerGroup, podman, true); err != nil {
|
||||||
return nil, err
|
return nil, warnings, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := addVolumes(container, service, ContainerGroup, unitsInfoMap, podman); err != nil {
|
if err := addVolumes(container, service, ContainerGroup, unitsInfoMap, podman); err != nil {
|
||||||
return nil, err
|
return nil, warnings, err
|
||||||
}
|
}
|
||||||
|
|
||||||
update, ok := container.Lookup(ContainerGroup, KeyAutoUpdate)
|
update, ok := container.Lookup(ContainerGroup, KeyAutoUpdate)
|
||||||
@ -794,7 +797,7 @@ func ConvertContainer(container *parser.UnitFile, isUser bool, unitsInfoMap map[
|
|||||||
exposedPort = strings.TrimSpace(exposedPort) // Allow whitespace after
|
exposedPort = strings.TrimSpace(exposedPort) // Allow whitespace after
|
||||||
|
|
||||||
if !isPortRange(exposedPort) {
|
if !isPortRange(exposedPort) {
|
||||||
return nil, fmt.Errorf("invalid port format '%s'", exposedPort)
|
return nil, warnings, fmt.Errorf("invalid port format '%s'", exposedPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
podman.add("--expose", exposedPort)
|
podman.add("--expose", exposedPort)
|
||||||
@ -804,10 +807,12 @@ func ConvertContainer(container *parser.UnitFile, isUser bool, unitsInfoMap map[
|
|||||||
|
|
||||||
podman.addEnv(podmanEnv)
|
podman.addEnv(podmanEnv)
|
||||||
|
|
||||||
labels := container.LookupAllKeyVal(ContainerGroup, KeyLabel)
|
labels, warn := container.LookupAllKeyVal(ContainerGroup, KeyLabel)
|
||||||
|
warnings = errors.Join(warnings, warn)
|
||||||
podman.addLabels(labels)
|
podman.addLabels(labels)
|
||||||
|
|
||||||
annotations := container.LookupAllKeyVal(ContainerGroup, KeyAnnotation)
|
annotations, warn := container.LookupAllKeyVal(ContainerGroup, KeyAnnotation)
|
||||||
|
warnings = errors.Join(warnings, warn)
|
||||||
podman.addAnnotations(annotations)
|
podman.addAnnotations(annotations)
|
||||||
|
|
||||||
masks := container.LookupAllArgs(ContainerGroup, KeyMask)
|
masks := container.LookupAllArgs(ContainerGroup, KeyMask)
|
||||||
@ -824,7 +829,7 @@ func ConvertContainer(container *parser.UnitFile, isUser bool, unitsInfoMap map[
|
|||||||
for _, envFile := range envFiles {
|
for _, envFile := range envFiles {
|
||||||
filePath, err := getAbsolutePath(container, envFile)
|
filePath, err := getAbsolutePath(container, envFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, warnings, err
|
||||||
}
|
}
|
||||||
podman.add("--env-file", filePath)
|
podman.add("--env-file", filePath)
|
||||||
}
|
}
|
||||||
@ -838,7 +843,7 @@ func ConvertContainer(container *parser.UnitFile, isUser bool, unitsInfoMap map[
|
|||||||
for _, mount := range mounts {
|
for _, mount := range mounts {
|
||||||
mountStr, err := resolveContainerMountParams(container, service, mount, unitsInfoMap)
|
mountStr, err := resolveContainerMountParams(container, service, mount, unitsInfoMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, warnings, err
|
||||||
}
|
}
|
||||||
podman.add("--mount", mountStr)
|
podman.add("--mount", mountStr)
|
||||||
}
|
}
|
||||||
@ -846,7 +851,7 @@ func ConvertContainer(container *parser.UnitFile, isUser bool, unitsInfoMap map[
|
|||||||
handleHealth(container, ContainerGroup, podman)
|
handleHealth(container, ContainerGroup, podman)
|
||||||
|
|
||||||
if err := handlePod(container, service, ContainerGroup, unitsInfoMap, podman); err != nil {
|
if err := handlePod(container, service, ContainerGroup, unitsInfoMap, podman); err != nil {
|
||||||
return nil, err
|
return nil, warnings, err
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePodmanArgs(container, ContainerGroup, podman)
|
handlePodmanArgs(container, ContainerGroup, podman)
|
||||||
@ -864,7 +869,7 @@ func ConvertContainer(container *parser.UnitFile, isUser bool, unitsInfoMap map[
|
|||||||
|
|
||||||
service.AddCmdline(ServiceGroup, "ExecStart", podman.Args)
|
service.AddCmdline(ServiceGroup, "ExecStart", podman.Args)
|
||||||
|
|
||||||
return service, nil
|
return service, warnings, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the unresolved container name that may contain '%'.
|
// Get the unresolved container name that may contain '%'.
|
||||||
@ -918,10 +923,12 @@ func defaultOneshotServiceGroup(service *parser.UnitFile, remainAfterExit bool)
|
|||||||
// The original Network group is kept around as X-Network.
|
// The original Network group is kept around as X-Network.
|
||||||
// Also returns the canonical network name, either auto-generated or user-defined via the
|
// Also returns the canonical network name, either auto-generated or user-defined via the
|
||||||
// NetworkName key-value.
|
// NetworkName key-value.
|
||||||
func ConvertNetwork(network *parser.UnitFile, name string, unitsInfoMap map[string]*UnitInfo, isUser bool) (*parser.UnitFile, error) {
|
func ConvertNetwork(network *parser.UnitFile, name string, unitsInfoMap map[string]*UnitInfo, isUser bool) (*parser.UnitFile, error, error) {
|
||||||
|
var warn, warnings error
|
||||||
|
|
||||||
unitInfo, ok := unitsInfoMap[network.Filename]
|
unitInfo, ok := unitsInfoMap[network.Filename]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("internal error while processing network %s", network.Filename)
|
return nil, warnings, fmt.Errorf("internal error while processing network %s", network.Filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
service := network.Dup()
|
service := network.Dup()
|
||||||
@ -934,7 +941,7 @@ func ConvertNetwork(network *parser.UnitFile, name string, unitsInfoMap map[stri
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := checkForUnknownKeys(network, NetworkGroup, supportedNetworkKeys); err != nil {
|
if err := checkForUnknownKeys(network, NetworkGroup, supportedNetworkKeys); err != nil {
|
||||||
return nil, err
|
return nil, warnings, err
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Rename old Network group to x-Network so that systemd ignores it */
|
/* Rename old Network group to x-Network so that systemd ignores it */
|
||||||
@ -979,10 +986,10 @@ func ConvertNetwork(network *parser.UnitFile, name string, unitsInfoMap map[stri
|
|||||||
ipRanges := network.LookupAll(NetworkGroup, KeyIPRange)
|
ipRanges := network.LookupAll(NetworkGroup, KeyIPRange)
|
||||||
if len(subnets) > 0 {
|
if len(subnets) > 0 {
|
||||||
if len(gateways) > len(subnets) {
|
if len(gateways) > len(subnets) {
|
||||||
return nil, fmt.Errorf("cannot set more gateways than subnets")
|
return nil, warnings, fmt.Errorf("cannot set more gateways than subnets")
|
||||||
}
|
}
|
||||||
if len(ipRanges) > len(subnets) {
|
if len(ipRanges) > len(subnets) {
|
||||||
return nil, fmt.Errorf("cannot set more ranges than subnets")
|
return nil, warnings, fmt.Errorf("cannot set more ranges than subnets")
|
||||||
}
|
}
|
||||||
for i := range subnets {
|
for i := range subnets {
|
||||||
podman.add("--subnet", subnets[i])
|
podman.add("--subnet", subnets[i])
|
||||||
@ -994,15 +1001,18 @@ func ConvertNetwork(network *parser.UnitFile, name string, unitsInfoMap map[stri
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if len(ipRanges) > 0 || len(gateways) > 0 {
|
} else if len(ipRanges) > 0 || len(gateways) > 0 {
|
||||||
return nil, fmt.Errorf("cannot set gateway or range without subnet")
|
return nil, warnings, fmt.Errorf("cannot set gateway or range without subnet")
|
||||||
}
|
}
|
||||||
|
|
||||||
networkOptions := network.LookupAllKeyVal(NetworkGroup, KeyOptions)
|
networkOptions, warn := network.LookupAllKeyVal(NetworkGroup, KeyOptions)
|
||||||
|
warnings = errors.Join(warnings, warn)
|
||||||
if len(networkOptions) > 0 {
|
if len(networkOptions) > 0 {
|
||||||
podman.addKeys("--opt", networkOptions)
|
podman.addKeys("--opt", networkOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
if labels := network.LookupAllKeyVal(NetworkGroup, KeyLabel); len(labels) > 0 {
|
labels, warn := network.LookupAllKeyVal(NetworkGroup, KeyLabel)
|
||||||
|
warnings = errors.Join(warnings, warn)
|
||||||
|
if len(labels) > 0 {
|
||||||
podman.addLabels(labels)
|
podman.addLabels(labels)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1016,7 +1026,7 @@ func ConvertNetwork(network *parser.UnitFile, name string, unitsInfoMap map[stri
|
|||||||
|
|
||||||
// Store the name of the created resource
|
// Store the name of the created resource
|
||||||
unitInfo.ResourceName = networkName
|
unitInfo.ResourceName = networkName
|
||||||
return service, nil
|
return service, warnings, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert a quadlet volume file (unit file with a Volume group) to a systemd
|
// Convert a quadlet volume file (unit file with a Volume group) to a systemd
|
||||||
@ -1025,10 +1035,11 @@ func ConvertNetwork(network *parser.UnitFile, name string, unitsInfoMap map[stri
|
|||||||
// The original Volume group is kept around as X-Volume.
|
// The original Volume group is kept around as X-Volume.
|
||||||
// Also returns the canonical volume name, either auto-generated or user-defined via the VolumeName
|
// Also returns the canonical volume name, either auto-generated or user-defined via the VolumeName
|
||||||
// key-value.
|
// key-value.
|
||||||
func ConvertVolume(volume *parser.UnitFile, name string, unitsInfoMap map[string]*UnitInfo, isUser bool) (*parser.UnitFile, error) {
|
func ConvertVolume(volume *parser.UnitFile, name string, unitsInfoMap map[string]*UnitInfo, isUser bool) (*parser.UnitFile, error, error) {
|
||||||
|
var warn, warnings error
|
||||||
unitInfo, ok := unitsInfoMap[volume.Filename]
|
unitInfo, ok := unitsInfoMap[volume.Filename]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("internal error while processing network %s", volume.Filename)
|
return nil, warnings, fmt.Errorf("internal error while processing network %s", volume.Filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
service := volume.Dup()
|
service := volume.Dup()
|
||||||
@ -1041,7 +1052,7 @@ func ConvertVolume(volume *parser.UnitFile, name string, unitsInfoMap map[string
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := checkForUnknownKeys(volume, VolumeGroup, supportedVolumeKeys); err != nil {
|
if err := checkForUnknownKeys(volume, VolumeGroup, supportedVolumeKeys); err != nil {
|
||||||
return nil, err
|
return nil, warnings, err
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Rename old Volume group to x-Volume so that systemd ignores it */
|
/* Rename old Volume group to x-Volume so that systemd ignores it */
|
||||||
@ -1059,7 +1070,8 @@ func ConvertVolume(volume *parser.UnitFile, name string, unitsInfoMap map[string
|
|||||||
// Need the containers filesystem mounted to start podman
|
// Need the containers filesystem mounted to start podman
|
||||||
service.Add(UnitGroup, "RequiresMountsFor", "%t/containers")
|
service.Add(UnitGroup, "RequiresMountsFor", "%t/containers")
|
||||||
|
|
||||||
labels := volume.LookupAllKeyVal(VolumeGroup, "Label")
|
labels, warn := volume.LookupAllKeyVal(VolumeGroup, "Label")
|
||||||
|
warnings = errors.Join(warnings, warn)
|
||||||
|
|
||||||
podman := createBasePodmanCommand(volume, VolumeGroup)
|
podman := createBasePodmanCommand(volume, VolumeGroup)
|
||||||
|
|
||||||
@ -1077,11 +1089,11 @@ func ConvertVolume(volume *parser.UnitFile, name string, unitsInfoMap map[string
|
|||||||
|
|
||||||
imageName, ok := volume.Lookup(VolumeGroup, KeyImage)
|
imageName, ok := volume.Lookup(VolumeGroup, KeyImage)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("the key %s is mandatory when using the image driver", KeyImage)
|
return nil, warnings, fmt.Errorf("the key %s is mandatory when using the image driver", KeyImage)
|
||||||
}
|
}
|
||||||
imageName, err := handleImageSource(imageName, service, unitsInfoMap)
|
imageName, err := handleImageSource(imageName, service, unitsInfoMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, warnings, err
|
||||||
}
|
}
|
||||||
|
|
||||||
opts.WriteString(imageName)
|
opts.WriteString(imageName)
|
||||||
@ -1126,7 +1138,7 @@ func ConvertVolume(volume *parser.UnitFile, name string, unitsInfoMap map[string
|
|||||||
if devValid {
|
if devValid {
|
||||||
podman.add("--opt", fmt.Sprintf("type=%s", devType))
|
podman.add("--opt", fmt.Sprintf("type=%s", devType))
|
||||||
} else {
|
} else {
|
||||||
return nil, fmt.Errorf("key Type can't be used without Device")
|
return nil, warnings, fmt.Errorf("key Type can't be used without Device")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1138,7 +1150,7 @@ func ConvertVolume(volume *parser.UnitFile, name string, unitsInfoMap map[string
|
|||||||
}
|
}
|
||||||
opts.WriteString(mountOpts)
|
opts.WriteString(mountOpts)
|
||||||
} else {
|
} else {
|
||||||
return nil, fmt.Errorf("key Options can't be used without Device")
|
return nil, warnings, fmt.Errorf("key Options can't be used without Device")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1160,7 +1172,7 @@ func ConvertVolume(volume *parser.UnitFile, name string, unitsInfoMap map[string
|
|||||||
// Store the name of the created resource
|
// Store the name of the created resource
|
||||||
unitInfo.ResourceName = volumeName
|
unitInfo.ResourceName = volumeName
|
||||||
|
|
||||||
return service, nil
|
return service, warnings, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ConvertKube(kube *parser.UnitFile, unitsInfoMap map[string]*UnitInfo, isUser bool) (*parser.UnitFile, error) {
|
func ConvertKube(kube *parser.UnitFile, unitsInfoMap map[string]*UnitInfo, isUser bool) (*parser.UnitFile, error) {
|
||||||
@ -1380,15 +1392,17 @@ func ConvertImage(image *parser.UnitFile, unitsInfoMap map[string]*UnitInfo, isU
|
|||||||
return service, nil
|
return service, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ConvertBuild(build *parser.UnitFile, unitsInfoMap map[string]*UnitInfo, isUser bool) (*parser.UnitFile, error) {
|
func ConvertBuild(build *parser.UnitFile, unitsInfoMap map[string]*UnitInfo, isUser bool) (*parser.UnitFile, error, error) {
|
||||||
|
var warn, warnings error
|
||||||
|
|
||||||
unitInfo, ok := unitsInfoMap[build.Filename]
|
unitInfo, ok := unitsInfoMap[build.Filename]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("internal error while processing network %s", build.Filename)
|
return nil, warnings, fmt.Errorf("internal error while processing network %s", build.Filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fast fail is ResouceName is not set
|
// Fast fail is ResouceName is not set
|
||||||
if len(unitInfo.ResourceName) == 0 {
|
if len(unitInfo.ResourceName) == 0 {
|
||||||
return nil, fmt.Errorf("no ImageTag key specified")
|
return nil, warnings, fmt.Errorf("no ImageTag key specified")
|
||||||
}
|
}
|
||||||
|
|
||||||
service := build.Dup()
|
service := build.Dup()
|
||||||
@ -1410,7 +1424,7 @@ func ConvertBuild(build *parser.UnitFile, unitsInfoMap map[string]*UnitInfo, isU
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := checkForUnknownKeys(build, BuildGroup, supportedBuildKeys); err != nil {
|
if err := checkForUnknownKeys(build, BuildGroup, supportedBuildKeys); err != nil {
|
||||||
return nil, err
|
return nil, warnings, err
|
||||||
}
|
}
|
||||||
|
|
||||||
podman := createBasePodmanCommand(build, BuildGroup)
|
podman := createBasePodmanCommand(build, BuildGroup)
|
||||||
@ -1445,17 +1459,21 @@ func ConvertBuild(build *parser.UnitFile, unitsInfoMap map[string]*UnitInfo, isU
|
|||||||
}
|
}
|
||||||
lookupAndAddAllStrings(build, BuildGroup, allStringKeys, podman)
|
lookupAndAddAllStrings(build, BuildGroup, allStringKeys, podman)
|
||||||
|
|
||||||
annotations := build.LookupAllKeyVal(BuildGroup, KeyAnnotation)
|
annotations, warn := build.LookupAllKeyVal(BuildGroup, KeyAnnotation)
|
||||||
|
warnings = errors.Join(warnings, warn)
|
||||||
|
|
||||||
podman.addAnnotations(annotations)
|
podman.addAnnotations(annotations)
|
||||||
|
|
||||||
podmanEnv := build.LookupAllKeyVal(BuildGroup, KeyEnvironment)
|
podmanEnv, warn := build.LookupAllKeyVal(BuildGroup, KeyEnvironment)
|
||||||
|
warnings = errors.Join(warnings, warn)
|
||||||
podman.addEnv(podmanEnv)
|
podman.addEnv(podmanEnv)
|
||||||
|
|
||||||
labels := build.LookupAllKeyVal(BuildGroup, KeyLabel)
|
labels, warn := build.LookupAllKeyVal(BuildGroup, KeyLabel)
|
||||||
|
warnings = errors.Join(warnings, warn)
|
||||||
podman.addLabels(labels)
|
podman.addLabels(labels)
|
||||||
|
|
||||||
if err := addNetworks(build, BuildGroup, service, unitsInfoMap, podman); err != nil {
|
if err := addNetworks(build, BuildGroup, service, unitsInfoMap, podman); err != nil {
|
||||||
return nil, err
|
return nil, warnings, err
|
||||||
}
|
}
|
||||||
|
|
||||||
secrets := build.LookupAllArgs(BuildGroup, KeySecret)
|
secrets := build.LookupAllArgs(BuildGroup, KeySecret)
|
||||||
@ -1464,7 +1482,7 @@ func ConvertBuild(build *parser.UnitFile, unitsInfoMap map[string]*UnitInfo, isU
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := addVolumes(build, service, BuildGroup, unitsInfoMap, podman); err != nil {
|
if err := addVolumes(build, service, BuildGroup, unitsInfoMap, podman); err != nil {
|
||||||
return nil, err
|
return nil, warnings, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// In order to build an image locally, we need either a File key pointing directly at a
|
// In order to build an image locally, we need either a File key pointing directly at a
|
||||||
@ -1473,13 +1491,13 @@ func ConvertBuild(build *parser.UnitFile, unitsInfoMap map[string]*UnitInfo, isU
|
|||||||
// an archive.
|
// an archive.
|
||||||
context, err := handleSetWorkingDirectory(build, service, BuildGroup)
|
context, err := handleSetWorkingDirectory(build, service, BuildGroup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, warnings, err
|
||||||
}
|
}
|
||||||
|
|
||||||
workingDirectory, okWD := service.Lookup(ServiceGroup, ServiceKeyWorkingDirectory)
|
workingDirectory, okWD := service.Lookup(ServiceGroup, ServiceKeyWorkingDirectory)
|
||||||
filePath, okFile := build.Lookup(BuildGroup, KeyFile)
|
filePath, okFile := build.Lookup(BuildGroup, KeyFile)
|
||||||
if (!okWD || len(workingDirectory) == 0) && (!okFile || len(filePath) == 0) && len(context) == 0 {
|
if (!okWD || len(workingDirectory) == 0) && (!okFile || len(filePath) == 0) && len(context) == 0 {
|
||||||
return nil, fmt.Errorf("neither SetWorkingDirectory, nor File key specified")
|
return nil, warnings, fmt.Errorf("neither SetWorkingDirectory, nor File key specified")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(filePath) > 0 {
|
if len(filePath) > 0 {
|
||||||
@ -1494,7 +1512,7 @@ func ConvertBuild(build *parser.UnitFile, unitsInfoMap map[string]*UnitInfo, isU
|
|||||||
} else if !filepath.IsAbs(filePath) && !isURL(filePath) {
|
} else if !filepath.IsAbs(filePath) && !isURL(filePath) {
|
||||||
// Special handling for relative filePaths
|
// Special handling for relative filePaths
|
||||||
if len(workingDirectory) == 0 {
|
if len(workingDirectory) == 0 {
|
||||||
return nil, fmt.Errorf("relative path in File key requires SetWorkingDirectory key to be set")
|
return nil, warnings, fmt.Errorf("relative path in File key requires SetWorkingDirectory key to be set")
|
||||||
}
|
}
|
||||||
podman.add(workingDirectory)
|
podman.add(workingDirectory)
|
||||||
}
|
}
|
||||||
@ -1502,7 +1520,7 @@ func ConvertBuild(build *parser.UnitFile, unitsInfoMap map[string]*UnitInfo, isU
|
|||||||
service.AddCmdline(ServiceGroup, "ExecStart", podman.Args)
|
service.AddCmdline(ServiceGroup, "ExecStart", podman.Args)
|
||||||
|
|
||||||
defaultOneshotServiceGroup(service, false)
|
defaultOneshotServiceGroup(service, false)
|
||||||
return service, nil
|
return service, warnings, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetBuiltImageName(buildUnit *parser.UnitFile) string {
|
func GetBuiltImageName(buildUnit *parser.UnitFile) string {
|
||||||
|
5
test/e2e/quadlet/label-unsupported-escape.container
Normal file
5
test/e2e/quadlet/label-unsupported-escape.container
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
## assert-podman-final-args localhost/imagename
|
||||||
|
|
||||||
|
[Container]
|
||||||
|
Image=localhost/imagename
|
||||||
|
Label=regex=^foo(\?.*)?$
|
@ -1048,6 +1048,7 @@ BOGUS=foo
|
|||||||
|
|
||||||
DescribeTable("Running expected warning quadlet test case",
|
DescribeTable("Running expected warning quadlet test case",
|
||||||
runWarningQuadletTestCase,
|
runWarningQuadletTestCase,
|
||||||
|
Entry("label-unsupported-escape.container", "label-unsupported-escape.container", "unsupported escape char"),
|
||||||
Entry("shortname.container", "shortname.container", "Warning: shortname.container specifies the image \"shortname\" which not a fully qualified image name. This is not ideal for performance and security reasons. See the podman-pull manpage discussion of short-name-aliases.conf for details."),
|
Entry("shortname.container", "shortname.container", "Warning: shortname.container specifies the image \"shortname\" which not a fully qualified image name. This is not ideal for performance and security reasons. See the podman-pull manpage discussion of short-name-aliases.conf for details."),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user