diff options
90 files changed, 1206 insertions, 738 deletions
diff --git a/.cirrus.yml b/.cirrus.yml index cf97f4467..958c6b0c7 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -7,10 +7,6 @@ env: #### # Name of the ultimate destination branch for this CI run, PR or post-merge. DEST_BRANCH: "main" - # Netavark branch to use when TEST_ENVIRON=host-netavark - NETAVARK_BRANCH: "main" - # Aardvark branch to use - AARDVARK_BRANCH: "main" # Overrides default location (/tmp/cirrus) for repo clone GOPATH: &gopath "/var/tmp/go" GOBIN: "${GOPATH}/bin" @@ -24,21 +20,16 @@ env: # Runner statistics log file path/name STATS_LOGFILE_SFX: 'runner_stats.log' STATS_LOGFILE: '$GOSRC/${CIRRUS_TASK_NAME}-${STATS_LOGFILE_SFX}' - # Netavark/aardvark location/options when TEST_ENVIRON=host-netavark - NETAVARK_URL: "https://api.cirrus-ci.com/v1/artifact/github/containers/netavark/success/binary.zip?branch=${NETAVARK_BRANCH}" - NETAVARK_DEBUG: 0 # set non-zero to use the debug-mode binary - AARDVARK_URL: "https://api.cirrus-ci.com/v1/artifact/github/containers/aardvark-dns/success/binary.zip?branch=${AARDVARK_BRANCH}" - AARDVARK_DEBUG: 0 # set non-zero to use the debug-mode binary #### #### Cache-image names to test with (double-quotes around names are critical) #### - FEDORA_NAME: "fedora-35" - PRIOR_FEDORA_NAME: "fedora-34" + FEDORA_NAME: "fedora-36" + PRIOR_FEDORA_NAME: "fedora-35" UBUNTU_NAME: "ubuntu-2110" # Google-cloud VM Images - IMAGE_SUFFIX: "c4831699639992320" + IMAGE_SUFFIX: "c4955393725038592" FEDORA_CACHE_IMAGE_NAME: "fedora-${IMAGE_SUFFIX}" PRIOR_FEDORA_CACHE_IMAGE_NAME: "prior-fedora-${IMAGE_SUFFIX}" UBUNTU_CACHE_IMAGE_NAME: "ubuntu-${IMAGE_SUFFIX}" @@ -53,7 +44,7 @@ env: #### N/B: Required ALL of these are set for every single task. #### TEST_FLAVOR: # int, sys, ext_svc, validate, automation, etc. - TEST_ENVIRON: host # 'host', 'host-netavark', or 'container' + TEST_ENVIRON: host # 'host', or 'container' PODBIN_NAME: podman # 'podman' or 'remote' PRIV_NAME: root # 'root' or 'rootless' DISTRO_NV: # any {PRIOR_,}{FEDORA,UBUNTU}_NAME value @@ -161,11 +152,11 @@ build_task: CTR_FQIN: ${FEDORA_CONTAINER_FQIN} # ID for re-use of build output _BUILD_CACHE_HANDLE: ${FEDORA_NAME}-build-${CIRRUS_BUILD_ID} - #- env: &priorfedora_envvars - # DISTRO_NV: ${PRIOR_FEDORA_NAME} - # VM_IMAGE_NAME: ${PRIOR_FEDORA_CACHE_IMAGE_NAME} - # CTR_FQIN: ${PRIOR_FEDORA_CONTAINER_FQIN} - # _BUILD_CACHE_HANDLE: ${PRIOR_FEDORA_NAME}-build-${CIRRUS_BUILD_ID} + - env: &priorfedora_envvars + DISTRO_NV: ${PRIOR_FEDORA_NAME} + VM_IMAGE_NAME: ${PRIOR_FEDORA_CACHE_IMAGE_NAME} + CTR_FQIN: ${PRIOR_FEDORA_CONTAINER_FQIN} + _BUILD_CACHE_HANDLE: ${PRIOR_FEDORA_NAME}-build-${CIRRUS_BUILD_ID} - env: &ubuntu_envvars DISTRO_NV: ${UBUNTU_NAME} VM_IMAGE_NAME: ${UBUNTU_CACHE_IMAGE_NAME} @@ -394,7 +385,7 @@ unit_test_task: - validate matrix: - env: *stdenvars - #- env: *priorfedora_envvars + - env: *priorfedora_envvars - env: *ubuntu_envvars # Special-case: Rootless on latest Fedora (standard) VM - name: "Rootless unit on $DISTRO_NV" @@ -515,11 +506,11 @@ container_integration_test_task: _BUILD_CACHE_HANDLE: ${FEDORA_NAME}-build-${CIRRUS_BUILD_ID} VM_IMAGE_NAME: ${FEDORA_CACHE_IMAGE_NAME} CTR_FQIN: ${FEDORA_CONTAINER_FQIN} - #- env: - # DISTRO_NV: ${PRIOR_FEDORA_NAME} - # _BUILD_CACHE_HANDLE: ${PRIOR_FEDORA_NAME}-build-${CIRRUS_BUILD_ID} - # VM_IMAGE_NAME: ${PRIOR_FEDORA_CACHE_IMAGE_NAME} - # CTR_FQIN: ${PRIOR_FEDORA_CONTAINER_FQIN} + - env: + DISTRO_NV: ${PRIOR_FEDORA_NAME} + _BUILD_CACHE_HANDLE: ${PRIOR_FEDORA_NAME}-build-${CIRRUS_BUILD_ID} + VM_IMAGE_NAME: ${PRIOR_FEDORA_CACHE_IMAGE_NAME} + CTR_FQIN: ${PRIOR_FEDORA_CONTAINER_FQIN} gce_instance: *standardvm timeout_in: 90m env: @@ -553,41 +544,6 @@ rootless_integration_test_task: always: *int_logs_artifacts -# Run various scenarios using upstream netavark/aardvark-dns binaries -netavark_task: - name: "Netavark $TEST_FLAVOR $PODBIN_NAME $PRIV_NAME" - alias: netavark - only_if: *not_build - skip: *branches_and_tags - depends_on: - - unit_test - gce_instance: *standardvm - matrix: - - env: &nenv - DISTRO_NV: ${FEDORA_NAME} - _BUILD_CACHE_HANDLE: ${FEDORA_NAME}-build-${CIRRUS_BUILD_ID} - VM_IMAGE_NAME: ${FEDORA_CACHE_IMAGE_NAME} - CTR_FQIN: ${FEDORA_CONTAINER_FQIN} - TEST_FLAVOR: int - TEST_ENVIRON: host-netavark - - env: - <<: *nenv - TEST_FLAVOR: int - PRIV_NAME: rootless - - env: - <<: *nenv - TEST_FLAVOR: sys - - env: - <<: *nenv - TEST_FLAVOR: sys - PRIV_NAME: rootless - clone_script: *noop # Comes from cache - gopath_cache: *ro_gopath_cache - setup_script: *setup - main_script: *main - always: *int_logs_artifacts - - # Always run subsequent to integration tests. While parallelism is lost # with runtime, debugging system-test failures can be more challenging # for some golang developers. Otherwise the following tasks run across @@ -841,7 +797,6 @@ success_task: - remote_integration_test - container_integration_test - rootless_integration_test - - netavark - local_system_test - remote_system_test - rootless_system_test diff --git a/cmd/podman/auto-update.go b/cmd/podman/auto-update.go index f8b9fba08..1dc29530e 100644 --- a/cmd/podman/auto-update.go +++ b/cmd/podman/auto-update.go @@ -57,7 +57,7 @@ func init() { flags.BoolVar(&autoUpdateOptions.Rollback, "rollback", true, "Rollback to previous image if update fails") flags.StringVar(&autoUpdateOptions.format, "format", "", "Change the output format to JSON or a Go template") - _ = autoUpdateCommand.RegisterFlagCompletionFunc("format", common.AutocompleteFormat(autoUpdateOutput{})) + _ = autoUpdateCommand.RegisterFlagCompletionFunc("format", common.AutocompleteFormat(&autoUpdateOutput{})) } func autoUpdate(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/common/completion.go b/cmd/podman/common/completion.go index c7d5d6d60..ddf922b2a 100644 --- a/cmd/podman/common/completion.go +++ b/cmd/podman/common/completion.go @@ -987,14 +987,12 @@ func AutocompleteFormat(o interface{}) func(cmd *cobra.Command, args []string, t fields := strings.Split(field[len(field)-1], ".") f := reflect.ValueOf(o) for i := 1; i < len(fields); i++ { - if f.Kind() == reflect.Ptr { - f = f.Elem() - } - - // the only supported type is struct - if f.Kind() != reflect.Struct { + val := getActualStructType(f) + if val == nil { + // no struct return nothing to complete return nil, cobra.ShellCompDirectiveNoFileComp } + f = *val // last field get all names to suggest if i == len(fields)-1 { @@ -1012,17 +1010,38 @@ func AutocompleteFormat(o interface{}) func(cmd *cobra.Command, args []string, t } } -// getStructFields reads all struct field names and method names and returns them. -func getStructFields(f reflect.Value, prefix string) []string { - suggestions := []string{} +// getActualStructType take the value and check if it is a struct, +// if it is pointer it will dereference it and when it is nil, +// it will create a new value from it to get the actual struct +// returns nil when type is not a struct +func getActualStructType(f reflect.Value) *reflect.Value { // follow the pointer first if f.Kind() == reflect.Ptr { + // if the pointer is nil we create a new value from the elements type + // this allows us to follow nil pointers and get the actual struct fields + if f.IsNil() { + f = reflect.New(f.Type().Elem()) + } f = f.Elem() } // we only support structs if f.Kind() != reflect.Struct { return nil } + return &f +} + +// getStructFields reads all struct field names and method names and returns them. +func getStructFields(f reflect.Value, prefix string) []string { + suggestions := []string{} + + val := getActualStructType(f) + if val == nil { + // no struct return nothing to complete + return nil + } + f = *val + // loop over all field names for j := 0; j < f.NumField(); j++ { field := f.Type().Field(j) @@ -1037,13 +1056,12 @@ func getStructFields(f reflect.Value, prefix string) []string { if kind == reflect.Struct { suffix = "." } - if strings.HasPrefix(fname, prefix) { - // add field name with suffix - suggestions = append(suggestions, fname+suffix) - } // if field is anonymous add the child fields as well if field.Anonymous { - suggestions = append(suggestions, getStructFields(f.FieldByIndex([]int{j}), prefix)...) + suggestions = append(suggestions, getStructFields(f.Field(j), prefix)...) + } else if strings.HasPrefix(fname, prefix) { + // add field name with suffix + suggestions = append(suggestions, fname+suffix) } } diff --git a/cmd/podman/common/completion_test.go b/cmd/podman/common/completion_test.go index d28ac3928..ae117a173 100644 --- a/cmd/podman/common/completion_test.go +++ b/cmd/podman/common/completion_test.go @@ -34,10 +34,9 @@ func TestAutocompleteFormat(t *testing.T) { Name string Age int Car *Car + Car2 *Car *Anonymous - }{ - Anonymous: &Anonymous{}, - } + }{} testStruct.Car = &Car{} testStruct.Car.Extras = map[string]string{"test": "1"} @@ -80,12 +79,12 @@ func TestAutocompleteFormat(t *testing.T) { { "fist level struct field name", "{{.", - []string{"{{.Name}}", "{{.Age}}", "{{.Car.", "{{.Anonymous.", "{{.Hello}}"}, + []string{"{{.Name}}", "{{.Age}}", "{{.Car.", "{{.Car2.", "{{.Hello}}"}, }, { "fist level struct field name", "{{ .", - []string{"{{ .Name}}", "{{ .Age}}", "{{ .Car.", "{{ .Anonymous.", "{{ .Hello}}"}, + []string{"{{ .Name}}", "{{ .Age}}", "{{ .Car.", "{{ .Car2.", "{{ .Hello}}"}, }, { "fist level struct field name", @@ -103,6 +102,11 @@ func TestAutocompleteFormat(t *testing.T) { []string{"{{ .Car.Brand}}"}, }, { + "second level nil struct field name", + "{{ .Car2.", + []string{"{{ .Car2.Brand}}", "{{ .Car2.Stats.", "{{ .Car2.Extras}}", "{{ .Car2.Color}}", "{{ .Car2.Type}}"}, + }, + { "three level struct field name", "{{ .Car.Stats.", []string{"{{ .Car.Stats.HP}}", "{{ .Car.Stats.Displacement}}"}, diff --git a/cmd/podman/containers/inspect.go b/cmd/podman/containers/inspect.go index 8c219b67c..03e6411a1 100644 --- a/cmd/podman/containers/inspect.go +++ b/cmd/podman/containers/inspect.go @@ -35,12 +35,7 @@ func init() { formatFlagName := "format" flags.StringVarP(&inspectOpts.Format, formatFlagName, "f", "json", "Format the output to a Go template or json") - _ = inspectCmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(define.InspectContainerData{ - State: &define.InspectContainerState{}, - NetworkSettings: &define.InspectNetworkSettings{}, - Config: &define.InspectContainerConfig{}, - HostConfig: &define.InspectContainerHostConfig{}, - })) + _ = inspectCmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(&define.InspectContainerData{})) validate.AddLatestFlag(inspectCmd, &inspectOpts.Latest) } diff --git a/cmd/podman/containers/ps.go b/cmd/podman/containers/ps.go index 4adae30c2..a011a8ae6 100644 --- a/cmd/podman/containers/ps.go +++ b/cmd/podman/containers/ps.go @@ -80,7 +80,7 @@ func listFlagSet(cmd *cobra.Command) { formatFlagName := "format" flags.StringVar(&listOpts.Format, formatFlagName, "", "Pretty-print containers to JSON or using a Go template") - _ = cmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(entities.ListContainer{})) + _ = cmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(&psReporter{})) lastFlagName := "last" flags.IntVarP(&listOpts.Last, lastFlagName, "n", -1, "Print the n last created containers (all states)") diff --git a/cmd/podman/containers/stats.go b/cmd/podman/containers/stats.go index 715f5c081..500671d31 100644 --- a/cmd/podman/containers/stats.go +++ b/cmd/podman/containers/stats.go @@ -67,7 +67,7 @@ func statFlags(cmd *cobra.Command) { formatFlagName := "format" flags.StringVar(&statsOptions.Format, formatFlagName, "", "Pretty-print container statistics to JSON or using a Go template") - _ = cmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(define.ContainerStats{})) + _ = cmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(&containerStats{})) flags.BoolVar(&statsOptions.NoReset, "no-reset", false, "Disable resetting the screen between intervals") flags.BoolVar(&statsOptions.NoStream, "no-stream", false, "Disable streaming stats and only pull the first result, default setting is false") diff --git a/cmd/podman/images/history.go b/cmd/podman/images/history.go index c05d3475b..e190941e7 100644 --- a/cmd/podman/images/history.go +++ b/cmd/podman/images/history.go @@ -69,7 +69,7 @@ func historyFlags(cmd *cobra.Command) { formatFlagName := "format" flags.StringVar(&opts.format, formatFlagName, "", "Change the output to JSON or a Go template") - _ = cmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(entities.ImageHistoryLayer{})) + _ = cmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(&historyReporter{})) flags.BoolVarP(&opts.human, "human", "H", true, "Display sizes and dates in human readable format") flags.BoolVar(&opts.noTrunc, "no-trunc", false, "Do not truncate the output") @@ -168,3 +168,11 @@ func (h historyReporter) ID() string { } return h.ImageHistoryLayer.ID } + +func (h historyReporter) CreatedAt() string { + return time.Unix(h.ImageHistoryLayer.Created.Unix(), 0).UTC().String() +} + +func (h historyReporter) CreatedSince() string { + return h.Created() +} diff --git a/cmd/podman/images/inspect.go b/cmd/podman/images/inspect.go index b4a79bc96..22c404b3f 100644 --- a/cmd/podman/images/inspect.go +++ b/cmd/podman/images/inspect.go @@ -34,7 +34,7 @@ func init() { formatFlagName := "format" flags.StringVarP(&inspectOpts.Format, formatFlagName, "f", "json", "Format the output to a Go template or json") - _ = inspectCmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(inspectTypes.ImageData{})) + _ = inspectCmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(&inspectTypes.ImageData{})) } func inspectExec(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/images/list.go b/cmd/podman/images/list.go index 58fb3e919..81011f9b1 100644 --- a/cmd/podman/images/list.go +++ b/cmd/podman/images/list.go @@ -94,7 +94,7 @@ func imageListFlagSet(cmd *cobra.Command) { formatFlagName := "format" flags.StringVar(&listFlag.format, formatFlagName, "", "Change the output format to JSON or a Go template") - _ = cmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(entities.ImageSummary{})) + _ = cmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(&imageReporter{})) flags.BoolVar(&listFlag.digests, "digests", false, "Show digests") flags.BoolVarP(&listFlag.noHeading, "noheading", "n", false, "Do not print column headings") diff --git a/cmd/podman/images/search.go b/cmd/podman/images/search.go index aa11cf254..335ea2b5a 100644 --- a/cmd/podman/images/search.go +++ b/cmd/podman/images/search.go @@ -9,6 +9,7 @@ import ( "github.com/containers/common/pkg/completion" "github.com/containers/common/pkg/report" "github.com/containers/image/v5/types" + "github.com/containers/podman/v4/cmd/podman/common" "github.com/containers/podman/v4/cmd/podman/registry" "github.com/containers/podman/v4/pkg/domain/entities" "github.com/pkg/errors" @@ -23,6 +24,7 @@ type searchOptionsWrapper struct { Compatible bool // Docker compat TLSVerifyCLI bool // Used to convert to an optional bool later Format string // For go templating + NoTrunc bool } // listEntryTag is a utility structure used for json serialization. @@ -86,13 +88,13 @@ func searchFlags(cmd *cobra.Command) { formatFlagName := "format" flags.StringVar(&searchOptions.Format, formatFlagName, "", "Change the output format to JSON or a Go template") - _ = cmd.RegisterFlagCompletionFunc(formatFlagName, completion.AutocompleteNone) + _ = cmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(&entities.ImageSearchReport{})) limitFlagName := "limit" flags.IntVar(&searchOptions.Limit, limitFlagName, 0, "Limit the number of results") _ = cmd.RegisterFlagCompletionFunc(limitFlagName, completion.AutocompleteNone) - flags.Bool("no-trunc", true, "Do not truncate the output. Default: true") + flags.BoolVar(&searchOptions.NoTrunc, "no-trunc", false, "Do not truncate the output") flags.BoolVar(&searchOptions.Compatible, "compatible", false, "List stars, official and automated columns (Docker compatibility)") authfileFlagName := "authfile" @@ -139,11 +141,10 @@ func imageSearch(cmd *cobra.Command, args []string) error { return nil } - noTrunc, _ := cmd.Flags().GetBool("no-trunc") isJSON := report.IsJSON(searchOptions.Format) for i, element := range searchReport { d := strings.ReplaceAll(element.Description, "\n", " ") - if len(d) > 44 && !(noTrunc || isJSON) { + if len(d) > 44 && !(searchOptions.NoTrunc || isJSON) { d = strings.TrimSpace(d[:44]) + "..." } searchReport[i].Description = d diff --git a/cmd/podman/machine/inspect.go b/cmd/podman/machine/inspect.go index 1884cf94d..21e5074b7 100644 --- a/cmd/podman/machine/inspect.go +++ b/cmd/podman/machine/inspect.go @@ -41,7 +41,7 @@ func init() { flags := inspectCmd.Flags() formatFlagName := "format" flags.StringVar(&inspectFlag.format, formatFlagName, "", "Format volume output using JSON or a Go template") - _ = inspectCmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(machine.InspectInfo{})) + _ = inspectCmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(&machine.InspectInfo{})) } func inspect(cmd *cobra.Command, args []string) error { @@ -59,16 +59,12 @@ func inspect(cmd *cobra.Command, args []string) error { errs = append(errs, err) continue } - state, err := vm.State(false) + ii, err := vm.Inspect() if err != nil { errs = append(errs, err) continue } - ii := machine.InspectInfo{ - State: state, - VM: vm, - } - vms = append(vms, ii) + vms = append(vms, *ii) } if len(inspectFlag.format) > 0 { // need jhonce to work his template magic diff --git a/cmd/podman/machine/list.go b/cmd/podman/machine/list.go index 587e521a3..c987bf71a 100644 --- a/cmd/podman/machine/list.go +++ b/cmd/podman/machine/list.go @@ -69,7 +69,7 @@ func init() { flags := lsCmd.Flags() formatFlagName := "format" flags.StringVar(&listFlag.format, formatFlagName, "{{.Name}}\t{{.VMType}}\t{{.Created}}\t{{.LastUp}}\t{{.CPUs}}\t{{.Memory}}\t{{.DiskSize}}\n", "Format volume output using JSON or a Go template") - _ = lsCmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(machineReporter{})) + _ = lsCmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(&machineReporter{})) flags.BoolVar(&listFlag.noHeading, "noheading", false, "Do not print headers") flags.BoolVarP(&listFlag.quiet, "quiet", "q", false, "Show only machine names") } diff --git a/cmd/podman/machine/set.go b/cmd/podman/machine/set.go index 4c15f1de1..a994c981b 100644 --- a/cmd/podman/machine/set.go +++ b/cmd/podman/machine/set.go @@ -4,6 +4,9 @@ package machine import ( + "fmt" + "os" + "github.com/containers/common/pkg/completion" "github.com/containers/podman/v4/cmd/podman/registry" "github.com/containers/podman/v4/pkg/machine" @@ -23,9 +26,17 @@ var ( ) var ( - setOpts = machine.SetOptions{} + setFlags = SetFlags{} + setOpts = machine.SetOptions{} ) +type SetFlags struct { + CPUs uint64 + DiskSize uint64 + Memory uint64 + Rootful bool +} + func init() { registry.Commands = append(registry.Commands, registry.CliCommand{ Command: setCmd, @@ -34,7 +45,32 @@ func init() { flags := setCmd.Flags() rootfulFlagName := "rootful" - flags.BoolVar(&setOpts.Rootful, rootfulFlagName, false, "Whether this machine should prefer rootful container execution") + flags.BoolVar(&setFlags.Rootful, rootfulFlagName, false, "Whether this machine should prefer rootful container execution") + + cpusFlagName := "cpus" + flags.Uint64Var( + &setFlags.CPUs, + cpusFlagName, 0, + "Number of CPUs", + ) + _ = setCmd.RegisterFlagCompletionFunc(cpusFlagName, completion.AutocompleteNone) + + diskSizeFlagName := "disk-size" + flags.Uint64Var( + &setFlags.DiskSize, + diskSizeFlagName, 0, + "Disk size in GB", + ) + + _ = setCmd.RegisterFlagCompletionFunc(diskSizeFlagName, completion.AutocompleteNone) + + memoryFlagName := "memory" + flags.Uint64VarP( + &setFlags.Memory, + memoryFlagName, "m", 0, + "Memory in MB", + ) + _ = setCmd.RegisterFlagCompletionFunc(memoryFlagName, completion.AutocompleteNone) } func setMachine(cmd *cobra.Command, args []string) error { @@ -53,5 +89,23 @@ func setMachine(cmd *cobra.Command, args []string) error { return err } - return vm.Set(vmName, setOpts) + if cmd.Flags().Changed("rootful") { + setOpts.Rootful = &setFlags.Rootful + } + if cmd.Flags().Changed("cpus") { + setOpts.CPUs = &setFlags.CPUs + } + if cmd.Flags().Changed("memory") { + setOpts.Memory = &setFlags.Memory + } + if cmd.Flags().Changed("disk-size") { + setOpts.DiskSize = &setFlags.DiskSize + } + + setErrs, lasterr := vm.Set(vmName, setOpts) + for _, err := range setErrs { + fmt.Fprintf(os.Stderr, "%v\n", err) + } + + return lasterr } diff --git a/cmd/podman/networks/inspect.go b/cmd/podman/networks/inspect.go index 3c07e5492..8f39ec395 100644 --- a/cmd/podman/networks/inspect.go +++ b/cmd/podman/networks/inspect.go @@ -1,6 +1,7 @@ package network import ( + "github.com/containers/common/libnetwork/types" "github.com/containers/podman/v4/cmd/podman/common" "github.com/containers/podman/v4/cmd/podman/inspect" "github.com/containers/podman/v4/cmd/podman/registry" @@ -32,7 +33,7 @@ func init() { formatFlagName := "format" flags.StringVarP(&inspectOpts.Format, formatFlagName, "f", "", "Pretty-print network to JSON or using a Go template") - _ = networkinspectCommand.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(nil)) + _ = networkinspectCommand.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(&types.Network{})) } func networkInspect(_ *cobra.Command, args []string) error { diff --git a/cmd/podman/networks/list.go b/cmd/podman/networks/list.go index f14e0ed0f..5d4be2a81 100644 --- a/cmd/podman/networks/list.go +++ b/cmd/podman/networks/list.go @@ -40,7 +40,7 @@ var ( func networkListFlags(flags *pflag.FlagSet) { formatFlagName := "format" flags.StringVar(&networkListOptions.Format, formatFlagName, "", "Pretty-print networks to JSON or using a Go template") - _ = networklistCommand.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(ListPrintReports{})) + _ = networklistCommand.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(&ListPrintReports{})) flags.BoolVarP(&networkListOptions.Quiet, "quiet", "q", false, "display only names") flags.BoolVar(&noTrunc, "no-trunc", false, "Do not truncate the network ID") diff --git a/cmd/podman/pods/inspect.go b/cmd/podman/pods/inspect.go index ae6a5ba88..bb30fe6e6 100644 --- a/cmd/podman/pods/inspect.go +++ b/cmd/podman/pods/inspect.go @@ -9,7 +9,6 @@ import ( "github.com/containers/podman/v4/cmd/podman/common" "github.com/containers/podman/v4/cmd/podman/registry" "github.com/containers/podman/v4/cmd/podman/validate" - "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/domain/entities" "github.com/pkg/errors" "github.com/spf13/cobra" @@ -43,7 +42,7 @@ func init() { formatFlagName := "format" flags.StringVarP(&inspectOptions.Format, formatFlagName, "f", "json", "Format the output to a Go template or json") - _ = inspectCmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(define.InspectPodData{})) + _ = inspectCmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(&entities.PodInspectReport{})) validate.AddLatestFlag(inspectCmd, &inspectOptions.Latest) } diff --git a/cmd/podman/pods/ps.go b/cmd/podman/pods/ps.go index 4a049541a..1275e65dc 100644 --- a/cmd/podman/pods/ps.go +++ b/cmd/podman/pods/ps.go @@ -57,7 +57,7 @@ func init() { formatFlagName := "format" flags.StringVar(&psInput.Format, formatFlagName, "", "Pretty-print pods to JSON or using a Go template") - _ = psCmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(ListPodReporter{ListPodsReport: &entities.ListPodsReport{}})) + _ = psCmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(&ListPodReporter{})) flags.Bool("noheading", false, "Do not print headers") flags.BoolVar(&psInput.Namespace, "namespace", false, "Display namespace information of the pod") diff --git a/cmd/podman/pods/stats.go b/cmd/podman/pods/stats.go index f7a56d3f3..9833f4cea 100644 --- a/cmd/podman/pods/stats.go +++ b/cmd/podman/pods/stats.go @@ -54,7 +54,7 @@ func init() { formatFlagName := "format" flags.StringVar(&statsOptions.Format, formatFlagName, "", "Pretty-print container statistics to JSON or using a Go template") - _ = statsCmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(entities.PodStatsReport{})) + _ = statsCmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(&entities.PodStatsReport{})) flags.BoolVar(&statsOptions.NoReset, "no-reset", false, "Disable resetting the screen when streaming") flags.BoolVar(&statsOptions.NoStream, "no-stream", false, "Disable streaming stats and only pull the first result") diff --git a/cmd/podman/secrets/inspect.go b/cmd/podman/secrets/inspect.go index 0977434f7..e8947e441 100644 --- a/cmd/podman/secrets/inspect.go +++ b/cmd/podman/secrets/inspect.go @@ -36,7 +36,7 @@ func init() { flags := inspectCmd.Flags() formatFlagName := "format" flags.StringVar(&format, formatFlagName, "", "Format volume output using Go template") - _ = inspectCmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(entities.SecretInfoReport{})) + _ = inspectCmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(&entities.SecretInfoReport{})) } func inspect(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/secrets/list.go b/cmd/podman/secrets/list.go index 2ef84cd48..558a16ccf 100644 --- a/cmd/podman/secrets/list.go +++ b/cmd/podman/secrets/list.go @@ -45,7 +45,7 @@ func init() { flags := lsCmd.Flags() formatFlagName := "format" flags.StringVar(&listFlag.format, formatFlagName, "{{.ID}}\t{{.Name}}\t{{.Driver}}\t{{.CreatedAt}}\t{{.UpdatedAt}}\t\n", "Format volume output using Go template") - _ = lsCmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(entities.SecretInfoReport{})) + _ = lsCmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(&entities.SecretInfoReport{})) filterFlagName := "filter" flags.StringSliceVarP(&listFlag.filter, filterFlagName, "f", []string{}, "Filter secret output") _ = lsCmd.RegisterFlagCompletionFunc(filterFlagName, common.AutocompleteSecretFilters) diff --git a/cmd/podman/system/connection/list.go b/cmd/podman/system/connection/list.go index fe37677df..2c5f6a310 100644 --- a/cmd/podman/system/connection/list.go +++ b/cmd/podman/system/connection/list.go @@ -38,7 +38,7 @@ func init() { }) listCmd.Flags().String("format", "", "Custom Go template for printing connections") - _ = listCmd.RegisterFlagCompletionFunc("format", common.AutocompleteFormat(namedDestination{})) + _ = listCmd.RegisterFlagCompletionFunc("format", common.AutocompleteFormat(&namedDestination{})) } type namedDestination struct { diff --git a/cmd/podman/system/events.go b/cmd/podman/system/events.go index 2723adc43..09e589d3c 100644 --- a/cmd/podman/system/events.go +++ b/cmd/podman/system/events.go @@ -51,7 +51,7 @@ func init() { formatFlagName := "format" flags.StringVar(&eventFormat, formatFlagName, "", "format the output using a Go template") - _ = eventsCommand.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(events.Event{})) + _ = eventsCommand.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(&events.Event{})) flags.BoolVar(&eventOptions.Stream, "stream", true, "stream new events; for testing only") diff --git a/cmd/podman/system/info.go b/cmd/podman/system/info.go index e95e9336d..f8fd946cd 100644 --- a/cmd/podman/system/info.go +++ b/cmd/podman/system/info.go @@ -66,7 +66,7 @@ func infoFlags(cmd *cobra.Command) { formatFlagName := "format" flags.StringVarP(&inFormat, formatFlagName, "f", "", "Change the output format to JSON or a Go template") - _ = cmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(define.Info{Host: &define.HostInfo{}, Store: &define.StoreInfo{}})) + _ = cmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(&define.Info{})) } func info(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/system/version.go b/cmd/podman/system/version.go index 9fb4a966a..7202b2c08 100644 --- a/cmd/podman/system/version.go +++ b/cmd/podman/system/version.go @@ -34,7 +34,7 @@ func init() { formatFlagName := "format" flags.StringVarP(&versionFormat, formatFlagName, "f", "", "Change the output format to JSON or a Go template") - _ = versionCommand.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(entities.SystemVersionReport{})) + _ = versionCommand.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(&entities.SystemVersionReport{})) } func version(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/volumes/inspect.go b/cmd/podman/volumes/inspect.go index 2230a2818..f21f9c233 100644 --- a/cmd/podman/volumes/inspect.go +++ b/cmd/podman/volumes/inspect.go @@ -41,7 +41,7 @@ func init() { formatFlagName := "format" flags.StringVarP(&inspectOpts.Format, formatFlagName, "f", "json", "Format volume output using Go template") - _ = inspectCommand.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(define.InspectVolumeData{})) + _ = inspectCommand.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(&define.InspectVolumeData{})) } func volumeInspect(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/volumes/list.go b/cmd/podman/volumes/list.go index 2edf04097..c14cf08bd 100644 --- a/cmd/podman/volumes/list.go +++ b/cmd/podman/volumes/list.go @@ -11,7 +11,6 @@ import ( "github.com/containers/podman/v4/cmd/podman/parse" "github.com/containers/podman/v4/cmd/podman/registry" "github.com/containers/podman/v4/cmd/podman/validate" - "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/domain/entities" "github.com/pkg/errors" "github.com/spf13/cobra" @@ -57,7 +56,7 @@ func init() { formatFlagName := "format" flags.StringVar(&cliOpts.Format, formatFlagName, "{{.Driver}}\t{{.Name}}\n", "Format volume output using Go template") - _ = lsCommand.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(define.InspectVolumeData{})) + _ = lsCommand.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(&entities.VolumeListReport{})) flags.Bool("noheading", false, "Do not print headers") flags.BoolVarP(&cliOpts.Quiet, "quiet", "q", false, "Print volume output in quiet mode") diff --git a/contrib/cirrus/lib.sh b/contrib/cirrus/lib.sh index 09a255e6f..0f02c166f 100644 --- a/contrib/cirrus/lib.sh +++ b/contrib/cirrus/lib.sh @@ -97,7 +97,7 @@ EPOCH_TEST_COMMIT="$CIRRUS_BASE_SHA" # testing operations on all platforms and versions. This is necessary # to avoid needlessly passing through global/system values across # contexts, such as host->container or root->rootless user -PASSTHROUGH_ENV_RE='(^CI.*)|(^CIRRUS)|(^DISTRO_NV)|(^GOPATH)|(^GOCACHE)|(^GOSRC)|(^SCRIPT_BASE)|(CGROUP_MANAGER)|(OCI_RUNTIME)|(^TEST.*)|(^PODBIN_NAME)|(^PRIV_NAME)|(^ALT_NAME)|(^ROOTLESS_USER)|(SKIP_USERNS)|(.*_NAME)|(.*_FQIN)' +PASSTHROUGH_ENV_RE='(^CI.*)|(^CIRRUS)|(^DISTRO_NV)|(^GOPATH)|(^GOCACHE)|(^GOSRC)|(^SCRIPT_BASE)|(CGROUP_MANAGER)|(OCI_RUNTIME)|(^TEST.*)|(^PODBIN_NAME)|(^PRIV_NAME)|(^ALT_NAME)|(^ROOTLESS_USER)|(SKIP_USERNS)|(.*_NAME)|(.*_FQIN)|(NETWORK_BACKEND)' # Unsafe env. vars for display SECRET_ENV_RE='(ACCOUNT)|(GC[EP]..+)|(SSH)|(PASSWORD)|(TOKEN)' @@ -169,10 +169,6 @@ setup_rootless() { groupadd -g $rootless_gid $ROOTLESS_USER useradd -g $rootless_gid -u $rootless_uid --no-user-group --create-home $ROOTLESS_USER - # We also set up rootless user for image-scp tests (running as root) - if [[ $PRIV_NAME = "rootless" ]]; then - chown -R $ROOTLESS_USER:$ROOTLESS_USER "$GOPATH" "$GOSRC" - fi echo "$ROOTLESS_USER ALL=(root) NOPASSWD: ALL" > /etc/sudoers.d/ci-rootless mkdir -p "$HOME/.ssh" "/home/$ROOTLESS_USER/.ssh" @@ -216,20 +212,39 @@ setup_rootless() { install_test_configs() { msg "Installing ./test/registries.conf system-wide." install -v -D -m 644 ./test/registries.conf /etc/containers/ - if [[ "$TEST_ENVIRON" =~ netavark ]]; then - # belt-and-suspenders: any pre-existing CNI config. will spoil - # default use tof netavark (when both are installed). - rm -rf /etc/cni/net.d/* - else - echo "Installing cni config, policy and registry config" - req_env_vars GOSRC SCRIPT_BASE - cd $GOSRC || exit 1 - install -v -D -m 644 ./cni/87-podman-bridge.conflist /etc/cni/net.d/ - # This config must always sort last in the list of networks (podman picks first one - # as the default). This config prevents allocation of network address space used - # by default in google cloud. https://cloud.google.com/vpc/docs/vpc#ip-ranges - install -v -D -m 644 $SCRIPT_BASE/99-do-not-use-google-subnets.conflist /etc/cni/net.d/ - fi +} + +use_cni() { + msg "Unsetting NETWORK_BACKEND for all subsequent environments." + echo "export -n NETWORK_BACKEND" >> /etc/ci_environment + echo "unset NETWORK_BACKEND" >> /etc/ci_environment + export -n NETWORK_BACKEND + unset NETWORK_BACKEND + msg "Installing default CNI configuration" + cd $GOSRC || exit 1 + rm -rvf /etc/cni/net.d + mkdir -p /etc/cni/net.d + install -v -D -m 644 ./cni/87-podman-bridge.conflist \ + /etc/cni/net.d/ + # This config must always sort last in the list of networks (podman picks + # first one as the default). This config prevents allocation of network + # address space used by default in google cloud. + # https://cloud.google.com/vpc/docs/vpc#ip-ranges + install -v -D -m 644 $SCRIPT_BASE/99-do-not-use-google-subnets.conflist \ + /etc/cni/net.d/ +} + +use_netavark() { + msg "Forcing NETWORK_BACKEND=netavark for all subsequent environments." + echo "NETWORK_BACKEND=netavark" >> /etc/ci_environment + export NETWORK_BACKEND=netavark # needed for install_test_configs() + msg "Removing any/all CNI configuration" + rm -rvf /etc/cni/net.d/* + + # TODO: Remove this when netavark/aardvark-dns development slows down + warn "Updating netavark/aardvark-dns to avoid frequent VM image rebuilds" + # N/B: This is coming from updates-testing repo in F36 + lilto dnf update -y netavark aardvark-dns } # Remove all files provided by the distro version of podman. diff --git a/contrib/cirrus/logcollector.sh b/contrib/cirrus/logcollector.sh index 0cfbf7135..d712713b4 100755 --- a/contrib/cirrus/logcollector.sh +++ b/contrib/cirrus/logcollector.sh @@ -40,32 +40,34 @@ case $1 in packages) # These names are common to Fedora and Ubuntu PKG_NAMES=(\ - conmon \ - containernetworking-plugins \ - containers-common \ - criu \ - crun \ - golang \ - podman \ - runc \ - skopeo \ - slirp4netns \ + conmon + containernetworking-plugins + containers-common + criu + crun + golang + podman + runc + skopeo + slirp4netns ) case $OS_RELEASE_ID in fedora) cat /etc/fedora-release PKG_LST_CMD='rpm -q --qf=%{N}-%{V}-%{R}-%{ARCH}\n' PKG_NAMES+=(\ - container-selinux \ - libseccomp \ + aardvark + container-selinux + libseccomp + netavark ) ;; ubuntu) cat /etc/issue PKG_LST_CMD='dpkg-query --show --showformat=${Package}-${Version}-${Architecture}\n' PKG_NAMES+=(\ - cri-o-runc \ - libseccomp2 \ + cri-o-runc + libseccomp2 ) ;; *) bad_os_id_ver ;; @@ -74,19 +76,6 @@ case $1 in echo "Cgroups: " $(stat -f -c %T /sys/fs/cgroup) # Any not-present packages will be listed as such $PKG_LST_CMD "${PKG_NAMES[@]}" | sort -u - - # TODO: Remove this once netavark/aardvark-dns packages are used - if [[ "$TEST_ENVIRON" =~ netavark ]]; then - _npath=/usr/local/libexec/podman/ - for name in netavark aardvark-dns; do - echo "$name binary details:" - if [[ -r "$_npath/${name}.info" ]]; then - cat "$_npath/${name}.info" - else - echo "WARNING: $_npath/${name}.info not found." - fi - done - fi ;; time) # Assumed to be empty/undefined outside of Cirrus-CI (.cirrus.yml) diff --git a/contrib/cirrus/runner.sh b/contrib/cirrus/runner.sh index 5d6ba9921..101270703 100755 --- a/contrib/cirrus/runner.sh +++ b/contrib/cirrus/runner.sh @@ -12,7 +12,7 @@ set -eo pipefail # most notably: # # PODBIN_NAME : "podman" (i.e. local) or "remote" -# TEST_ENVIRON : 'host', 'host-netavark', or 'container'; desired environment in which to run +# TEST_ENVIRON : 'host', or 'container'; desired environment in which to run # CONTAINER : 1 if *currently* running inside a container, 0 if host # @@ -449,6 +449,13 @@ if [[ "$PRIV_NAME" == "rootless" ]] && [[ "$UID" -eq 0 ]]; then # https://github.com/containers/podman/issues/10857 rm -rf /var/lib/cni + # This must be done at the last second, otherwise `make` calls + # in setup_environment (as root) will balk about ownership. + msg "Recursively chowning \$GOPATH and \$GOSRC to $ROOTLESS_USER" + if [[ $PRIV_NAME = "rootless" ]]; then + chown -R $ROOTLESS_USER:$ROOTLESS_USER "$GOPATH" "$GOSRC" + fi + req_env_vars ROOTLESS_USER msg "Re-executing runner through ssh as user '$ROOTLESS_USER'" msg "************************************************************" diff --git a/contrib/cirrus/setup_environment.sh b/contrib/cirrus/setup_environment.sh index 742289733..e3eb46783 100755 --- a/contrib/cirrus/setup_environment.sh +++ b/contrib/cirrus/setup_environment.sh @@ -38,13 +38,12 @@ done cp hack/podman-registry /bin -# Make sure cni network plugins directory exists -mkdir -p /etc/cni/net.d - # Some test operations & checks require a git "identity" _gc='git config --file /root/.gitconfig' $_gc user.email "TMcTestFace@example.com" $_gc user.name "Testy McTestface" +# Bypass git safety/security checks when operating in a throwaway environment +git config --system --add safe.directory $GOSRC # Ensure that all lower-level contexts and child-processes have # ready access to higher level orchestration (e.g Cirrus-CI) @@ -84,13 +83,6 @@ case "$CG_FS_TYPE" in else echo "OCI_RUNTIME=runc" >> /etc/ci_environment fi - - # As a general policy CGv1 + runc should coincide with the "older" - # VM Images in CI. Verify this is the case. - if [[ -n "$VM_IMAGE_NAME" ]] && [[ ! "$VM_IMAGE_NAME" =~ prior ]] - then - die "Most recent distro. version should never run with CGv1" - fi fi ;; cgroup2fs) @@ -99,13 +91,6 @@ case "$CG_FS_TYPE" in # which uses runc as the default. warn "Forcing testing with crun instead of runc" echo "OCI_RUNTIME=crun" >> /etc/ci_environment - - # As a general policy CGv2 + crun should coincide with the "newer" - # VM Images in CI. Verify this is the case. - if [[ -n "$VM_IMAGE_NAME" ]] && [[ "$VM_IMAGE_NAME" =~ prior ]] - then - die "Least recent distro. version should never run with CGv2" - fi fi ;; *) die_unknown CG_FS_TYPE @@ -130,6 +115,19 @@ case "$OS_RELEASE_ID" in msg "Enabling container_manage_cgroup" setsebool container_manage_cgroup true fi + + # For release 36 and later, netavark/aardvark is the default + # networking stack for podman. All previous releases only have + # CNI networking available. Upgrading from one to the other is + # not supported at this time. Support execution of the upgrade + # tests in F36 and later, by disabling Netavark and enabling CNI. + if [[ "$OS_RELEASE_VER" -ge 36 ]] && \ + [[ "$TEST_FLAVOR" != "upgrade_test" ]]; + then + use_netavark + else # Fedora < 36, or upgrade testing. + use_cni + fi ;; *) die_unknown OS_RELEASE_ID esac @@ -137,7 +135,7 @@ esac # Required to be defined by caller: The environment where primary testing happens # shellcheck disable=SC2154 case "$TEST_ENVIRON" in - host*) + host) # The e2e tests wrongly guess `--cgroup-manager` option # shellcheck disable=SC2154 if [[ "$CG_FS_TYPE" == "cgroup2fs" ]] || [[ "$PRIV_NAME" == "root" ]] @@ -148,43 +146,6 @@ case "$TEST_ENVIRON" in warn "Forcing CGROUP_MANAGER=cgroupfs" echo "CGROUP_MANAGER=cgroupfs" >> /etc/ci_environment fi - # TODO: For the foreseeable future, need to support running tests - # with and without the latest netavark/aardvark. Once they're more - # stable and widely supported in Fedora, they can be pre-installed - # from its RPM at VM image build-time. - if [[ "$TEST_ENVIRON" =~ netavark ]]; then - for info in "netavark $NETAVARK_BRANCH $NETAVARK_URL $NETAVARK_DEBUG" \ - "aardvark-dns $AARDVARK_BRANCH $AARDVARK_URL $AARDVARK_DEBUG"; do - - read _name _branch _url _debug <<<"$info" - req_env_vars _name _branch _url _debug - msg "Downloading latest $_name from upstream branch '$_branch'" - # Use identifiable archive filename in of a get_ci_env.sh environment - curl --fail --location -o /tmp/$_name.zip "$_url" - - # Needs to be in a specific location - # ref: https://github.com/containers/common/blob/main/pkg/config/config_linux.go#L39 - _pdir=/usr/local/libexec/podman - mkdir -p $_pdir - cd $_pdir - msg "$PWD" - unzip /tmp/$_name.zip - if ((_debug)); then - warn "Using debug $_name binary" - mv $_name.debug $_name - else - rm $_name.debug - fi - chmod 0755 $_pdir/$_name - cd - - done - - restorecon -F -v $_nvdir - # This is critical, it signals to all tests that netavark - # use is expected. - msg "Forcing NETWORK_BACKEND=netavark in all subsequent environments." - echo "NETWORK_BACKEND=netavark" >> /etc/ci_environment - fi ;; container) if ((CONTAINER==0)); then # not yet inside a container @@ -345,6 +306,9 @@ case "$TEST_FLAVOR" in # Guarantee the docker daemon can't be started, even by accident rm -vf $(type -P dockerd) + msg "Recursively chowning source to $ROOTLESS_USER" + chown -R $ROOTLESS_USER:$ROOTLESS_USER "$GOPATH" "$GOSRC" + msg "Obtaining necessary gitlab-runner testing bits" slug="gitlab.com/gitlab-org/gitlab-runner" helper_fqin="registry.gitlab.com/gitlab-org/gitlab-runner/gitlab-runner-helper:x86_64-latest-pwsh" diff --git a/docs/source/markdown/podman-history.1.md b/docs/source/markdown/podman-history.1.md index af35814c2..16f1e48e6 100644 --- a/docs/source/markdown/podman-history.1.md +++ b/docs/source/markdown/podman-history.1.md @@ -23,10 +23,11 @@ Valid placeholders for the Go template are listed below: | --------------- | ----------------------------------------------------------------------------- | | .ID | Image ID | | .Created | if --human, time elapsed since creation, otherwise time stamp of creation | -| .CreatedBy | Command used to create the layer | -| .Size | Size of layer on disk | -| .Comment | Comment for the layer | - +| .CreatedAt | Time when the image layer was created | +| .CreatedBy | Command used to create the layer | +| .CreatedSince | Elapsed time since the image layer was created | +| .Size | Size of layer on disk | +| .Comment | Comment for the layer | ## OPTIONS Print the numeric IDs only (default *false*). diff --git a/docs/source/markdown/podman-machine-set.1.md b/docs/source/markdown/podman-machine-set.1.md index a4918eacf..de90ee4b0 100644 --- a/docs/source/markdown/podman-machine-set.1.md +++ b/docs/source/markdown/podman-machine-set.1.md @@ -8,17 +8,29 @@ podman\-machine\-set - Sets a virtual machine setting ## DESCRIPTION -Sets an updatable virtual machine setting. - -Options mirror values passed to `podman machine init`. Only a limited -subset can be changed after machine initialization. +Change a machine setting. ## OPTIONS +#### **--cpus**=*number* + +Number of CPUs. +Only supported for QEMU machines. + +#### **--disk-size**=*number* + +Size of the disk for the guest VM in GB. +Can only be increased. Only supported for QEMU machines. + #### **--help** Print usage statement. +#### **--memory**, **-m**=*number* + +Memory (in MB). +Only supported for QEMU machines. + #### **--rootful**=*true|false* Whether this machine should prefer rootful (`true`) or rootless (`false`) diff --git a/docs/source/markdown/podman-search.1.md b/docs/source/markdown/podman-search.1.md index 81a67d762..5b49d7f8e 100644 --- a/docs/source/markdown/podman-search.1.md +++ b/docs/source/markdown/podman-search.1.md @@ -90,7 +90,7 @@ The result contains the Image name and its tag, one line for every tag associate #### **--no-trunc** -Do not truncate the output (default *true*). +Do not truncate the output (default *false*). #### **--tls-verify** diff --git a/docs/source/markdown/podman-volume-create.1.md b/docs/source/markdown/podman-volume-create.1.md index 365a5acac..06fadcaa1 100644 --- a/docs/source/markdown/podman-volume-create.1.md +++ b/docs/source/markdown/podman-volume-create.1.md @@ -38,7 +38,8 @@ The `device` option sets the device to be mounted, and is equivalent to the `dev The `o` option sets options for the mount, and is equivalent to the `-o` flag to **mount(8)** with these exceptions: - The `o` option supports `uid` and `gid` options to set the UID and GID of the created volume that are not normally supported by **mount(8)**. - - The `o` option supports the `size` option to set the maximum size of the created volume and the `inodes` option to set the maximum number of inodes for the volume. Currently these flags are only supported on "xfs" file system mounted with the `prjquota` flag described in the **xfs_quota(8)** man page. + - The `o` option supports the `size` option to set the maximum size of the created volume, the `inodes` option to set the maximum number of inodes for the volume and `noquota` to completely disable quota support even for tracking of disk usage. Currently these flags are only supported on "xfs" file system mounted with the `prjquota` flag described in the **xfs_quota(8)** man page. + - The `o` option supports . - Using volume options other then the UID/GID options with the **local** driver requires root privileges. When not using the **local** driver, the given options are passed directly to the volume plugin. In this case, supported options are dictated by the plugin in question, not Podman. @@ -9,7 +9,7 @@ require ( github.com/checkpoint-restore/checkpointctl v0.0.0-20220321135231-33f4a66335f0 github.com/checkpoint-restore/go-criu/v5 v5.3.0 github.com/container-orchestrated-devices/container-device-interface v0.4.0 - github.com/containernetworking/cni v1.0.1 + github.com/containernetworking/cni v1.1.0 github.com/containernetworking/plugins v1.1.1 github.com/containers/buildah v1.25.2-0.20220423102655-8f2bb8876f3f github.com/containers/common v0.47.5-0.20220425182415-4081e6be9356 @@ -347,8 +347,9 @@ github.com/containerd/zfs v1.0.0/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNR github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= -github.com/containernetworking/cni v1.0.1 h1:9OIL/sZmMYDBe+G8svzILAlulUpaDTUjeAbtH/JNLBo= github.com/containernetworking/cni v1.0.1/go.mod h1:AKuhXbN5EzmD4yTNtfSsX3tPcmtrBI6QcRV0NiNt15Y= +github.com/containernetworking/cni v1.1.0 h1:T00oIz4hef+/p9gpRZa57SnIN+QnbmAHBjbxaOSFo9U= +github.com/containernetworking/cni v1.1.0/go.mod h1:sDpYKmGVENF3s6uvMvGgldDWeG8dMxakj/u+i9ht9vw= github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM= github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8= github.com/containernetworking/plugins v1.0.1/go.mod h1:QHCfGpaTwYTbbH+nZXKVTxNBDZcxSOplJT5ico8/FLE= diff --git a/libpod/options.go b/libpod/options.go index 57e2d7cf6..98eb45e76 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -1634,6 +1634,19 @@ func WithVolumeNoChown() VolumeCreateOption { } } +// WithVolumeDisableQuota prevents the volume from being assigned a quota. +func WithVolumeDisableQuota() VolumeCreateOption { + return func(volume *Volume) error { + if volume.valid { + return define.ErrVolumeFinalized + } + + volume.config.DisableQuota = true + + return nil + } +} + // withSetAnon sets a bool notifying libpod that this volume is anonymous and // should be removed when containers using it are removed and volumes are // specified for removal. diff --git a/libpod/pod.go b/libpod/pod.go index ed2d97b37..237c42901 100644 --- a/libpod/pod.go +++ b/libpod/pod.go @@ -1,7 +1,6 @@ package libpod import ( - "context" "fmt" "sort" "strings" @@ -159,6 +158,15 @@ func (p *Pod) CPUQuota() int64 { return 0 } +// NetworkMode returns the Network mode given by the user ex: pod, private... +func (p *Pod) NetworkMode() string { + infra, err := p.runtime.GetContainer(p.state.InfraContainerID) + if err != nil { + return "" + } + return infra.NetworkMode() +} + // PidMode returns the PID mode given by the user ex: pod, private... func (p *Pod) PidMode() string { infra, err := p.runtime.GetContainer(p.state.InfraContainerID) @@ -296,35 +304,9 @@ func (p *Pod) CgroupPath() (string, error) { if err := p.updatePod(); err != nil { return "", err } - if p.state.CgroupPath != "" { - return p.state.CgroupPath, nil - } if p.state.InfraContainerID == "" { return "", errors.Wrap(define.ErrNoSuchCtr, "pod has no infra container") } - - id, err := p.infraContainerID() - if err != nil { - return "", err - } - - if id != "" { - ctr, err := p.infraContainer() - if err != nil { - return "", errors.Wrapf(err, "could not get infra") - } - if ctr != nil { - ctr.Start(context.Background(), true) - cgroupPath, err := ctr.CgroupPath() - fmt.Println(cgroupPath) - if err != nil { - return "", errors.Wrapf(err, "could not get container cgroup") - } - p.state.CgroupPath = cgroupPath - p.save() - return cgroupPath, nil - } - } return p.state.CgroupPath, nil } diff --git a/libpod/pod_api.go b/libpod/pod_api.go index 48049798b..ba30d878e 100644 --- a/libpod/pod_api.go +++ b/libpod/pod_api.go @@ -593,7 +593,7 @@ func (p *Pod) Inspect() (*define.InspectPodData, error) { return nil, err } infraConfig = new(define.InspectPodInfraConfig) - infraConfig.HostNetwork = !infra.config.ContainerNetworkConfig.UseImageHosts + infraConfig.HostNetwork = p.NetworkMode() == "host" infraConfig.StaticIP = infra.config.ContainerNetworkConfig.StaticIP infraConfig.NoManageResolvConf = infra.config.UseImageResolvConf infraConfig.NoManageHosts = infra.config.UseImageHosts diff --git a/libpod/runtime_pod_linux.go b/libpod/runtime_pod_linux.go index 2bbccfdf6..62ec7df60 100644 --- a/libpod/runtime_pod_linux.go +++ b/libpod/runtime_pod_linux.go @@ -199,10 +199,15 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool, // Go through and lock all containers so we can operate on them all at // once. // First loop also checks that we are ready to go ahead and remove. + containersLocked := true for _, ctr := range ctrs { ctrLock := ctr.lock ctrLock.Lock() - defer ctrLock.Unlock() + defer func() { + if containersLocked { + ctrLock.Unlock() + } + }() // If we're force-removing, no need to check status. if force { @@ -304,6 +309,12 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool, } } + // let's unlock the containers so if there is any cleanup process, it can terminate its execution + for _, ctr := range ctrs { + ctr.lock.Unlock() + } + containersLocked = false + // Remove pod cgroup, if present if p.state.CgroupPath != "" { logrus.Debugf("Removing pod cgroup %s", p.state.CgroupPath) @@ -332,7 +343,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool, } } if err == nil { - if err := conmonCgroup.Delete(); err != nil { + if err = conmonCgroup.Delete(); err != nil { if removalErr == nil { removalErr = errors.Wrapf(err, "error removing pod %s conmon cgroup", p.ID()) } else { diff --git a/libpod/runtime_volume_linux.go b/libpod/runtime_volume_linux.go index 241f6e2f2..f8788e183 100644 --- a/libpod/runtime_volume_linux.go +++ b/libpod/runtime_volume_linux.go @@ -73,7 +73,7 @@ func (r *Runtime) newVolume(options ...VolumeCreateOption) (_ *Volume, deferredE return nil, errors.Wrapf(err, "invalid volume option %s for driver 'local'", key) } } - case "o", "type", "uid", "gid", "size", "inodes": + case "o", "type", "uid", "gid", "size", "inodes", "noquota": // Do nothing, valid keys default: return nil, errors.Wrapf(define.ErrInvalidArg, "invalid mount option %s for driver 'local'", key) @@ -111,23 +111,28 @@ func (r *Runtime) newVolume(options ...VolumeCreateOption) (_ *Volume, deferredE if err := LabelVolumePath(fullVolPath); err != nil { return nil, err } - projectQuotaSupported := false - - q, err := quota.NewControl(r.config.Engine.VolumePath) - if err == nil { - projectQuotaSupported = true - } - quota := quota.Quota{} - if volume.config.Size > 0 || volume.config.Inodes > 0 { - if !projectQuotaSupported { - return nil, errors.New("Volume options size and inodes not supported. Filesystem does not support Project Quota") + if volume.config.DisableQuota { + if volume.config.Size > 0 || volume.config.Inodes > 0 { + return nil, errors.New("volume options size and inodes cannot be used without quota") } - quota.Size = volume.config.Size - quota.Inodes = volume.config.Inodes - } - if projectQuotaSupported { - if err := q.SetQuota(fullVolPath, quota); err != nil { - return nil, errors.Wrapf(err, "failed to set size quota size=%d inodes=%d for volume directory %q", volume.config.Size, volume.config.Inodes, fullVolPath) + } else { + projectQuotaSupported := false + q, err := quota.NewControl(r.config.Engine.VolumePath) + if err == nil { + projectQuotaSupported = true + } + quota := quota.Quota{} + if volume.config.Size > 0 || volume.config.Inodes > 0 { + if !projectQuotaSupported { + return nil, errors.New("volume options size and inodes not supported. Filesystem does not support Project Quota") + } + quota.Size = volume.config.Size + quota.Inodes = volume.config.Inodes + } + if projectQuotaSupported { + if err := q.SetQuota(fullVolPath, quota); err != nil { + return nil, errors.Wrapf(err, "failed to set size quota size=%d inodes=%d for volume directory %q", volume.config.Size, volume.config.Inodes, fullVolPath) + } } } diff --git a/libpod/volume.go b/libpod/volume.go index bffafdc15..ab461a37f 100644 --- a/libpod/volume.go +++ b/libpod/volume.go @@ -52,6 +52,9 @@ type VolumeConfig struct { Size uint64 `json:"size"` // Inodes maximum of the volume. Inodes uint64 `json:"inodes"` + // DisableQuota indicates that the volume should completely disable using any + // quota tracking. + DisableQuota bool `json:"disableQuota,omitempty"` } // VolumeState holds the volume's mutable state. diff --git a/libpod/volume_internal.go b/libpod/volume_internal.go index 9850c2ea1..e0ebb729d 100644 --- a/libpod/volume_internal.go +++ b/libpod/volume_internal.go @@ -52,6 +52,9 @@ func (v *Volume) needsMount() bool { if _, ok := v.config.Options["SIZE"]; ok { index++ } + if _, ok := v.config.Options["NOQUOTA"]; ok { + index++ + } // when uid or gid is set there is also the "o" option // set so we have to ignore this one as well if index > 0 { diff --git a/pkg/domain/infra/abi/parse/parse.go b/pkg/domain/infra/abi/parse/parse.go index 2d1adab74..3bac2ef99 100644 --- a/pkg/domain/infra/abi/parse/parse.go +++ b/pkg/domain/infra/abi/parse/parse.go @@ -73,6 +73,11 @@ func VolumeOptions(opts map[string]string) ([]libpod.VolumeCreateOption, error) finalVal = append(finalVal, o) // set option "GID": "$gid" volumeOptions["GID"] = splitO[1] + case "noquota": + logrus.Debugf("Removing noquota from options and adding WithVolumeDisableQuota") + libpodOptions = append(libpodOptions, libpod.WithVolumeDisableQuota()) + // set option "NOQUOTA": "true" + volumeOptions["NOQUOTA"] = "true" default: finalVal = append(finalVal, o) } diff --git a/pkg/machine/config.go b/pkg/machine/config.go index 5bbaf8c51..9a0ce757a 100644 --- a/pkg/machine/config.go +++ b/pkg/machine/config.go @@ -4,6 +4,8 @@ package machine import ( + errors2 "errors" + "io/ioutil" "net" "net/url" "os" @@ -12,6 +14,7 @@ import ( "github.com/containers/storage/pkg/homedir" "github.com/pkg/errors" + "github.com/sirupsen/logrus" ) type InitOptions struct { @@ -68,7 +71,7 @@ type Download struct { Artifact string CompressionType string Format string - ImageName string `json:"image_name"` + ImageName string LocalPath string LocalUncompressedFile string Sha256sum string @@ -95,7 +98,10 @@ type ListResponse struct { } type SetOptions struct { - Rootful bool + CPUs *uint64 + DiskSize *uint64 + Memory *uint64 + Rootful *bool } type SSHOptions struct { @@ -117,8 +123,9 @@ type InspectOptions struct{} type VM interface { Init(opts InitOptions) (bool, error) + Inspect() (*InspectInfo, error) Remove(name string, opts RemoveOptions) (string, func() error, error) - Set(name string, opts SetOptions) error + Set(name string, opts SetOptions) ([]error, error) SSH(name string, opts SSHOptions) error Start(name string, opts StartOptions) error State(bypass bool) (Status, error) @@ -130,8 +137,14 @@ type DistributionDownload interface { Get() *Download } type InspectInfo struct { - State Status - VM + ConfigPath VMFile + Created time.Time + Image ImageConfig + LastUp time.Time + Name string + Resources ResourceConfig + SSHConfig SSHConfig + State Status } func (rc RemoteConnectionType) MakeSSHURL(host, path, port, userName string) url.URL { @@ -183,3 +196,121 @@ func GetConfDir(vmType string) (string, error) { mkdirErr := os.MkdirAll(confDir, 0755) return confDir, mkdirErr } + +// ResourceConfig describes physical attributes of the machine +type ResourceConfig struct { + // CPUs to be assigned to the VM + CPUs uint64 + // Disk size in gigabytes assigned to the vm + DiskSize uint64 + // Memory in megabytes assigned to the vm + Memory uint64 +} + +const maxSocketPathLength int = 103 + +type VMFile struct { + // Path is the fully qualified path to a file + Path string + // Symlink is a shortened version of Path by using + // a symlink + Symlink *string `json:"symlink,omitempty"` +} + +// GetPath returns the working path for a machinefile. it returns +// the symlink unless one does not exist +func (m *VMFile) GetPath() string { + if m.Symlink == nil { + return m.Path + } + return *m.Symlink +} + +// Delete removes the machinefile symlink (if it exists) and +// the actual path +func (m *VMFile) Delete() error { + if m.Symlink != nil { + if err := os.Remove(*m.Symlink); err != nil && !errors2.Is(err, os.ErrNotExist) { + logrus.Errorf("unable to remove symlink %q", *m.Symlink) + } + } + if err := os.Remove(m.Path); err != nil && !errors2.Is(err, os.ErrNotExist) { + return err + } + return nil +} + +// Read the contents of a given file and return in []bytes +func (m *VMFile) Read() ([]byte, error) { + return ioutil.ReadFile(m.GetPath()) +} + +// NewMachineFile is a constructor for VMFile +func NewMachineFile(path string, symlink *string) (*VMFile, error) { + if len(path) < 1 { + return nil, errors2.New("invalid machine file path") + } + if symlink != nil && len(*symlink) < 1 { + return nil, errors2.New("invalid symlink path") + } + mf := VMFile{Path: path} + if symlink != nil && len(path) > maxSocketPathLength { + if err := mf.makeSymlink(symlink); err != nil && !errors2.Is(err, os.ErrExist) { + return nil, err + } + } + return &mf, nil +} + +// makeSymlink for macOS creates a symlink in $HOME/.podman/ +// for a machinefile like a socket +func (m *VMFile) makeSymlink(symlink *string) error { + homedir, err := os.UserHomeDir() + if err != nil { + return err + } + sl := filepath.Join(homedir, ".podman", *symlink) + // make the symlink dir and throw away if it already exists + if err := os.MkdirAll(filepath.Dir(sl), 0700); err != nil && !errors2.Is(err, os.ErrNotExist) { + return err + } + m.Symlink = &sl + return os.Symlink(m.Path, sl) +} + +type Mount struct { + ReadOnly bool + Source string + Tag string + Target string + Type string +} + +// ImageConfig describes the bootable image for the VM +type ImageConfig struct { + // IgnitionFile is the path to the filesystem where the + // ignition file was written (if needs one) + IgnitionFile VMFile `json:"IgnitionFilePath"` + // ImageStream is the update stream for the image + ImageStream string + // ImageFile is the fq path to + ImagePath VMFile `json:"ImagePath"` +} + +// HostUser describes the host user +type HostUser struct { + // Whether this machine should run in a rootful or rootless manner + Rootful bool + // UID is the numerical id of the user that called machine + UID int +} + +// SSHConfig contains remote access information for SSH +type SSHConfig struct { + // IdentityPath is the fq path to the ssh priv key + IdentityPath string + // SSH port for user networking + Port int + // RemoteUsername of the vm user + RemoteUsername string +} diff --git a/pkg/machine/e2e/config.go b/pkg/machine/e2e/config.go index 7d75ca6bc..c17b840d3 100644 --- a/pkg/machine/e2e/config.go +++ b/pkg/machine/e2e/config.go @@ -131,7 +131,7 @@ func (m *machineTestBuilder) setTimeout(timeout time.Duration) *machineTestBuild func (mb *machineTestBuilder) toQemuInspectInfo() ([]qemuMachineInspectInfo, int, error) { args := []string{"machine", "inspect"} args = append(args, mb.names...) - session, err := runWrapper(mb.podmanBinary, args, defaultTimeout) + session, err := runWrapper(mb.podmanBinary, args, defaultTimeout, true) if err != nil { return nil, -1, err } @@ -140,11 +140,15 @@ func (mb *machineTestBuilder) toQemuInspectInfo() ([]qemuMachineInspectInfo, int return mii, session.ExitCode(), err } +func (m *machineTestBuilder) runWithoutWait() (*machineSession, error) { + return runWrapper(m.podmanBinary, m.cmd, m.timeout, false) +} + func (m *machineTestBuilder) run() (*machineSession, error) { - return runWrapper(m.podmanBinary, m.cmd, m.timeout) + return runWrapper(m.podmanBinary, m.cmd, m.timeout, true) } -func runWrapper(podmanBinary string, cmdArgs []string, timeout time.Duration) (*machineSession, error) { +func runWrapper(podmanBinary string, cmdArgs []string, timeout time.Duration, wait bool) (*machineSession, error) { if len(os.Getenv("DEBUG")) > 0 { cmdArgs = append([]string{"--log-level=debug"}, cmdArgs...) } @@ -156,8 +160,10 @@ func runWrapper(podmanBinary string, cmdArgs []string, timeout time.Duration) (* return nil, err } ms := machineSession{session} - ms.waitWithTimeout(timeout) - fmt.Println("output:", ms.outputToString()) + if wait { + ms.waitWithTimeout(timeout) + fmt.Println("output:", ms.outputToString()) + } return &ms, nil } diff --git a/pkg/machine/e2e/config_set.go b/pkg/machine/e2e/config_set.go new file mode 100644 index 000000000..b310ab1b9 --- /dev/null +++ b/pkg/machine/e2e/config_set.go @@ -0,0 +1,43 @@ +package e2e + +import ( + "strconv" +) + +type setMachine struct { + cpus *uint + diskSize *uint + memory *uint + + cmd []string +} + +func (i *setMachine) buildCmd(m *machineTestBuilder) []string { + cmd := []string{"machine", "set"} + if i.cpus != nil { + cmd = append(cmd, "--cpus", strconv.Itoa(int(*i.cpus))) + } + if i.diskSize != nil { + cmd = append(cmd, "--disk-size", strconv.Itoa(int(*i.diskSize))) + } + if i.memory != nil { + cmd = append(cmd, "--memory", strconv.Itoa(int(*i.memory))) + } + cmd = append(cmd, m.name) + i.cmd = cmd + return cmd +} + +func (i *setMachine) withCPUs(num uint) *setMachine { + i.cpus = &num + return i +} +func (i *setMachine) withDiskSize(size uint) *setMachine { + i.diskSize = &size + return i +} + +func (i *setMachine) withMemory(num uint) *setMachine { + i.memory = &num + return i +} diff --git a/pkg/machine/e2e/init_test.go b/pkg/machine/e2e/init_test.go index 309d460a9..304122738 100644 --- a/pkg/machine/e2e/init_test.go +++ b/pkg/machine/e2e/init_test.go @@ -28,13 +28,13 @@ var _ = Describe("podman machine init", func() { reallyLongName := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" session, err := mb.setName(reallyLongName).setCmd(&i).run() Expect(err).To(BeNil()) - Expect(session.ExitCode()).To(Equal(125)) + Expect(session).To(Exit(125)) }) It("simple init", func() { i := new(initMachine) session, err := mb.setCmd(i.withImagePath(mb.imagePath)).run() Expect(err).To(BeNil()) - Expect(session.ExitCode()).To(Equal(0)) + Expect(session).To(Exit(0)) inspectBefore, ec, err := mb.toQemuInspectInfo() Expect(err).To(BeNil()) @@ -52,7 +52,7 @@ var _ = Describe("podman machine init", func() { i := initMachine{} session, err := mb.setCmd(i.withImagePath(mb.imagePath)).run() Expect(err).To(BeNil()) - Expect(session.ExitCode()).To(Equal(0)) + Expect(session).To(Exit(0)) inspectBefore, ec, err := mb.toQemuInspectInfo() Expect(ec).To(BeZero()) diff --git a/pkg/machine/e2e/inspect_test.go b/pkg/machine/e2e/inspect_test.go index 30d810b8f..e282dd21d 100644 --- a/pkg/machine/e2e/inspect_test.go +++ b/pkg/machine/e2e/inspect_test.go @@ -7,6 +7,7 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + . "github.com/onsi/gomega/gexec" ) var _ = Describe("podman machine stop", func() { @@ -27,24 +28,24 @@ var _ = Describe("podman machine stop", func() { reallyLongName := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" session, err := mb.setName(reallyLongName).setCmd(&i).run() Expect(err).To(BeNil()) - Expect(session.ExitCode()).To(Equal(125)) + Expect(session).To(Exit(125)) }) It("inspect two machines", func() { i := new(initMachine) foo1, err := mb.setName("foo1").setCmd(i.withImagePath(mb.imagePath)).run() Expect(err).To(BeNil()) - Expect(foo1.ExitCode()).To(Equal(0)) + Expect(foo1).To(Exit(0)) ii := new(initMachine) foo2, err := mb.setName("foo2").setCmd(ii.withImagePath(mb.imagePath)).run() Expect(err).To(BeNil()) - Expect(foo2.ExitCode()).To(Equal(0)) + Expect(foo2).To(Exit(0)) inspect := new(inspectMachine) inspectSession, err := mb.setName("foo1").setCmd(inspect).run() Expect(err).To(BeNil()) - Expect(inspectSession.ExitCode()).To(Equal(0)) + Expect(inspectSession).To(Exit(0)) type fakeInfos struct { Status string diff --git a/pkg/machine/e2e/list_test.go b/pkg/machine/e2e/list_test.go index e7a439945..0ce9063f9 100644 --- a/pkg/machine/e2e/list_test.go +++ b/pkg/machine/e2e/list_test.go @@ -70,6 +70,33 @@ var _ = Describe("podman machine list", func() { Expect(util.StringInSlice(name1, listNames)).To(BeTrue()) Expect(util.StringInSlice(name2, listNames)).To(BeTrue()) }) + + It("list machine: check if running while starting", func() { + i := new(initMachine) + session, err := mb.setCmd(i.withImagePath(mb.imagePath)).run() + Expect(err).To(BeNil()) + Expect(session).To(Exit(0)) + s := new(startMachine) + startSession, err := mb.setCmd(s).runWithoutWait() + Expect(err).To(BeNil()) + l := new(listMachine) + for { // needs to be infinite because we need to check if running when inspect returns to avoid race conditions. + listSession, err := mb.setCmd(l).run() + Expect(listSession).To(Exit(0)) + Expect(err).To(BeNil()) + if startSession.ExitCode() == -1 { + Expect(listSession.outputToString()).NotTo(ContainSubstring("Currently running")) + } else { + break + } + } + Expect(startSession).To(Exit(0)) + listSession, err := mb.setCmd(l).run() + Expect(listSession).To(Exit(0)) + Expect(err).To(BeNil()) + Expect(listSession.outputToString()).To(ContainSubstring("Currently running")) + Expect(listSession.outputToString()).NotTo(ContainSubstring("Less than a second ago")) // check to make sure time created is accurate + }) }) func stripAsterisk(sl []string) { diff --git a/pkg/machine/e2e/rm_test.go b/pkg/machine/e2e/rm_test.go index 011da5dde..43b8c594c 100644 --- a/pkg/machine/e2e/rm_test.go +++ b/pkg/machine/e2e/rm_test.go @@ -3,6 +3,7 @@ package e2e import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + . "github.com/onsi/gomega/gexec" ) var _ = Describe("podman machine rm", func() { @@ -23,14 +24,14 @@ var _ = Describe("podman machine rm", func() { reallyLongName := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" session, err := mb.setName(reallyLongName).setCmd(&i).run() Expect(err).To(BeNil()) - Expect(session.ExitCode()).To(Equal(125)) + Expect(session).To(Exit(125)) }) It("Remove machine", func() { i := new(initMachine) session, err := mb.setCmd(i.withImagePath(mb.imagePath)).run() Expect(err).To(BeNil()) - Expect(session.ExitCode()).To(Equal(0)) + Expect(session).To(Exit(0)) rm := rmMachine{} _, err = mb.setCmd(rm.withForce()).run() Expect(err).To(BeNil()) @@ -46,18 +47,18 @@ var _ = Describe("podman machine rm", func() { i := new(initMachine) session, err := mb.setCmd(i.withImagePath(mb.imagePath).withNow()).run() Expect(err).To(BeNil()) - Expect(session.ExitCode()).To(Equal(0)) + Expect(session).To(Exit(0)) rm := new(rmMachine) // Removing a running machine should fail stop, err := mb.setCmd(rm).run() Expect(err).To(BeNil()) - Expect(stop.ExitCode()).To(Equal(125)) + Expect(stop).To(Exit(125)) // Removing again with force stopAgain, err := mb.setCmd(rm.withForce()).run() Expect(err).To(BeNil()) - Expect(stopAgain.ExitCode()).To(BeZero()) + Expect(stopAgain).To(Exit(0)) // Inspect to be dead sure _, ec, err := mb.toQemuInspectInfo() diff --git a/pkg/machine/e2e/set_test.go b/pkg/machine/e2e/set_test.go new file mode 100644 index 000000000..9af29c560 --- /dev/null +++ b/pkg/machine/e2e/set_test.go @@ -0,0 +1,134 @@ +package e2e + +import ( + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + . "github.com/onsi/gomega/gexec" +) + +var _ = Describe("podman machine set", func() { + var ( + mb *machineTestBuilder + testDir string + ) + + BeforeEach(func() { + testDir, mb = setup() + }) + AfterEach(func() { + teardown(originalHomeDir, testDir, mb) + }) + + It("set machine cpus", func() { + name := randomString(12) + i := new(initMachine) + session, err := mb.setName(name).setCmd(i.withImagePath(mb.imagePath)).run() + Expect(err).To(BeNil()) + Expect(session).To(Exit(0)) + + set := setMachine{} + setSession, err := mb.setName(name).setCmd(set.withCPUs(2)).run() + Expect(err).To(BeNil()) + Expect(setSession).To(Exit(0)) + + s := new(startMachine) + startSession, err := mb.setCmd(s).run() + Expect(err).To(BeNil()) + Expect(startSession).To(Exit(0)) + + ssh2 := sshMachine{} + sshSession2, err := mb.setName(name).setCmd(ssh2.withSSHComand([]string{"lscpu", "|", "grep", "\"CPU(s):\"", "|", "head", "-1"})).run() + Expect(err).To(BeNil()) + Expect(sshSession2).To(Exit(0)) + Expect(sshSession2.outputToString()).To(ContainSubstring("2")) + + // Setting a running machine results in 125 + runner, err := mb.setName(name).setCmd(set.withCPUs(4)).run() + Expect(err).To(BeNil()) + Expect(runner).To(Exit(125)) + }) + + It("increase machine disk size", func() { + name := randomString(12) + i := new(initMachine) + session, err := mb.setName(name).setCmd(i.withImagePath(mb.imagePath)).run() + Expect(err).To(BeNil()) + Expect(session).To(Exit(0)) + + set := setMachine{} + setSession, err := mb.setName(name).setCmd(set.withDiskSize(102)).run() + Expect(err).To(BeNil()) + Expect(setSession).To(Exit(0)) + + // shrinking disk size iss verboten + shrink, err := mb.setName(name).setCmd(set.withDiskSize(5)).run() + Expect(err).To(BeNil()) + Expect(shrink).To(Exit(125)) + + s := new(startMachine) + startSession, err := mb.setCmd(s).run() + Expect(err).To(BeNil()) + Expect(startSession).To(Exit(0)) + + ssh2 := sshMachine{} + sshSession2, err := mb.setName(name).setCmd(ssh2.withSSHComand([]string{"sudo", "fdisk", "-l", "|", "grep", "Disk"})).run() + Expect(err).To(BeNil()) + Expect(sshSession2).To(Exit(0)) + Expect(sshSession2.outputToString()).To(ContainSubstring("102 GiB")) + }) + + It("set machine ram", func() { + name := randomString(12) + i := new(initMachine) + session, err := mb.setName(name).setCmd(i.withImagePath(mb.imagePath)).run() + Expect(err).To(BeNil()) + Expect(session).To(Exit(0)) + + set := setMachine{} + setSession, err := mb.setName(name).setCmd(set.withMemory(4000)).run() + Expect(err).To(BeNil()) + Expect(setSession).To(Exit(0)) + + s := new(startMachine) + startSession, err := mb.setCmd(s).run() + Expect(err).To(BeNil()) + Expect(startSession).To(Exit(0)) + + ssh2 := sshMachine{} + sshSession2, err := mb.setName(name).setCmd(ssh2.withSSHComand([]string{"cat", "/proc/meminfo", "|", "numfmt", "--field", "2", "--from-unit=Ki", "--to-unit=Mi", "|", "sed", "'s/ kB/M/g'", "|", "grep", "MemTotal"})).run() + Expect(err).To(BeNil()) + Expect(sshSession2).To(Exit(0)) + Expect(sshSession2.outputToString()).To(ContainSubstring("3824")) + }) + + It("no settings should change if no flags", func() { + name := randomString(12) + i := new(initMachine) + session, err := mb.setName(name).setCmd(i.withImagePath(mb.imagePath)).run() + Expect(err).To(BeNil()) + Expect(session).To(Exit(0)) + + set := setMachine{} + setSession, err := mb.setName(name).setCmd(&set).run() + Expect(err).To(BeNil()) + Expect(setSession).To(Exit(0)) + + s := new(startMachine) + startSession, err := mb.setCmd(s).run() + Expect(err).To(BeNil()) + Expect(startSession).To(Exit(0)) + + ssh2 := sshMachine{} + sshSession2, err := mb.setName(name).setCmd(ssh2.withSSHComand([]string{"lscpu", "|", "grep", "\"CPU(s):\"", "|", "head", "-1"})).run() + Expect(err).To(BeNil()) + Expect(sshSession2).To(Exit(0)) + Expect(sshSession2.outputToString()).To(ContainSubstring("1")) + + ssh3 := sshMachine{} + sshSession3, err := mb.setName(name).setCmd(ssh3.withSSHComand([]string{"sudo", "fdisk", "-l", "|", "grep", "Disk"})).run() + Expect(err).To(BeNil()) + Expect(sshSession3).To(Exit(0)) + Expect(sshSession3.outputToString()).To(ContainSubstring("100 GiB")) + }) + +}) diff --git a/pkg/machine/e2e/ssh_test.go b/pkg/machine/e2e/ssh_test.go index 90296fa10..155d39a64 100644 --- a/pkg/machine/e2e/ssh_test.go +++ b/pkg/machine/e2e/ssh_test.go @@ -3,6 +3,7 @@ package e2e import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + . "github.com/onsi/gomega/gexec" ) var _ = Describe("podman machine ssh", func() { @@ -23,7 +24,7 @@ var _ = Describe("podman machine ssh", func() { ssh := sshMachine{} session, err := mb.setName(name).setCmd(ssh).run() Expect(err).To(BeNil()) - Expect(session.ExitCode()).To(Equal(125)) + Expect(session).To(Exit(125)) // TODO seems like stderr is not being returned; re-enabled when fixed //Expect(session.outputToString()).To(ContainSubstring("not exist")) }) @@ -33,14 +34,14 @@ var _ = Describe("podman machine ssh", func() { i := new(initMachine) session, err := mb.setName(name).setCmd(i.withImagePath(mb.imagePath)).run() Expect(err).To(BeNil()) - Expect(session.ExitCode()).To(Equal(0)) + Expect(session).To(Exit(0)) ssh := sshMachine{} sshSession, err := mb.setName(name).setCmd(ssh).run() Expect(err).To(BeNil()) // TODO seems like stderr is not being returned; re-enabled when fixed //Expect(sshSession.outputToString()).To(ContainSubstring("is not running")) - Expect(sshSession.ExitCode()).To(Equal(125)) + Expect(sshSession).To(Exit(125)) }) It("ssh to running machine and check os-type", func() { @@ -48,12 +49,12 @@ var _ = Describe("podman machine ssh", func() { i := new(initMachine) session, err := mb.setName(name).setCmd(i.withImagePath(mb.imagePath).withNow()).run() Expect(err).To(BeNil()) - Expect(session.ExitCode()).To(Equal(0)) + Expect(session).To(Exit(0)) ssh := sshMachine{} sshSession, err := mb.setName(name).setCmd(ssh.withSSHComand([]string{"cat", "/etc/os-release"})).run() Expect(err).To(BeNil()) - Expect(sshSession.ExitCode()).To(Equal(0)) + Expect(sshSession).To(Exit(0)) Expect(sshSession.outputToString()).To(ContainSubstring("Fedora CoreOS")) }) }) diff --git a/pkg/machine/e2e/start_test.go b/pkg/machine/e2e/start_test.go index 1cda0e8f1..1de66eb9a 100644 --- a/pkg/machine/e2e/start_test.go +++ b/pkg/machine/e2e/start_test.go @@ -4,6 +4,7 @@ import ( "github.com/containers/podman/v4/pkg/machine" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + . "github.com/onsi/gomega/gexec" ) var _ = Describe("podman machine start", func() { @@ -22,11 +23,11 @@ var _ = Describe("podman machine start", func() { i := new(initMachine) session, err := mb.setCmd(i.withImagePath(mb.imagePath)).run() Expect(err).To(BeNil()) - Expect(session.ExitCode()).To(Equal(0)) + Expect(session).To(Exit(0)) s := new(startMachine) startSession, err := mb.setCmd(s).run() Expect(err).To(BeNil()) - Expect(startSession.ExitCode()).To(Equal(0)) + Expect(startSession).To(Exit(0)) info, ec, err := mb.toQemuInspectInfo() Expect(err).To(BeNil()) diff --git a/pkg/machine/e2e/stop_test.go b/pkg/machine/e2e/stop_test.go index 5dee6a345..0c27045a6 100644 --- a/pkg/machine/e2e/stop_test.go +++ b/pkg/machine/e2e/stop_test.go @@ -3,6 +3,7 @@ package e2e import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + . "github.com/onsi/gomega/gexec" ) var _ = Describe("podman machine stop", func() { @@ -23,24 +24,24 @@ var _ = Describe("podman machine stop", func() { reallyLongName := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" session, err := mb.setName(reallyLongName).setCmd(&i).run() Expect(err).To(BeNil()) - Expect(session.ExitCode()).To(Equal(125)) + Expect(session).To(Exit(125)) }) It("Stop running machine", func() { i := new(initMachine) session, err := mb.setCmd(i.withImagePath(mb.imagePath).withNow()).run() Expect(err).To(BeNil()) - Expect(session.ExitCode()).To(Equal(0)) + Expect(session).To(Exit(0)) stop := new(stopMachine) // Removing a running machine should fail stopSession, err := mb.setCmd(stop).run() Expect(err).To(BeNil()) - Expect(stopSession.ExitCode()).To(Equal(0)) + Expect(stopSession).To(Exit(0)) // Stopping it again should not result in an error stopAgain, err := mb.setCmd(stop).run() Expect(err).To(BeNil()) - Expect(stopAgain.ExitCode()).To(BeZero()) + Expect(stopAgain).To(Exit((0))) }) }) diff --git a/pkg/machine/qemu/config.go b/pkg/machine/qemu/config.go index 9473eef6f..56c95e3b3 100644 --- a/pkg/machine/qemu/config.go +++ b/pkg/machine/qemu/config.go @@ -4,13 +4,9 @@ package qemu import ( - "errors" - "io/ioutil" - "os" - "path/filepath" "time" - "github.com/sirupsen/logrus" + "github.com/containers/podman/v4/pkg/machine" ) const ( @@ -23,7 +19,7 @@ const ( Stable string = "stable" // Max length of fully qualified socket path - maxSocketPathLength int = 103 + ) type Provider struct{} @@ -36,7 +32,7 @@ type MachineVMV1 struct { // The command line representation of the qemu command CmdLine []string // Mounts is the list of remote filesystems to mount - Mounts []Mount + Mounts []machine.Mount // IdentityPath is the fq path to the ssh priv key IdentityPath string // IgnitionFilePath is the fq path to the .ign file @@ -65,27 +61,27 @@ type MachineVMV1 struct { type MachineVM struct { // ConfigPath is the path to the configuration file - ConfigPath MachineFile + ConfigPath machine.VMFile // The command line representation of the qemu command CmdLine []string // HostUser contains info about host user - HostUser + machine.HostUser // ImageConfig describes the bootable image - ImageConfig + machine.ImageConfig // Mounts is the list of remote filesystems to mount - Mounts []Mount + Mounts []machine.Mount // Name of VM Name string // PidFilePath is the where the PID file lives - PidFilePath MachineFile + PidFilePath machine.VMFile // QMPMonitor is the qemu monitor object for sending commands QMPMonitor Monitor // ReadySocket tells host when vm is booted - ReadySocket MachineFile + ReadySocket machine.VMFile // ResourceConfig is physical attrs of the VM - ResourceConfig + machine.ResourceConfig // SSHConfig for accessing the remote vm - SSHConfig + machine.SSHConfig // Starting tells us whether the machine is running or if we have just dialed it to start it Starting bool // Created contains the original created time instead of querying the file mod time @@ -94,59 +90,6 @@ type MachineVM struct { LastUp time.Time } -// ImageConfig describes the bootable image for the VM -type ImageConfig struct { - IgnitionFilePath MachineFile - // ImageStream is the update stream for the image - ImageStream string - // ImagePath is the fq path to - ImagePath MachineFile -} - -// HostUser describes the host user -type HostUser struct { - // Whether this machine should run in a rootful or rootless manner - Rootful bool - // UID is the numerical id of the user that called machine - UID int -} - -// SSHConfig contains remote access information for SSH -type SSHConfig struct { - // IdentityPath is the fq path to the ssh priv key - IdentityPath string - // SSH port for user networking - Port int - // RemoteUsername of the vm user - RemoteUsername string -} - -// ResourceConfig describes physical attributes of the machine -type ResourceConfig struct { - // CPUs to be assigned to the VM - CPUs uint64 - // Memory in megabytes assigned to the vm - Memory uint64 - // Disk size in gigabytes assigned to the vm - DiskSize uint64 -} - -type MachineFile struct { - // Path is the fully qualified path to a file - Path string - // Symlink is a shortened version of Path by using - // a symlink - Symlink *string -} - -type Mount struct { - Type string - Tag string - Source string - Target string - ReadOnly bool -} - type Monitorv1 struct { // Address portion of the qmp monitor (/tmp/tmp.sock) Address string @@ -158,7 +101,7 @@ type Monitorv1 struct { type Monitor struct { // Address portion of the qmp monitor (/tmp/tmp.sock) - Address MachineFile + Address machine.VMFile // Network portion of the qmp monitor (unix) Network string // Timeout in seconds for qmp monitor transactions @@ -170,64 +113,3 @@ var ( // qmp monitor interactions. defaultQMPTimeout = 2 * time.Second ) - -// GetPath returns the working path for a machinefile. it returns -// the symlink unless one does not exist -func (m *MachineFile) GetPath() string { - if m.Symlink == nil { - return m.Path - } - return *m.Symlink -} - -// Delete removes the machinefile symlink (if it exists) and -// the actual path -func (m *MachineFile) Delete() error { - if m.Symlink != nil { - if err := os.Remove(*m.Symlink); err != nil && !errors.Is(err, os.ErrNotExist) { - logrus.Errorf("unable to remove symlink %q", *m.Symlink) - } - } - if err := os.Remove(m.Path); err != nil && !errors.Is(err, os.ErrNotExist) { - return err - } - return nil -} - -// Read the contents of a given file and return in []bytes -func (m *MachineFile) Read() ([]byte, error) { - return ioutil.ReadFile(m.GetPath()) -} - -// NewMachineFile is a constructor for MachineFile -func NewMachineFile(path string, symlink *string) (*MachineFile, error) { - if len(path) < 1 { - return nil, errors.New("invalid machine file path") - } - if symlink != nil && len(*symlink) < 1 { - return nil, errors.New("invalid symlink path") - } - mf := MachineFile{Path: path} - if symlink != nil && len(path) > maxSocketPathLength { - if err := mf.makeSymlink(symlink); err != nil && !errors.Is(err, os.ErrExist) { - return nil, err - } - } - return &mf, nil -} - -// makeSymlink for macOS creates a symlink in $HOME/.podman/ -// for a machinefile like a socket -func (m *MachineFile) makeSymlink(symlink *string) error { - homedir, err := os.UserHomeDir() - if err != nil { - return err - } - sl := filepath.Join(homedir, ".podman", *symlink) - // make the symlink dir and throw away if it already exists - if err := os.MkdirAll(filepath.Dir(sl), 0700); err != nil && !errors.Is(err, os.ErrNotExist) { - return err - } - m.Symlink = &sl - return os.Symlink(m.Path, sl) -} diff --git a/pkg/machine/qemu/config_test.go b/pkg/machine/qemu/config_test.go index 264de9ae8..0fbb5b3bf 100644 --- a/pkg/machine/qemu/config_test.go +++ b/pkg/machine/qemu/config_test.go @@ -6,6 +6,7 @@ import ( "reflect" "testing" + "github.com/containers/podman/v4/pkg/machine" "github.com/containers/podman/v4/test/utils" ) @@ -37,7 +38,7 @@ func TestMachineFile_GetPath(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - m := &MachineFile{ + m := &machine.VMFile{ Path: tt.fields.Path, //nolint: scopelint Symlink: tt.fields.Symlink, //nolint: scopelint } @@ -73,7 +74,7 @@ func TestNewMachineFile(t *testing.T) { sym := "my.sock" longSym := filepath.Join(homedir, ".podman", sym) - m := MachineFile{ + m := machine.VMFile{ Path: p, Symlink: nil, } @@ -84,7 +85,7 @@ func TestNewMachineFile(t *testing.T) { tests := []struct { name string args args - want *MachineFile + want *machine.VMFile wantErr bool }{ { @@ -96,7 +97,7 @@ func TestNewMachineFile(t *testing.T) { { name: "Good with short symlink", args: args{p, &sym}, - want: &MachineFile{p, nil}, + want: &machine.VMFile{Path: p}, wantErr: false, }, { @@ -114,14 +115,14 @@ func TestNewMachineFile(t *testing.T) { { name: "Good with long symlink", args: args{longp, &sym}, - want: &MachineFile{longp, &longSym}, + want: &machine.VMFile{Path: longp, Symlink: &longSym}, wantErr: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := NewMachineFile(tt.args.path, tt.args.symlink) //nolint: scopelint - if (err != nil) != tt.wantErr { //nolint: scopelint + got, err := machine.NewMachineFile(tt.args.path, tt.args.symlink) //nolint: scopelint + if (err != nil) != tt.wantErr { //nolint: scopelint t.Errorf("NewMachineFile() error = %v, wantErr %v", err, tt.wantErr) //nolint: scopelint return } diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go index 5481bad29..35eea5fb4 100644 --- a/pkg/machine/qemu/machine.go +++ b/pkg/machine/qemu/machine.go @@ -71,12 +71,12 @@ func (p *Provider) NewMachine(opts machine.InitOptions) (machine.VM, error) { if len(opts.Name) > 0 { vm.Name = opts.Name } - ignitionFile, err := NewMachineFile(filepath.Join(vmConfigDir, vm.Name+".ign"), nil) + ignitionFile, err := machine.NewMachineFile(filepath.Join(vmConfigDir, vm.Name+".ign"), nil) if err != nil { return nil, err } - vm.IgnitionFilePath = *ignitionFile - imagePath, err := NewMachineFile(opts.ImagePath, nil) + vm.IgnitionFile = *ignitionFile + imagePath, err := machine.NewMachineFile(opts.ImagePath, nil) if err != nil { return nil, err } @@ -105,14 +105,13 @@ func (p *Provider) NewMachine(opts machine.InitOptions) (machine.VM, error) { if err != nil { return nil, err } - cmd := []string{execPath} // Add memory cmd = append(cmd, []string{"-m", strconv.Itoa(int(vm.Memory))}...) // Add cpus cmd = append(cmd, []string{"-smp", strconv.Itoa(int(vm.CPUs))}...) // Add ignition file - cmd = append(cmd, []string{"-fw_cfg", "name=opt/com.coreos/config,file=" + vm.IgnitionFilePath.GetPath()}...) + cmd = append(cmd, []string{"-fw_cfg", "name=opt/com.coreos/config,file=" + vm.IgnitionFile.GetPath()}...) // Add qmp socket monitor, err := NewQMPMonitor("unix", vm.Name, defaultQMPTimeout) if err != nil { @@ -158,9 +157,9 @@ func migrateVM(configPath string, config []byte, vm *MachineVM) error { return err } - pidFilePath := MachineFile{Path: pidFile} + pidFilePath := machine.VMFile{Path: pidFile} qmpMonitor := Monitor{ - Address: MachineFile{Path: old.QMPMonitor.Address}, + Address: machine.VMFile{Path: old.QMPMonitor.Address}, Network: old.QMPMonitor.Network, Timeout: old.QMPMonitor.Timeout, } @@ -169,18 +168,18 @@ func migrateVM(configPath string, config []byte, vm *MachineVM) error { return err } virtualSocketPath := filepath.Join(socketPath, "podman", vm.Name+"_ready.sock") - readySocket := MachineFile{Path: virtualSocketPath} + readySocket := machine.VMFile{Path: virtualSocketPath} - vm.HostUser = HostUser{} - vm.ImageConfig = ImageConfig{} - vm.ResourceConfig = ResourceConfig{} - vm.SSHConfig = SSHConfig{} + vm.HostUser = machine.HostUser{} + vm.ImageConfig = machine.ImageConfig{} + vm.ResourceConfig = machine.ResourceConfig{} + vm.SSHConfig = machine.SSHConfig{} - ignitionFilePath, err := NewMachineFile(old.IgnitionFilePath, nil) + ignitionFilePath, err := machine.NewMachineFile(old.IgnitionFilePath, nil) if err != nil { return err } - imagePath, err := NewMachineFile(old.ImagePath, nil) + imagePath, err := machine.NewMachineFile(old.ImagePath, nil) if err != nil { return err } @@ -194,7 +193,7 @@ func migrateVM(configPath string, config []byte, vm *MachineVM) error { vm.CmdLine = old.CmdLine vm.DiskSize = old.DiskSize vm.IdentityPath = old.IdentityPath - vm.IgnitionFilePath = *ignitionFilePath + vm.IgnitionFile = *ignitionFilePath vm.ImagePath = *imagePath vm.ImageStream = old.ImageStream vm.Memory = old.Memory @@ -229,7 +228,7 @@ func migrateVM(configPath string, config []byte, vm *MachineVM) error { // and returns a vm instance func (p *Provider) LoadVMByName(name string) (machine.VM, error) { vm := &MachineVM{Name: name} - vm.HostUser = HostUser{UID: -1} // posix reserves -1, so use it to signify undefined + vm.HostUser = machine.HostUser{UID: -1} // posix reserves -1, so use it to signify undefined if err := vm.update(); err != nil { return nil, err } @@ -270,7 +269,7 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) { if err != nil { return false, err } - uncompressedFile, err := NewMachineFile(dd.Get().LocalUncompressedFile, nil) + uncompressedFile, err := machine.NewMachineFile(dd.Get().LocalUncompressedFile, nil) if err != nil { return false, err } @@ -286,7 +285,7 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) { if err != nil { return false, err } - imagePath, err := NewMachineFile(g.Get().LocalUncompressedFile, nil) + imagePath, err := machine.NewMachineFile(g.Get().LocalUncompressedFile, nil) if err != nil { return false, err } @@ -308,7 +307,7 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) { return false, err } - mounts := []Mount{} + mounts := []machine.Mount{} for i, volume := range opts.Volumes { tag := fmt.Sprintf("vol%d", i) paths := strings.SplitN(volume, ":", 3) @@ -338,7 +337,7 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) { virtfsOptions += ",readonly" } v.CmdLine = append(v.CmdLine, []string{"-virtfs", virtfsOptions}...) - mounts = append(mounts, Mount{Type: MountType9p, Tag: tag, Source: source, Target: target, ReadOnly: readonly}) + mounts = append(mounts, machine.Mount{Type: MountType9p, Tag: tag, Source: source, Target: target, ReadOnly: readonly}) } } v.Mounts = mounts @@ -390,25 +389,9 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) { if err != nil { return false, err } - // Resize the disk image to input disk size - // only if the virtualdisk size is less than - // the given disk size - if opts.DiskSize<<(10*3) > originalDiskSize { - // Find the qemu executable - cfg, err := config.Default() - if err != nil { - return false, err - } - resizePath, err := cfg.FindHelperBinary("qemu-img", true) - if err != nil { - return false, err - } - resize := exec.Command(resizePath, []string{"resize", v.getImageFile(), strconv.Itoa(int(opts.DiskSize)) + "G"}...) - resize.Stdout = os.Stdout - resize.Stderr = os.Stderr - if err := resize.Run(); err != nil { - return false, errors.Errorf("resizing image: %q", err) - } + + if err := v.resizeDisk(opts.DiskSize, originalDiskSize>>(10*3)); err != nil { + return false, err } // If the user provides an ignition file, we need to // copy it into the conf dir @@ -432,14 +415,14 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) { return err == nil, err } -func (v *MachineVM) Set(_ string, opts machine.SetOptions) error { - if v.Rootful == opts.Rootful { - return nil - } +func (v *MachineVM) Set(_ string, opts machine.SetOptions) ([]error, error) { + // If one setting fails to be applied, the others settings will not fail and still be applied. + // The setting(s) that failed to be applied will have its errors returned in setErrors + var setErrors []error state, err := v.State(false) if err != nil { - return err + return setErrors, err } if state == machine.Running { @@ -447,26 +430,45 @@ func (v *MachineVM) Set(_ string, opts machine.SetOptions) error { if v.Name != machine.DefaultMachineName { suffix = " " + v.Name } - return errors.Errorf("cannot change setting while the vm is running, run 'podman machine stop%s' first", suffix) + return setErrors, errors.Errorf("cannot change settings while the vm is running, run 'podman machine stop%s' first", suffix) } - changeCon, err := machine.AnyConnectionDefault(v.Name, v.Name+"-root") - if err != nil { - return err + if opts.Rootful != nil && v.Rootful != *opts.Rootful { + if err := v.setRootful(*opts.Rootful); err != nil { + setErrors = append(setErrors, errors.Wrapf(err, "failed to set rootful option")) + } else { + v.Rootful = *opts.Rootful + } } - if changeCon { - newDefault := v.Name - if opts.Rootful { - newDefault += "-root" - } - if err := machine.ChangeDefault(newDefault); err != nil { - return err + if opts.CPUs != nil && v.CPUs != *opts.CPUs { + v.CPUs = *opts.CPUs + v.editCmdLine("-smp", strconv.Itoa(int(v.CPUs))) + } + + if opts.Memory != nil && v.Memory != *opts.Memory { + v.Memory = *opts.Memory + v.editCmdLine("-m", strconv.Itoa(int(v.Memory))) + } + + if opts.DiskSize != nil && v.DiskSize != *opts.DiskSize { + if err := v.resizeDisk(*opts.DiskSize, v.DiskSize); err != nil { + setErrors = append(setErrors, errors.Wrapf(err, "failed to resize disk")) + } else { + v.DiskSize = *opts.DiskSize } } - v.Rootful = opts.Rootful - return v.writeConfig() + err = v.writeConfig() + if err != nil { + setErrors = append(setErrors, err) + } + + if len(setErrors) > 0 { + return setErrors, setErrors[0] + } + + return setErrors, nil } // Start executes the qemu command line and forks it @@ -806,7 +808,7 @@ func NewQMPMonitor(network, name string, timeout time.Duration) (Monitor, error) if timeout == 0 { timeout = defaultQMPTimeout } - address, err := NewMachineFile(filepath.Join(rtDir, "qmp_"+name+".sock"), nil) + address, err := machine.NewMachineFile(filepath.Join(rtDir, "qmp_"+name+".sock"), nil) if err != nil { return Monitor{}, err } @@ -1063,11 +1065,11 @@ func getVMInfos() ([]*machine.ListResponse, error) { return err } - if !vm.LastUp.IsZero() { + if !vm.LastUp.IsZero() { // this means we have already written a time to the config listEntry.LastUp = vm.LastUp - } else { + } else { // else we just created the machine AKA last up = created time listEntry.LastUp = vm.Created - vm.Created = time.Now() + vm.LastUp = listEntry.LastUp if err := vm.writeConfig(); err != nil { return err } @@ -1235,14 +1237,14 @@ func (v *MachineVM) userGlobalSocketLink() (string, error) { return filepath.Join(filepath.Dir(path), "podman.sock"), err } -func (v *MachineVM) forwardSocketPath() (*MachineFile, error) { +func (v *MachineVM) forwardSocketPath() (*machine.VMFile, error) { sockName := "podman.sock" path, err := machine.GetDataDir(v.Name) if err != nil { logrus.Errorf("Resolving data dir: %s", err.Error()) return nil, err } - return NewMachineFile(filepath.Join(path, sockName), &sockName) + return machine.NewMachineFile(filepath.Join(path, sockName), &sockName) } func (v *MachineVM) setConfigPath() error { @@ -1251,7 +1253,7 @@ func (v *MachineVM) setConfigPath() error { return err } - configPath, err := NewMachineFile(filepath.Join(vmConfigDir, v.Name)+".json", nil) + configPath, err := machine.NewMachineFile(filepath.Join(vmConfigDir, v.Name)+".json", nil) if err != nil { return err } @@ -1265,7 +1267,7 @@ func (v *MachineVM) setReadySocket() error { if err != nil { return err } - virtualSocketPath, err := NewMachineFile(filepath.Join(rtPath, "podman", readySocketName), &readySocketName) + virtualSocketPath, err := machine.NewMachineFile(filepath.Join(rtPath, "podman", readySocketName), &readySocketName) if err != nil { return err } @@ -1283,7 +1285,7 @@ func (v *MachineVM) setPIDSocket() error { } pidFileName := fmt.Sprintf("%s.pid", v.Name) socketDir := filepath.Join(rtPath, "podman") - pidFilePath, err := NewMachineFile(filepath.Join(socketDir, pidFileName), &pidFileName) + pidFilePath, err := machine.NewMachineFile(filepath.Join(socketDir, pidFileName), &pidFileName) if err != nil { return err } @@ -1460,5 +1462,85 @@ func (v *MachineVM) getImageFile() string { // getIgnitionFile wrapper returns the path to the ignition file func (v *MachineVM) getIgnitionFile() string { - return v.IgnitionFilePath.GetPath() + return v.IgnitionFile.GetPath() +} + +// Inspect returns verbose detail about the machine +func (v *MachineVM) Inspect() (*machine.InspectInfo, error) { + state, err := v.State(false) + if err != nil { + return nil, err + } + + return &machine.InspectInfo{ + ConfigPath: v.ConfigPath, + Created: v.Created, + Image: v.ImageConfig, + LastUp: v.LastUp, + Name: v.Name, + Resources: v.ResourceConfig, + SSHConfig: v.SSHConfig, + State: state, + }, nil +} + +// resizeDisk increases the size of the machine's disk in GB. +func (v *MachineVM) resizeDisk(diskSize uint64, oldSize uint64) error { + // Resize the disk image to input disk size + // only if the virtualdisk size is less than + // the given disk size + if diskSize < oldSize { + return errors.Errorf("new disk size must be larger than current disk size: %vGB", oldSize) + } + + // Find the qemu executable + cfg, err := config.Default() + if err != nil { + return err + } + resizePath, err := cfg.FindHelperBinary("qemu-img", true) + if err != nil { + return err + } + resize := exec.Command(resizePath, []string{"resize", v.getImageFile(), strconv.Itoa(int(diskSize)) + "G"}...) + resize.Stdout = os.Stdout + resize.Stderr = os.Stderr + if err := resize.Run(); err != nil { + return errors.Errorf("resizing image: %q", err) + } + + return nil +} + +func (v *MachineVM) setRootful(rootful bool) error { + changeCon, err := machine.AnyConnectionDefault(v.Name, v.Name+"-root") + if err != nil { + return err + } + + if changeCon { + newDefault := v.Name + if rootful { + newDefault += "-root" + } + err := machine.ChangeDefault(newDefault) + if err != nil { + return err + } + } + return nil +} + +func (v *MachineVM) editCmdLine(flag string, value string) { + found := false + for i, val := range v.CmdLine { + if val == flag { + found = true + v.CmdLine[i+1] = value + break + } + } + if !found { + v.CmdLine = append(v.CmdLine, []string{flag, value}...) + } } diff --git a/pkg/machine/qemu/machine_test.go b/pkg/machine/qemu/machine_test.go new file mode 100644 index 000000000..62ca6068a --- /dev/null +++ b/pkg/machine/qemu/machine_test.go @@ -0,0 +1,17 @@ +package qemu + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestEditCmd(t *testing.T) { + vm := new(MachineVM) + vm.CmdLine = []string{"command", "-flag", "value"} + + vm.editCmdLine("-flag", "newvalue") + vm.editCmdLine("-anotherflag", "anothervalue") + + require.Equal(t, vm.CmdLine, []string{"command", "-flag", "newvalue", "-anotherflag", "anothervalue"}) +} diff --git a/pkg/machine/wsl/machine.go b/pkg/machine/wsl/machine.go index f57dbd299..addcb7c8a 100644 --- a/pkg/machine/wsl/machine.go +++ b/pkg/machine/wsl/machine.go @@ -155,7 +155,7 @@ type Provider struct{} type MachineVM struct { // IdentityPath is the fq path to the ssh priv key IdentityPath string - // IgnitionFilePath is the fq path to the .ign file + // ImageStream is the version of fcos being used ImageStream string // ImagePath is the fq path to ImagePath string @@ -736,28 +736,34 @@ func pipeCmdPassThrough(name string, input string, arg ...string) error { return cmd.Run() } -func (v *MachineVM) Set(name string, opts machine.SetOptions) error { - if v.Rootful == opts.Rootful { - return nil +func (v *MachineVM) Set(_ string, opts machine.SetOptions) ([]error, error) { + // If one setting fails to be applied, the others settings will not fail and still be applied. + // The setting(s) that failed to be applied will have its errors returned in setErrors + var setErrors []error + + if opts.Rootful != nil && v.Rootful != *opts.Rootful { + err := v.setRootful(*opts.Rootful) + if err != nil { + setErrors = append(setErrors, errors.Wrapf(err, "error setting rootful option")) + } else { + v.Rootful = *opts.Rootful + } } - changeCon, err := machine.AnyConnectionDefault(v.Name, v.Name+"-root") - if err != nil { - return err + if opts.CPUs != nil { + setErrors = append(setErrors, errors.Errorf("changing CPUs not suppored for WSL machines")) } - if changeCon { - newDefault := v.Name - if opts.Rootful { - newDefault += "-root" - } - if err := machine.ChangeDefault(newDefault); err != nil { - return err - } + if opts.Memory != nil { + setErrors = append(setErrors, errors.Errorf("changing memory not suppored for WSL machines")) + } - v.Rootful = opts.Rootful - return v.writeConfig() + if opts.DiskSize != nil { + setErrors = append(setErrors, errors.Errorf("changing Disk Size not suppored for WSL machines")) + } + + return setErrors, v.writeConfig() } func (v *MachineVM) Start(name string, _ machine.StartOptions) error { @@ -1362,3 +1368,26 @@ func (p *Provider) IsValidVMName(name string) (bool, error) { func (p *Provider) CheckExclusiveActiveVM() (bool, string, error) { return false, "", nil } + +func (v *MachineVM) setRootful(rootful bool) error { + changeCon, err := machine.AnyConnectionDefault(v.Name, v.Name+"-root") + if err != nil { + return err + } + + if changeCon { + newDefault := v.Name + if rootful { + newDefault += "-root" + } + err := machine.ChangeDefault(newDefault) + if err != nil { + return err + } + } + return nil +} + +func (v *MachineVM) Inspect() (*machine.InspectInfo, error) { + return nil, define.ErrNotImplemented +} diff --git a/test/e2e/build_test.go b/test/e2e/build_test.go index 0c665687d..b8aad1084 100644 --- a/test/e2e/build_test.go +++ b/test/e2e/build_test.go @@ -53,8 +53,8 @@ var _ = Describe("Podman build", func() { inspect := podmanTest.Podman([]string{"inspect", iid}) inspect.WaitWithDefaultTimeout() data := inspect.InspectImageJSON() - Expect(data[0].Os).To(Equal(runtime.GOOS)) - Expect(data[0].Architecture).To(Equal(runtime.GOARCH)) + Expect(data[0]).To(HaveField("Os", runtime.GOOS)) + Expect(data[0]).To(HaveField("Architecture", runtime.GOARCH)) session = podmanTest.Podman([]string{"rmi", ALPINE}) session.WaitWithDefaultTimeout() @@ -110,8 +110,8 @@ var _ = Describe("Podman build", func() { inspect := podmanTest.Podman([]string{"inspect", "test"}) inspect.WaitWithDefaultTimeout() data := inspect.InspectImageJSON() - Expect(data[0].Os).To(Equal(runtime.GOOS)) - Expect(data[0].Architecture).To(Equal(runtime.GOARCH)) + Expect(data[0]).To(HaveField("Os", runtime.GOOS)) + Expect(data[0]).To(HaveField("Architecture", runtime.GOARCH)) st, err := os.Stat(logfile) Expect(err).To(BeNil()) diff --git a/test/e2e/checkpoint_image_test.go b/test/e2e/checkpoint_image_test.go index 8274dfc80..6c2a000e8 100644 --- a/test/e2e/checkpoint_image_test.go +++ b/test/e2e/checkpoint_image_test.go @@ -91,9 +91,9 @@ var _ = Describe("Podman checkpoint", func() { inspectOut := inspect.InspectContainerToJSON() Expect(inspectOut[0].State.Checkpointed).To(BeFalse(), ".State.Checkpointed") Expect(inspectOut[0].State.Restored).To(BeFalse(), ".State.Restored") - Expect(inspectOut[0].State.CheckpointPath).To(Equal("")) - Expect(inspectOut[0].State.CheckpointLog).To(Equal("")) - Expect(inspectOut[0].State.RestoreLog).To(Equal("")) + Expect(inspectOut[0].State).To(HaveField("CheckpointPath", "")) + Expect(inspectOut[0].State).To(HaveField("CheckpointLog", "")) + Expect(inspectOut[0].State).To(HaveField("RestoreLog", "")) result := podmanTest.Podman([]string{"container", "checkpoint", "--create-image", checkpointImage, "--keep", containerID}) result.WaitWithDefaultTimeout() diff --git a/test/e2e/checkpoint_test.go b/test/e2e/checkpoint_test.go index 2dc99bdc9..ac1677539 100644 --- a/test/e2e/checkpoint_test.go +++ b/test/e2e/checkpoint_test.go @@ -99,9 +99,9 @@ var _ = Describe("Podman checkpoint", func() { inspectOut := inspect.InspectContainerToJSON() Expect(inspectOut[0].State.Checkpointed).To(BeFalse(), ".State.Checkpointed") Expect(inspectOut[0].State.Restored).To(BeFalse(), ".State.Restored") - Expect(inspectOut[0].State.CheckpointPath).To(Equal("")) - Expect(inspectOut[0].State.CheckpointLog).To(Equal("")) - Expect(inspectOut[0].State.RestoreLog).To(Equal("")) + Expect(inspectOut[0].State).To(HaveField("CheckpointPath", "")) + Expect(inspectOut[0].State).To(HaveField("CheckpointLog", "")) + Expect(inspectOut[0].State).To(HaveField("RestoreLog", "")) result := podmanTest.Podman([]string{ "container", @@ -125,7 +125,7 @@ var _ = Describe("Podman checkpoint", func() { Expect(inspectOut[0].State.Restored).To(BeFalse(), ".State.Restored") Expect(inspectOut[0].State.CheckpointPath).To(ContainSubstring("userdata/checkpoint")) Expect(inspectOut[0].State.CheckpointLog).To(ContainSubstring("userdata/dump.log")) - Expect(inspectOut[0].State.RestoreLog).To(Equal("")) + Expect(inspectOut[0].State).To(HaveField("RestoreLog", "")) result = podmanTest.Podman([]string{ "container", @@ -179,9 +179,9 @@ var _ = Describe("Podman checkpoint", func() { inspectOut = inspect.InspectContainerToJSON() Expect(inspectOut[0].State.Checkpointed).To(BeFalse(), ".State.Checkpointed") Expect(inspectOut[0].State.Restored).To(BeFalse(), ".State.Restored") - Expect(inspectOut[0].State.CheckpointPath).To(Equal("")) - Expect(inspectOut[0].State.CheckpointLog).To(Equal("")) - Expect(inspectOut[0].State.RestoreLog).To(Equal("")) + Expect(inspectOut[0].State).To(HaveField("CheckpointPath", "")) + Expect(inspectOut[0].State).To(HaveField("CheckpointLog", "")) + Expect(inspectOut[0].State).To(HaveField("RestoreLog", "")) }) It("podman checkpoint a running container by name", func() { diff --git a/test/e2e/commit_test.go b/test/e2e/commit_test.go index 78b607f1e..1de30e423 100644 --- a/test/e2e/commit_test.go +++ b/test/e2e/commit_test.go @@ -92,7 +92,7 @@ var _ = Describe("Podman commit", func() { check := podmanTest.Podman([]string{"inspect", "foobar.com/test1-image:latest"}) check.WaitWithDefaultTimeout() data := check.InspectImageJSON() - Expect(data[0].Comment).To(Equal("testing-commit")) + Expect(data[0]).To(HaveField("Comment", "testing-commit")) }) It("podman commit container with author", func() { @@ -107,7 +107,7 @@ var _ = Describe("Podman commit", func() { check := podmanTest.Podman([]string{"inspect", "foobar.com/test1-image:latest"}) check.WaitWithDefaultTimeout() data := check.InspectImageJSON() - Expect(data[0].Author).To(Equal("snoopy")) + Expect(data[0]).To(HaveField("Author", "snoopy")) }) It("podman commit container with change flag", func() { @@ -293,7 +293,7 @@ var _ = Describe("Podman commit", func() { check := podmanTest.Podman([]string{"inspect", "foobar.com/test1-image:latest"}) check.WaitWithDefaultTimeout() data := check.InspectImageJSON() - Expect(data[0].ID).To(Equal(string(id))) + Expect(data[0]).To(HaveField("ID", string(id))) }) It("podman commit should not commit secret", func() { diff --git a/test/e2e/container_clone_test.go b/test/e2e/container_clone_test.go index 42b477da0..c47a89332 100644 --- a/test/e2e/container_clone_test.go +++ b/test/e2e/container_clone_test.go @@ -68,8 +68,8 @@ var _ = Describe("Podman container clone", func() { ctrInspect := podmanTest.Podman([]string{"inspect", clone.OutputToString()}) ctrInspect.WaitWithDefaultTimeout() Expect(ctrInspect).To(Exit(0)) - Expect(ctrInspect.InspectContainerToJSON()[0].ImageName).To(Equal(fedoraMinimal)) - Expect(ctrInspect.InspectContainerToJSON()[0].Name).To(Equal("new_name")) + Expect(ctrInspect.InspectContainerToJSON()[0]).To(HaveField("ImageName", fedoraMinimal)) + Expect(ctrInspect.InspectContainerToJSON()[0]).To(HaveField("Name", "new_name")) }) It("podman container clone name test", func() { @@ -84,7 +84,7 @@ var _ = Describe("Podman container clone", func() { cloneInspect.WaitWithDefaultTimeout() Expect(cloneInspect).To(Exit(0)) cloneData := cloneInspect.InspectContainerToJSON() - Expect(cloneData[0].Name).To(Equal("testing123")) + Expect(cloneData[0]).To(HaveField("Name", "testing123")) }) It("podman container clone resource limits override", func() { @@ -104,7 +104,7 @@ var _ = Describe("Podman container clone", func() { cloneInspect.WaitWithDefaultTimeout() Expect(cloneInspect).To(Exit(0)) cloneData := cloneInspect.InspectContainerToJSON() - Expect(createData[0].HostConfig.NanoCpus).To(Equal(cloneData[0].HostConfig.NanoCpus)) + Expect(createData[0].HostConfig).To(HaveField("NanoCpus", cloneData[0].HostConfig.NanoCpus)) create = podmanTest.Podman([]string{"create", "--memory=5", ALPINE}) create.WaitWithDefaultTimeout() @@ -122,7 +122,7 @@ var _ = Describe("Podman container clone", func() { cloneInspect.WaitWithDefaultTimeout() Expect(cloneInspect).To(Exit(0)) cloneData = cloneInspect.InspectContainerToJSON() - Expect(createData[0].HostConfig.MemorySwap).To(Equal(cloneData[0].HostConfig.MemorySwap)) + Expect(createData[0].HostConfig).To(HaveField("MemorySwap", cloneData[0].HostConfig.MemorySwap)) create = podmanTest.Podman([]string{"create", "--cpus=5", ALPINE}) create.WaitWithDefaultTimeout() @@ -145,7 +145,7 @@ var _ = Describe("Podman container clone", func() { Expect(cloneInspect).To(Exit(0)) cloneData = cloneInspect.InspectContainerToJSON() Expect(createData[0].HostConfig.NanoCpus).ToNot(Equal(cloneData[0].HostConfig.NanoCpus)) - Expect(cloneData[0].HostConfig.NanoCpus).To(Equal(nanoCPUs)) + Expect(cloneData[0].HostConfig).To(HaveField("NanoCpus", nanoCPUs)) create = podmanTest.Podman([]string{"create", ALPINE}) create.WaitWithDefaultTimeout() @@ -158,7 +158,7 @@ var _ = Describe("Podman container clone", func() { cloneInspect.WaitWithDefaultTimeout() Expect(cloneInspect).To(Exit(0)) cloneData = cloneInspect.InspectContainerToJSON() - Expect(cloneData[0].HostConfig.MemorySwappiness).To(Equal(int64(0))) + Expect(cloneData[0].HostConfig).To(HaveField("MemorySwappiness", int64(0))) }) diff --git a/test/e2e/container_create_volume_test.go b/test/e2e/container_create_volume_test.go index 62a2541b9..015b1742a 100644 --- a/test/e2e/container_create_volume_test.go +++ b/test/e2e/container_create_volume_test.go @@ -47,7 +47,7 @@ func checkDataVolumeContainer(pTest *PodmanTestIntegration, image, cont, dest, d inspect := pTest.InspectContainer(cont) Expect(inspect).To(HaveLen(1)) Expect(inspect[0].Mounts).To(HaveLen(1)) - Expect(inspect[0].Mounts[0].Destination).To(Equal(dest)) + Expect(inspect[0].Mounts[0]).To(HaveField("Destination", dest)) mntName, mntSource := inspect[0].Mounts[0].Name, inspect[0].Mounts[0].Source diff --git a/test/e2e/create_test.go b/test/e2e/create_test.go index 4c3b5604a..d0813459d 100644 --- a/test/e2e/create_test.go +++ b/test/e2e/create_test.go @@ -268,7 +268,7 @@ var _ = Describe("Podman create", func() { Expect(session).Should(Exit(0)) ctrJSON := podmanTest.InspectContainer(ctrName) - Expect(podData.ID).To(Equal(ctrJSON[0].Pod)) // Make sure the container's pod matches the pod's ID + Expect(podData).To(HaveField("ID", ctrJSON[0].Pod)) // Make sure the container's pod matches the pod's ID }) It("podman run entrypoint and cmd test", func() { @@ -281,7 +281,7 @@ var _ = Describe("Podman create", func() { Expect(ctrJSON).To(HaveLen(1)) Expect(ctrJSON[0].Config.Cmd).To(HaveLen(1)) Expect(ctrJSON[0].Config.Cmd[0]).To(Equal("redis-server")) - Expect(ctrJSON[0].Config.Entrypoint).To(Equal("docker-entrypoint.sh")) + Expect(ctrJSON[0].Config).To(HaveField("Entrypoint", "docker-entrypoint.sh")) }) It("podman create --pull", func() { @@ -413,8 +413,8 @@ var _ = Describe("Podman create", func() { inspect.WaitWithDefaultTimeout() data := inspect.InspectContainerToJSON() Expect(data).To(HaveLen(1)) - Expect(data[0].HostConfig.RestartPolicy.Name).To(Equal("on-failure")) - Expect(data[0].HostConfig.RestartPolicy.MaximumRetryCount).To(Equal(uint(5))) + Expect(data[0].HostConfig.RestartPolicy).To(HaveField("Name", "on-failure")) + Expect(data[0].HostConfig.RestartPolicy).To(HaveField("MaximumRetryCount", uint(5))) }) It("podman create with --restart-policy=always:5 fails", func() { @@ -434,7 +434,7 @@ var _ = Describe("Podman create", func() { inspect.WaitWithDefaultTimeout() data := inspect.InspectContainerToJSON() Expect(data).To(HaveLen(1)) - Expect(data[0].HostConfig.RestartPolicy.Name).To(Equal(unlessStopped)) + Expect(data[0].HostConfig.RestartPolicy).To(HaveField("Name", unlessStopped)) }) It("podman create with -m 1000000 sets swap to 2000000", func() { @@ -448,7 +448,7 @@ var _ = Describe("Podman create", func() { inspect.WaitWithDefaultTimeout() data := inspect.InspectContainerToJSON() Expect(data).To(HaveLen(1)) - Expect(data[0].HostConfig.MemorySwap).To(Equal(int64(2 * numMem))) + Expect(data[0].HostConfig).To(HaveField("MemorySwap", int64(2*numMem))) }) It("podman create --cpus 5 sets nanocpus", func() { @@ -463,7 +463,7 @@ var _ = Describe("Podman create", func() { inspect.WaitWithDefaultTimeout() data := inspect.InspectContainerToJSON() Expect(data).To(HaveLen(1)) - Expect(data[0].HostConfig.NanoCpus).To(Equal(int64(nanoCPUs))) + Expect(data[0].HostConfig).To(HaveField("NanoCpus", int64(nanoCPUs))) }) It("podman create --replace", func() { @@ -491,7 +491,7 @@ var _ = Describe("Podman create", func() { inspect.WaitWithDefaultTimeout() data := inspect.InspectContainerToJSON() Expect(data).To(HaveLen(1)) - Expect(data[0].Config.StopSignal).To(Equal(uint(15))) + Expect(data[0].Config).To(HaveField("StopSignal", uint(15))) }) It("podman create --tz", func() { @@ -509,7 +509,7 @@ var _ = Describe("Podman create", func() { inspect.WaitWithDefaultTimeout() data := inspect.InspectContainerToJSON() Expect(data).To(HaveLen(1)) - Expect(data[0].Config.Timezone).To(Equal("Pacific/Honolulu")) + Expect(data[0].Config).To(HaveField("Timezone", "Pacific/Honolulu")) session = podmanTest.Podman([]string{"create", "--tz", "local", "--name", "lcl", ALPINE, "date"}) session.WaitWithDefaultTimeout() @@ -517,7 +517,7 @@ var _ = Describe("Podman create", func() { inspect.WaitWithDefaultTimeout() data = inspect.InspectContainerToJSON() Expect(data).To(HaveLen(1)) - Expect(data[0].Config.Timezone).To(Equal("local")) + Expect(data[0].Config).To(HaveField("Timezone", "local")) }) It("podman create --umask", func() { @@ -531,7 +531,7 @@ var _ = Describe("Podman create", func() { inspect.WaitWithDefaultTimeout() data := inspect.InspectContainerToJSON() Expect(data).To(HaveLen(1)) - Expect(data[0].Config.Umask).To(Equal("0022")) + Expect(data[0].Config).To(HaveField("Umask", "0022")) session = podmanTest.Podman([]string{"create", "--umask", "0002", "--name", "umask", ALPINE}) session.WaitWithDefaultTimeout() @@ -539,7 +539,7 @@ var _ = Describe("Podman create", func() { inspect.WaitWithDefaultTimeout() data = inspect.InspectContainerToJSON() Expect(data).To(HaveLen(1)) - Expect(data[0].Config.Umask).To(Equal("0002")) + Expect(data[0].Config).To(HaveField("Umask", "0002")) session = podmanTest.Podman([]string{"create", "--umask", "0077", "--name", "fedora", fedoraMinimal}) session.WaitWithDefaultTimeout() @@ -547,7 +547,7 @@ var _ = Describe("Podman create", func() { inspect.WaitWithDefaultTimeout() data = inspect.InspectContainerToJSON() Expect(data).To(HaveLen(1)) - Expect(data[0].Config.Umask).To(Equal("0077")) + Expect(data[0].Config).To(HaveField("Umask", "0077")) session = podmanTest.Podman([]string{"create", "--umask", "22", "--name", "umask-short", ALPINE}) session.WaitWithDefaultTimeout() @@ -555,7 +555,7 @@ var _ = Describe("Podman create", func() { inspect.WaitWithDefaultTimeout() data = inspect.InspectContainerToJSON() Expect(data).To(HaveLen(1)) - Expect(data[0].Config.Umask).To(Equal("0022")) + Expect(data[0].Config).To(HaveField("Umask", "0022")) session = podmanTest.Podman([]string{"create", "--umask", "9999", "--name", "bad", ALPINE}) session.WaitWithDefaultTimeout() @@ -689,8 +689,8 @@ var _ = Describe("Podman create", func() { idata := setup.InspectImageJSON() // returns []inspect.ImageData Expect(idata).To(HaveLen(1)) - Expect(idata[0].Os).To(Equal(runtime.GOOS)) - Expect(idata[0].Architecture).To(Equal("arm64")) + Expect(idata[0]).To(HaveField("Os", runtime.GOOS)) + Expect(idata[0]).To(HaveField("Architecture", "arm64")) }) It("podman create --uid/gidmap --pod conflict test", func() { diff --git a/test/e2e/generate_kube_test.go b/test/e2e/generate_kube_test.go index 1e9d725b7..c92c1519f 100644 --- a/test/e2e/generate_kube_test.go +++ b/test/e2e/generate_kube_test.go @@ -66,12 +66,12 @@ var _ = Describe("Podman generate kube", func() { pod := new(v1.Pod) err := yaml.Unmarshal(kube.Out.Contents(), pod) Expect(err).To(BeNil()) - Expect(pod.Spec.HostNetwork).To(Equal(false)) + Expect(pod.Spec).To(HaveField("HostNetwork", false)) Expect(pod.Spec.SecurityContext).To(BeNil()) Expect(pod.Spec.DNSConfig).To(BeNil()) - Expect(pod.Spec.Containers[0].WorkingDir).To(Equal("")) + Expect(pod.Spec.Containers[0]).To(HaveField("WorkingDir", "")) Expect(pod.Spec.Containers[0].Env).To(BeNil()) - Expect(pod.Name).To(Equal("top-pod")) + Expect(pod).To(HaveField("Name", "top-pod")) numContainers := 0 for range pod.Spec.Containers { @@ -165,7 +165,7 @@ var _ = Describe("Podman generate kube", func() { pod := new(v1.Pod) err := yaml.Unmarshal(kube.Out.Contents(), pod) Expect(err).To(BeNil()) - Expect(pod.Spec.HostNetwork).To(Equal(false)) + Expect(pod.Spec).To(HaveField("HostNetwork", false)) numContainers := 0 for range pod.Spec.Containers { @@ -211,7 +211,7 @@ var _ = Describe("Podman generate kube", func() { pod := new(v1.Pod) err := yaml.Unmarshal(kube.Out.Contents(), pod) Expect(err).To(BeNil()) - Expect(pod.Spec.HostNetwork).To(Equal(false)) + Expect(pod.Spec).To(HaveField("HostNetwork", false)) numContainers := len(pod.Spec.Containers) + len(pod.Spec.InitContainers) Expect(numContainers).To(Equal(3)) @@ -232,7 +232,7 @@ var _ = Describe("Podman generate kube", func() { pod = new(v1.Pod) err = yaml.Unmarshal(kube.Out.Contents(), pod) Expect(err).To(BeNil()) - Expect(pod.Spec.HostNetwork).To(Equal(false)) + Expect(pod.Spec).To(HaveField("HostNetwork", false)) numContainers = len(pod.Spec.Containers) + len(pod.Spec.InitContainers) Expect(numContainers).To(Equal(2)) @@ -257,7 +257,7 @@ var _ = Describe("Podman generate kube", func() { pod = new(v1.Pod) err = yaml.Unmarshal(kube.Out.Contents(), pod) Expect(err).To(BeNil()) - Expect(pod.Spec.HostNetwork).To(Equal(false)) + Expect(pod.Spec).To(HaveField("HostNetwork", false)) numContainers = len(pod.Spec.Containers) + len(pod.Spec.InitContainers) Expect(numContainers).To(Equal(1)) @@ -279,7 +279,7 @@ var _ = Describe("Podman generate kube", func() { pod := new(v1.Pod) err := yaml.Unmarshal(kube.Out.Contents(), pod) Expect(err).To(BeNil()) - Expect(pod.Spec.HostNetwork).To(Equal(true)) + Expect(pod.Spec).To(HaveField("HostNetwork", true)) }) It("podman generate kube on container with host network", func() { @@ -294,7 +294,7 @@ var _ = Describe("Podman generate kube", func() { pod := new(v1.Pod) err := yaml.Unmarshal(kube.Out.Contents(), pod) Expect(err).To(BeNil()) - Expect(pod.Spec.HostNetwork).To(Equal(true)) + Expect(pod.Spec).To(HaveField("HostNetwork", true)) }) It("podman generate kube on pod with hostAliases", func() { @@ -325,8 +325,8 @@ var _ = Describe("Podman generate kube", func() { err := yaml.Unmarshal(kube.Out.Contents(), pod) Expect(err).To(BeNil()) Expect(pod.Spec.HostAliases).To(HaveLen(2)) - Expect(pod.Spec.HostAliases[0].IP).To(Equal(testIP)) - Expect(pod.Spec.HostAliases[1].IP).To(Equal(testIP)) + Expect(pod.Spec.HostAliases[0]).To(HaveField("IP", testIP)) + Expect(pod.Spec.HostAliases[1]).To(HaveField("IP", testIP)) }) It("podman generate service kube on pod", func() { @@ -347,7 +347,7 @@ var _ = Describe("Podman generate kube", func() { Expect(err).To(BeNil()) Expect(svc.Spec.Ports).To(HaveLen(1)) Expect(svc.Spec.Ports[0].TargetPort.IntValue()).To(Equal(4000)) - Expect(svc.Spec.Ports[0].Protocol).To(Equal(v1.ProtocolUDP)) + Expect(svc.Spec.Ports[0]).To(HaveField("Protocol", v1.ProtocolUDP)) pod := new(v1.Pod) err = yaml.Unmarshal([]byte(arr[1]), pod) @@ -506,7 +506,7 @@ var _ = Describe("Podman generate kube", func() { containers := pod.Spec.Containers Expect(containers).To(HaveLen(1)) Expect(containers[0].Ports).To(HaveLen(1)) - Expect(containers[0].Ports[0].Protocol).To(Equal(v1.ProtocolUDP)) + Expect(containers[0].Ports[0]).To(HaveField("Protocol", v1.ProtocolUDP)) }) It("podman generate and reimport kube on pod", func() { @@ -776,8 +776,9 @@ var _ = Describe("Podman generate kube", func() { Expect(pod.Spec.DNSConfig.Nameservers).To(ContainElement("8.8.8.8")) Expect(pod.Spec.DNSConfig.Searches).To(ContainElement("foobar.com")) Expect(len(pod.Spec.DNSConfig.Options)).To(BeNumerically(">", 0)) - Expect(pod.Spec.DNSConfig.Options[0].Name).To(Equal("color")) - Expect(*pod.Spec.DNSConfig.Options[0].Value).To(Equal("blue")) + Expect(pod.Spec.DNSConfig.Options[0]).To(HaveField("Name", "color")) + s := "blue" + Expect(pod.Spec.DNSConfig.Options[0]).To(HaveField("Value", &s)) }) It("podman generate kube multiple container dns servers and options are cumulative", func() { @@ -819,8 +820,9 @@ var _ = Describe("Podman generate kube", func() { Expect(pod.Spec.DNSConfig.Nameservers).To(ContainElement("8.8.8.8")) Expect(pod.Spec.DNSConfig.Searches).To(ContainElement("foobar.com")) Expect(len(pod.Spec.DNSConfig.Options)).To(BeNumerically(">", 0)) - Expect(pod.Spec.DNSConfig.Options[0].Name).To(Equal("color")) - Expect(*pod.Spec.DNSConfig.Options[0].Value).To(Equal("blue")) + Expect(pod.Spec.DNSConfig.Options[0]).To(HaveField("Name", "color")) + s := "blue" + Expect(pod.Spec.DNSConfig.Options[0]).To(HaveField("Value", &s)) }) It("podman generate kube - set entrypoint as command", func() { @@ -841,8 +843,8 @@ var _ = Describe("Podman generate kube", func() { containers := pod.Spec.Containers Expect(containers).To(HaveLen(1)) - Expect(containers[0].Command).To(Equal([]string{"/bin/sleep"})) - Expect(containers[0].Args).To(Equal([]string{"10s"})) + Expect(containers[0]).To(HaveField("Command", []string{"/bin/sleep"})) + Expect(containers[0]).To(HaveField("Args", []string{"10s"})) }) It("podman generate kube - use command from image unless explicitly set in the podman command", func() { @@ -881,7 +883,7 @@ var _ = Describe("Podman generate kube", func() { containers = pod.Spec.Containers Expect(containers).To(HaveLen(1)) - Expect(containers[0].Command).To(Equal(cmd)) + Expect(containers[0]).To(HaveField("Command", cmd)) }) It("podman generate kube - use entrypoint from image unless --entrypoint is set", func() { @@ -916,7 +918,7 @@ ENTRYPOINT ["sleep"]` containers := pod.Spec.Containers Expect(containers).To(HaveLen(1)) - Expect(containers[0].Args).To(Equal([]string{"10s"})) + Expect(containers[0]).To(HaveField("Args", []string{"10s"})) session = podmanTest.Podman([]string{"create", "--pod", "new:testpod-2", "--entrypoint", "echo", image, "hello"}) session.WaitWithDefaultTimeout() @@ -934,8 +936,8 @@ ENTRYPOINT ["sleep"]` containers = pod.Spec.Containers Expect(containers).To(HaveLen(1)) - Expect(containers[0].Command).To(Equal([]string{"echo"})) - Expect(containers[0].Args).To(Equal([]string{"hello"})) + Expect(containers[0]).To(HaveField("Command", []string{"echo"})) + Expect(containers[0]).To(HaveField("Args", []string{"hello"})) }) It("podman generate kube - --privileged container", func() { @@ -1018,7 +1020,7 @@ USER test1` pvc := new(v1.PersistentVolumeClaim) err := yaml.Unmarshal(kube.Out.Contents(), pvc) Expect(err).To(BeNil()) - Expect(pvc.Name).To(Equal(vol)) + Expect(pvc).To(HaveField("Name", vol)) Expect(pvc.Spec.AccessModes[0]).To(Equal(v1.ReadWriteOnce)) Expect(pvc.Spec.Resources.Requests.Storage().String()).To(Equal("1Gi")) }) @@ -1040,7 +1042,7 @@ USER test1` pvc := new(v1.PersistentVolumeClaim) err := yaml.Unmarshal(kube.Out.Contents(), pvc) Expect(err).To(BeNil()) - Expect(pvc.Name).To(Equal(vol)) + Expect(pvc).To(HaveField("Name", vol)) Expect(pvc.Spec.AccessModes[0]).To(Equal(v1.ReadWriteOnce)) Expect(pvc.Spec.Resources.Requests.Storage().String()).To(Equal("1Gi")) @@ -1092,8 +1094,8 @@ USER test1` pod := new(v1.Pod) err := yaml.Unmarshal(kube.Out.Contents(), pod) Expect(err).To(BeNil()) - Expect(pod.Spec.Containers[0].WorkingDir).To(Equal("")) - Expect(pod.Spec.Containers[1].WorkingDir).To(Equal("/root")) + Expect(pod.Spec.Containers[0]).To(HaveField("WorkingDir", "")) + Expect(pod.Spec.Containers[1]).To(HaveField("WorkingDir", "/root")) for _, ctr := range []string{"top1", "top2"} { Expect(pod.Annotations).To(HaveKeyWithValue("io.containers.autoupdate/"+ctr, "registry")) diff --git a/test/e2e/healthcheck_run_test.go b/test/e2e/healthcheck_run_test.go index 23f1a1dbf..a41c10162 100644 --- a/test/e2e/healthcheck_run_test.go +++ b/test/e2e/healthcheck_run_test.go @@ -168,7 +168,7 @@ var _ = Describe("Podman healthcheck run", func() { session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) inspect := podmanTest.InspectContainer("hc") - Expect(inspect[0].State.Health.Status).To(Equal("starting")) + Expect(inspect[0].State.Health).To(HaveField("Status", "starting")) }) It("podman healthcheck failed checks in start-period should not change status", func() { @@ -189,9 +189,9 @@ var _ = Describe("Podman healthcheck run", func() { Expect(hc).Should(Exit(1)) inspect := podmanTest.InspectContainer("hc") - Expect(inspect[0].State.Health.Status).To(Equal("starting")) + Expect(inspect[0].State.Health).To(HaveField("Status", "starting")) // test old podman compat (see #11645) - Expect(inspect[0].State.Healthcheck().Status).To(Equal("starting")) + Expect(inspect[0].State.Healthcheck()).To(HaveField("Status", "starting")) }) It("podman healthcheck failed checks must reach retries before unhealthy ", func() { @@ -204,16 +204,16 @@ var _ = Describe("Podman healthcheck run", func() { Expect(hc).Should(Exit(1)) inspect := podmanTest.InspectContainer("hc") - Expect(inspect[0].State.Health.Status).To(Equal("starting")) + Expect(inspect[0].State.Health).To(HaveField("Status", "starting")) hc = podmanTest.Podman([]string{"healthcheck", "run", "hc"}) hc.WaitWithDefaultTimeout() Expect(hc).Should(Exit(1)) inspect = podmanTest.InspectContainer("hc") - Expect(inspect[0].State.Health.Status).To(Equal(define.HealthCheckUnhealthy)) + Expect(inspect[0].State.Health).To(HaveField("Status", define.HealthCheckUnhealthy)) // test old podman compat (see #11645) - Expect(inspect[0].State.Healthcheck().Status).To(Equal(define.HealthCheckUnhealthy)) + Expect(inspect[0].State.Healthcheck()).To(HaveField("Status", define.HealthCheckUnhealthy)) }) It("podman healthcheck good check results in healthy even in start-period", func() { @@ -226,7 +226,7 @@ var _ = Describe("Podman healthcheck run", func() { Expect(hc).Should(Exit(0)) inspect := podmanTest.InspectContainer("hc") - Expect(inspect[0].State.Health.Status).To(Equal(define.HealthCheckHealthy)) + Expect(inspect[0].State.Health).To(HaveField("Status", define.HealthCheckHealthy)) }) It("podman healthcheck unhealthy but valid arguments check", func() { @@ -249,14 +249,14 @@ var _ = Describe("Podman healthcheck run", func() { Expect(hc).Should(Exit(1)) inspect := podmanTest.InspectContainer("hc") - Expect(inspect[0].State.Health.Status).To(Equal("starting")) + Expect(inspect[0].State.Health).To(HaveField("Status", "starting")) hc = podmanTest.Podman([]string{"healthcheck", "run", "hc"}) hc.WaitWithDefaultTimeout() Expect(hc).Should(Exit(1)) inspect = podmanTest.InspectContainer("hc") - Expect(inspect[0].State.Health.Status).To(Equal(define.HealthCheckUnhealthy)) + Expect(inspect[0].State.Health).To(HaveField("Status", define.HealthCheckUnhealthy)) foo := podmanTest.Podman([]string{"exec", "hc", "touch", "/foo"}) foo.WaitWithDefaultTimeout() @@ -267,7 +267,7 @@ var _ = Describe("Podman healthcheck run", func() { Expect(hc).Should(Exit(0)) inspect = podmanTest.InspectContainer("hc") - Expect(inspect[0].State.Health.Status).To(Equal(define.HealthCheckHealthy)) + Expect(inspect[0].State.Health).To(HaveField("Status", define.HealthCheckHealthy)) // Test podman ps --filter heath is working (#11687) ps := podmanTest.Podman([]string{"ps", "--filter", "health=healthy"}) @@ -328,6 +328,6 @@ HEALTHCHECK CMD ls -l / 2>&1`, ALPINE) // Check to make sure a default time interval value was added Expect(inspect[0].Config.Healthcheck.Interval).To(BeNumerically("==", 30000000000)) // Check to make sure characters were not coerced to utf8 - Expect(inspect[0].Config.Healthcheck.Test).To(Equal([]string{"CMD-SHELL", "ls -l / 2>&1"})) + Expect(inspect[0].Config.Healthcheck).To(HaveField("Test", []string{"CMD-SHELL", "ls -l / 2>&1"})) }) }) diff --git a/test/e2e/image_scp_test.go b/test/e2e/image_scp_test.go index 5abdf74f8..2ad3cc75e 100644 --- a/test/e2e/image_scp_test.go +++ b/test/e2e/image_scp_test.go @@ -75,7 +75,7 @@ var _ = Describe("podman image scp", func() { cfg, err := config.ReadCustomConfig() Expect(err).ShouldNot(HaveOccurred()) - Expect(cfg.Engine.ActiveService).To(Equal("QA")) + Expect(cfg.Engine).To(HaveField("ActiveService", "QA")) Expect(cfg.Engine.ServiceDestinations).To(HaveKeyWithValue("QA", config.Destination{ URI: "ssh://root@server.fubar.com:2222/run/podman/podman.sock", diff --git a/test/e2e/init_test.go b/test/e2e/init_test.go index c4c090daf..fdb2b41a1 100644 --- a/test/e2e/init_test.go +++ b/test/e2e/init_test.go @@ -57,7 +57,7 @@ var _ = Describe("Podman init", func() { result.WaitWithDefaultTimeout() Expect(result).Should(Exit(0)) conData := result.InspectContainerToJSON() - Expect(conData[0].State.Status).To(Equal("initialized")) + Expect(conData[0].State).To(HaveField("Status", "initialized")) }) It("podman init single container by name", func() { @@ -72,7 +72,7 @@ var _ = Describe("Podman init", func() { result.WaitWithDefaultTimeout() Expect(result).Should(Exit(0)) conData := result.InspectContainerToJSON() - Expect(conData[0].State.Status).To(Equal("initialized")) + Expect(conData[0].State).To(HaveField("Status", "initialized")) }) It("podman init latest container", func() { @@ -87,7 +87,7 @@ var _ = Describe("Podman init", func() { result.WaitWithDefaultTimeout() Expect(result).Should(Exit(0)) conData := result.InspectContainerToJSON() - Expect(conData[0].State.Status).To(Equal("initialized")) + Expect(conData[0].State).To(HaveField("Status", "initialized")) }) It("podman init all three containers, one running", func() { @@ -107,17 +107,17 @@ var _ = Describe("Podman init", func() { result.WaitWithDefaultTimeout() Expect(result).Should(Exit(0)) conData := result.InspectContainerToJSON() - Expect(conData[0].State.Status).To(Equal("initialized")) + Expect(conData[0].State).To(HaveField("Status", "initialized")) result2 := podmanTest.Podman([]string{"inspect", "test2"}) result2.WaitWithDefaultTimeout() Expect(result2).Should(Exit(0)) conData2 := result2.InspectContainerToJSON() - Expect(conData2[0].State.Status).To(Equal("initialized")) + Expect(conData2[0].State).To(HaveField("Status", "initialized")) result3 := podmanTest.Podman([]string{"inspect", "test3"}) result3.WaitWithDefaultTimeout() Expect(result3).Should(Exit(0)) conData3 := result3.InspectContainerToJSON() - Expect(conData3[0].State.Status).To(Equal("running")) + Expect(conData3[0].State).To(HaveField("Status", "running")) }) It("podman init running container errors", func() { diff --git a/test/e2e/inspect_test.go b/test/e2e/inspect_test.go index bb5a3a6ad..25b938d07 100644 --- a/test/e2e/inspect_test.go +++ b/test/e2e/inspect_test.go @@ -189,7 +189,7 @@ var _ = Describe("Podman inspect", func() { imageData := session.InspectImageJSON() Expect(imageData[0].HealthCheck.Timeout).To(BeNumerically("==", 3000000000)) Expect(imageData[0].HealthCheck.Interval).To(BeNumerically("==", 60000000000)) - Expect(imageData[0].HealthCheck.Test).To(Equal([]string{"CMD-SHELL", "curl -f http://localhost/ || exit 1"})) + Expect(imageData[0].HealthCheck).To(HaveField("Test", []string{"CMD-SHELL", "curl -f http://localhost/ || exit 1"})) }) It("podman inspect --latest with no container fails", func() { @@ -217,7 +217,7 @@ var _ = Describe("Podman inspect", func() { imageJSON := imageInspect.InspectImageJSON() Expect(imageJSON).To(HaveLen(1)) - Expect(baseJSON[0].ID).To(Equal(imageJSON[0].ID)) + Expect(baseJSON[0]).To(HaveField("ID", imageJSON[0].ID)) }) It("podman [image, container] inspect on container", func() { @@ -242,7 +242,7 @@ var _ = Describe("Podman inspect", func() { imageInspect.WaitWithDefaultTimeout() Expect(imageInspect).To(ExitWithError()) - Expect(baseJSON[0].ID).To(Equal(ctrJSON[0].ID)) + Expect(baseJSON[0]).To(HaveField("ID", ctrJSON[0].ID)) }) It("podman inspect always produces a valid array", func() { @@ -264,7 +264,7 @@ var _ = Describe("Podman inspect", func() { Expect(baseInspect).To(ExitWithError()) baseJSON := baseInspect.InspectContainerToJSON() Expect(baseJSON).To(HaveLen(1)) - Expect(baseJSON[0].Name).To(Equal(ctrName)) + Expect(baseJSON[0]).To(HaveField("Name", ctrName)) }) It("podman inspect container + image with same name gives container", func() { @@ -283,7 +283,7 @@ var _ = Describe("Podman inspect", func() { Expect(baseInspect).Should(Exit(0)) baseJSON := baseInspect.InspectContainerToJSON() Expect(baseJSON).To(HaveLen(1)) - Expect(baseJSON[0].Name).To(Equal(ctrName)) + Expect(baseJSON[0]).To(HaveField("Name", ctrName)) }) It("podman inspect - HostConfig.SecurityOpt ", func() { @@ -307,7 +307,7 @@ var _ = Describe("Podman inspect", func() { Expect(baseInspect).Should(Exit(0)) baseJSON := baseInspect.InspectContainerToJSON() Expect(baseJSON).To(HaveLen(1)) - Expect(baseJSON[0].HostConfig.SecurityOpt).To(Equal([]string{"label=type:spc_t,label=level:s0", "seccomp=unconfined"})) + Expect(baseJSON[0].HostConfig).To(HaveField("SecurityOpt", []string{"label=type:spc_t,label=level:s0", "seccomp=unconfined"})) }) It("podman inspect pod", func() { @@ -321,7 +321,7 @@ var _ = Describe("Podman inspect", func() { Expect(inspect).Should(Exit(0)) Expect(inspect.OutputToString()).To(BeValidJSON()) podData := inspect.InspectPodArrToJSON() - Expect(podData[0].Name).To(Equal(podName)) + Expect(podData[0]).To(HaveField("Name", podName)) }) It("podman inspect pod with type", func() { @@ -335,7 +335,7 @@ var _ = Describe("Podman inspect", func() { Expect(inspect).Should(Exit(0)) Expect(inspect.OutputToString()).To(BeValidJSON()) podData := inspect.InspectPodArrToJSON() - Expect(podData[0].Name).To(Equal(podName)) + Expect(podData[0]).To(HaveField("Name", podName)) }) It("podman inspect latest pod", func() { @@ -350,7 +350,7 @@ var _ = Describe("Podman inspect", func() { Expect(inspect).Should(Exit(0)) Expect(inspect.OutputToString()).To(BeValidJSON()) podData := inspect.InspectPodArrToJSON() - Expect(podData[0].Name).To(Equal(podName)) + Expect(podData[0]).To(HaveField("Name", podName)) }) It("podman inspect latest defaults to latest container", func() { SkipIfRemote("--latest flag n/a") @@ -371,7 +371,7 @@ var _ = Describe("Podman inspect", func() { Expect(inspect).Should(Exit(0)) Expect(inspect.OutputToString()).To(BeValidJSON()) containerData := inspect.InspectContainerToJSON() - Expect(containerData[0].Name).To(Equal(infra)) + Expect(containerData[0]).To(HaveField("Name", infra)) }) It("podman inspect network", func() { diff --git a/test/e2e/network_create_test.go b/test/e2e/network_create_test.go index 82b99bd68..a6e927ca2 100644 --- a/test/e2e/network_create_test.go +++ b/test/e2e/network_create_test.go @@ -59,7 +59,7 @@ var _ = Describe("Podman network create", func() { Expect(err).To(BeNil()) Expect(results).To(HaveLen(1)) result := results[0] - Expect(result.Name).To(Equal(netName)) + Expect(result).To(HaveField("Name", netName)) Expect(result.Subnets).To(HaveLen(1)) Expect(result.Subnets[0].Subnet.String()).To(Equal("10.11.12.0/24")) Expect(result.Subnets[0].Gateway.String()).To(Equal("10.11.12.1")) @@ -102,7 +102,7 @@ var _ = Describe("Podman network create", func() { Expect(err).To(BeNil()) Expect(results).To(HaveLen(1)) result := results[0] - Expect(result.Name).To(Equal(netName)) + Expect(result).To(HaveField("Name", netName)) Expect(result.Subnets).To(HaveLen(1)) Expect(result.Subnets[0].Gateway.String()).To(Equal("fd00:1:2:3::1")) Expect(result.Subnets[0].Subnet.String()).To(Equal("fd00:1:2:3::/64")) @@ -141,7 +141,7 @@ var _ = Describe("Podman network create", func() { Expect(err).To(BeNil()) Expect(results).To(HaveLen(1)) result := results[0] - Expect(result.Name).To(Equal(netName)) + Expect(result).To(HaveField("Name", netName)) Expect(result.Subnets).To(HaveLen(2)) Expect(result.Subnets[0].Subnet.IP).ToNot(BeNil()) Expect(result.Subnets[1].Subnet.IP).ToNot(BeNil()) @@ -173,7 +173,7 @@ var _ = Describe("Podman network create", func() { Expect(err).To(BeNil()) Expect(results).To(HaveLen(1)) result = results[0] - Expect(result.Name).To(Equal(netName2)) + Expect(result).To(HaveField("Name", netName2)) Expect(result.Subnets).To(HaveLen(2)) Expect(result.Subnets[0].Subnet.IP).ToNot(BeNil()) Expect(result.Subnets[1].Subnet.IP).ToNot(BeNil()) diff --git a/test/e2e/network_test.go b/test/e2e/network_test.go index 89a9005f5..c67a4baed 100644 --- a/test/e2e/network_test.go +++ b/test/e2e/network_test.go @@ -293,8 +293,8 @@ var _ = Describe("Podman network", func() { Expect(conData[0].NetworkSettings.Networks).To(HaveLen(1)) net, ok := conData[0].NetworkSettings.Networks[netName] Expect(ok).To(BeTrue()) - Expect(net.NetworkID).To(Equal(netName)) - Expect(net.IPPrefixLen).To(Equal(24)) + Expect(net).To(HaveField("NetworkID", netName)) + Expect(net).To(HaveField("IPPrefixLen", 24)) Expect(net.IPAddress).To(HavePrefix("10.50.50.")) // Necessary to ensure the CNI network is removed cleanly @@ -329,10 +329,10 @@ var _ = Describe("Podman network", func() { Expect(conData[0].NetworkSettings.Networks).To(HaveLen(2)) net1, ok := conData[0].NetworkSettings.Networks[netName1] Expect(ok).To(BeTrue()) - Expect(net1.NetworkID).To(Equal(netName1)) + Expect(net1).To(HaveField("NetworkID", netName1)) net2, ok := conData[0].NetworkSettings.Networks[netName2] Expect(ok).To(BeTrue()) - Expect(net2.NetworkID).To(Equal(netName2)) + Expect(net2).To(HaveField("NetworkID", netName2)) // Necessary to ensure the CNI network is removed cleanly rmAll := podmanTest.Podman([]string{"rm", "-t", "0", "-f", ctrName}) @@ -366,13 +366,13 @@ var _ = Describe("Podman network", func() { Expect(conData[0].NetworkSettings.Networks).To(HaveLen(2)) net1, ok := conData[0].NetworkSettings.Networks[netName1] Expect(ok).To(BeTrue()) - Expect(net1.NetworkID).To(Equal(netName1)) - Expect(net1.IPPrefixLen).To(Equal(25)) + Expect(net1).To(HaveField("NetworkID", netName1)) + Expect(net1).To(HaveField("IPPrefixLen", 25)) Expect(net1.IPAddress).To(HavePrefix("10.50.51.")) net2, ok := conData[0].NetworkSettings.Networks[netName2] Expect(ok).To(BeTrue()) - Expect(net2.NetworkID).To(Equal(netName2)) - Expect(net2.IPPrefixLen).To(Equal(26)) + Expect(net2).To(HaveField("NetworkID", netName2)) + Expect(net2).To(HaveField("IPPrefixLen", 26)) Expect(net2.IPAddress).To(HavePrefix("10.50.51.")) // Necessary to ensure the CNI network is removed cleanly @@ -601,7 +601,7 @@ var _ = Describe("Podman network", func() { Expect(err).To(BeNil()) Expect(results).To(HaveLen(1)) result := results[0] - Expect(result.NetworkInterface).To(Equal("")) + Expect(result).To(HaveField("NetworkInterface", "")) Expect(result.IPAMOptions).To(HaveKeyWithValue("driver", "dhcp")) nc = podmanTest.Podman([]string{"network", "rm", net}) @@ -628,8 +628,8 @@ var _ = Describe("Podman network", func() { Expect(results).To(HaveLen(1)) result := results[0] - Expect(result.Driver).To(Equal("macvlan")) - Expect(result.NetworkInterface).To(Equal("lo")) + Expect(result).To(HaveField("Driver", "macvlan")) + Expect(result).To(HaveField("NetworkInterface", "lo")) Expect(result.IPAMOptions).To(HaveKeyWithValue("driver", "dhcp")) Expect(result.Subnets).To(HaveLen(0)) @@ -672,8 +672,8 @@ var _ = Describe("Podman network", func() { result := results[0] Expect(result.Options).To(HaveKeyWithValue("mtu", "1500")) - Expect(result.Driver).To(Equal("macvlan")) - Expect(result.NetworkInterface).To(Equal("lo")) + Expect(result).To(HaveField("Driver", "macvlan")) + Expect(result).To(HaveField("NetworkInterface", "lo")) Expect(result.IPAMOptions).To(HaveKeyWithValue("driver", "host-local")) Expect(result.Subnets).To(HaveLen(1)) diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go index 46a8e88bc..aaefa4625 100644 --- a/test/e2e/play_kube_test.go +++ b/test/e2e/play_kube_test.go @@ -2220,7 +2220,7 @@ spec: Expect(ctr[0].Config.WorkingDir).To(ContainSubstring("/etc")) Expect(ctr[0].Config.Labels).To(HaveKeyWithValue("key1", ContainSubstring("value1"))) Expect(ctr[0].Config.Labels).To(HaveKeyWithValue("key1", ContainSubstring("value1"))) - Expect(ctr[0].Config.StopSignal).To(Equal(uint(51))) + Expect(ctr[0].Config).To(HaveField("StopSignal", uint(51))) }) // Deployment related tests @@ -2528,7 +2528,7 @@ VOLUME %s`, ALPINE, hostPathDir+"/") // only one will be mounted. Host path volumes take precedence. ctrJSON := inspect.InspectContainerToJSON() Expect(ctrJSON[0].Mounts).To(HaveLen(1)) - Expect(ctrJSON[0].Mounts[0].Type).To(Equal("bind")) + Expect(ctrJSON[0].Mounts[0]).To(HaveField("Type", "bind")) }) diff --git a/test/e2e/pod_create_test.go b/test/e2e/pod_create_test.go index 8def80213..0c7886a93 100644 --- a/test/e2e/pod_create_test.go +++ b/test/e2e/pod_create_test.go @@ -279,7 +279,7 @@ var _ = Describe("Podman pod create", func() { ctrInspect.WaitWithDefaultTimeout() Expect(ctrInspect).Should(Exit(0)) ctrJSON := ctrInspect.InspectContainerToJSON() - Expect(ctrJSON[0].NetworkSettings.IPAddress).To(Equal(ip)) + Expect(ctrJSON[0].NetworkSettings).To(HaveField("IPAddress", ip)) }) It("podman create pod with IP address and no infra should fail", func() { @@ -336,7 +336,7 @@ var _ = Describe("Podman pod create", func() { check := podmanTest.Podman([]string{"pod", "inspect", "abc"}) check.WaitWithDefaultTimeout() data := check.InspectPodToJSON() - Expect(data.ID).To(Equal(string(id))) + Expect(data).To(HaveField("ID", string(id))) }) It("podman pod create --replace", func() { @@ -551,8 +551,8 @@ ENTRYPOINT ["sleep","99999"] podInspect.WaitWithDefaultTimeout() Expect(podInspect).Should(Exit(0)) podJSON := podInspect.InspectPodToJSON() - Expect(podJSON.CPUPeriod).To(Equal(period)) - Expect(podJSON.CPUQuota).To(Equal(quota)) + Expect(podJSON).To(HaveField("CPUPeriod", period)) + Expect(podJSON).To(HaveField("CPUQuota", quota)) }) It("podman pod create --cpuset-cpus", func() { @@ -573,7 +573,7 @@ ENTRYPOINT ["sleep","99999"] podInspect.WaitWithDefaultTimeout() Expect(podInspect).Should(Exit(0)) podJSON := podInspect.InspectPodToJSON() - Expect(podJSON.CPUSetCPUs).To(Equal(in)) + Expect(podJSON).To(HaveField("CPUSetCPUs", in)) }) It("podman pod create --pid", func() { @@ -587,7 +587,7 @@ ENTRYPOINT ["sleep","99999"] podInspect.WaitWithDefaultTimeout() Expect(podInspect).Should(Exit(0)) podJSON := podInspect.InspectPodToJSON() - Expect(podJSON.InfraConfig.PidNS).To(Equal(ns)) + Expect(podJSON.InfraConfig).To(HaveField("PidNS", ns)) podName = "pidPod2" ns = "pod" @@ -607,7 +607,7 @@ ENTRYPOINT ["sleep","99999"] podInspect.WaitWithDefaultTimeout() Expect(podInspect).Should(Exit(0)) podJSON = podInspect.InspectPodToJSON() - Expect(podJSON.InfraConfig.PidNS).To(Equal("host")) + Expect(podJSON.InfraConfig).To(HaveField("PidNS", "host")) podName = "pidPod4" ns = "private" @@ -620,7 +620,7 @@ ENTRYPOINT ["sleep","99999"] podInspect.WaitWithDefaultTimeout() Expect(podInspect).Should(Exit(0)) podJSON = podInspect.InspectPodToJSON() - Expect(podJSON.InfraConfig.PidNS).To(Equal("private")) + Expect(podJSON.InfraConfig).To(HaveField("PidNS", "private")) podName = "pidPod5" ns = "container:randomfakeid" @@ -856,7 +856,7 @@ ENTRYPOINT ["sleep","99999"] podInspect.WaitWithDefaultTimeout() Expect(podInspect).Should(Exit(0)) data := podInspect.InspectPodToJSON() - Expect(data.Mounts[0].Name).To(Equal(volName)) + Expect(data.Mounts[0]).To(HaveField("Name", volName)) ctrName := "testCtr" ctrCreate := podmanTest.Podman([]string{"create", "--pod", podName, "--name", ctrName, ALPINE}) ctrCreate.WaitWithDefaultTimeout() @@ -865,7 +865,7 @@ ENTRYPOINT ["sleep","99999"] ctrInspect.WaitWithDefaultTimeout() Expect(ctrInspect).Should(Exit(0)) ctrData := ctrInspect.InspectContainerToJSON() - Expect(ctrData[0].Mounts[0].Name).To(Equal(volName)) + Expect(ctrData[0].Mounts[0]).To(HaveField("Name", volName)) ctr2 := podmanTest.Podman([]string{"run", "--pod", podName, ALPINE, "sh", "-c", "echo hello >> " + "/tmp1/test"}) ctr2.WaitWithDefaultTimeout() @@ -934,7 +934,7 @@ ENTRYPOINT ["sleep","99999"] ctrInspect.WaitWithDefaultTimeout() Expect(ctrInspect).Should(Exit(0)) data := ctrInspect.InspectContainerToJSON() - Expect(data[0].Mounts[0].Name).To(Equal(volName)) + Expect(data[0].Mounts[0]).To(HaveField("Name", volName)) podName := "testPod" podCreate := podmanTest.Podman([]string{"pod", "create", "--volumes-from", ctrName, "--name", podName}) podCreate.WaitWithDefaultTimeout() @@ -943,7 +943,7 @@ ENTRYPOINT ["sleep","99999"] podInspect.WaitWithDefaultTimeout() Expect(podInspect).Should(Exit(0)) podData := podInspect.InspectPodToJSON() - Expect(podData.Mounts[0].Name).To(Equal(volName)) + Expect(podData.Mounts[0]).To(HaveField("Name", volName)) ctr2 := podmanTest.Podman([]string{"run", "--pod", podName, ALPINE, "sh", "-c", "echo hello >> " + "/tmp1/test"}) ctr2.WaitWithDefaultTimeout() @@ -986,7 +986,7 @@ ENTRYPOINT ["sleep","99999"] Expect(ctrCreate).Should(Exit(0)) ctrInspect := podmanTest.InspectContainer(ctrCreate.OutputToString()) - Expect(ctrInspect[0].HostConfig.SecurityOpt).To(Equal([]string{"label=type:spc_t", "seccomp=unconfined"})) + Expect(ctrInspect[0].HostConfig).To(HaveField("SecurityOpt", []string{"label=type:spc_t", "seccomp=unconfined"})) podCreate = podmanTest.Podman([]string{"pod", "create", "--security-opt", "label=disable"}) podCreate.WaitWithDefaultTimeout() @@ -1012,7 +1012,7 @@ ENTRYPOINT ["sleep","99999"] Expect(ctrCreate).Should(Exit(0)) ctrInspect := podmanTest.InspectContainer(ctrCreate.OutputToString()) - Expect(ctrInspect[0].HostConfig.SecurityOpt).To(Equal([]string{"seccomp=unconfined"})) + Expect(ctrInspect[0].HostConfig).To(HaveField("SecurityOpt", []string{"seccomp=unconfined"})) }) It("podman pod create --security-opt apparmor test", func() { @@ -1028,7 +1028,7 @@ ENTRYPOINT ["sleep","99999"] Expect(ctrCreate).Should(Exit(0)) inspect := podmanTest.InspectContainer(ctrCreate.OutputToString()) - Expect(inspect[0].AppArmorProfile).To(Equal(apparmor.Profile)) + Expect(inspect[0]).To(HaveField("AppArmorProfile", apparmor.Profile)) }) @@ -1090,7 +1090,7 @@ ENTRYPOINT ["sleep","99999"] if podmanTest.CgroupManager == "cgroupfs" || !rootless.IsRootless() { Expect(inspect[0].HostConfig.CgroupParent).To(HaveLen(0)) } else if podmanTest.CgroupManager == "systemd" { - Expect(inspect[0].HostConfig.CgroupParent).To(Equal("user.slice")) + Expect(inspect[0].HostConfig).To(HaveField("CgroupParent", "user.slice")) } podCreate2 := podmanTest.Podman([]string{"pod", "create", "--share", "cgroup,ipc,net,uts", "--share-parent=false", "--infra-name", "cgroupCtr"}) diff --git a/test/e2e/pod_initcontainers_test.go b/test/e2e/pod_initcontainers_test.go index cefaa3dc1..3c660c5bf 100644 --- a/test/e2e/pod_initcontainers_test.go +++ b/test/e2e/pod_initcontainers_test.go @@ -66,7 +66,7 @@ var _ = Describe("Podman init containers", func() { inspect.WaitWithDefaultTimeout() Expect(inspect).Should(Exit(0)) data := inspect.InspectPodToJSON() - Expect(data.State).To(Equal(define.PodStateRunning)) + Expect(data).To(HaveField("State", define.PodStateRunning)) }) It("podman create init container should fail in running pod", func() { diff --git a/test/e2e/pod_inspect_test.go b/test/e2e/pod_inspect_test.go index 19a2772fd..dcc70e4a5 100644 --- a/test/e2e/pod_inspect_test.go +++ b/test/e2e/pod_inspect_test.go @@ -58,7 +58,7 @@ var _ = Describe("Podman pod inspect", func() { Expect(inspect).Should(Exit(0)) Expect(inspect.OutputToString()).To(BeValidJSON()) podData := inspect.InspectPodToJSON() - Expect(podData.ID).To(Equal(podid)) + Expect(podData).To(HaveField("ID", podid)) }) It("podman pod inspect (CreateCommand)", func() { @@ -98,7 +98,7 @@ var _ = Describe("Podman pod inspect", func() { Expect(err).To(BeNil()) Expect(inspectJSON.InfraConfig).To(Not(BeNil())) Expect(inspectJSON.InfraConfig.PortBindings["80/tcp"]).To(HaveLen(1)) - Expect(inspectJSON.InfraConfig.PortBindings["80/tcp"][0].HostPort).To(Equal("8383")) + Expect(inspectJSON.InfraConfig.PortBindings["80/tcp"][0]).To(HaveField("HostPort", "8383")) }) It("podman pod inspect outputs show correct MAC", func() { diff --git a/test/e2e/pull_test.go b/test/e2e/pull_test.go index 231869e8c..d13334651 100644 --- a/test/e2e/pull_test.go +++ b/test/e2e/pull_test.go @@ -514,7 +514,7 @@ var _ = Describe("Podman pull", func() { Expect(data).To(HaveLen(1)) Expect(data[0].RepoTags).To(HaveLen(1)) Expect(data[0].RepoTags[0]).To(Equal(t.tag1)) - Expect(data[0].ID).To(Equal(image1)) + Expect(data[0]).To(HaveField("ID", image1)) } }) @@ -541,8 +541,8 @@ var _ = Describe("Podman pull", func() { data := setup.InspectImageJSON() // returns []inspect.ImageData Expect(data).To(HaveLen(1)) - Expect(data[0].Os).To(Equal(runtime.GOOS)) - Expect(data[0].Architecture).To(Equal("arm64")) + Expect(data[0]).To(HaveField("Os", runtime.GOOS)) + Expect(data[0]).To(HaveField("Architecture", "arm64")) }) It("podman pull --arch", func() { @@ -568,7 +568,7 @@ var _ = Describe("Podman pull", func() { data := setup.InspectImageJSON() // returns []inspect.ImageData Expect(data).To(HaveLen(1)) - Expect(data[0].Os).To(Equal(runtime.GOOS)) - Expect(data[0].Architecture).To(Equal("arm64")) + Expect(data[0]).To(HaveField("Os", runtime.GOOS)) + Expect(data[0]).To(HaveField("Architecture", "arm64")) }) }) diff --git a/test/e2e/run_apparmor_test.go b/test/e2e/run_apparmor_test.go index 64a01deb7..ed88ab7a0 100644 --- a/test/e2e/run_apparmor_test.go +++ b/test/e2e/run_apparmor_test.go @@ -61,7 +61,7 @@ var _ = Describe("Podman run", func() { cid := session.OutputToString() // Verify that apparmor.Profile is being set inspect := podmanTest.InspectContainer(cid) - Expect(inspect[0].AppArmorProfile).To(Equal(apparmor.Profile)) + Expect(inspect[0]).To(HaveField("AppArmorProfile", apparmor.Profile)) }) It("podman run no apparmor --privileged", func() { @@ -73,7 +73,7 @@ var _ = Describe("Podman run", func() { cid := session.OutputToString() // Verify that apparmor.Profile is being set inspect := podmanTest.InspectContainer(cid) - Expect(inspect[0].AppArmorProfile).To(Equal("")) + Expect(inspect[0]).To(HaveField("AppArmorProfile", "")) }) It("podman run no apparmor --security-opt=apparmor.Profile --privileged", func() { @@ -85,7 +85,7 @@ var _ = Describe("Podman run", func() { cid := session.OutputToString() // Verify that apparmor.Profile is being set inspect := podmanTest.InspectContainer(cid) - Expect(inspect[0].AppArmorProfile).To(Equal(apparmor.Profile)) + Expect(inspect[0]).To(HaveField("AppArmorProfile", apparmor.Profile)) }) It("podman run apparmor aa-test-profile", func() { @@ -116,7 +116,7 @@ profile aa-test-profile flags=(attach_disconnected,mediate_deleted) { cid := session.OutputToString() // Verify that apparmor.Profile is being set inspect := podmanTest.InspectContainer(cid) - Expect(inspect[0].AppArmorProfile).To(Equal("aa-test-profile")) + Expect(inspect[0]).To(HaveField("AppArmorProfile", "aa-test-profile")) }) It("podman run apparmor invalid", func() { @@ -135,7 +135,7 @@ profile aa-test-profile flags=(attach_disconnected,mediate_deleted) { cid := session.OutputToString() // Verify that apparmor.Profile is being set inspect := podmanTest.InspectContainer(cid) - Expect(inspect[0].AppArmorProfile).To(Equal("unconfined")) + Expect(inspect[0]).To(HaveField("AppArmorProfile", "unconfined")) }) It("podman run apparmor disabled --security-opt apparmor fails", func() { @@ -156,7 +156,7 @@ profile aa-test-profile flags=(attach_disconnected,mediate_deleted) { cid := session.OutputToString() // Verify that apparmor.Profile is being set inspect := podmanTest.InspectContainer(cid) - Expect(inspect[0].AppArmorProfile).To(Equal("")) + Expect(inspect[0]).To(HaveField("AppArmorProfile", "")) }) It("podman run apparmor disabled unconfined", func() { @@ -169,6 +169,6 @@ profile aa-test-profile flags=(attach_disconnected,mediate_deleted) { cid := session.OutputToString() // Verify that apparmor.Profile is being set inspect := podmanTest.InspectContainer(cid) - Expect(inspect[0].AppArmorProfile).To(Equal("")) + Expect(inspect[0]).To(HaveField("AppArmorProfile", "")) }) }) diff --git a/test/e2e/run_networking_test.go b/test/e2e/run_networking_test.go index 49c387227..53a91b2b3 100644 --- a/test/e2e/run_networking_test.go +++ b/test/e2e/run_networking_test.go @@ -99,7 +99,7 @@ var _ = Describe("Podman run networking", func() { Expect(inspectOut[0].NetworkSettings.Ports).To(HaveLen(1)) Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"]).To(HaveLen(1)) Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Not(Equal("80"))) - Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal("")) + Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0]).To(HaveField("HostIP", "")) }) It("podman run -p 80-82 -p 8090:8090", func() { @@ -111,16 +111,16 @@ var _ = Describe("Podman run networking", func() { Expect(inspectOut[0].NetworkSettings.Ports).To(HaveLen(4)) Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"]).To(HaveLen(1)) Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Not(Equal("80"))) - Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal("")) + Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0]).To(HaveField("HostIP", "")) Expect(inspectOut[0].NetworkSettings.Ports["81/tcp"]).To(HaveLen(1)) Expect(inspectOut[0].NetworkSettings.Ports["81/tcp"][0].HostPort).To(Not(Equal("81"))) - Expect(inspectOut[0].NetworkSettings.Ports["81/tcp"][0].HostIP).To(Equal("")) + Expect(inspectOut[0].NetworkSettings.Ports["81/tcp"][0]).To(HaveField("HostIP", "")) Expect(inspectOut[0].NetworkSettings.Ports["82/tcp"]).To(HaveLen(1)) Expect(inspectOut[0].NetworkSettings.Ports["82/tcp"][0].HostPort).To(Not(Equal("82"))) - Expect(inspectOut[0].NetworkSettings.Ports["82/tcp"][0].HostIP).To(Equal("")) + Expect(inspectOut[0].NetworkSettings.Ports["82/tcp"][0]).To(HaveField("HostIP", "")) Expect(inspectOut[0].NetworkSettings.Ports["8090/tcp"]).To(HaveLen(1)) - Expect(inspectOut[0].NetworkSettings.Ports["8090/tcp"][0].HostPort).To(Equal("8090")) - Expect(inspectOut[0].NetworkSettings.Ports["8090/tcp"][0].HostIP).To(Equal("")) + Expect(inspectOut[0].NetworkSettings.Ports["8090/tcp"][0]).To(HaveField("HostPort", "8090")) + Expect(inspectOut[0].NetworkSettings.Ports["8090/tcp"][0]).To(HaveField("HostIP", "")) }) It("podman run -p 80-81 -p 8180-8181", func() { @@ -132,16 +132,16 @@ var _ = Describe("Podman run networking", func() { Expect(inspectOut[0].NetworkSettings.Ports).To(HaveLen(4)) Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"]).To(HaveLen(1)) Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Not(Equal("80"))) - Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal("")) + Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0]).To(HaveField("HostIP", "")) Expect(inspectOut[0].NetworkSettings.Ports["81/tcp"]).To(HaveLen(1)) Expect(inspectOut[0].NetworkSettings.Ports["81/tcp"][0].HostPort).To(Not(Equal("81"))) - Expect(inspectOut[0].NetworkSettings.Ports["81/tcp"][0].HostIP).To(Equal("")) + Expect(inspectOut[0].NetworkSettings.Ports["81/tcp"][0]).To(HaveField("HostIP", "")) Expect(inspectOut[0].NetworkSettings.Ports["8180/tcp"]).To(HaveLen(1)) Expect(inspectOut[0].NetworkSettings.Ports["8180/tcp"][0].HostPort).To(Not(Equal("8180"))) - Expect(inspectOut[0].NetworkSettings.Ports["8180/tcp"][0].HostIP).To(Equal("")) + Expect(inspectOut[0].NetworkSettings.Ports["8180/tcp"][0]).To(HaveField("HostIP", "")) Expect(inspectOut[0].NetworkSettings.Ports["8181/tcp"]).To(HaveLen(1)) Expect(inspectOut[0].NetworkSettings.Ports["8181/tcp"][0].HostPort).To(Not(Equal("8181"))) - Expect(inspectOut[0].NetworkSettings.Ports["8181/tcp"][0].HostIP).To(Equal("")) + Expect(inspectOut[0].NetworkSettings.Ports["8181/tcp"][0]).To(HaveField("HostIP", "")) }) It("podman run -p 80 -p 8280-8282:8280-8282", func() { @@ -153,16 +153,16 @@ var _ = Describe("Podman run networking", func() { Expect(inspectOut[0].NetworkSettings.Ports).To(HaveLen(4)) Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"]).To(HaveLen(1)) Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Not(Equal("80"))) - Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal("")) + Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0]).To(HaveField("HostIP", "")) Expect(inspectOut[0].NetworkSettings.Ports["8280/tcp"]).To(HaveLen(1)) - Expect(inspectOut[0].NetworkSettings.Ports["8280/tcp"][0].HostPort).To(Equal("8280")) - Expect(inspectOut[0].NetworkSettings.Ports["8280/tcp"][0].HostIP).To(Equal("")) + Expect(inspectOut[0].NetworkSettings.Ports["8280/tcp"][0]).To(HaveField("HostPort", "8280")) + Expect(inspectOut[0].NetworkSettings.Ports["8280/tcp"][0]).To(HaveField("HostIP", "")) Expect(inspectOut[0].NetworkSettings.Ports["8281/tcp"]).To(HaveLen(1)) - Expect(inspectOut[0].NetworkSettings.Ports["8281/tcp"][0].HostPort).To(Equal("8281")) - Expect(inspectOut[0].NetworkSettings.Ports["8281/tcp"][0].HostIP).To(Equal("")) + Expect(inspectOut[0].NetworkSettings.Ports["8281/tcp"][0]).To(HaveField("HostPort", "8281")) + Expect(inspectOut[0].NetworkSettings.Ports["8281/tcp"][0]).To(HaveField("HostIP", "")) Expect(inspectOut[0].NetworkSettings.Ports["8282/tcp"]).To(HaveLen(1)) - Expect(inspectOut[0].NetworkSettings.Ports["8282/tcp"][0].HostPort).To(Equal("8282")) - Expect(inspectOut[0].NetworkSettings.Ports["8282/tcp"][0].HostIP).To(Equal("")) + Expect(inspectOut[0].NetworkSettings.Ports["8282/tcp"][0]).To(HaveField("HostPort", "8282")) + Expect(inspectOut[0].NetworkSettings.Ports["8282/tcp"][0]).To(HaveField("HostIP", "")) }) It("podman run -p 8380:80", func() { @@ -173,8 +173,8 @@ var _ = Describe("Podman run networking", func() { Expect(inspectOut).To(HaveLen(1)) Expect(inspectOut[0].NetworkSettings.Ports).To(HaveLen(1)) Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"]).To(HaveLen(1)) - Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Equal("8380")) - Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal("")) + Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0]).To(HaveField("HostPort", "8380")) + Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0]).To(HaveField("HostIP", "")) }) It("podman run -p 8480:80/TCP", func() { @@ -187,8 +187,8 @@ var _ = Describe("Podman run networking", func() { Expect(inspectOut[0].NetworkSettings.Ports).To(HaveLen(1)) // "tcp" in lower characters Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"]).To(HaveLen(1)) - Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Equal("8480")) - Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal("")) + Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0]).To(HaveField("HostPort", "8480")) + Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0]).To(HaveField("HostIP", "")) }) It("podman run -p 80/udp", func() { @@ -200,7 +200,7 @@ var _ = Describe("Podman run networking", func() { Expect(inspectOut[0].NetworkSettings.Ports).To(HaveLen(1)) Expect(inspectOut[0].NetworkSettings.Ports["80/udp"]).To(HaveLen(1)) Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0].HostPort).To(Not(Equal("80"))) - Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0].HostIP).To(Equal("")) + Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0]).To(HaveField("HostIP", "")) }) It("podman run -p 127.0.0.1:8580:80", func() { @@ -211,8 +211,8 @@ var _ = Describe("Podman run networking", func() { Expect(inspectOut).To(HaveLen(1)) Expect(inspectOut[0].NetworkSettings.Ports).To(HaveLen(1)) Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"]).To(HaveLen(1)) - Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Equal("8580")) - Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal("127.0.0.1")) + Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0]).To(HaveField("HostPort", "8580")) + Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0]).To(HaveField("HostIP", "127.0.0.1")) }) It("podman run -p 127.0.0.1:8680:80/udp", func() { @@ -223,8 +223,8 @@ var _ = Describe("Podman run networking", func() { Expect(inspectOut).To(HaveLen(1)) Expect(inspectOut[0].NetworkSettings.Ports).To(HaveLen(1)) Expect(inspectOut[0].NetworkSettings.Ports["80/udp"]).To(HaveLen(1)) - Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0].HostPort).To(Equal("8680")) - Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0].HostIP).To(Equal("127.0.0.1")) + Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0]).To(HaveField("HostPort", "8680")) + Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0]).To(HaveField("HostIP", "127.0.0.1")) }) It("podman run -p [::1]:8780:80/udp", func() { @@ -235,8 +235,8 @@ var _ = Describe("Podman run networking", func() { Expect(inspectOut).To(HaveLen(1)) Expect(inspectOut[0].NetworkSettings.Ports).To(HaveLen(1)) Expect(inspectOut[0].NetworkSettings.Ports["80/udp"]).To(HaveLen(1)) - Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0].HostPort).To(Equal("8780")) - Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0].HostIP).To(Equal("::1")) + Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0]).To(HaveField("HostPort", "8780")) + Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0]).To(HaveField("HostIP", "::1")) }) It("podman run -p [::1]:8880:80/tcp", func() { @@ -247,8 +247,8 @@ var _ = Describe("Podman run networking", func() { Expect(inspectOut).To(HaveLen(1)) Expect(inspectOut[0].NetworkSettings.Ports).To(HaveLen(1)) Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"]).To(HaveLen(1)) - Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Equal("8880")) - Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal("::1")) + Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0]).To(HaveField("HostPort", "8880")) + Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0]).To(HaveField("HostIP", "::1")) }) It("podman run --expose 80 -P", func() { @@ -260,7 +260,7 @@ var _ = Describe("Podman run networking", func() { Expect(inspectOut[0].NetworkSettings.Ports).To(HaveLen(1)) Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"]).To(HaveLen(1)) Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Not(Equal("0"))) - Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal("")) + Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0]).To(HaveField("HostIP", "")) }) It("podman run --expose 80/udp -P", func() { @@ -272,7 +272,7 @@ var _ = Describe("Podman run networking", func() { Expect(inspectOut[0].NetworkSettings.Ports).To(HaveLen(1)) Expect(inspectOut[0].NetworkSettings.Ports["80/udp"]).To(HaveLen(1)) Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0].HostPort).To(Not(Equal("0"))) - Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0].HostIP).To(Equal("")) + Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0]).To(HaveField("HostIP", "")) }) It("podman run --expose 80 -p 80", func() { @@ -284,7 +284,7 @@ var _ = Describe("Podman run networking", func() { Expect(inspectOut[0].NetworkSettings.Ports).To(HaveLen(1)) Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"]).To(HaveLen(1)) Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Not(Equal("80"))) - Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal("")) + Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0]).To(HaveField("HostIP", "")) }) It("podman run --publish-all with EXPOSE port ranges in Dockerfile", func() { @@ -332,7 +332,7 @@ EXPOSE 2004-2005/tcp`, ALPINE) Expect(inspectOut[0].NetworkSettings.Ports).To(HaveLen(1)) Expect(inspectOut[0].NetworkSettings.Ports["8980/udp"]).To(HaveLen(1)) Expect(inspectOut[0].NetworkSettings.Ports["8980/udp"][0].HostPort).To(Not(Equal("8980"))) - Expect(inspectOut[0].NetworkSettings.Ports["8980/udp"][0].HostIP).To(Equal("127.0.0.1")) + Expect(inspectOut[0].NetworkSettings.Ports["8980/udp"][0]).To(HaveField("HostIP", "127.0.0.1")) }) It("podman run -p :8181", func() { @@ -344,7 +344,7 @@ EXPOSE 2004-2005/tcp`, ALPINE) Expect(inspectOut[0].NetworkSettings.Ports).To(HaveLen(1)) Expect(inspectOut[0].NetworkSettings.Ports["8181/tcp"]).To(HaveLen(1)) Expect(inspectOut[0].NetworkSettings.Ports["8181/tcp"][0].HostPort).To(Not(Equal("8181"))) - Expect(inspectOut[0].NetworkSettings.Ports["8181/tcp"][0].HostIP).To(Equal("")) + Expect(inspectOut[0].NetworkSettings.Ports["8181/tcp"][0]).To(HaveField("HostIP", "")) }) It("podman run -p xxx:8080 -p yyy:8080", func() { @@ -371,8 +371,8 @@ EXPOSE 2004-2005/tcp`, ALPINE) Expect(inspectOut).To(HaveLen(1)) Expect(inspectOut[0].NetworkSettings.Ports).To(HaveLen(1)) Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"]).To(HaveLen(1)) - Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Equal("9280")) - Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal("")) + Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0]).To(HaveField("HostPort", "9280")) + Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0]).To(HaveField("HostIP", "")) }) It("podman run network expose host port 80 to container port", func() { @@ -763,18 +763,18 @@ EXPOSE 2004-2005/tcp`, ALPINE) checkNetworkNsInspect := func(name string) { inspectOut := podmanTest.InspectContainer(name) - Expect(inspectOut[0].NetworkSettings.IPAddress).To(Equal("10.25.40.0")) - Expect(inspectOut[0].NetworkSettings.IPPrefixLen).To(Equal(24)) + Expect(inspectOut[0].NetworkSettings).To(HaveField("IPAddress", "10.25.40.0")) + Expect(inspectOut[0].NetworkSettings).To(HaveField("IPPrefixLen", 24)) Expect(len(inspectOut[0].NetworkSettings.SecondaryIPAddresses)).To(Equal(1)) - Expect(inspectOut[0].NetworkSettings.SecondaryIPAddresses[0].Addr).To(Equal("10.88.0.0")) - Expect(inspectOut[0].NetworkSettings.SecondaryIPAddresses[0].PrefixLength).To(Equal(16)) - Expect(inspectOut[0].NetworkSettings.GlobalIPv6Address).To(Equal("fd04:3e42:4a4e:3381::")) - Expect(inspectOut[0].NetworkSettings.GlobalIPv6PrefixLen).To(Equal(64)) + Expect(inspectOut[0].NetworkSettings.SecondaryIPAddresses[0]).To(HaveField("Addr", "10.88.0.0")) + Expect(inspectOut[0].NetworkSettings.SecondaryIPAddresses[0]).To(HaveField("PrefixLength", 16)) + Expect(inspectOut[0].NetworkSettings).To(HaveField("GlobalIPv6Address", "fd04:3e42:4a4e:3381::")) + Expect(inspectOut[0].NetworkSettings).To(HaveField("GlobalIPv6PrefixLen", 64)) Expect(len(inspectOut[0].NetworkSettings.SecondaryIPv6Addresses)).To(Equal(0)) - Expect(inspectOut[0].NetworkSettings.MacAddress).To(Equal("46:7f:45:6e:4f:c8")) + Expect(inspectOut[0].NetworkSettings).To(HaveField("MacAddress", "46:7f:45:6e:4f:c8")) Expect(len(inspectOut[0].NetworkSettings.AdditionalMacAddresses)).To(Equal(1)) Expect(inspectOut[0].NetworkSettings.AdditionalMacAddresses[0]).To(Equal("56:6e:35:5d:3e:a8")) - Expect(inspectOut[0].NetworkSettings.Gateway).To(Equal("10.25.40.0")) + Expect(inspectOut[0].NetworkSettings).To(HaveField("Gateway", "10.25.40.0")) } @@ -796,7 +796,7 @@ EXPOSE 2004-2005/tcp`, ALPINE) Expect(delNetworkNamespace).Should(Exit(0)) inspectOut := podmanTest.InspectContainer(name) - Expect(inspectOut[0].NetworkSettings.IPAddress).To(Equal("")) + Expect(inspectOut[0].NetworkSettings).To(HaveField("IPAddress", "")) Expect(len(inspectOut[0].NetworkSettings.Networks)).To(Equal(0)) }) @@ -1133,6 +1133,8 @@ EXPOSE 2004-2005/tcp`, ALPINE) }) It("podman run with ipam none driver", func() { + // Test fails, issue #13931 + SkipIfNetavark(podmanTest) net := "ipam" + stringid.GenerateNonCryptoID() session := podmanTest.Podman([]string{"network", "create", "--ipam-driver=none", net}) session.WaitWithDefaultTimeout() diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go index 4c399dc2b..386a27a2f 100644 --- a/test/e2e/run_test.go +++ b/test/e2e/run_test.go @@ -288,7 +288,7 @@ var _ = Describe("Podman run", func() { result.WaitWithDefaultTimeout() Expect(result).Should(Exit(0)) conData := result.InspectContainerToJSON() - Expect(conData[0].Path).To(Equal("/dev/init")) + Expect(conData[0]).To(HaveField("Path", "/dev/init")) Expect(conData[0].Config.Annotations).To(HaveKeyWithValue("io.podman.annotations.init", "TRUE")) }) @@ -300,7 +300,7 @@ var _ = Describe("Podman run", func() { result.WaitWithDefaultTimeout() Expect(result).Should(Exit(0)) conData := result.InspectContainerToJSON() - Expect(conData[0].Path).To(Equal("/dev/init")) + Expect(conData[0]).To(HaveField("Path", "/dev/init")) Expect(conData[0].Config.Annotations).To(HaveKeyWithValue("io.podman.annotations.init", "TRUE")) }) @@ -312,7 +312,7 @@ var _ = Describe("Podman run", func() { result.WaitWithDefaultTimeout() Expect(result).Should(Exit(0)) conData := result.InspectContainerToJSON() - Expect(conData[0].Path).To(Equal("ls")) + Expect(conData[0]).To(HaveField("Path", "ls")) Expect(conData[0].Config.Annotations).To(HaveKeyWithValue("io.podman.annotations.init", "FALSE")) }) diff --git a/test/e2e/run_volume_test.go b/test/e2e/run_volume_test.go index a31c1959e..4f1013f8d 100644 --- a/test/e2e/run_volume_test.go +++ b/test/e2e/run_volume_test.go @@ -588,8 +588,8 @@ VOLUME /test/`, ALPINE) data := podmanTest.InspectContainer(ctrName) Expect(data).To(HaveLen(1)) Expect(data[0].Mounts).To(HaveLen(1)) - Expect(data[0].Mounts[0].Source).To(Equal("/tmp")) - Expect(data[0].Mounts[0].Destination).To(Equal("/test")) + Expect(data[0].Mounts[0]).To(HaveField("Source", "/tmp")) + Expect(data[0].Mounts[0]).To(HaveField("Destination", "/test")) }) It("podman run with overlay volume flag", func() { diff --git a/test/system/110-history.bats b/test/system/110-history.bats index 0f6d75cb3..da6f2177c 100644 --- a/test/system/110-history.bats +++ b/test/system/110-history.bats @@ -55,4 +55,17 @@ size | -\\\?[0-9]\\\+ } +@test "podman image history Created" { + # Values from image LIST + run_podman image list --format '{{.CreatedSince}}--{{.CreatedAt}}' $IMAGE + from_imagelist="$output" + assert "$from_imagelist" =~ "^[0-9].* ago--[0-9]+-[0-9]+-[0-9]+ [0-9:]+ " \ + "CreatedSince and CreatedAt look reasonable" + + # Values from image HISTORY + run_podman image history --format '{{.CreatedSince}}--{{.CreatedAt}}' $IMAGE + assert "${lines[0]}" == "$from_imagelist" \ + "CreatedSince and CreatedAt from image history should == image list" +} + # vim: filetype=sh diff --git a/test/system/200-pod.bats b/test/system/200-pod.bats index ef4bf1a6c..64f95f723 100644 --- a/test/system/200-pod.bats +++ b/test/system/200-pod.bats @@ -381,4 +381,32 @@ EOF is "$output" ".*$container_3_ID.*" } +@test "podman pod create share net" { + run_podman pod create --name test + run_podman pod inspect test --format {{.InfraConfig.HostNetwork}} + is "$output" "false" "Default network sharing should be false" + run_podman pod rm test + + run_podman pod create --name test --share ipc --network private + run_podman pod inspect test --format {{.InfraConfig.HostNetwork}} + is "$output" "false" "Private network sharing with only ipc should be false" + run_podman pod rm test + + run_podman pod create --name test --share net --network private + run_podman pod inspect test --format {{.InfraConfig.HostNetwork}} + is "$output" "false" "Private network sharing with only net should be false" + run_podman pod rm test + + run_podman pod create --name test --share net --network host + run_podman pod inspect test --format {{.InfraConfig.HostNetwork}} + is "$output" "true" "Host network sharing with only net should be true" + run_podman pod rm test + + run_podman pod create --name test --share ipc --network host + run_podman pod inspect test --format {{.InfraConfig.HostNetwork}} + is "$output" "true" "Host network sharing with only ipc should be true" + run_podman pod rm test + +} + # vim: filetype=sh diff --git a/test/test_podman_baseline.sh b/test/test_podman_baseline.sh index 5a420fe60..5ef2d1bda 100755 --- a/test/test_podman_baseline.sh +++ b/test/test_podman_baseline.sh @@ -309,6 +309,28 @@ else echo "Overlay test within limits failed" fi +before=`xfs_quota -x -c 'report -N -p' $TMPDIR | grep -c ^#` +podman $PODMANBASE volume create -o o=noquota test-no-quota +after=`xfs_quota -x -c 'report -N -p' $TMPDIR | grep -c ^#` + +if [ $before != $after ]; +then + echo "Test -o=noquota doesn't create a projid failed" +else + echo "Test -o=noquota doesn't create a projid passed" +fi + +before=`xfs_quota -x -c 'report -N -p' $TMPDIR | grep -c ^#` +podman $PODMANBASE volume create -o test-no-quota +after=`xfs_quota -x -c 'report -N -p' $TMPDIR | grep -c ^#` + +if [ $before == $after ]; +then + echo "Test without -o=noquota creates a projid failed" +else + echo "Test without -o=noquota creates a projid passed" +fi + ######## # Expected to fail ######## diff --git a/vendor/github.com/containernetworking/cni/libcni/conf.go b/vendor/github.com/containernetworking/cni/libcni/conf.go index d28135ff3..3cd6a59d1 100644 --- a/vendor/github.com/containernetworking/cni/libcni/conf.go +++ b/vendor/github.com/containernetworking/cni/libcni/conf.go @@ -21,6 +21,8 @@ import ( "os" "path/filepath" "sort" + + "github.com/containernetworking/cni/pkg/types" ) type NotFoundError struct { @@ -41,8 +43,8 @@ func (e NoConfigsFoundError) Error() string { } func ConfFromBytes(bytes []byte) (*NetworkConfig, error) { - conf := &NetworkConfig{Bytes: bytes} - if err := json.Unmarshal(bytes, &conf.Network); err != nil { + conf := &NetworkConfig{Bytes: bytes, Network: &types.NetConf{}} + if err := json.Unmarshal(bytes, conf.Network); err != nil { return nil, fmt.Errorf("error parsing configuration: %w", err) } if conf.Network.Type == "" { diff --git a/vendor/github.com/containernetworking/cni/pkg/version/plugin.go b/vendor/github.com/containernetworking/cni/pkg/version/plugin.go index d4bc9d169..17b22b6b0 100644 --- a/vendor/github.com/containernetworking/cni/pkg/version/plugin.go +++ b/vendor/github.com/containernetworking/cni/pkg/version/plugin.go @@ -86,8 +86,8 @@ func (*PluginDecoder) Decode(jsonBytes []byte) (PluginInfo, error) { // minor, and micro numbers or returns an error func ParseVersion(version string) (int, int, int, error) { var major, minor, micro int - if version == "" { - return -1, -1, -1, fmt.Errorf("invalid version %q: the version is empty", version) + if version == "" { // special case: no version declared == v0.1.0 + return 0, 1, 0, nil } parts := strings.Split(version, ".") diff --git a/vendor/modules.txt b/vendor/modules.txt index 9837b3e61..bbee8a7fb 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -72,7 +72,7 @@ github.com/containerd/containerd/sys # github.com/containerd/stargz-snapshotter/estargz v0.11.4 github.com/containerd/stargz-snapshotter/estargz github.com/containerd/stargz-snapshotter/estargz/errorutil -# github.com/containernetworking/cni v1.0.1 +# github.com/containernetworking/cni v1.1.0 ## explicit github.com/containernetworking/cni/libcni github.com/containernetworking/cni/pkg/invoke |