summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml188
-rw-r--r--Makefile1
-rw-r--r--cmd/podman/generate.go23
-rw-r--r--cmd/podman/generate_kube.go (renamed from cmd/podman/kube_generate.go)67
-rw-r--r--cmd/podman/kube.go23
-rw-r--r--commands.md1
-rw-r--r--completions/bash/podman28
-rw-r--r--contrib/cirrus/README.md166
-rwxr-xr-xcontrib/cirrus/build_vm_images.sh39
-rwxr-xr-xcontrib/cirrus/integration_test.sh9
-rw-r--r--contrib/cirrus/lib.sh54
-rw-r--r--contrib/cirrus/packer/.gitignore7
-rw-r--r--contrib/cirrus/packer/Makefile108
-rw-r--r--contrib/cirrus/packer/README.md3
-rw-r--r--contrib/cirrus/packer/fah_base-setup.sh45
-rw-r--r--contrib/cirrus/packer/fah_setup.sh23
-rw-r--r--contrib/cirrus/packer/fedora_base-setup.sh27
-rw-r--r--contrib/cirrus/packer/fedora_setup.sh3
-rw-r--r--contrib/cirrus/packer/image-builder-image_base-setup.sh75
-rw-r--r--contrib/cirrus/packer/libpod_base_images.yml179
-rw-r--r--contrib/cirrus/packer/libpod_images.json130
-rw-r--r--contrib/cirrus/packer/libpod_images.yml91
-rw-r--r--contrib/cirrus/packer/make-user-data.sh20
-rw-r--r--contrib/cirrus/packer/rhel_base-setup.sh52
-rw-r--r--contrib/cirrus/packer/rhel_setup.sh38
-rw-r--r--contrib/cirrus/packer/ubuntu_setup.sh3
-rwxr-xr-xcontrib/cirrus/setup_environment.sh13
-rwxr-xr-xcontrib/cirrus/system_test.sh2
-rwxr-xr-xcontrib/cirrus/unit_test.sh12
-rwxr-xr-xcontrib/cirrus/verify_source.sh30
-rw-r--r--contrib/python/podman/Makefile6
-rw-r--r--contrib/python/pypodman/Makefile4
-rw-r--r--contrib/python/pypodman/pypodman/lib/__init__.py9
-rw-r--r--contrib/python/pypodman/pypodman/lib/action_base.py30
-rw-r--r--contrib/python/pypodman/pypodman/lib/actions/_create_args.py61
-rw-r--r--contrib/python/pypodman/pypodman/lib/actions/commit_action.py9
-rw-r--r--contrib/python/pypodman/pypodman/lib/actions/history_action.py10
-rw-r--r--contrib/python/pypodman/pypodman/lib/actions/images_action.py6
-rw-r--r--contrib/python/pypodman/pypodman/lib/actions/info_action.py4
-rw-r--r--contrib/python/pypodman/pypodman/lib/actions/inspect_action.py11
-rw-r--r--contrib/python/pypodman/pypodman/lib/actions/kill_action.py12
-rw-r--r--contrib/python/pypodman/pypodman/lib/actions/pause_action.py4
-rw-r--r--contrib/python/pypodman/pypodman/lib/actions/pod/create_parser.py9
-rw-r--r--contrib/python/pypodman/pypodman/lib/actions/pod/kill_parser.py14
-rw-r--r--contrib/python/pypodman/pypodman/lib/actions/pod/pause_parser.py6
-rw-r--r--contrib/python/pypodman/pypodman/lib/actions/pod/processes_parser.py15
-rw-r--r--contrib/python/pypodman/pypodman/lib/actions/pod/remove_parser.py13
-rw-r--r--contrib/python/pypodman/pypodman/lib/actions/pod/restart_parser.py6
-rw-r--r--contrib/python/pypodman/pypodman/lib/actions/pod/start_parser.py6
-rw-r--r--contrib/python/pypodman/pypodman/lib/actions/pod/stop_parser.py6
-rw-r--r--contrib/python/pypodman/pypodman/lib/actions/pod/unpause_parser.py6
-rw-r--r--contrib/python/pypodman/pypodman/lib/actions/pod_action.py2
-rw-r--r--contrib/python/pypodman/pypodman/lib/actions/port_action.py6
-rw-r--r--contrib/python/pypodman/pypodman/lib/actions/push_action.py10
-rw-r--r--contrib/python/pypodman/pypodman/lib/actions/restart_action.py4
-rw-r--r--contrib/python/pypodman/pypodman/lib/actions/rm_action.py12
-rw-r--r--contrib/python/pypodman/pypodman/lib/actions/rmi_action.py12
-rw-r--r--contrib/python/pypodman/pypodman/lib/actions/search_action.py16
-rw-r--r--contrib/python/pypodman/pypodman/lib/actions/start_action.py21
-rw-r--r--contrib/python/pypodman/pypodman/lib/actions/version_action.py6
-rw-r--r--contrib/python/pypodman/pypodman/lib/parser_actions.py110
-rw-r--r--contrib/python/pypodman/pypodman/lib/podman_parser.py12
-rw-r--r--docs/podman-generate-kube.1.md119
-rw-r--r--docs/podman-generate.1.md19
-rw-r--r--libpod/kube.go142
-rw-r--r--test/e2e/generate_kube_test.go106
66 files changed, 1650 insertions, 654 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index 625b96fdd..09f13a7d0 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -5,48 +5,118 @@
# and storage.
gcp_credentials: ENCRYPTED[885c6e4297dd8d6f67593c42b810353af0c505a7a670e2c6fd830c56e86bbb2debcc3c18f942d0d46ab36b63521061d4]
-# Default VM to use for testing, unless values overriden by specific tasks (below)
-gce_instance:
- image_project: "libpod-218412"
- zone: "us-central1-a" # Required by Cirrus for the time being
- cpu: 2
- memory: "4Gb"
- disk: 40
-
-# Main collection of env. varss to set for all scripts. All others
-# are cooked in by $SCRIPT_BASE/setup_environment.sh
+# Default timeout for each task
+timeout_in: 120m
+
+# Main collection of env. vars to set for all tasks and scripts.
env:
- FEDORA_CNI_COMMIT: "412b6d31280682bb4fab4446f113c22ff1886554"
- CNI_COMMIT: "7480240de9749f9a0a5c8614b17f1f03e0c06ab9"
- CRIO_COMMIT: "7a283c391abb7bd25086a8ff91dbb36ebdd24466"
- CRIU_COMMIT: "c74b83cd49c00589c0c0468ba5fe685b67fdbd0a"
- RUNC_COMMIT: "96ec2177ae841256168fcf76954f7177af9446eb"
+ ####
+ #### Global variables used for all tasks
+ ####
# File to update in home-dir with task-specific env. var values
ENVLIB: ".bash_profile"
# Overrides default location (/tmp/cirrus) for repo clone
- CIRRUS_WORKING_DIR: "/go/src/github.com/containers/libpod"
+ CIRRUS_WORKING_DIR: "/var/tmp/go/src/github.com/containers/libpod"
# Required so $ENVLIB gets loaded
CIRRUS_SHELL: "/bin/bash"
# Save a little typing (path relative to $CIRRUS_WORKING_DIR)
SCRIPT_BASE: "./contrib/cirrus"
PACKER_BASE: "./contrib/cirrus/packer"
+
+ ####
+ #### Variables for composing new cache-images (used in PR testing) from
+ #### base-images (pre-existing in GCE)
+ ####
+ # Git commits to use while building dependencies into cache-images
+ FEDORA_CNI_COMMIT: "412b6d31280682bb4fab4446f113c22ff1886554"
+ CNI_COMMIT: "7480240de9749f9a0a5c8614b17f1f03e0c06ab9"
+ CRIO_COMMIT: "7a283c391abb7bd25086a8ff91dbb36ebdd24466"
+ CRIU_COMMIT: "c74b83cd49c00589c0c0468ba5fe685b67fdbd0a"
+ RUNC_COMMIT: "25f3f893c86d07426df93b7aa172f33fdf093fbd"
+ # CSV of cache-image names to build (see $PACKER_BASE/libpod_images.json)
+ PACKER_BUILDS: "ubuntu-18,fedora-29" # TODO: fah-29,rhel-7,centos-7
+ # Version of packer to use
+ PACKER_VER: "1.3.1"
+ # Google-maintained base-image names
+ UBUNTU_BASE_IMAGE: "ubuntu-1804-bionic-v20181203a"
+ CENTOS_BASE_IMAGE: "centos-7-v20181113"
+ # Manually produced base-image names (see $SCRIPT_BASE/README.md)
+ FEDORA_BASE_IMAGE: "fedora-cloud-base-29-1-2-1541789245"
+ FAH_BASE_IMAGE: "fedora-atomichost-29-20181025-1-1541787861"
+ # RHEL image must be imported, google bills extra for their native image.
+ RHEL_BASE_IMAGE: "rhel-guest-image-7-6-210-x86-64-qcow2-1541783972"
+
+ ####
+ #### Credentials and other secret-sauces, decrypted at runtime when authorized.
+ ####
+ # Freenode IRC credentials for posting status messages
IRCID: ENCRYPTED[e87bba62a8e924dc70bdb2b66b16f6ab4a60d2870e6e5534ae9e2b0076f483c71c84091c655ca239101e6816c5ec0883]
+ # Command to register a RHEL VM to install/update packages
+ RHSM_COMMAND: ENCRYPTED[5caa5ff8c5370c3d25c7a1a28168501ab0fa2e5e3b627926f6eaba02b3fed965a7638a6151657809661f8c905c7dc187]
+ # Needed to build GCE images, within a GCE VM
+ SERVICE_ACCOUNT: ENCRYPTED[99e9a0b1c23f8dd29e83dfdf164f064cfd17afd9b895ca3b5e4c41170bd4290a8366fe2ad8e7a210b9f751711d1d002a]
+ # User ID for cirrus to ssh into VMs
+ GCE_SSH_USERNAME: ENCRYPTED[a7706b9e4b8bbb47f76358df7407f4fffa2e8552531190cc0b3315180c4b50588f560c4f85731e99cb5f43a396778277]
+ # Name where this repositories cloud resources are located
+ GCP_PROJECT_ID: ENCRYPTED[7c80e728e046b1c76147afd156a32c1c57d4a1ac1eab93b7e68e718c61ca8564fc61fef815952b8ae0a64e7034b8fe4f]
+
+ # Space separated list of environment variables to unset before testing
+ UNSET_ENV_VARS: >-
+ GCP_PROJECT_ID GCE_SSH_USERNAME SERVICE_ACCOUNT RHSM_COMMAND BUILT_IMAGE_SUFFIX
+ IRCID RHEL_BASE_IMAGE FAH_BASE_IMAGE FEDORA_BASE_IMAGE CENTOS_BASE_IMAGE
+ UBUNTU_BASE_IMAGE PACKER_VER PACKER_BUILDS RUNC_COMMIT CRIU_COMMIT
+ CRIO_COMMIT CNI_COMMIT FEDORA_CNI_COMMIT PACKER_BASE SCRIPT_BASE
+ CIRRUS_SHELL CIRRUS_WORKING_DIR ENVLIB BUILT_IMAGE_SUFFIX CIRRUS_CI
+ CI_NODE_INDEX CI_NODE_TOTAL CIRRUS_BASE_BRANCH CIRRUS_BASE_SHA
+ CIRRUS_BRANCH CIRRUS_BUILD_ID CIRRUS_CHANGE_IN_REPO CIRRUS_CLONE_DEPTH
+ CIRRUS_COMMIT_MESSAGE CIRRUS_CHANGE_MESSAGE CIRRUS_REPO_CLONE_HOST
+ CIRRUS_DEFAULT_BRANCH CIRRUS_PR CIRRUS_TAG CIRRUS_OS CIRRUS_TASK_NAME
+ CIRRUS_TASK_ID CIRRUS_REPO_NAME CIRRUS_REPO_OWNER CIRRUS_REPO_FULL_NAME
+ CIRRUS_REPO_CLONE_URL CIRRUS_SHELL CIRRUS_USER_COLLABORATOR CIRRUS_USER_PERMISSION
+ CIRRUS_WORKING_DIR CIRRUS_HTTP_CACHE_HOST PACKER_BUILDS BUILT_IMAGE_SUFFIX
+ XDG_DATA_DIRS XDG_RUNTIME_DIR XDG_SESSION_ID
+
+# Every *_task runs in parallel in separate VMsd. The name prefix only for reference
+# in WebUI, and will be followed by matrix details. This task gates all others with
+# quick format, lint, and unit tests on the standard platform.
+gating_task:
+
+ env:
+ CIRRUS_WORKING_DIR: "/usr/src/libpod"
+
+ # Runs within Cirrus's "community cluster"
+ container:
+ image: "quay.io/libpod/gate:latest"
+ cpu: 4
+ memory: 12
+
+ gate_script:
+ - '/usr/local/bin/entrypoint.sh validate'
+ - '/usr/local/bin/entrypoint.sh lint'
+
-# Every *_task runs in parallel in separate VMs. The name prefix only for reference
-# in WebUI, and will be followed by matrix details. This task does all the
-# per-pr unit/integration testing.
-full_vm_testing_task:
+# This task does the unit and integration testing for every platform
+testing_task:
+
+ depends_on:
+ - "gating"
gce_instance:
- # Generate multiple 'test' tasks, covering all possible
- # 'matrix' combinations. All run in parallel.
+ image_project: "libpod-218412"
+ zone: "us-central1-a" # Required by Cirrus for the time being
+ cpu: 2
+ memory: "4Gb"
+ disk: 40
+ # Generate multiple parallel tasks, covering all possible
+ # 'matrix' combinations.
matrix:
- # Images are generated separetly, from build_images_task (below)
+ # Images are generated separately, from build_images_task (below)
image_name: "ubuntu-18-libpod-0c954a67"
- # TODO: Make these work (also build_images_task below)
- #image_name: "rhel-server-ec2-7-5-165-1-libpod-fce09afe"
- #image_name: "centos-7-v20180911-libpod-fce09afe"
- #image_name: "fedora-cloud-base-28-1-1-7-libpod-fce09afe"
+ image_name: "fedora-29-libpod-0c954a67"
+ # TODO: tests fail
+ # image_name: "rhel-7-something-something"
+ # image_name: "centos-7-something-something"
+ # image_name: "fah-29-libpod-5070733157859328"
timeout_in: 120m
@@ -55,11 +125,9 @@ full_vm_testing_task:
setup_environment_script: $SCRIPT_BASE/setup_environment.sh
# ...or lists of strings
- verify_source_script:
- - whoami # root!
- - $SCRIPT_BASE/verify_source.sh
-
- unit_test_script: $SCRIPT_BASE/unit_test.sh
+ unit_test_script:
+ - go version
+ - $SCRIPT_BASE/unit_test.sh
integration_test_script: $SCRIPT_BASE/integration_test.sh
@@ -68,8 +136,7 @@ full_vm_testing_task:
# Because system tests are stored within the repository, it is sometimes
# necessary to execute them within a PR to validate changes.
-
-optional_system_testing_task:
+optional_testing_task:
# Only run system tests in PRs (not on merge) if magic string is present
# in the PR description. Post-merge system testing is assumed to happen
@@ -79,12 +146,13 @@ optional_system_testing_task:
$CIRRUS_CHANGE_MESSAGE =~ '.*\*\*\*\s*CIRRUS:\s*SYSTEM\s*TEST\s*\*\*\*.*'
gce_instance:
+ image_project: "libpod-218412"
matrix:
- image_name: "ubuntu-1804-bionic-v20180911-libpod-e8d18305"
+ image_name: "ubuntu-18-libpod-0c954a67"
+ image_name: "fedora-29-libpod-0c954a67"
# TODO: Make these work (also build_images_task below)
#image_name: "rhel-server-ec2-7-5-165-1-libpod-fce09afe"
#image_name: "centos-7-v20180911-libpod-fce09afe"
- #image_name: "fedora-cloud-base-28-1-1-7-libpod-fce09afe"
timeout_in: 60m
@@ -93,13 +161,11 @@ optional_system_testing_task:
success_script: $SCRIPT_BASE/success.sh
-# This task builds new cache-images for future PR testing. These images save
-# time installing/setting up the environment while an engineer is waiting.
-# The 'active' cache-images for full_vm_testing are selected by the
-# 'image_name' keys. Updating those items requires manually modification,
-# but this could be automated (see comment at end of build_vm_images_task).
-
-build_vm_images_task:
+# Build new cache-images for future PR testing, but only after a PR merge.
+# The cache-images save install/setup time needed test every PR. The 'active' images
+# are selected by the 'image_name' items tasks above. Currently this requires
+# manually updating the names, but this could be automated (see comment below).
+cache_images_task:
# Only produce new cache-images after a PR merge, and if a magic string
# is present in the most recent commit-message.
only_if: >-
@@ -108,45 +174,27 @@ build_vm_images_task:
# Require tests to pass first.
depends_on:
- - full_vm_testing # i.e. 'full_vm_testing_task'
-
- env:
- # CSV of packer builder names to enable (see $PACKER_BASE/libpod_images.json)
- PACKER_BUILDS: "ubuntu-18"
- # TODO: Make these work (also full_vm_testing_task above)
- # PACKER_BUILDS: "rhel-7,centos-7,fedora-28,ubuntu-18"
- CENTOS_BASE_IMAGE: "centos-7-v20180911"
- RHEL_BASE_IMAGE: "rhel-server-ec2-7-5-165-1"
- FEDORA_BASE_IMAGE: "fedora-cloud-base-28-1-1-7"
- UBUNTU_BASE_IMAGE: "ubuntu-1804-bionic-v20180911"
- # low-level base VM image name inputs to packer
-
- # Command to register a RHEL VM
- RHSM_COMMAND: ENCRYPTED[5caa5ff8c5370c3d25c7a1a28168501ab0fa2e5e3b627926f6eaba02b3fed965a7638a6151657809661f8c905c7dc187]
- # Additional environment variables needed to build GCE images, within a GCE VM
- SERVICE_ACCOUNT: ENCRYPTED[99e9a0b1c23f8dd29e83dfdf164f064cfd17afd9b895ca3b5e4c41170bd4290a8366fe2ad8e7a210b9f751711d1d002a]
- GCE_SSH_USERNAME: ENCRYPTED[a7706b9e4b8bbb47f76358df7407f4fffa2e8552531190cc0b3315180c4b50588f560c4f85731e99cb5f43a396778277]
- GCP_PROJECT_ID: ENCRYPTED[7c80e728e046b1c76147afd156a32c1c57d4a1ac1eab93b7e68e718c61ca8564fc61fef815952b8ae0a64e7034b8fe4f]
- # Version of packer to use
- PACKER_VER: "1.3.1"
+ - "gating"
+ - "testing"
# VMs created by packer are not cleaned up by cirrus
auto_cancellation: $CI != "true"
gce_instance:
- image_name: "image-builder-image" # Simply CentOS 7 + packer dependencies
+ image_project: "libpod-218412"
+ zone: "us-central1-a" # Required by Cirrus for the time being
+ cpu: 4
+ memory: "4Gb"
+ disk: 20
+ image_name: "image-builder-image-1541772081" # Simply CentOS 7 + packer dependencies
# Additional permissions for building GCE images, within a GCE VM
scopes:
- compute
- devstorage.full_control
- # Doesn't need many local resources to run
- cpu: 2
- memory: "2Gb"
- disk: 20
environment_script: $SCRIPT_BASE/setup_environment.sh
build_vm_images_script: $SCRIPT_BASE/build_vm_images.sh
- # TODO,Continuous Delivery: Automaticly open a libpod PR after using 'sed' to replace
+ # TODO,Continuous Delivery: Automatically open a libpod PR after using 'sed' to replace
# the image_names with the new (just build) images. That will
# cause a new round of testing to happen (via the PR) using
# the new images. When all is good, the PR may be manually
diff --git a/Makefile b/Makefile
index 78e7b62d3..6e75800b4 100644
--- a/Makefile
+++ b/Makefile
@@ -172,6 +172,7 @@ testunit: libpodimage
localunit: test/goecho/goecho varlink_generate
$(GO) test -tags "$(BUILDTAGS)" -cover $(PACKAGES)
+ $(MAKE) -C contrib/cirrus/packer test
ginkgo:
ginkgo -v -tags "$(BUILDTAGS)" -cover -flakeAttempts 3 -progress -trace -noColor test/e2e/.
diff --git a/cmd/podman/generate.go b/cmd/podman/generate.go
new file mode 100644
index 000000000..765d0ee70
--- /dev/null
+++ b/cmd/podman/generate.go
@@ -0,0 +1,23 @@
+package main
+
+import (
+ "github.com/urfave/cli"
+)
+
+var (
+ generateSubCommands = []cli.Command{
+ containerKubeCommand,
+ }
+
+ generateDescription = "generate structured data based for a containers and pods"
+ kubeCommand = cli.Command{
+ Name: "generate",
+ Usage: "generated structured data",
+ Description: generateDescription,
+ ArgsUsage: "",
+ Subcommands: generateSubCommands,
+ UseShortOptionHandling: true,
+ OnUsageError: usageErrorHandler,
+ Hidden: true,
+ }
+)
diff --git a/cmd/podman/kube_generate.go b/cmd/podman/generate_kube.go
index a18912668..de9f701b0 100644
--- a/cmd/podman/kube_generate.go
+++ b/cmd/podman/generate_kube.go
@@ -6,10 +6,11 @@ import (
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/rootless"
+ podmanVersion "github.com/containers/libpod/version"
"github.com/ghodss/yaml"
"github.com/pkg/errors"
- "github.com/sirupsen/logrus"
"github.com/urfave/cli"
+ "k8s.io/api/core/v1"
)
var (
@@ -18,16 +19,15 @@ var (
Name: "service, s",
Usage: "only generate YAML for kubernetes service object",
},
- LatestFlag,
}
containerKubeDescription = "Generate Kubernetes Pod YAML"
containerKubeCommand = cli.Command{
- Name: "generate",
- Usage: "Generate Kubernetes pod YAML for a container",
+ Name: "kube",
+ Usage: "Generate Kubernetes pod YAML for a container or pod",
Description: containerKubeDescription,
Flags: sortFlags(containerKubeFlags),
Action: generateKubeYAMLCmd,
- ArgsUsage: "CONTAINER-NAME",
+ ArgsUsage: "CONTAINER|POD-NAME",
UseShortOptionHandling: true,
OnUsageError: usageErrorHandler,
}
@@ -36,9 +36,13 @@ var (
// generateKubeYAMLCmdgenerates or replays kube
func generateKubeYAMLCmd(c *cli.Context) error {
var (
- container *libpod.Container
- err error
- output []byte
+ podYAML *v1.Pod
+ container *libpod.Container
+ err error
+ output []byte
+ pod *libpod.Pod
+ mashalledBytes []byte
+ servicePorts []v1.ServicePort
)
if rootless.IsRootless() {
@@ -46,10 +50,7 @@ func generateKubeYAMLCmd(c *cli.Context) error {
}
args := c.Args()
if len(args) > 1 || (len(args) < 1 && !c.Bool("latest")) {
- return errors.Errorf("you must provide one container ID or name or --latest")
- }
- if c.Bool("service") {
- return errors.Wrapf(libpod.ErrNotImplemented, "service generation")
+ return errors.Errorf("you must provide one container|pod ID or name or --latest")
}
runtime, err := libpodruntime.GetRuntime(c)
@@ -59,33 +60,43 @@ func generateKubeYAMLCmd(c *cli.Context) error {
defer runtime.Shutdown(false)
// Get the container in question
- if c.Bool("latest") {
- container, err = runtime.GetLatestContainer()
+ container, err = runtime.LookupContainer(args[0])
+ if err != nil {
+ pod, err = runtime.LookupPod(args[0])
+ if err != nil {
+ return err
+ }
+ podYAML, servicePorts, err = pod.GenerateForKube()
} else {
- container, err = runtime.LookupContainer(args[0])
+ if len(container.Dependencies()) > 0 {
+ return errors.Wrapf(libpod.ErrNotImplemented, "containers with dependencies")
+ }
+ podYAML, err = container.GenerateForKube()
}
if err != nil {
return err
}
- if len(container.Dependencies()) > 0 {
- return errors.Wrapf(libpod.ErrNotImplemented, "containers with dependencies")
+ if c.Bool("service") {
+ serviceYAML := libpod.GenerateKubeServiceFromV1Pod(podYAML, servicePorts)
+ mashalledBytes, err = yaml.Marshal(serviceYAML)
+ } else {
+ // Marshall the results
+ mashalledBytes, err = yaml.Marshal(podYAML)
}
-
- podYAML, err := container.InspectForKube()
if err != nil {
return err
}
- developmentComment := []byte("# Generation of Kubenetes YAML is still under development!\n")
- logrus.Warn("This function is still under heavy development.")
- // Marshall the results
- b, err := yaml.Marshal(podYAML)
- if err != nil {
- return err
- }
- output = append(output, developmentComment...)
- output = append(output, b...)
+ header := `# Generation of Kubenetes YAML is still under development!
+#
+# Save the output of this file and use kubectl create -f to import
+# it into Kubernetes.
+#
+# Created with podman-%s
+`
+ output = append(output, []byte(fmt.Sprintf(header, podmanVersion.Version))...)
+ output = append(output, mashalledBytes...)
// Output the v1.Pod with the v1.Container
fmt.Println(string(output))
diff --git a/cmd/podman/kube.go b/cmd/podman/kube.go
deleted file mode 100644
index 2cb407c09..000000000
--- a/cmd/podman/kube.go
+++ /dev/null
@@ -1,23 +0,0 @@
-package main
-
-import (
- "github.com/urfave/cli"
-)
-
-var (
- kubeSubCommands = []cli.Command{
- containerKubeCommand,
- }
-
- kubeDescription = "Work with Kubernetes objects"
- kubeCommand = cli.Command{
- Name: "kube",
- Usage: "Import and export Kubernetes objections from and to Podman",
- Description: containerDescription,
- ArgsUsage: "",
- Subcommands: kubeSubCommands,
- UseShortOptionHandling: true,
- OnUsageError: usageErrorHandler,
- Hidden: true,
- }
-)
diff --git a/commands.md b/commands.md
index 8e1a2dd7a..43796722f 100644
--- a/commands.md
+++ b/commands.md
@@ -16,6 +16,7 @@
| [podman-diff(1)](/docs/podman-diff.1.md) | Inspect changes on a container or image's filesystem |[![...](/docs/play.png)](https://asciinema.org/a/FXfWB9CKYFwYM4EfqW3NSZy1G)|
| [podman-exec(1)](/docs/podman-exec.1.md) | Execute a command in a running container
| [podman-export(1)](/docs/podman-export.1.md) | Export container's filesystem contents as a tar archive |[![...](/docs/play.png)](https://asciinema.org/a/913lBIRAg5hK8asyIhhkQVLtV)|
+| [podman-generate(1)](/docs/podman-generate.1.md) | Generate structured output based on Podman containers and pods | |
| [podman-history(1)](/docs/podman-history.1.md) | Shows the history of an image |[![...](/docs/play.png)](https://asciinema.org/a/bCvUQJ6DkxInMELZdc5DinNSx)|
| [podman-image(1)](/docs/podman-image.1.md) | Manage Images||
| [podman-images(1)](/docs/podman-images.1.md) | List images in local storage |[![...](/docs/play.png)](https://asciinema.org/a/133649)|
diff --git a/completions/bash/podman b/completions/bash/podman
index eda7e5973..9a8adb502 100644
--- a/completions/bash/podman
+++ b/completions/bash/podman
@@ -876,6 +876,25 @@ _podman_container_wait() {
_podman_wait
}
+_podman_generate() {
+ local boolean_options="
+ --help
+ -h
+ "
+ subcommands="
+ kube
+ "
+ __podman_subcommands "$subcommands $aliases" && return
+
+ case "$cur" in
+ -*)
+ COMPREPLY=( $( compgen -W "--help" -- "$cur" ) )
+ ;;
+ *)
+ COMPREPLY=( $( compgen -W "$subcommands" -- "$cur" ) )
+ ;;
+ esac
+}
_podman_container() {
local boolean_options="
--help
@@ -2219,6 +2238,14 @@ _podman_logout() {
_complete_ "$options_with_args" "$boolean_options"
}
+_podman_generate_kube() {
+ local options_with_args=""
+
+ local boolean_options="
+ -s
+ --service
+ "
+
_podman_container_runlabel() {
local options_with_args="
--authfile
@@ -2704,6 +2731,7 @@ _podman_podman() {
diff
exec
export
+ generate
history
images
import
diff --git a/contrib/cirrus/README.md b/contrib/cirrus/README.md
index fa233a2cb..c5c976358 100644
--- a/contrib/cirrus/README.md
+++ b/contrib/cirrus/README.md
@@ -5,6 +5,7 @@
Similar to other integrated github CI/CD services, Cirrus utilizes a simple
YAML-based configuration/description file: ``.cirrus.yml``. Ref: https://cirrus-ci.org/
+
## Workflow
All tasks execute in parallel, unless there are conditions or dependencies
@@ -12,24 +13,34 @@ which alter this behavior. Within each task, each script executes in sequence,
so long as any previous script exited successfully. The overall state of each
task (pass or fail) is set based on the exit status of the last script to execute.
-### ``full_vm_testing`` Task
-1. Unconditionally, spin up one VM per ``matrix: image_name`` item defined
- in ``.cirrus.yml``. Once accessible, ``ssh`` into each VM and run the following
- scripts.
+### ``gating`` Task
+
+***N/B: Steps below are performed by automation***
+
+1. Launch a purpose-built container in Cirrus's community cluster.
+ For container image details, please see
+ [the contributors guide](https://github.com/containers/libpod/blob/master/CONTRIBUTING.md#go-format-and-lint).
+
+3. ``validate``: Perform standard `make validate` source verification,
+ Should run for less than a minute or two.
+
+4. ``lint``: Execute regular `make lint` to check for any code cruft.
+ Should also run for less than a few minutes.
+
-2. ``setup_environment.sh``: Configure root's ``.bash_profile``
- for all subsequent scripts (each run in a new shell). Any
- distribution-specific environment variables are also defined
- here. For example, setting tags/flags to use compiling.
+### ``testing`` Task
-3. ``verify_source.sh``: Perform per-distribution source
- verification, lint-checking, etc. This acts as a minimal
- gate, blocking extended use of VMs when a PR's code or commits
- would otherwise not be accepted. Should run for less than a minute.
+***N/B: Steps below are performed by automation***
-4. ``unit_test.sh``: Execute unit-testing, as defined by the ``Makefile``.
- This should execute within 10-minutes, but often much faster.
+1. After `gating` passes, spin up one VM per
+ `matrix: image_name` item. Once accessible, ``ssh``
+ into each VM as the `root` user.
+
+2. ``setup_environment.sh``: Configure root's `.bash_profile`
+ for all subsequent scripts (each run in a new shell). Any
+ distribution-specific environment variables are also defined
+ here. For example, setting tags/flags to use compiling.
5. ``integration_test.sh``: Execute integration-testing. This is
much more involved, and relies on access to external
@@ -37,9 +48,12 @@ task (pass or fail) is set based on the exit status of the last script to execut
Total execution time is capped at 2-hours (includes all the above)
but this script normally completes in less than an hour.
-### ``optional_system_testing`` Task
-1. Optionally executes in parallel with ``full_vm_testing``. Requires
+### ``optional_testing`` Task
+
+***N/B: Steps below are performed by automation***
+
+1. Optionally executes in parallel with ``testing``. Requires
**prior** to job-start, the magic string ``***CIRRUS: SYSTEM TEST***``
is found in the pull-request *description*. The *description* is the first
text-box under the main *summary* line in the github WebUI.
@@ -49,16 +63,17 @@ task (pass or fail) is set based on the exit status of the last script to execut
3. ``system_test.sh``: Build both dependencies and libpod, install them,
then execute `make localsystem` from the repository root.
-### ``build_vm_images`` Task
-1. When a PR is merged (``$CIRRUS_BRANCH`` == ``master``), Cirrus
- checks the last commit message. If it contains the magic string
- ``***CIRRUS: REBUILD IMAGES***``, then this task continues.
+### ``cache_images`` Task
-2. Execute run another round of the ``full_vm_testing`` task (above).
- After the tests pass (post-merge), spin up a special VM
- (from the `image-builder-image`) capable of communicating with the
- GCE API. Once accessible, ``ssh`` into the VM and run the following scripts.
+***N/B: Steps below are performed by automation***
+
+1. When a PR is merged (``$CIRRUS_BRANCH`` == ``master``), run another
+ round of the ``gating`` and ``testing`` tasks (above).
+
+2. Assuming tests pass, if the commit message contains the magic string
+ ``***CIRRUS: REBUILD IMAGES***``, then this task continues. Otherwise
+ simply mark the master branch as 'passed'.
3. ``setup_environment.sh``: Same as for other tasks.
@@ -70,13 +85,108 @@ task (pass or fail) is set based on the exit status of the last script to execut
1. On a base-image VM, as root, copy the current state of the repository
into ``/tmp/libpod``.
2. Execute distribution-specific scripts to prepare the image for
- use by the ``full_vm_testing`` task (above). These scripts all
- end with the suffix `_setup.sh` within the `$PACKER_BASE` directory.
+ use by the ``integration_testing`` task (above). For example,
+ ``fedora_setup.sh``.
3. If successful, shut down each VM and create a new GCE Image
- named after the base image and the commit sha of the merge.
+ named with the base image, and the commit sha of the merge.
***Note:*** The ``.cirrus.yml`` file must be manually updated with the new
images names, then the change sent in via a secondary pull-request. This
-ensures that all the ``full_vm_testing`` tasks can pass with the new images,
+ensures that all the ``integration_testing`` tasks can pass with the new images,
before subjecting all future PRs to them. A workflow to automate this
process is described in comments at the end of the ``.cirrus.yml`` file.
+
+### Base-images
+
+Base-images are VM disk-images specially prepared for executing as GCE VMs.
+In particular, they run services on startup similar in purpose/function
+as the standard 'cloud-init' services.
+
+* The google services are required for full support of ssh-key management
+ and GCE OAuth capabilities. Google provides native images in GCE
+ with services pre-installed, for many platforms. For example,
+ RHEL, CentOS, and Ubuntu.
+
+* Google does ***not*** provide any images for Fedora or Fedora Atomic
+ Host (as of 11/2018), nor do they provide a base-image prepared to
+ run packer for creating other images in the ``build_vm_images`` Task
+ (above).
+
+* Base images do not need to be produced often, but doing so completely
+ manually would be time-consuming and error-prone. Therefor a special
+ semi-automatic *Makefile* target is provided to assist with producing
+ all the base-images: ``libpod_base_images``
+
+To produce new base-images, including an `image-builder-image` (used by
+the ``cache_images`` Task) some input parameters are required:
+
+ * ``GCP_PROJECT_ID``: The complete GCP project ID string e.g. foobar-12345
+ identifying where the images will be stored.
+
+ * ``GOOGLE_APPLICATION_CREDENTIALS``: A *JSON* file containing
+ credentials for a GCE service account. This can be [a service
+ account](https://cloud.google.com/docs/authentication/production#obtaining_and_providing_service_account_credentials_manually)
+ or [end-user
+ credentials](https://cloud.google.com/docs/authentication/end-user#creating_your_client_credentials]
+
+ * ``RHEL_IMAGE_FILE`` and ``RHEL_CSUM_FILE`` complete paths
+ to a `rhel-server-ec2-*.raw.xz` and it's cooresponding
+ checksum file. These must be supplied manually because
+ they're not available directly via URL like other images.
+
+ * ``RHSM_COMMAND`` contains the complete string needed to register
+ the VM for installing package dependencies. The VM will be de-registered
+ upon completion.
+
+ * Optionally, CSV's may be specified to ``PACKER_BUILDS``
+ to limit the base-images produced. For example,
+ ``PACKER_BUILDS=fedora,image-builder-image``.
+
+The following process should be performed on a bare-metal CentOS 7 machine
+with network access to GCE. Software dependencies can be obtained from
+the ``packer/image-builder-image_base_setup.sh`` script.
+
+Alternatively, an existing image-builder-image may be used from within GCE.
+However it must be created with elevated cloud privileges. For example,
+
+```
+$ alias pgcloud='sudo podman run -it --rm -e AS_ID=$UID
+ -e AS_USER=$USER -v /home/$USER:/home/$USER:z cevich/gcloud_centos:latest'
+
+$ URL=https://www.googleapis.com/auth
+$ SCOPES=$URL/userinfo.email,$URL/compute,$URL/devstorage.full_control
+
+$ pgcloud compute instances create $USER-making-images \
+ --image-family image-builder-image \
+ --boot-disk-size "200GB" \
+ --min-cpu-platform "Intel Haswell" \
+ --machine-type n1-standard-2 \
+ --scopes $SCOPES
+
+$ pgcloud compute ssh centos@$USER-making-images
+...
+```
+
+When ready, change to the ``packer`` sub-directory, and run:
+
+```
+$ make libpod_base_images GCP_PROJECT_ID=<VALUE> \
+ GOOGLE_APPLICATION_CREDENTIALS=<VALUE> \
+ RHEL_IMAGE_FILE=<VALUE> \
+ RHEL_CSUM_FILE=<VALUE> \
+ PACKER_BUILDS=<OPTIONAL>
+```
+
+Assuming this is successful (hence the semi-automatic part), packer will
+produce a ``packer-manifest.json`` output file. This contains the base-image
+names suitable for updating in ``.cirrus.yml``, `env` keys ``*_BASE_IMAGE``.
+
+On failure, it should be possible to determine the problem from the packer
+output. The only exception is for the Fedora and FAH builds, which utilize
+local qemu-kvm virtualisation. To observe the serial-port output from those
+builds, set the ``TTYDEV`` parameter to your current device. For example:
+
+```
+$ make libpod_base_images ... TTYDEV=$(tty)
+ ...
+```
diff --git a/contrib/cirrus/build_vm_images.sh b/contrib/cirrus/build_vm_images.sh
index c8ff55445..ecdf1d877 100755
--- a/contrib/cirrus/build_vm_images.sh
+++ b/contrib/cirrus/build_vm_images.sh
@@ -8,12 +8,13 @@ CNI_COMMIT $CNI_COMMIT
CRIO_COMMIT $CRIO_COMMIT
RUNC_COMMIT $RUNC_COMMIT
PACKER_BUILDS $PACKER_BUILDS
+BUILT_IMAGE_SUFFIX $BUILT_IMAGE_SUFFIX
CENTOS_BASE_IMAGE $CENTOS_BASE_IMAGE
UBUNTU_BASE_IMAGE $UBUNTU_BASE_IMAGE
FEDORA_BASE_IMAGE $FEDORA_BASE_IMAGE
+FAH_BASE_IMAGE $FAH_BASE_IMAGE
RHEL_BASE_IMAGE $RHEL_BASE_IMAGE
RHSM_COMMAND $RHSM_COMMAND
-BUILT_IMAGE_SUFFIX $BUILT_IMAGE_SUFFIX
SERVICE_ACCOUNT $SERVICE_ACCOUNT
GCE_SSH_USERNAME $GCE_SSH_USERNAME
GCP_PROJECT_ID $GCP_PROJECT_ID
@@ -28,28 +29,24 @@ show_env_vars
# Assume basic dependencies are all met, but there could be a newer version
# of the packer binary
PACKER_FILENAME="packer_${PACKER_VER}_linux_amd64.zip"
-mkdir -p "$HOME/packer"
-cd "$HOME/packer"
-# image_builder_image has packer pre-installed, check if same version requested
-if ! [[ -r "$PACKER_FILENAME" ]]
+if [[ -d "$HOME/packer" ]]
then
- curl -L -O https://releases.hashicorp.com/packer/$PACKER_VER/$PACKER_FILENAME
- curl -L https://releases.hashicorp.com/packer/${PACKER_VER}/packer_${PACKER_VER}_SHA256SUMS | \
- grep 'linux_amd64' > ./sha256sums
- sha256sum --check ./sha256sums
- unzip -o $PACKER_FILENAME
- ./packer --help &> /dev/null # verify exit(0)
+ cd "$HOME/packer"
+ # image_builder_image has packer pre-installed, check if same version requested
+ if [[ -r "$PACKER_FILENAME" ]]
+ then
+ cp $PACKER_FILENAME "$GOSRC/$PACKER_BASE/"
+ cp packer "$GOSRC/$PACKER_BASE/"
+ fi
fi
set -x
-cd "$GOSRC"
-# N/B: /usr/sbin/packer is a DIFFERENT tool, and will exit 0 given the args below :(
-TEMPLATE="./$PACKER_BASE/libpod_images.json"
-
-$HOME/packer/packer inspect "$TEMPLATE"
-
-#$HOME/packer/packer build -machine-readable "-only=$PACKER_BUILDS" "$TEMPLATE" | tee /tmp/packer_log.csv
-$HOME/packer/packer build "-only=$PACKER_BUILDS" "$TEMPLATE"
-
-# TODO: Report back to PR names of built images
+cd "$GOSRC/$PACKER_BASE"
+make libpod_images \
+ PACKER_BUILDS=$PACKER_BUILDS \
+ PACKER_VER=$PACKER_VER \
+ GOSRC=$GOSRC \
+ SCRIPT_BASE=$SCRIPT_BASE \
+ PACKER_BASE=$PACKER_BASE \
+ BUILT_IMAGE_SUFFIX=$BUILT_IMAGE_SUFFIX
diff --git a/contrib/cirrus/integration_test.sh b/contrib/cirrus/integration_test.sh
index 226053724..a50bd448f 100755
--- a/contrib/cirrus/integration_test.sh
+++ b/contrib/cirrus/integration_test.sh
@@ -9,7 +9,7 @@ OS_RELEASE_ID $OS_RELEASE_ID
OS_RELEASE_VER $OS_RELEASE_VER
"
-show_env_vars
+clean_env
set -x
cd "$GOSRC"
@@ -19,10 +19,13 @@ case "${OS_RELEASE_ID}-${OS_RELEASE_VER}" in
make test-binaries "BUILDTAGS=$BUILDTAGS"
SKIP_USERNS=1 make localintegration "BUILDTAGS=$BUILDTAGS"
;;
- fedora-28) ;& # Continue to the next item
+ fedora-29) ;& # Continue to the next item
+ fedora-28) ;&
centos-7) ;&
rhel-7)
- stub 'integration testing not working on $OS_RELEASE_ID'
+ make install PREFIX=/usr ETCDIR=/etc
+ make test-binaries
+ make localintegration
;;
*) bad_os_id_ver ;;
esac
diff --git a/contrib/cirrus/lib.sh b/contrib/cirrus/lib.sh
index 04314e5fe..985264f22 100644
--- a/contrib/cirrus/lib.sh
+++ b/contrib/cirrus/lib.sh
@@ -4,8 +4,8 @@
# to be sourced by other scripts, not called directly.
# Under some contexts these values are not set, make sure they are.
-USER="$(whoami)"
-HOME="$(getent passwd $USER | cut -d : -f 6)"
+export USER="$(whoami)"
+export HOME="$(getent passwd $USER | cut -d : -f 6)"
if ! [[ "$PATH" =~ "/usr/local/bin" ]]
then
export PATH="$PATH:/usr/local/bin"
@@ -73,6 +73,18 @@ PACKER_BUILDS $PACKER_BUILDS
do
[[ -z "$NAME" ]] || echo "export $NAME=\"$VALUE\""
done
+ echo ""
+ echo "##### $(go version) #####"
+ echo ""
+}
+
+# Unset environment variables not needed for testing purposes
+clean_env() {
+ req_env_var "
+ UNSET_ENV_VARS $UNSET_ENV_VARS
+ "
+ echo "Unsetting $(echo $UNSET_ENV_VARS | wc -w) environment variables"
+ unset -v UNSET_ENV_VARS $UNSET_ENV_VARS || true # don't fail on read-only
}
# Return a GCE image-name compatible string representation of distribution name
@@ -269,21 +281,29 @@ install_varlink(){
}
_finalize(){
+ set +e # Don't fail at the very end
+ set +e # make errors non-fatal
echo "Removing leftover giblets from cloud-init"
cd /
sudo rm -rf /var/lib/cloud/instance?
sudo rm -rf /root/.ssh/*
sudo rm -rf /home/*
+ sudo rm -rf /tmp/*
+ sudo rm -rf /tmp/.??*
+ sync
+ sudo fstrim -av
}
rh_finalize(){
+ set +e # Don't fail at the very end
# Allow root ssh-logins
if [[ -r /etc/cloud/cloud.cfg ]]
then
sudo sed -re 's/^disable_root:.*/disable_root: 0/g' -i /etc/cloud/cloud.cfg
fi
echo "Resetting to fresh-state for usage as cloud-image."
- sudo $(type -P dnf || type -P yum) clean all
+ PKG=$(type -P dnf || type -P yum || echo "")
+ [[ -z "$PKG" ]] || sudo $PKG clean all # not on atomic
sudo rm -rf /var/cache/{yum,dnf}
sudo rm -f /etc/udev/rules.d/*-persistent-*.rules
sudo touch /.unconfigured # force firstboot to run
@@ -291,7 +311,35 @@ rh_finalize(){
}
ubuntu_finalize(){
+ set +e # Don't fail at the very end
echo "Resetting to fresh-state for usage as cloud-image."
sudo rm -rf /var/cache/apt
_finalize
}
+
+rhel_exit_handler() {
+ set +ex
+ req_env_var "
+ GOPATH $GOPATH
+ RHSMCMD $RHSMCMD
+ "
+ cd /
+ sudo rm -rf "$RHSMCMD"
+ sudo rm -rf "$GOPATH"
+ sudo subscription-manager remove --all
+ sudo subscription-manager unregister
+ sudo subscription-manager clean
+}
+
+rhsm_enable() {
+ req_env_var "
+ RHSM_COMMAND $RHSM_COMMAND
+ "
+ export GOPATH="$(mktemp -d)"
+ export RHSMCMD="$(mktemp)"
+ trap "rhel_exit_handler" EXIT
+ # Avoid logging sensitive details
+ echo "$RHSM_COMMAND" > "$RHSMCMD"
+ ooe.sh sudo bash "$RHSMCMD"
+ sudo rm -rf "$RHSMCMD"
+}
diff --git a/contrib/cirrus/packer/.gitignore b/contrib/cirrus/packer/.gitignore
new file mode 100644
index 000000000..8f7bdeaf7
--- /dev/null
+++ b/contrib/cirrus/packer/.gitignore
@@ -0,0 +1,7 @@
+*json
+packer
+packer*zip
+packer_cache
+cidata*
+meta-data
+user-data
diff --git a/contrib/cirrus/packer/Makefile b/contrib/cirrus/packer/Makefile
new file mode 100644
index 000000000..9bf27373e
--- /dev/null
+++ b/contrib/cirrus/packer/Makefile
@@ -0,0 +1,108 @@
+
+# N/B: PACKER_BUILDS variable is required. Should contain CSV of
+# builder name(s) from applicable YAML file,
+# e.g for names see libpod_images.yml
+
+PACKER_VER ?= 1.3.1
+PACKER_DIST_FILENAME := packer_${PACKER_VER}_linux_amd64.zip
+
+# Only needed for libpod_base_images target
+TIMESTAMP := $(shell date +%s)
+GOSRC ?= $(shell realpath "./../../../")
+PACKER_BASE ?= contrib/cirrus/packer
+SCRIPT_BASE ?= contrib/cirrus
+
+# For debugging nested-virt, use
+#TTYDEV := $(shell tty)
+TTYDEV := /dev/null
+
+.PHONY: all
+all: libpod_images
+
+%.json: %.yml
+ @python3 -c 'import json,yaml; json.dump( yaml.load(open("$<").read()), open("$@","w"), indent=2);'
+
+${PACKER_DIST_FILENAME}:
+ @curl -L --silent --show-error \
+ -O https://releases.hashicorp.com/packer/${PACKER_VER}/${PACKER_DIST_FILENAME}
+
+packer: ${PACKER_DIST_FILENAME}
+ @curl -L --silent --show-error \
+ https://releases.hashicorp.com/packer/${PACKER_VER}/packer_${PACKER_VER}_SHA256SUMS \
+ | grep 'linux_amd64' > /tmp/packer_sha256sums
+ @sha256sum --check /tmp/packer_sha256sums
+ @unzip -o ${PACKER_DIST_FILENAME}
+ @touch --reference=Makefile ${PACKER_DIST_FILENAME}
+
+.PHONY: test
+test: libpod_base_images.json libpod_images.json packer
+ ./packer inspect libpod_base_images.json > /dev/null
+ ./packer inspect libpod_images.json > /dev/null
+ @echo "All good"
+
+.PHONY: libpod_images
+libpod_images: libpod_images.json packer
+ifndef PACKER_BUILDS
+ $(error PACKER_BUILDS is undefined, expected builder-names CSV)
+endif
+ ./packer build -only=${PACKER_BUILDS} \
+ -var GOSRC=$(GOSRC) \
+ -var PACKER_BASE=$(PACKER_BASE) \
+ -var SCRIPT_BASE=$(SCRIPT_BASE) \
+ libpod_images.json
+ @echo ""
+ @echo "Finished. The images mentioned above, and in packer-manifest.json"
+ @echo "can be used in .cirrus.yml as values for the 'image_name' keys"
+ @echo ""
+
+cidata.ssh:
+ ssh-keygen -f $@ -P "" -q
+
+cidata.ssh.pub: cidata.ssh
+ touch $@
+
+meta-data:
+ echo "local-hostname: localhost.localdomain" > $@
+
+user-data: cidata.ssh.pub
+ bash make-user-data.sh
+
+cidata.iso: user-data meta-data
+ genisoimage -output cidata.iso -volid cidata -input-charset utf-8 -joliet -rock user-data meta-data
+
+# This is intended to be run by a human, with admin access to the libpod GCE project.
+.PHONY: libpod_base_images
+libpod_base_images: libpod_base_images.json cidata.iso cidata.ssh packer
+ifndef GCP_PROJECT_ID
+ $(error GCP_PROJECT_ID is undefined, expected complete GCP project ID string e.g. foobar-12345)
+endif
+ifndef GOOGLE_APPLICATION_CREDENTIALS
+ $(error GOOGLE_APPLICATION_CREDENTIALS is undefined, expected absolute path to JSON file, like $HOME/.config/gcloud/legacy_credentials/*/adc.json)
+endif
+ifndef RHEL_IMAGE_FILE
+ $(error RHEL_IMAGE_FILE is undefined, expected full path to a rhel-server-ec2-*.raw.xz file)
+endif
+ifndef RHEL_CSUM_FILE
+ $(error RHEL_CSUM_FILE is undefined, expected full path to a rhel-server-ec2-*.raw.xz.SHA256SUM file)
+endif
+ifndef RHSM_COMMAND
+ $(error RHSM_COMMAND is undefined, expected string required for temporarily registering VM)
+endif
+ PACKER_CACHE_DIR=/tmp ./packer build \
+ -var TIMESTAMP=$(TIMESTAMP) \
+ -var TTYDEV=$(TTYDEV) \
+ -var GCP_PROJECT_ID=$(GCP_PROJECT_ID) \
+ -var GOOGLE_APPLICATION_CREDENTIALS=$(GOOGLE_APPLICATION_CREDENTIALS) \
+ -var GOSRC=$(GOSRC) \
+ -var PACKER_BASE=$(PACKER_BASE) \
+ -var SCRIPT_BASE=$(SCRIPT_BASE) \
+ -var RHEL_BASE_IMAGE_NAME=$(shell basename $(RHEL_IMAGE_FILE) | tr -d '[[:space:]]' | sed -r -e 's/\.x86_64\.raw\.xz//' | tr '[[:upper:]]' '[[:lower:]]' | tr '[[:punct:]]' '-') \
+ -var RHEL_IMAGE_FILE=$(RHEL_IMAGE_FILE) \
+ -var RHEL_CSUM_FILE=$(RHEL_CSUM_FILE) \
+ -var 'RHSM_COMMAND=$(RHSM_COMMAND)' \
+ -only $(PACKER_BUILDS) \
+ libpod_base_images.json
+ @echo ""
+ @echo "Finished. The images mentioned above, and in packer-manifest.json"
+ @echo "can be used in .cirrus.yml as values for the *_BASE_IMAGE keys."
+ @echo ""
diff --git a/contrib/cirrus/packer/README.md b/contrib/cirrus/packer/README.md
index 8ff6947e9..9a07ed960 100644
--- a/contrib/cirrus/packer/README.md
+++ b/contrib/cirrus/packer/README.md
@@ -1,2 +1,3 @@
These are definitions and scripts consumed by packer to produce the
-various distribution images used for CI testing.
+various distribution images used for CI testing. For more details
+see the [Cirrus CI documentation](../README.md)
diff --git a/contrib/cirrus/packer/fah_base-setup.sh b/contrib/cirrus/packer/fah_base-setup.sh
new file mode 100644
index 000000000..606c4f336
--- /dev/null
+++ b/contrib/cirrus/packer/fah_base-setup.sh
@@ -0,0 +1,45 @@
+
+# N/B: This script is not intended to be run by humans. It is used to configure the
+# FAH base image for importing, so that it will boot in GCE.
+
+set -e
+
+# Load in library (copied by packer, before this script was run)
+source $GOSRC/$SCRIPT_BASE/lib.sh
+
+install_ooe
+
+if [[ "$1" == "pre" ]]
+then
+ echo "Upgrading Atomic Host"
+ setenforce 0
+ ooe.sh atomic host upgrade
+
+ echo "Configuring Repositories"
+ ooe.sh sudo tee /etc/yum.repos.d/ngompa-gce-oslogin.repo <<EOF
+[ngompa-gce-oslogin]
+name=Copr repo for gce-oslogin owned by ngompa
+baseurl=https://copr-be.cloud.fedoraproject.org/results/ngompa/gce-oslogin/fedora-\$releasever-\$basearch/
+type=rpm-md
+skip_if_unavailable=True
+gpgcheck=1
+gpgkey=https://copr-be.cloud.fedoraproject.org/results/ngompa/gce-oslogin/pubkey.gpg
+repo_gpgcheck=0
+enabled=1
+enabled_metadata=1
+EOF
+ echo "Installing necessary packages and google services"
+ # Google services are enabled by default, upon install.
+ ooe.sh rpm-ostree install rng-tools google-compute-engine google-compute-engine-oslogin
+ echo "Rebooting..."
+ systemctl reboot # Required for upgrade + package installs to be active
+elif [[ "$1" == "post" ]]
+then
+ echo "Enabling necessary services"
+ systemctl enable rngd # Must reboot before enabling
+ rh_finalize
+ echo "SUCCESS!"
+else
+ echo "Expected to be called with 'pre' or 'post'"
+ exit 6
+fi
diff --git a/contrib/cirrus/packer/fah_setup.sh b/contrib/cirrus/packer/fah_setup.sh
new file mode 100644
index 000000000..2e053b396
--- /dev/null
+++ b/contrib/cirrus/packer/fah_setup.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+# This script is called by packer on the subject fah VM, to setup the podman
+# build/test environment. It's not intended to be used outside of this context.
+
+set -e
+
+# Load in library (copied by packer, before this script was run)
+source /tmp/libpod/$SCRIPT_BASE/lib.sh
+
+req_env_var "
+SCRIPT_BASE $SCRIPT_BASE
+"
+
+install_ooe
+
+ooe.sh sudo atomic host upgrade
+
+ooe.sh sudo rpm-ostree uninstall cloud-init
+
+rh_finalize
+
+echo "SUCCESS!"
diff --git a/contrib/cirrus/packer/fedora_base-setup.sh b/contrib/cirrus/packer/fedora_base-setup.sh
new file mode 100644
index 000000000..c0a1e422c
--- /dev/null
+++ b/contrib/cirrus/packer/fedora_base-setup.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+# N/B: This script is not intended to be run by humans. It is used to configure the
+# fedora base image for importing, so that it will boot in GCE
+
+set -e
+
+# Load in library (copied by packer, before this script was run)
+source $GOSRC/$SCRIPT_BASE/lib.sh
+
+[[ "$1" == "post" ]] || exit 0 # nothing to do
+
+install_ooe
+
+echo "Updating packages"
+ooe.sh dnf -y update
+
+echo "Installing necessary packages and google services"
+ooe.sh dnf -y copr enable ngompa/gce-oslogin
+ooe.sh dnf -y install rng-tools google-compute-engine google-compute-engine-oslogin
+
+echo "Enabling services"
+ooe.sh systemctl enable rngd
+
+rh_finalize
+
+echo "SUCCESS!"
diff --git a/contrib/cirrus/packer/fedora_setup.sh b/contrib/cirrus/packer/fedora_setup.sh
index f9fea04a7..4e4391e59 100644
--- a/contrib/cirrus/packer/fedora_setup.sh
+++ b/contrib/cirrus/packer/fedora_setup.sh
@@ -10,6 +10,7 @@ source /tmp/libpod/$SCRIPT_BASE/lib.sh
req_env_var "
SCRIPT_BASE $SCRIPT_BASE
+FEDORA_CNI_COMMIT $FEDORA_CNI_COMMIT
CNI_COMMIT $CNI_COMMIT
CRIO_COMMIT $CRIO_COMMIT
CRIU_COMMIT $CRIU_COMMIT
@@ -65,11 +66,13 @@ ooe.sh sudo dnf install -y \
runc \
skopeo-containers \
slirp4netns \
+ unzip \
which \
xz
install_varlink
+CNI_COMMIT=$FEDORA_CNI_COMMIT
install_cni_plugins
install_buildah
diff --git a/contrib/cirrus/packer/image-builder-image_base-setup.sh b/contrib/cirrus/packer/image-builder-image_base-setup.sh
new file mode 100644
index 000000000..b8e2824a7
--- /dev/null
+++ b/contrib/cirrus/packer/image-builder-image_base-setup.sh
@@ -0,0 +1,75 @@
+#!/bin/bash
+
+# This script is called by packer on a vanilla CentOS VM, to setup the image
+# used for building images FROM base images. It's not intended to be used
+# outside of this context.
+
+set -e
+
+[[ "$1" == "post" ]] || exit 0 # pre stage not needed
+
+# Load in library (copied by packer, before this script was run)
+source $GOSRC/$SCRIPT_BASE/lib.sh
+
+req_env_var "
+ TIMESTAMP $TIMESTAMP
+ GOSRC $GOSRC
+ SCRIPT_BASE $SCRIPT_BASE
+ PACKER_BASE $PACKER_BASE
+"
+
+install_ooe
+
+echo "Updating packages"
+ooe.sh sudo yum -y update
+
+echo "Configuring repositories"
+ooe.sh sudo yum -y install centos-release-scl epel-release
+
+echo "Installing packages"
+ooe.sh sudo yum -y install \
+ genisoimage \
+ golang \
+ google-cloud-sdk \
+ libvirt \
+ libvirt-admin \
+ libvirt-client \
+ libvirt-daemon \
+ make \
+ python34 \
+ python34 \
+ python34-PyYAML \
+ python34-PyYAML \
+ qemu-img \
+ qemu-kvm \
+ qemu-kvm-tools \
+ qemu-user \
+ rsync \
+ unzip \
+ util-linux \
+ vim
+
+sudo ln -s /usr/libexec/qemu-kvm /usr/bin/
+
+sudo tee /etc/modprobe.d/kvm-nested.conf <<EOF
+options kvm-intel nested=1
+options kvm-intel enable_shadow_vmcs=1
+options kvm-intel enable_apicv=1
+options kvm-intel ept=1
+EOF
+
+echo "Installing packer"
+sudo mkdir -p /root/$(basename $PACKER_BASE)
+sudo cp $GOSRC/$PACKER_BASE/*packer* /root/$(basename $PACKER_BASE)
+sudo mkdir -p /root/$(basename $SCRIPT_BASE)
+sudo cp $GOSRC/$SCRIPT_BASE/*.sh /root/$(basename $SCRIPT_BASE)
+
+install_scl_git
+
+echo "Cleaning up"
+cd /
+rm -rf $GOSRC
+
+rh_finalize
+
+echo "SUCCESS!"
diff --git a/contrib/cirrus/packer/libpod_base_images.yml b/contrib/cirrus/packer/libpod_base_images.yml
new file mode 100644
index 000000000..4ae44e0d9
--- /dev/null
+++ b/contrib/cirrus/packer/libpod_base_images.yml
@@ -0,0 +1,179 @@
+---
+
+variables:
+ # Complete local path to this repository (Required)
+ GOSRC:
+ # Relative path to this (packer) subdirectory (Required)
+ PACKER_BASE:
+ # Relative path to cirrus scripts subdirectory (Required)
+ SCRIPT_BASE:
+ # Unique ID for naming new base-images (required)
+ TIMESTAMP:
+ # Required for output from qemu builders
+ TTYDEV:
+ # RHEL images require click-through agreements to obtain (required)
+ RHEL_BASE_IMAGE_NAME:
+ RHEL_IMAGE_FILE:
+ RHEL_CSUM_FILE:
+ # RHEL requires a subscription to install/update packages
+ RHSM_COMMAND:
+
+ # Fedora images are obtainable by direct download
+ FEDORA_IMAGE_URL: "https://dl.fedoraproject.org/pub/fedora/linux/releases/29/Cloud/x86_64/images/Fedora-Cloud-Base-29-1.2.x86_64.qcow2"
+ FEDORA_CSUM_URL: "https://dl.fedoraproject.org/pub/fedora/linux/releases/29/Cloud/x86_64/images/Fedora-Cloud-29-1.2-x86_64-CHECKSUM"
+ FEDORA_BASE_IMAGE_NAME: 'fedora-cloud-base-29-1-2' # Name to use in GCE
+ FAH_IMAGE_URL: "https://dl.fedoraproject.org/pub/alt/atomic/stable/Fedora-Atomic-29-20181025.1/AtomicHost/x86_64/images/Fedora-AtomicHost-29-20181025.1.x86_64.qcow2"
+ FAH_CSUM_URL: "https://dl.fedoraproject.org/pub/alt/atomic/stable/Fedora-Atomic-29-20181025.1/AtomicHost/x86_64/images/Fedora-AtomicHost-29-20181025.1-x86_64-CHECKSUM"
+ FAH_BASE_IMAGE_NAME: 'fedora-atomichost-29-20181025-1' # Name to use in GCE
+
+ # The name of the image in GCE used for packer build libpod_images.yml
+ IBI_BASE_NAME: 'image-builder-image'
+ CIDATA_ISO: 'cidata.iso' # produced by Makefile
+
+ # Path to json file (required, likely ~/.config/gcloud/legacy_credentials/*/adc.json)
+ GOOGLE_APPLICATION_CREDENTIALS:
+ # The complete project ID (required, not the short name)
+ GCP_PROJECT_ID:
+ # Pre-existing storage bucket w/ lifecycle-enabled
+ XFERBUCKET: "packer-import" # pre-created, globally unique, lifecycle-enabled
+
+# Don't leak sensitive values in error messages / output
+sensitive-variables:
+ - 'GOOGLE_APPLICATION_CREDENTIALS'
+ - 'GCP_PROJECT_ID'
+ - 'RHSM_COMMAND'
+
+# What images to produce in which cloud
+builders:
+ - name: '{{user `IBI_BASE_NAME`}}'
+ type: 'googlecompute'
+ image_name: '{{user `IBI_BASE_NAME`}}-{{user `TIMESTAMP`}}'
+ image_family: '{{user `IBI_BASE_NAME`}}'
+ source_image_project_id: 'centos-cloud'
+ source_image_family: 'centos-7'
+ project_id: '{{user `GCP_PROJECT_ID`}}'
+ account_file: '{{user `GOOGLE_APPLICATION_CREDENTIALS`}}'
+ communicator: 'ssh'
+ ssh_username: 'centos'
+ ssh_pty: 'true'
+ # The only supported zone in Cirrus-CI, as of addition of this comment
+ zone: 'us-central1-a'
+ # Enable nested virtualization in case it's ever needed
+ image_licenses:
+ - 'https://www.googleapis.com/compute/v1/projects/vm-options/global/licenses/enable-vmx'
+ min_cpu_platform: "Intel Broadwell" # nested-virt requirement
+
+ - &nested_virt
+ name: 'fedora'
+ type: 'qemu'
+ accelerator: "kvm"
+ iso_url: '{{user `FEDORA_IMAGE_URL`}}'
+ disk_image: true
+ format: "raw"
+ disk_size: 5120
+ iso_checksum_url: '{{user `FEDORA_CSUM_URL`}}'
+ iso_checksum_type: "sha256"
+ output_directory: '/tmp/{{build_name}}'
+ vm_name: "disk.raw" # actually qcow2, name required for post-processing
+ boot_wait: '5s'
+ shutdown_command: 'shutdown -h now'
+ headless: true
+ qemu_binary: "/usr/libexec/qemu-kvm"
+ qemuargs: # List-of-list format required to override packer-generated args
+ - - "-m"
+ - "1024"
+ - - "-cpu"
+ - "host"
+ - - "-device"
+ - "virtio-rng-pci"
+ - - "-chardev"
+ - "tty,id=pts,path={{user `TTYDEV`}}"
+ - - "-device"
+ - "isa-serial,chardev=pts"
+ - - "-cdrom"
+ - "{{user `CIDATA_ISO`}}"
+ - - "-netdev"
+ - "user,id=net0,hostfwd=tcp::{{ .SSHHostPort }}-:22"
+ - - "-device"
+ - "virtio-net,netdev=net0"
+ communicator: 'ssh'
+ ssh_private_key_file: 'cidata.ssh'
+ ssh_username: 'root'
+
+ - <<: *nested_virt
+ name: 'fah'
+ iso_url: '{{user `FAH_IMAGE_URL`}}'
+ iso_checksum_url: '{{user `FAH_CSUM_URL`}}'
+ disk_size: 10240
+
+ - <<: *nested_virt
+ name: 'rhel'
+ iso_url: 'file://{{user `RHEL_IMAGE_FILE`}}'
+ iso_checksum_url: 'file://{{user `RHEL_CSUM_FILE`}}'
+ disk_size: 10240
+
+provisioners:
+ - type: 'shell'
+ inline:
+ - 'mkdir -p /tmp/libpod/{{user `SCRIPT_BASE`}}'
+ - 'mkdir -p /tmp/libpod/{{user `PACKER_BASE`}}'
+
+ - type: 'file'
+ source: '{{user `GOSRC`}}/.cirrus.yml'
+ destination: '/tmp/libpod/.cirrus.yml'
+
+ - type: 'file'
+ source: '{{user `GOSRC`}}/{{user `SCRIPT_BASE`}}/'
+ destination: '/tmp/libpod/{{user `SCRIPT_BASE`}}/'
+
+ - type: 'file'
+ source: '{{user `GOSRC`}}/{{user `PACKER_BASE`}}/'
+ destination: '/tmp/libpod/{{user `PACKER_BASE`}}/'
+
+ - &shell_script
+ type: 'shell'
+ inline:
+ - 'chmod +x /tmp/libpod/{{user `PACKER_BASE`}}/{{build_name}}_base-setup.sh'
+ - '/tmp/libpod/{{user `PACKER_BASE`}}/{{build_name}}_base-setup.sh pre'
+ expect_disconnect: true # Allow this to reboot the VM
+ environment_vars:
+ - 'TIMESTAMP={{user `TIMESTAMP`}}'
+ - 'GOSRC=/tmp/libpod'
+ - 'SCRIPT_BASE={{user `SCRIPT_BASE`}}'
+ - 'PACKER_BASE={{user `PACKER_BASE`}}'
+ - 'RHSM_COMMAND={{user `RHSM_COMMAND`}}'
+
+ - <<: *shell_script
+ inline: ['{{user `GOSRC`}}/{{user `PACKER_BASE`}}/{{build_name}}_base-setup.sh']
+ expect_disconnect: false
+ pause_before: '10s'
+ inline:
+ - '/tmp/libpod/{{user `PACKER_BASE`}}/{{build_name}}_base-setup.sh post'
+
+post-processors:
+ - - type: "compress"
+ only: ['fedora', 'fah', 'rhel']
+ output: '/tmp/{{build_name}}/disk.raw.tar.gz'
+ format: '.tar.gz'
+ compression_level: 9
+ - &gcp_import
+ only: ['fedora']
+ type: "googlecompute-import"
+ project_id: '{{user `GCP_PROJECT_ID`}}'
+ account_file: '{{user `GOOGLE_APPLICATION_CREDENTIALS`}}'
+ bucket: '{{user `XFERBUCKET`}}'
+ gcs_object_name: '{{build_name}}-{{user `TIMESTAMP`}}-{{uuid}}.tar.gz'
+ image_name: "{{user `FEDORA_BASE_IMAGE_NAME`}}-{{user `TIMESTAMP`}}"
+ image_description: 'Based on {{user `FEDORA_IMAGE_URL`}}'
+ image_family: '{{user `FEDORA_BASE_IMAGE_NAME`}}'
+ - <<: *gcp_import
+ only: ['fah']
+ image_name: "{{user `FAH_BASE_IMAGE_NAME`}}-{{user `TIMESTAMP`}}"
+ image_description: 'Based on {{user `FAH_IMAGE_URL`}}'
+ image_family: '{{user `FAH_BASE_IMAGE_NAME`}}'
+ - <<: *gcp_import
+ only: ['rhel']
+ image_name: "{{user `RHEL_BASE_IMAGE_NAME`}}-{{user `TIMESTAMP`}}"
+ image_description: 'Based on {{user `RHEL_IMAGE_FILE`}}'
+ image_family: '{{user `RHEL_BASE_IMAGE_NAME`}}'
+ - type: 'manifest'
diff --git a/contrib/cirrus/packer/libpod_images.json b/contrib/cirrus/packer/libpod_images.json
deleted file mode 100644
index 9dac3e8ea..000000000
--- a/contrib/cirrus/packer/libpod_images.json
+++ /dev/null
@@ -1,130 +0,0 @@
-{
- "variables": {
- "FEDORA_CNI_COMMIT": "{{env `FEDORA_CNI_COMMIT`}}",
- "CNI_COMMIT": "{{env `CNI_COMMIT`}}",
- "CRIO_COMMIT": "{{env `CRIO_COMMIT`}}",
- "CRIU_COMMIT": "{{env `CRIU_COMMIT`}}",
- "RUNC_COMMIT": "{{env `RUNC_COMMIT`}}",
-
- "CENTOS_BASE_IMAGE": "{{env `CENTOS_BASE_IMAGE`}}" ,
- "UBUNTU_BASE_IMAGE": "{{env `UBUNTU_BASE_IMAGE`}}",
- "FEDORA_BASE_IMAGE": "{{env `FEDORA_BASE_IMAGE`}}",
- "RHEL_BASE_IMAGE": "{{env `RHEL_BASE_IMAGE`}}",
-
- "GOSRC": "{{env `GOSRC`}}",
- "PACKER_BASE": "{{env `PACKER_BASE`}}",
- "SCRIPT_BASE": "{{env `SCRIPT_BASE`}}",
-
- "SERVICE_ACCOUNT": "{{env `SERVICE_ACCOUNT`}}",
- "GCP_PROJECT_ID": "{{env `GCP_PROJECT_ID`}}",
- "BUILT_IMAGE_SUFFIX": "{{env `BUILT_IMAGE_SUFFIX`}}",
- "GCE_SSH_USERNAME": "{{env `GCE_SSH_USERNAME`}}",
- "RHSM_COMMAND": "{{env `RHSM_COMMAND`}}"
- },
- "sensitive-variables": [
- "GCP_PROJECT_ID", "SERVICE_ACCOUNT", "GCE_SSH_USERNAME", "RHSM_COMMAND"
- ],
- "builders": [
- {
- "name": "rhel-7",
- "type": "googlecompute",
- "project_id": "{{user `GCP_PROJECT_ID`}}",
- "zone": "us-central1-a",
- "source_image": "{{user `RHEL_BASE_IMAGE`}}",
- "image_name": "{{user `RHEL_BASE_IMAGE`}}{{user `BUILT_IMAGE_SUFFIX`}}",
- "image_family": "{{user `RHEL_BASE_IMAGE`}}-libpod",
- "service_account_email": "{{user `SERVICE_ACCOUNT`}}",
- "communicator": "ssh",
- "ssh_username": "ec2-user",
- "ssh_pty": "true"
- },{
- "name": "centos-7",
- "type": "googlecompute",
- "project_id": "{{user `GCP_PROJECT_ID`}}",
- "zone": "us-central1-a",
- "source_image": "{{user `CENTOS_BASE_IMAGE`}}",
- "image_name": "{{user `CENTOS_BASE_IMAGE`}}{{user `BUILT_IMAGE_SUFFIX`}}",
- "image_family": "{{user `CENTOS_BASE_IMAGE`}}-libpod",
- "service_account_email": "{{user `SERVICE_ACCOUNT`}}",
- "communicator": "ssh",
- "ssh_username": "{{user `GCE_SSH_USERNAME`}}",
- "ssh_pty": "true"
- },{
- "name": "fedora-28",
- "type": "googlecompute",
- "project_id": "{{user `GCP_PROJECT_ID`}}",
- "zone": "us-central1-a",
- "source_image": "{{user `FEDORA_BASE_IMAGE`}}",
- "image_name": "{{user `FEDORA_BASE_IMAGE`}}{{user `BUILT_IMAGE_SUFFIX`}}",
- "image_family": "{{user `FEDORA_BASE_IMAGE`}}-libpod",
- "service_account_email": "{{user `SERVICE_ACCOUNT`}}",
- "communicator": "ssh",
- "ssh_username": "fedora",
- "ssh_pty": "true"
- },{
- "name": "ubuntu-18",
- "type": "googlecompute",
- "project_id": "{{user `GCP_PROJECT_ID`}}",
- "zone": "us-central1-a",
- "source_image": "{{user `UBUNTU_BASE_IMAGE`}}",
- "image_name": "{{user `UBUNTU_BASE_IMAGE`}}{{user `BUILT_IMAGE_SUFFIX`}}",
- "image_family": "{{user `UBUNTU_BASE_IMAGE`}}-libpod",
- "service_account_email": "{{user `SERVICE_ACCOUNT`}}",
- "communicator": "ssh",
- "ssh_username": "{{user `GCE_SSH_USERNAME`}}",
- "ssh_pty": "true"
- }
- ],
- "provisioners": [
- {
- "type": "file",
- "source": "{{user `GOSRC`}}",
- "destination": "/tmp/libpod"
- },{
- "type": "shell",
- "only": ["rhel-7"],
- "script": "{{user `GOSRC`}}/{{user `PACKER_BASE`}}/rhel_setup.sh",
- "environment_vars": [
- "SCRIPT_BASE={{user `SCRIPT_BASE`}}",
- "CNI_COMMIT={{user `CNI_COMMIT`}}",
- "CRIO_COMMIT={{user `CRIO_COMMIT`}}",
- "CRIU_COMMIT={{user `CRIU_COMMIT`}}",
- "RUNC_COMMIT={{user `RUNC_COMMIT`}}",
- "RHSM_COMMAND={{user `RHSM_COMMAND`}}"
- ]
- },{
- "type": "shell",
- "only": ["centos-7"],
- "script": "{{user `GOSRC`}}/{{user `PACKER_BASE`}}/centos_setup.sh",
- "environment_vars": [
- "SCRIPT_BASE={{user `SCRIPT_BASE`}}",
- "CNI_COMMIT={{user `CNI_COMMIT`}}",
- "CRIO_COMMIT={{user `CRIO_COMMIT`}}",
- "CRIU_COMMIT={{user `CRIU_COMMIT`}}",
- "RUNC_COMMIT={{user `RUNC_COMMIT`}}"
- ]
- },{
- "type": "shell",
- "only": ["fedora-28"],
- "script": "{{user `GOSRC`}}/{{user `PACKER_BASE`}}/fedora_setup.sh",
- "environment_vars": [
- "SCRIPT_BASE={{user `SCRIPT_BASE`}}",
- "CNI_COMMIT={{user `FEDORA_CNI_COMMIT`}}",
- "CRIO_COMMIT={{user `CRIO_COMMIT`}}",
- "CRIU_COMMIT={{user `CRIU_COMMIT`}}",
- "RUNC_COMMIT={{user `RUNC_COMMIT`}}"
- ]
- },{
- "type": "shell",
- "only": ["ubuntu-18"],
- "script": "{{user `GOSRC`}}/{{user `PACKER_BASE`}}/ubuntu_setup.sh",
- "environment_vars": [
- "SCRIPT_BASE={{user `SCRIPT_BASE`}}",
- "CNI_COMMIT={{user `CNI_COMMIT`}}",
- "CRIO_COMMIT={{user `CRIO_COMMIT`}}",
- "CRIU_COMMIT={{user `CRIU_COMMIT`}}",
- "RUNC_COMMIT={{user `RUNC_COMMIT`}}"
- ]
- }
- ]
-}
diff --git a/contrib/cirrus/packer/libpod_images.yml b/contrib/cirrus/packer/libpod_images.yml
new file mode 100644
index 000000000..7b95b08cc
--- /dev/null
+++ b/contrib/cirrus/packer/libpod_images.yml
@@ -0,0 +1,91 @@
+---
+
+# All of these are required
+variables:
+ # Names of GCE Base images to start from, in .cirrus.yml
+ RHEL_BASE_IMAGE: '{{env `RHEL_BASE_IMAGE`}}'
+ CENTOS_BASE_IMAGE: '{{env `CENTOS_BASE_IMAGE`}}'
+ UBUNTU_BASE_IMAGE: '{{env `UBUNTU_BASE_IMAGE`}}'
+ FEDORA_BASE_IMAGE: '{{env `FEDORA_BASE_IMAGE`}}'
+ FAH_BASE_IMAGE: '{{env `FAH_BASE_IMAGE`}}'
+
+ # libpod dependencies to build and install into images
+ FEDORA_CNI_COMMIT: "{{env `FEDORA_CNI_COMMIT`}}"
+ CNI_COMMIT: "{{env `CNI_COMMIT`}}"
+ CRIO_COMMIT: "{{env `CRIO_COMMIT`}}"
+ CRIU_COMMIT: "{{env `CRIU_COMMIT`}}"
+ RUNC_COMMIT: "{{env `RUNC_COMMIT`}}"
+
+ BUILT_IMAGE_SUFFIX: '{{env `BUILT_IMAGE_SUFFIX`}}'
+ GOSRC: '{{env `GOSRC`}}'
+ PACKER_BASE: '{{env `PACKER_BASE`}}'
+ SCRIPT_BASE: '{{env `SCRIPT_BASE`}}'
+
+ # Protected credentials, decrypted by Cirrus at runtime
+ GCE_SSH_USERNAME: '{{env `GCE_SSH_USERNAME`}}'
+ GCP_PROJECT_ID: '{{env `GCP_PROJECT_ID`}}'
+ RHSM_COMMAND: '{{env `RHSM_COMMAND`}}'
+ SERVICE_ACCOUNT: '{{env `SERVICE_ACCOUNT`}}'
+ GOOGLE_APPLICATION_CREDENTIALS: '{{env `GOOGLE_APPLICATION_CREDENTIALS`}}'
+
+# Don't leak sensitive values in error messages / output
+sensitive-variables:
+ - 'GCE_SSH_USERNAME'
+ - 'GCP_PROJECT_ID'
+ - 'RHSM_COMMAND'
+ - 'SERVICE_ACCOUNT'
+
+# What images to produce in which cloud
+builders:
+ # v----- is a YAML anchor, allows referencing this object by name (below)
+ - &gce_hosted_image
+ name: 'ubuntu-18'
+ type: 'googlecompute'
+ image_name: '{{build_name}}{{user `BUILT_IMAGE_SUFFIX`}}'
+ image_family: '{{build_name}}-libpod'
+ source_image: '{{user `UBUNTU_BASE_IMAGE`}}'
+ disk_size: 20
+ project_id: '{{user `GCP_PROJECT_ID`}}'
+ service_account_email: '{{user `SERVICE_ACCOUNT`}}'
+ communicator: 'ssh'
+ ssh_username: '{{user `GCE_SSH_USERNAME`}}'
+ ssh_pty: 'true'
+ # The only supported zone in Cirrus-CI, as of addition of this comment
+ zone: 'us-central1-a'
+
+ # v----- is a YAML alias, allows partial re-use of the anchor object
+ - <<: *gce_hosted_image
+ name: 'rhel-7'
+ source_image: '{{user `RHEL_BASE_IMAGE`}}'
+
+ - <<: *gce_hosted_image
+ name: 'centos-7'
+ source_image: '{{user `CENTOS_BASE_IMAGE`}}'
+
+ - <<: *gce_hosted_image
+ name: 'fedora-29'
+ source_image: '{{user `FEDORA_BASE_IMAGE`}}'
+
+ - <<: *gce_hosted_image
+ name: 'fah-29'
+ source_image: '{{user `FAH_BASE_IMAGE`}}'
+
+# The brains of the operation, making actual modifications to the base-image.
+provisioners:
+ - type: 'file'
+ source: '{{user `GOSRC`}}'
+ destination: '/tmp/libpod'
+
+ - type: 'shell'
+ script: '{{user `GOSRC`}}/{{user `PACKER_BASE`}}/{{split build_name "-" 0}}_setup.sh'
+ environment_vars:
+ - 'SCRIPT_BASE={{user `SCRIPT_BASE`}}'
+ - 'CNI_COMMIT={{user `CNI_COMMIT`}}'
+ - 'FEDORA_CNI_COMMIT={{user `FEDORA_CNI_COMMIT`}}'
+ - 'CRIO_COMMIT={{user `CRIO_COMMIT`}}'
+ - 'CRIU_COMMIT={{user `CRIU_COMMIT`}}'
+ - 'RUNC_COMMIT={{user `RUNC_COMMIT`}}'
+ - 'RHSM_COMMAND={{user `RHSM_COMMAND`}}'
+
+post-processors:
+ - - type: 'manifest'
diff --git a/contrib/cirrus/packer/make-user-data.sh b/contrib/cirrus/packer/make-user-data.sh
new file mode 100644
index 000000000..7f7fa1c1a
--- /dev/null
+++ b/contrib/cirrus/packer/make-user-data.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+# This script is utilized by Makefile, it's not intended to be run by humans
+
+cat <<EOF > user-data
+#cloud-config
+timezone: US/Eastern
+growpart:
+ mode: auto
+disable_root: false
+ssh_pwauth: True
+ssh_import_id: [root]
+ssh_authorized_keys:
+ - $(cat cidata.ssh.pub)
+users:
+ - name: root
+ primary-group: root
+ homedir: /root
+ system: true
+EOF
diff --git a/contrib/cirrus/packer/rhel_base-setup.sh b/contrib/cirrus/packer/rhel_base-setup.sh
new file mode 100644
index 000000000..8b2073d4f
--- /dev/null
+++ b/contrib/cirrus/packer/rhel_base-setup.sh
@@ -0,0 +1,52 @@
+#!/bin/bash
+
+# N/B: This script is not intended to be run by humans. It is used to configure the
+# rhel base image for importing, so that it will boot in GCE
+
+set -e
+
+[[ "$1" == "post" ]] || exit 0 # pre stage is not needed
+
+# Load in library (copied by packer, before this script was run)
+source $GOSRC/$SCRIPT_BASE/lib.sh
+
+req_env_var "
+ RHSM_COMMAND $RHSM_COMMAND
+"
+
+install_ooe
+
+echo "Setting up repos"
+# Frequently needed
+ooe.sh sudo yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
+
+# Required for google to manage ssh keys
+ooe.sh sudo tee /etc/yum.repos.d/google-cloud-sdk.repo << EOM
+[google-cloud-compute]
+name=google-cloud-compute
+baseurl=https://packages.cloud.google.com/yum/repos/google-cloud-compute-el7-x86_64
+enabled=1
+gpgcheck=1
+repo_gpgcheck=1
+gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg
+ https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
+EOM
+
+rhsm_enable
+
+echo "Installing/removing packages"
+ooe.sh sudo yum -y install google-compute-engine google-compute-engine-oslogin
+ooe.sh sudo yum -y erase "cloud-init" "rh-amazon-rhui-client*" || true
+ooe.sh sudo systemctl enable \
+ google-accounts-daemon \
+ google-clock-skew-daemon \
+ google-instance-setup \
+ google-network-daemon \
+ google-shutdown-scripts \
+ google-startup-scripts
+
+rhel_exit_handler # release subscription!
+
+rh_finalize
+
+echo "SUCCESS!"
diff --git a/contrib/cirrus/packer/rhel_setup.sh b/contrib/cirrus/packer/rhel_setup.sh
index d296713fc..7f0d4e589 100644
--- a/contrib/cirrus/packer/rhel_setup.sh
+++ b/contrib/cirrus/packer/rhel_setup.sh
@@ -18,24 +18,7 @@ RHSM_COMMAND $RHSM_COMMAND
install_ooe
-export GOPATH="$(mktemp -d)"
-export RHSMCMD="$(mktemp)"
-
-exit_handler() {
- set +ex
- cd /
- sudo rm -rf "$RHSMCMD"
- sudo rm -rf "$GOPATH"
- sudo subscription-manager remove --all
- sudo subscription-manager unregister
- sudo subscription-manager clean
-}
-trap "exit_handler" EXIT
-
-# Avoid logging sensitive details
-echo "$RHSM_COMMAND" > "$RHSMCMD"
-ooe.sh sudo bash "$RHSMCMD"
-sudo rm -rf "$RHSMCMD"
+rhsm_enable
ooe.sh sudo yum -y erase "rh-amazon-rhui-client*"
ooe.sh sudo subscription-manager repos "--disable=*"
@@ -47,21 +30,6 @@ ooe.sh sudo subscription-manager repos \
ooe.sh sudo yum -y update
-# Frequently needed
-ooe.sh sudo yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
-
-# Required for google to manage ssh keys
-sudo tee -a /etc/yum.repos.d/google-cloud-sdk.repo << EOM
-[google-cloud-compute]
-name=google-cloud-compute
-baseurl=https://packages.cloud.google.com/yum/repos/google-cloud-compute-el7-x86_64
-enabled=1
-gpgcheck=1
-repo_gpgcheck=1
-gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg
- https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
-EOM
-
ooe.sh sudo yum -y install \
atomic-registries \
btrfs-progs-devel \
@@ -74,8 +42,6 @@ ooe.sh sudo yum -y install \
golang \
golang-github-cpuguy83-go-md2man \
golang-github-cpuguy83-go-md2man \
- google-compute-engine \
- google-compute-engine-oslogin \
gpgme-devel \
iptables \
libassuan-devel \
@@ -118,7 +84,7 @@ install_criu
install_packer_copied_files
-exit_handler # release subscription!
+rhel_exit_handler # release subscription!
rh_finalize
diff --git a/contrib/cirrus/packer/ubuntu_setup.sh b/contrib/cirrus/packer/ubuntu_setup.sh
index ef209a4a4..6e3613462 100644
--- a/contrib/cirrus/packer/ubuntu_setup.sh
+++ b/contrib/cirrus/packer/ubuntu_setup.sh
@@ -21,6 +21,7 @@ install_ooe
export GOPATH="$(mktemp -d)"
trap "sudo rm -rf $GOPATH" EXIT
+# Avoid getting stuck waiting for user input
export DEBIAN_FRONTEND=noninteractive
# Try twice as workaround for minor networking problems
@@ -56,6 +57,8 @@ ooe.sh sudo -E apt-get -qq install --no-install-recommends \
libostree-dev \
libprotobuf-c0-dev \
libprotobuf-dev \
+ libseccomp-dev \
+ libseccomp2 \
libtool \
libudev-dev \
lsof \
diff --git a/contrib/cirrus/setup_environment.sh b/contrib/cirrus/setup_environment.sh
index 2563b5f43..5ba842cf1 100755
--- a/contrib/cirrus/setup_environment.sh
+++ b/contrib/cirrus/setup_environment.sh
@@ -16,12 +16,11 @@ CIRRUS_BUILD_ID $CIRRUS_BUILD_ID"
cd "$CIRRUS_WORKING_DIR" # for clarity of initial conditions
# Verify basic dependencies
-for depbin in go rsync unzip sha256sum curl make
+for depbin in go rsync unzip sha256sum curl make python3 git
do
if ! type -P "$depbin" &> /dev/null
then
- echo "ERROR: $depbin binary not found in $PATH"
- exit 2
+ echo "***** WARNING: $depbin binary not found in $PATH *****"
fi
done
@@ -35,14 +34,15 @@ then
# N/B: Single-quote items evaluated every time, double-quotes only once (right now).
for envstr in \
"$MARK" \
+ "export EPOCH_TEST_COMMIT=\"$CIRRUS_BASE_SHA\"" \
"export HEAD=\"$CIRRUS_CHANGE_IN_REPO\"" \
"export TRAVIS=\"1\"" \
"export GOSRC=\"$CIRRUS_WORKING_DIR\"" \
"export OS_RELEASE_ID=\"$(os_release_id)\"" \
"export OS_RELEASE_VER=\"$(os_release_ver)\"" \
- "export OS_REL_VER=\"${OS_RELEASE_ID}-${OS_RELEASE_VER}\"" \
+ "export OS_REL_VER=\"$(os_release_id)-$(os_release_ver)\"" \
"export BUILT_IMAGE_SUFFIX=\"-$CIRRUS_REPO_NAME-${CIRRUS_CHANGE_IN_REPO:0:8}\"" \
- "export GOPATH=\"/go\"" \
+ "export GOPATH=\"/var/tmp/go\"" \
'export PATH="$HOME/bin:$GOPATH/bin:/usr/local/bin:$PATH"' \
'export LD_LIBRARY_PATH="/usr/local/lib${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}"'
do
@@ -57,7 +57,8 @@ then
install_runc_from_git
envstr='export BUILDTAGS="seccomp $($GOSRC/hack/btrfs_tag.sh) $($GOSRC/hack/btrfs_installed_tag.sh) $($GOSRC/hack/ostree_tag.sh) varlink exclude_graphdriver_devicemapper"'
;;
- fedora-28) ;& # Continue to the next item
+ fedora-29) ;& # Continue to the next item
+ fedora-28) ;&
centos-7) ;&
rhel-7)
envstr='unset BUILDTAGS' # Use default from Makefile
diff --git a/contrib/cirrus/system_test.sh b/contrib/cirrus/system_test.sh
index 7c727d336..66974f8c6 100755
--- a/contrib/cirrus/system_test.sh
+++ b/contrib/cirrus/system_test.sh
@@ -9,7 +9,7 @@ OS_RELEASE_ID $OS_RELEASE_ID
OS_RELEASE_VER $OS_RELEASE_VER
"
-show_env_vars
+clean_env
set -x
cd "$GOSRC"
diff --git a/contrib/cirrus/unit_test.sh b/contrib/cirrus/unit_test.sh
index cacc23045..e5b167e79 100755
--- a/contrib/cirrus/unit_test.sh
+++ b/contrib/cirrus/unit_test.sh
@@ -9,22 +9,22 @@ OS_RELEASE_ID $OS_RELEASE_ID
OS_RELEASE_VER $OS_RELEASE_VER
"
-show_env_vars
+clean_env
set -x
cd "$GOSRC"
case "${OS_RELEASE_ID}-${OS_RELEASE_VER}" in
ubuntu-18)
+ make install.tools "BUILDTAGS=$BUILDTAGS"
make localunit "BUILDTAGS=$BUILDTAGS"
make "BUILDTAGS=$BUILDTAGS"
;;
- fedora-28)
+ fedora-29) ;& # Continue to the next item
+ centos-7) ;&
+ rhel-7)
+ make install.tools
make localunit
make
;;
- centos-7) ;& # Continue to the next item
- rhel-7)
- stub 'unit testing not working on $OS_RELEASE_ID'
- ;;
*) bad_os_id_ver ;;
esac
diff --git a/contrib/cirrus/verify_source.sh b/contrib/cirrus/verify_source.sh
deleted file mode 100755
index 860bafc00..000000000
--- a/contrib/cirrus/verify_source.sh
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/bin/bash
-
-set -e
-source $(dirname $0)/lib.sh
-
-req_env_var "
-OS_RELEASE_ID $OS_RELEASE_ID
-OS_RELEASE_VER $OS_RELEASE_VER
-"
-
-show_env_vars
-
-set -x
-cd "$GOSRC"
-
-case "${OS_RELEASE_ID}-${OS_RELEASE_VER}" in
- ubuntu-18)
- make install.tools "BUILDTAGS=$BUILDTAGS"
- make validate "BUILDTAGS=$BUILDTAGS"
- # make lint "BUILDTAGS=$BUILDTAGS"
- ;;
- fedora-28) ;&
- centos-7) ;&
- rhel-7)
- make install.tools
- make validate
- # make lint
- ;;
- *) bad_os_id_ver ;;
-esac
diff --git a/contrib/python/podman/Makefile b/contrib/python/podman/Makefile
index 11a7568d1..0cbfe2fb3 100644
--- a/contrib/python/podman/Makefile
+++ b/contrib/python/podman/Makefile
@@ -1,6 +1,6 @@
PYTHON ?= $(shell command -v python3 2>/dev/null || command -v python)
DESTDIR ?= /
-PODMAN_VERSION ?= '0.0.4'
+PODMAN_VERSION ?= '0.11.1.1'
.PHONY: python-podman
python-podman:
@@ -22,8 +22,8 @@ install:
.PHONY: upload
upload:
- $(PODMAN_VERSION) $(PYTHON) setup.py sdist bdist_wheel
- twine upload --repository-url https://test.pypi.org/legacy/ dist/*
+ PODMAN_VERSION=$(PODMAN_VERSION) $(PYTHON) setup.py sdist bdist_wheel
+ twine upload --verbose --repository-url https://test.pypi.org/legacy/ dist/*
.PHONY: clobber
clobber: uninstall clean
diff --git a/contrib/python/pypodman/Makefile b/contrib/python/pypodman/Makefile
index 272145c5d..230eee44d 100644
--- a/contrib/python/pypodman/Makefile
+++ b/contrib/python/pypodman/Makefile
@@ -1,6 +1,6 @@
PYTHON ?= $(shell command -v python3 2>/dev/null || command -v python)
DESTDIR := /
-PODMAN_VERSION ?= '0.0.4'
+PODMAN_VERSION ?= '0.11.1.1'
.PHONY: python-pypodman
python-pypodman:
@@ -22,7 +22,7 @@ install:
.PHONY: upload
upload:
- $(PODMAN_VERSION) $(PYTHON) setup.py sdist bdist_wheel
+ PODMAN_VERSION=$(PODMAN_VERSION) $(PYTHON) setup.py sdist bdist_wheel
twine upload --repository-url https://test.pypi.org/legacy/ dist/*
.PHONY: clobber
diff --git a/contrib/python/pypodman/pypodman/lib/__init__.py b/contrib/python/pypodman/pypodman/lib/__init__.py
index be1b5f467..d9a434254 100644
--- a/contrib/python/pypodman/pypodman/lib/__init__.py
+++ b/contrib/python/pypodman/pypodman/lib/__init__.py
@@ -3,18 +3,17 @@ import sys
import podman
from pypodman.lib.action_base import AbstractActionBase
-from pypodman.lib.parser_actions import (BooleanAction, BooleanValidate,
- ChangeAction, PathAction,
- PositiveIntAction, UnitAction)
+from pypodman.lib.parser_actions import (ChangeAction, PathAction,
+ PositiveIntAction, SignalAction,
+ UnitAction)
from pypodman.lib.podman_parser import PodmanArgumentParser
from pypodman.lib.report import Report, ReportColumn
# Silence pylint overlording...
-assert BooleanAction
-assert BooleanValidate
assert ChangeAction
assert PathAction
assert PositiveIntAction
+assert SignalAction
assert UnitAction
__all__ = [
diff --git a/contrib/python/pypodman/pypodman/lib/action_base.py b/contrib/python/pypodman/pypodman/lib/action_base.py
index a950c362b..5cba7ac5c 100644
--- a/contrib/python/pypodman/pypodman/lib/action_base.py
+++ b/contrib/python/pypodman/pypodman/lib/action_base.py
@@ -17,29 +17,21 @@ class AbstractActionBase(abc.ABC):
Use set_defaults() to set attributes "class_" and "method". These will
be invoked as class_(parsed_args).method()
"""
- parent.add_argument(
+ parent.add_flag(
'--all',
- action='store_true',
- help=('list all items.'
- ' (default: no-op, included for compatibility.)'))
- parent.add_argument(
- '--no-trunc',
- '--notruncate',
- action='store_false',
- dest='truncate',
+ help='list all items.')
+ parent.add_flag(
+ '--truncate',
+ '--trunc',
default=True,
- help='Display extended information. (default: False)')
- parent.add_argument(
- '--noheading',
- action='store_false',
- dest='heading',
+ help="Truncate id's and other long fields.")
+ parent.add_flag(
+ '--heading',
default=True,
- help=('Omit the table headings from the output.'
- ' (default: False)'))
- parent.add_argument(
+ help='Include table headings in the output.')
+ parent.add_flag(
'--quiet',
- action='store_true',
- help='List only the IDs. (default: %(default)s)')
+ help='List only the IDs.')
def __init__(self, args):
"""Construct class."""
diff --git a/contrib/python/pypodman/pypodman/lib/actions/_create_args.py b/contrib/python/pypodman/pypodman/lib/actions/_create_args.py
index 207f52796..8ab4292e8 100644
--- a/contrib/python/pypodman/pypodman/lib/actions/_create_args.py
+++ b/contrib/python/pypodman/pypodman/lib/actions/_create_args.py
@@ -1,6 +1,6 @@
"""Implement common create container arguments together."""
-from pypodman.lib import BooleanAction, UnitAction
+from pypodman.lib import SignalAction, UnitAction
class CreateArguments():
@@ -108,11 +108,9 @@ class CreateArguments():
metavar='NODES',
help=('Memory nodes (MEMs) in which to allow execution (0-3, 0,1).'
' Only effective on NUMA systems'))
- parser.add_argument(
+ parser.add_flag(
'--detach',
'-d',
- action=BooleanAction,
- default=False,
help='Detached mode: run the container in the background and'
' print the new container ID. (default: False)')
parser.add_argument(
@@ -218,7 +216,7 @@ class CreateArguments():
# only way for argparse to handle these options.
vol_args = {
- 'choices': ['bind', 'tmpfs', 'ignore'],
+ 'choices': ('bind', 'tmpfs', 'ignore'),
'metavar': 'MODE',
'type': str.lower,
'help': 'Tells podman how to handle the builtin image volumes',
@@ -228,12 +226,10 @@ class CreateArguments():
volume_group.add_argument('--image-volume', **vol_args)
volume_group.add_argument('--builtin-volume', **vol_args)
- parser.add_argument(
+ parser.add_flag(
'--interactive',
'-i',
- action=BooleanAction,
- default=False,
- help='Keep STDIN open even if not attached. (default: False)')
+ help='Keep STDIN open even if not attached.')
parser.add_argument('--ipc', help='Create namespace')
parser.add_argument(
'--kernel-memory', action=UnitAction, help='Kernel memory limit')
@@ -278,10 +274,9 @@ class CreateArguments():
metavar='BRIDGE',
help='Set the Network mode for the container.'
' (format: bridge, host, container:UUID, ns:PATH, none)')
- parser.add_argument(
+ parser.add_flag(
'--oom-kill-disable',
- action=BooleanAction,
- help='Whether to disable OOM Killer for the container or not')
+ help='Whether to disable OOM Killer for the container or not.')
parser.add_argument(
'--oom-score-adj',
choices=range(-1000, 1000),
@@ -298,41 +293,33 @@ class CreateArguments():
help=("Tune the container's pids limit."
" Set -1 to have unlimited pids for the container."))
parser.add_argument('--pod', help='Run container in an existing pod')
- parser.add_argument(
+ parser.add_flag(
'--privileged',
- action=BooleanAction,
help='Give extended privileges to this container.')
parser.add_argument(
'--publish',
'-p',
metavar='RANGE',
help="Publish a container's port, or range of ports, to the host")
- parser.add_argument(
+ parser.add_flag(
'--publish-all',
'-P',
- action=BooleanAction,
help='Publish all exposed ports to random'
- ' ports on the host interfaces'
- '(default: False)')
- parser.add_argument(
+ ' ports on the host interfaces.')
+ parser.add_flag(
'--quiet',
'-q',
- action='store_true',
help='Suppress output information when pulling images')
- parser.add_argument(
+ parser.add_flag(
'--read-only',
- action=BooleanAction,
help="Mount the container's root filesystem as read only.")
- parser.add_argument(
+ parser.add_flag(
'--rm',
- action=BooleanAction,
- default=False,
help='Automatically remove the container when it exits.')
parser.add_argument(
'--rootfs',
- action='store_true',
- help=('If specified, the first argument refers to an'
- ' exploded container on the file system of remote host.'))
+ help='If specified, the first argument refers to an'
+ ' exploded container on the file system of remote host.')
parser.add_argument(
'--security-opt',
action='append',
@@ -340,15 +327,14 @@ class CreateArguments():
help='Set security options.')
parser.add_argument(
'--shm-size', action=UnitAction, help='Size of /dev/shm')
- parser.add_argument(
+ parser.add_flag(
'--sig-proxy',
- action=BooleanAction,
- default=True,
help='Proxy signals sent to the podman run'
' command to the container process')
parser.add_argument(
'--stop-signal',
- metavar='SIGTERM',
+ action=SignalAction,
+ default='TERM',
help='Signal to stop a container')
parser.add_argument(
'--stop-timeout',
@@ -374,11 +360,9 @@ class CreateArguments():
metavar='MOUNT',
help='Create a tmpfs mount.'
' (default: rw,noexec,nosuid,nodev,size=65536k.)')
- parser.add_argument(
+ parser.add_flag(
'--tty',
'-t',
- action=BooleanAction,
- default=False,
help='Allocate a pseudo-TTY for standard input of container.')
parser.add_argument(
'--uidmap',
@@ -394,15 +378,16 @@ class CreateArguments():
parser.add_argument(
'--user',
'-u',
- help=('Sets the username or UID used and optionally'
- ' the groupname or GID for the specified command.'))
+ help='Sets the username or UID used and optionally'
+ ' the groupname or GID for the specified command.')
parser.add_argument(
'--userns',
metavar='NAMESPACE',
help='Set the user namespace mode for the container')
parser.add_argument(
'--uts',
- choices=['host', 'ns'],
+ choices=('host', 'ns'),
+ type=str.lower,
help='Set the UTS mode for the container')
parser.add_argument('--volume', '-v', help='Create a bind mount.')
parser.add_argument(
diff --git a/contrib/python/pypodman/pypodman/lib/actions/commit_action.py b/contrib/python/pypodman/pypodman/lib/actions/commit_action.py
index 21924e938..c166e1aff 100644
--- a/contrib/python/pypodman/pypodman/lib/actions/commit_action.py
+++ b/contrib/python/pypodman/pypodman/lib/actions/commit_action.py
@@ -2,7 +2,7 @@
import sys
import podman
-from pypodman.lib import AbstractActionBase, BooleanAction, ChangeAction
+from pypodman.lib import AbstractActionBase, ChangeAction
class Commit(AbstractActionBase):
@@ -44,17 +44,14 @@ class Commit(AbstractActionBase):
help='Set commit message for committed image'
' (Only on docker images.)',
)
- parser.add_argument(
+ parser.add_flag(
'--pause',
'-p',
- action=BooleanAction,
- default=True,
help='Pause the container when creating an image',
)
- parser.add_argument(
+ parser.add_flag(
'--quiet',
'-q',
- action='store_true',
help='Suppress output',
)
parser.add_argument(
diff --git a/contrib/python/pypodman/pypodman/lib/actions/history_action.py b/contrib/python/pypodman/pypodman/lib/actions/history_action.py
index f9aaa54f6..76c3ad756 100644
--- a/contrib/python/pypodman/pypodman/lib/actions/history_action.py
+++ b/contrib/python/pypodman/pypodman/lib/actions/history_action.py
@@ -5,8 +5,7 @@ from collections import OrderedDict
import humanize
import podman
-from pypodman.lib import (AbstractActionBase, BooleanAction, Report,
- ReportColumn)
+from pypodman.lib import AbstractActionBase, Report, ReportColumn
class History(AbstractActionBase):
@@ -17,13 +16,10 @@ class History(AbstractActionBase):
"""Add History command to parent parser."""
parser = parent.add_parser('history', help='report image history')
super().subparser(parser)
- parser.add_argument(
+ parser.add_flag(
'--human',
'-H',
- action=BooleanAction,
- default='True',
- help='Display sizes and dates in human readable format.'
- ' (default: %(default)s)')
+ help='Display sizes and dates in human readable format.')
parser.add_argument(
'--format',
choices=('json', 'table'),
diff --git a/contrib/python/pypodman/pypodman/lib/actions/images_action.py b/contrib/python/pypodman/pypodman/lib/actions/images_action.py
index 29bf90dd2..21376eeeb 100644
--- a/contrib/python/pypodman/pypodman/lib/actions/images_action.py
+++ b/contrib/python/pypodman/pypodman/lib/actions/images_action.py
@@ -24,11 +24,9 @@ class Images(AbstractActionBase):
help=('Change sort ordered of displayed images.'
' (default: %(default)s)'))
- group = parser.add_mutually_exclusive_group()
- group.add_argument(
+ parser.add_flag(
'--digests',
- action='store_true',
- help='Include digests with images. (default: %(default)s)')
+ help='Include digests with images.')
parser.set_defaults(class_=cls, method='list')
def __init__(self, args):
diff --git a/contrib/python/pypodman/pypodman/lib/actions/info_action.py b/contrib/python/pypodman/pypodman/lib/actions/info_action.py
index 988284541..3c854a358 100644
--- a/contrib/python/pypodman/pypodman/lib/actions/info_action.py
+++ b/contrib/python/pypodman/pypodman/lib/actions/info_action.py
@@ -22,10 +22,6 @@ class Info(AbstractActionBase):
" (default: yaml)")
parser.set_defaults(class_=cls, method='info')
- def __init__(self, args):
- """Construct Info class."""
- super().__init__(args)
-
def info(self):
"""Report on Podman Service."""
try:
diff --git a/contrib/python/pypodman/pypodman/lib/actions/inspect_action.py b/contrib/python/pypodman/pypodman/lib/actions/inspect_action.py
index a581e7e4e..ca5ad2215 100644
--- a/contrib/python/pypodman/pypodman/lib/actions/inspect_action.py
+++ b/contrib/python/pypodman/pypodman/lib/actions/inspect_action.py
@@ -22,12 +22,9 @@ class Inspect(AbstractActionBase):
type=str.lower,
help='Type of object to inspect',
)
- parser.add_argument(
+ parser.add_flag(
'--size',
- action='store_true',
- default=False,
- help='Display the total file size if the type is a container.'
- ' Always True.')
+ help='Display the total file size if the type is a container.')
parser.add_argument(
'objects',
nargs='+',
@@ -35,10 +32,6 @@ class Inspect(AbstractActionBase):
)
parser.set_defaults(class_=cls, method='inspect')
- def __init__(self, args):
- """Construct Inspect class."""
- super().__init__(args)
-
def _get_container(self, ident):
try:
logging.debug("Getting container %s", ident)
diff --git a/contrib/python/pypodman/pypodman/lib/actions/kill_action.py b/contrib/python/pypodman/pypodman/lib/actions/kill_action.py
index cb3d3f035..e8fb4e74d 100644
--- a/contrib/python/pypodman/pypodman/lib/actions/kill_action.py
+++ b/contrib/python/pypodman/pypodman/lib/actions/kill_action.py
@@ -1,9 +1,8 @@
"""Remote client command for signaling podman containers."""
-import signal
import sys
import podman
-from pypodman.lib import AbstractActionBase
+from pypodman.lib import AbstractActionBase, SignalAction
class Kill(AbstractActionBase):
@@ -16,10 +15,9 @@ class Kill(AbstractActionBase):
parser.add_argument(
'--signal',
'-s',
- choices=range(1, signal.NSIG),
- metavar='[1,{}]'.format(signal.NSIG),
+ action=SignalAction,
default=9,
- help='Signal to send to the container. (default: 9)')
+ help='Signal to send to the container. (default: %(default)s)')
parser.add_argument(
'containers',
nargs='+',
@@ -27,10 +25,6 @@ class Kill(AbstractActionBase):
)
parser.set_defaults(class_=cls, method='kill')
- def __init__(self, args):
- """Construct Kill class."""
- super().__init__(args)
-
def kill(self):
"""Signal provided containers."""
try:
diff --git a/contrib/python/pypodman/pypodman/lib/actions/pause_action.py b/contrib/python/pypodman/pypodman/lib/actions/pause_action.py
index ab64d8b81..7dc02f7fe 100644
--- a/contrib/python/pypodman/pypodman/lib/actions/pause_action.py
+++ b/contrib/python/pypodman/pypodman/lib/actions/pause_action.py
@@ -19,10 +19,6 @@ class Pause(AbstractActionBase):
)
parser.set_defaults(class_=cls, method='pause')
- def __init__(self, args):
- """Construct Pause class."""
- super().__init__(args)
-
def pause(self):
"""Pause provided containers."""
try:
diff --git a/contrib/python/pypodman/pypodman/lib/actions/pod/create_parser.py b/contrib/python/pypodman/pypodman/lib/actions/pod/create_parser.py
index 46c1e3e51..4e0bde777 100644
--- a/contrib/python/pypodman/pypodman/lib/actions/pod/create_parser.py
+++ b/contrib/python/pypodman/pypodman/lib/actions/pod/create_parser.py
@@ -2,7 +2,7 @@
import sys
import podman
-from pypodman.lib import AbstractActionBase, BooleanAction
+from pypodman.lib import AbstractActionBase
class CreatePod(AbstractActionBase):
@@ -20,12 +20,9 @@ class CreatePod(AbstractActionBase):
type=str,
help='Path to cgroups under which the'
' cgroup for the pod will be created.')
- parser.add_argument(
+ parser.add_flag(
'--infra',
- action=BooleanAction,
- default=True,
- help='Create an infra container and associate it with the pod'
- '(default: %(default)s)')
+ help='Create an infra container and associate it with the pod.')
parser.add_argument(
'-l',
'--label',
diff --git a/contrib/python/pypodman/pypodman/lib/actions/pod/kill_parser.py b/contrib/python/pypodman/pypodman/lib/actions/pod/kill_parser.py
index 430ec34e0..9b6229939 100644
--- a/contrib/python/pypodman/pypodman/lib/actions/pod/kill_parser.py
+++ b/contrib/python/pypodman/pypodman/lib/actions/pod/kill_parser.py
@@ -3,7 +3,7 @@ import signal
import sys
import podman
-from pypodman.lib import AbstractActionBase
+from pypodman.lib import AbstractActionBase, SignalAction
from pypodman.lib import query_model as query_pods
@@ -15,18 +15,16 @@ class KillPod(AbstractActionBase):
"""Add Pod Kill command to parent parser."""
parser = parent.add_parser('kill', help='signal containers in pod')
- parser.add_argument(
- '-a',
+ parser.add_flag(
'--all',
- action='store_true',
- help='Sends signal to all pods')
+ '-a',
+ help='Sends signal to all pods.')
parser.add_argument(
'-s',
'--signal',
- choices=range(1, signal.NSIG),
- metavar='[1,{}]'.format(signal.NSIG),
+ action=SignalAction,
default=9,
- help='Signal to send to the pod. (default: 9)')
+ help='Signal to send to the pod. (default: %(default)s)')
parser.add_argument('pod', nargs='*', help='pod(s) to signal')
parser.set_defaults(class_=cls, method='kill')
diff --git a/contrib/python/pypodman/pypodman/lib/actions/pod/pause_parser.py b/contrib/python/pypodman/pypodman/lib/actions/pod/pause_parser.py
index daae028d4..c751314ca 100644
--- a/contrib/python/pypodman/pypodman/lib/actions/pod/pause_parser.py
+++ b/contrib/python/pypodman/pypodman/lib/actions/pod/pause_parser.py
@@ -13,8 +13,10 @@ class PausePod(AbstractActionBase):
def subparser(cls, parent):
"""Add Pod Pause command to parent parser."""
parser = parent.add_parser('pause', help='pause containers in pod')
- parser.add_argument(
- '-a', '--all', action='store_true', help='Pause all pods')
+ parser.add_flag(
+ '--all',
+ '-a',
+ help='Pause all pods.')
parser.add_argument('pod', nargs='*', help='pod(s) to pause.')
parser.set_defaults(class_=cls, method='pause')
diff --git a/contrib/python/pypodman/pypodman/lib/actions/pod/processes_parser.py b/contrib/python/pypodman/pypodman/lib/actions/pod/processes_parser.py
index ecfcb883a..855e313c7 100644
--- a/contrib/python/pypodman/pypodman/lib/actions/pod/processes_parser.py
+++ b/contrib/python/pypodman/pypodman/lib/actions/pod/processes_parser.py
@@ -14,18 +14,15 @@ class ProcessesPod(AbstractActionBase):
parser = parent.add_parser('ps', help='list processes of pod')
super().subparser(parser)
- parser.add_argument(
+ parser.add_flag(
'--ctr-names',
- action='store_true',
- help='Include container name in the info field')
- parser.add_argument(
+ help='Include container name in the info field.')
+ parser.add_flag(
'--ctr-ids',
- action='store_true',
- help='Include container ID in the info field')
- parser.add_argument(
+ help='Include container ID in the info field.')
+ parser.add_flag(
'--ctr-status',
- action='store_true',
- help='Include container status in the info field')
+ help='Include container status in the info field.')
parser.add_argument(
'--format',
choices=('json'),
diff --git a/contrib/python/pypodman/pypodman/lib/actions/pod/remove_parser.py b/contrib/python/pypodman/pypodman/lib/actions/pod/remove_parser.py
index 40eeb7203..289325d14 100644
--- a/contrib/python/pypodman/pypodman/lib/actions/pod/remove_parser.py
+++ b/contrib/python/pypodman/pypodman/lib/actions/pod/remove_parser.py
@@ -13,13 +13,14 @@ class RemovePod(AbstractActionBase):
def subparser(cls, parent):
"""Add Pod Rm command to parent parser."""
parser = parent.add_parser('rm', help='Delete pod and container(s)')
- parser.add_argument(
- '-a', '--all', action='store_true', help='Remove all pods')
- parser.add_argument(
- '-f',
+ parser.add_flag(
+ '--all',
+ '-a',
+ help='Remove all pods.')
+ parser.add_flag(
'--force',
- action='store_true',
- help='Stop and remove container(s) then delete pod')
+ '-f',
+ help='Stop and remove container(s) then delete pod.')
parser.add_argument(
'pod', nargs='*', help='Pod to remove. Or, use --all')
parser.set_defaults(class_=cls, method='remove')
diff --git a/contrib/python/pypodman/pypodman/lib/actions/pod/restart_parser.py b/contrib/python/pypodman/pypodman/lib/actions/pod/restart_parser.py
index af489ad28..53f45b6de 100644
--- a/contrib/python/pypodman/pypodman/lib/actions/pod/restart_parser.py
+++ b/contrib/python/pypodman/pypodman/lib/actions/pod/restart_parser.py
@@ -13,8 +13,10 @@ class RestartPod(AbstractActionBase):
def subparser(cls, parent):
"""Add Pod Restart command to parent parser."""
parser = parent.add_parser('restart', help='restart containers in pod')
- parser.add_argument(
- '-a', '--all', action='store_true', help='Restart all pods')
+ parser.add_flag(
+ '--all',
+ '-a',
+ help='Restart all pods.')
parser.add_argument(
'pod', nargs='*', help='Pod to restart. Or, use --all')
parser.set_defaults(class_=cls, method='restart')
diff --git a/contrib/python/pypodman/pypodman/lib/actions/pod/start_parser.py b/contrib/python/pypodman/pypodman/lib/actions/pod/start_parser.py
index 0ddc336bf..ff62b839e 100644
--- a/contrib/python/pypodman/pypodman/lib/actions/pod/start_parser.py
+++ b/contrib/python/pypodman/pypodman/lib/actions/pod/start_parser.py
@@ -14,8 +14,10 @@ class StartPod(AbstractActionBase):
def subparser(cls, parent):
"""Add Pod Start command to parent parser."""
parser = parent.add_parser('start', help='start pod')
- parser.add_argument(
- '-a', '--all', action='store_true', help='Start all pods')
+ parser.add_flag(
+ '--all',
+ '-a',
+ help='Start all pods.')
parser.add_argument(
'pod', nargs='*', help='Pod to start. Or, use --all')
parser.set_defaults(class_=cls, method='start')
diff --git a/contrib/python/pypodman/pypodman/lib/actions/pod/stop_parser.py b/contrib/python/pypodman/pypodman/lib/actions/pod/stop_parser.py
index 7054fd38a..cbf2bf1e7 100644
--- a/contrib/python/pypodman/pypodman/lib/actions/pod/stop_parser.py
+++ b/contrib/python/pypodman/pypodman/lib/actions/pod/stop_parser.py
@@ -13,8 +13,10 @@ class StopPod(AbstractActionBase):
def subparser(cls, parent):
"""Add Pod Stop command to parent parser."""
parser = parent.add_parser('stop', help='stop pod')
- parser.add_argument(
- '-a', '--all', action='store_true', help='Stop all pods')
+ parser.add_flag(
+ '--all',
+ '-a',
+ help='Stop all pods.')
parser.add_argument(
'pod', nargs='*', help='Pod to stop. Or, use --all')
parser.set_defaults(class_=cls, method='stop')
diff --git a/contrib/python/pypodman/pypodman/lib/actions/pod/unpause_parser.py b/contrib/python/pypodman/pypodman/lib/actions/pod/unpause_parser.py
index 90e1ddbe2..5186cf9cc 100644
--- a/contrib/python/pypodman/pypodman/lib/actions/pod/unpause_parser.py
+++ b/contrib/python/pypodman/pypodman/lib/actions/pod/unpause_parser.py
@@ -13,8 +13,10 @@ class UnpausePod(AbstractActionBase):
def subparser(cls, parent):
"""Add Pod Unpause command to parent parser."""
parser = parent.add_parser('unpause', help='unpause pod')
- parser.add_argument(
- '-a', '--all', action='store_true', help='Unpause all pods')
+ parser.add_flag(
+ '--all',
+ '-a',
+ help='Unpause all pods.')
parser.add_argument(
'pod', nargs='*', help='Pod to unpause. Or, use --all')
parser.set_defaults(class_=cls, method='unpause')
diff --git a/contrib/python/pypodman/pypodman/lib/actions/pod_action.py b/contrib/python/pypodman/pypodman/lib/actions/pod_action.py
index 046af34bb..4b8997a05 100644
--- a/contrib/python/pypodman/pypodman/lib/actions/pod_action.py
+++ b/contrib/python/pypodman/pypodman/lib/actions/pod_action.py
@@ -5,6 +5,8 @@ import sys
from pypodman.lib import AbstractActionBase
+# pylint: disable=wildcard-import
+# pylint: disable=unused-wildcard-import
from .pod import *
diff --git a/contrib/python/pypodman/pypodman/lib/actions/port_action.py b/contrib/python/pypodman/pypodman/lib/actions/port_action.py
index d2a8ded46..6913f3813 100644
--- a/contrib/python/pypodman/pypodman/lib/actions/port_action.py
+++ b/contrib/python/pypodman/pypodman/lib/actions/port_action.py
@@ -13,16 +13,13 @@ class Port(AbstractActionBase):
"""Add Port command to parent parser."""
parser = parent.add_parser(
'port', help='retrieve ports from containers')
- parser.add_argument(
+ parser.add_flag(
'--all',
'-a',
- action='store_true',
- default=False,
help='List all known port mappings for running containers')
parser.add_argument(
'containers',
nargs='*',
- default=None,
help='containers to list ports',
)
parser.set_defaults(class_=cls, method='port')
@@ -61,3 +58,4 @@ class Port(AbstractActionBase):
file=sys.stderr,
flush=True)
return 1
+ return 0
diff --git a/contrib/python/pypodman/pypodman/lib/actions/push_action.py b/contrib/python/pypodman/pypodman/lib/actions/push_action.py
index 0030cb5b9..8e86ca335 100644
--- a/contrib/python/pypodman/pypodman/lib/actions/push_action.py
+++ b/contrib/python/pypodman/pypodman/lib/actions/push_action.py
@@ -15,12 +15,10 @@ class Push(AbstractActionBase):
'push',
help='push image elsewhere',
)
- parser.add_argument(
+ parser.add_flag(
'--tlsverify',
- action='store_true',
- default=True,
help='Require HTTPS and verify certificates when'
- ' contacting registries (default: %(default)s)')
+ ' contacting registries.')
parser.add_argument(
'image', nargs=1, help='name or id of image to push')
parser.add_argument(
@@ -30,10 +28,6 @@ class Push(AbstractActionBase):
)
parser.set_defaults(class_=cls, method='push')
- def __init__(self, args):
- """Construct Push class."""
- super().__init__(args)
-
def pull(self):
"""Store image elsewhere."""
try:
diff --git a/contrib/python/pypodman/pypodman/lib/actions/restart_action.py b/contrib/python/pypodman/pypodman/lib/actions/restart_action.py
index d99d1ad65..415594920 100644
--- a/contrib/python/pypodman/pypodman/lib/actions/restart_action.py
+++ b/contrib/python/pypodman/pypodman/lib/actions/restart_action.py
@@ -23,10 +23,6 @@ class Restart(AbstractActionBase):
'targets', nargs='+', help='container id(s) to restart')
parser.set_defaults(class_=cls, method='restart')
- def __init__(self, args):
- """Construct Restart class."""
- super().__init__(args)
-
def restart(self):
"""Restart container(s)."""
try:
diff --git a/contrib/python/pypodman/pypodman/lib/actions/rm_action.py b/contrib/python/pypodman/pypodman/lib/actions/rm_action.py
index e8074ef4e..99ff6c460 100644
--- a/contrib/python/pypodman/pypodman/lib/actions/rm_action.py
+++ b/contrib/python/pypodman/pypodman/lib/actions/rm_action.py
@@ -12,20 +12,14 @@ class Rm(AbstractActionBase):
def subparser(cls, parent):
"""Add Rm command to parent parser."""
parser = parent.add_parser('rm', help='delete container(s)')
- parser.add_argument(
- '-f',
+ parser.add_flag(
'--force',
- action='store_true',
- help=('force delete of running container(s).'
- ' (default: %(default)s)'))
+ '-f',
+ help='force delete of running container(s).')
parser.add_argument(
'targets', nargs='+', help='container id(s) to delete')
parser.set_defaults(class_=cls, method='remove')
- def __init__(self, args):
- """Construct Rm class."""
- super().__init__(args)
-
def remove(self):
"""Remove container(s)."""
for ident in self._args.targets:
diff --git a/contrib/python/pypodman/pypodman/lib/actions/rmi_action.py b/contrib/python/pypodman/pypodman/lib/actions/rmi_action.py
index c6ba835cb..7c3d0bd79 100644
--- a/contrib/python/pypodman/pypodman/lib/actions/rmi_action.py
+++ b/contrib/python/pypodman/pypodman/lib/actions/rmi_action.py
@@ -12,19 +12,13 @@ class Rmi(AbstractActionBase):
def subparser(cls, parent):
"""Add Rmi command to parent parser."""
parser = parent.add_parser('rmi', help='delete image(s)')
- parser.add_argument(
- '-f',
+ parser.add_flag(
'--force',
- action='store_true',
- help=('force delete of image(s) and associated containers.'
- ' (default: %(default)s)'))
+ '-f',
+ help='force delete of image(s) and associated containers.')
parser.add_argument('targets', nargs='+', help='image id(s) to delete')
parser.set_defaults(class_=cls, method='remove')
- def __init__(self, args):
- """Construct Rmi class."""
- super().__init__(args)
-
def remove(self):
"""Remove image(s)."""
for ident in self._args.targets:
diff --git a/contrib/python/pypodman/pypodman/lib/actions/search_action.py b/contrib/python/pypodman/pypodman/lib/actions/search_action.py
index d2a585d92..b7b8b465d 100644
--- a/contrib/python/pypodman/pypodman/lib/actions/search_action.py
+++ b/contrib/python/pypodman/pypodman/lib/actions/search_action.py
@@ -4,8 +4,8 @@ import sys
from collections import OrderedDict
import podman
-from pypodman.lib import (AbstractActionBase, BooleanValidate,
- PositiveIntAction, Report, ReportColumn)
+from pypodman.lib import (AbstractActionBase, PositiveIntAction, Report,
+ ReportColumn)
class FilterAction(argparse.Action):
@@ -58,16 +58,16 @@ class FilterAction(argparse.Action):
if val < 0:
parser.error(msg)
elif opt == 'is-automated':
- try:
- val = BooleanValidate()(val)
- except ValueError:
+ if val.capitalize() in ('True', 'False'):
+ val = bool(val)
+ else:
msg = ('{} option "is-automated"'
' must be True or False.'.format(self.dest))
parser.error(msg)
elif opt == 'is-official':
- try:
- val = BooleanValidate()(val)
- except ValueError:
+ if val.capitalize() in ('True', 'False'):
+ val = bool(val)
+ else:
msg = ('{} option "is-official"'
' must be True or False.'.format(self.dest))
parser.error(msg)
diff --git a/contrib/python/pypodman/pypodman/lib/actions/start_action.py b/contrib/python/pypodman/pypodman/lib/actions/start_action.py
index f312fb3fa..5f88731dc 100644
--- a/contrib/python/pypodman/pypodman/lib/actions/start_action.py
+++ b/contrib/python/pypodman/pypodman/lib/actions/start_action.py
@@ -2,7 +2,7 @@
import sys
import podman
-from pypodman.lib import AbstractActionBase, BooleanAction
+from pypodman.lib import AbstractActionBase
class Start(AbstractActionBase):
@@ -12,12 +12,10 @@ class Start(AbstractActionBase):
def subparser(cls, parent):
"""Add Start command to parent parser."""
parser = parent.add_parser('start', help='start container')
- parser.add_argument(
+ parser.add_flag(
'--attach',
'-a',
- action=BooleanAction,
- default=False,
- help="Attach container's STDOUT and STDERR (default: %(default)s)")
+ help="Attach container's STDOUT and STDERR.")
parser.add_argument(
'--detach-keys',
metavar='KEY(s)',
@@ -25,18 +23,14 @@ class Start(AbstractActionBase):
help='Override the key sequence for detaching a container.'
' (format: a single character [a-Z] or ctrl-<value> where'
' <value> is one of: a-z, @, ^, [, , or _) (default: ^D)')
- parser.add_argument(
+ parser.add_flag(
'--interactive',
'-i',
- action=BooleanAction,
- default=False,
- help="Attach container's STDIN (default: %(default)s)")
+ help="Attach container's STDIN.")
# TODO: Implement sig-proxy
- parser.add_argument(
+ parser.add_flag(
'--sig-proxy',
- action=BooleanAction,
- default=False,
- help="Proxy received signals to the process (default: %(default)s)"
+ help="Proxy received signals to the process."
)
parser.add_argument(
'containers',
@@ -74,3 +68,4 @@ class Start(AbstractActionBase):
file=sys.stderr,
flush=True)
return 1
+ return 0
diff --git a/contrib/python/pypodman/pypodman/lib/actions/version_action.py b/contrib/python/pypodman/pypodman/lib/actions/version_action.py
index 12b6dc576..29a0cabe4 100644
--- a/contrib/python/pypodman/pypodman/lib/actions/version_action.py
+++ b/contrib/python/pypodman/pypodman/lib/actions/version_action.py
@@ -1,9 +1,7 @@
"""Remote client command for reporting on Podman service."""
-import json
import sys
import podman
-import yaml
from pypodman.lib import AbstractActionBase
@@ -17,10 +15,6 @@ class Version(AbstractActionBase):
'version', help='report version on podman service')
parser.set_defaults(class_=cls, method='version')
- def __init__(self, args):
- """Construct Version class."""
- super().__init__(args)
-
def version(self):
"""Report on Podman Service."""
try:
diff --git a/contrib/python/pypodman/pypodman/lib/parser_actions.py b/contrib/python/pypodman/pypodman/lib/parser_actions.py
index 77ee14761..3ff12cab8 100644
--- a/contrib/python/pypodman/pypodman/lib/parser_actions.py
+++ b/contrib/python/pypodman/pypodman/lib/parser_actions.py
@@ -6,6 +6,7 @@ The constructors are very verbose but remain for IDE support.
import argparse
import copy
import os
+import signal
# API defined by argparse.Action therefore shut up pylint
# pragma pylint: disable=redefined-builtin
@@ -13,22 +14,8 @@ import os
# pragma pylint: disable=too-many-arguments
-class BooleanValidate():
- """Validate value is boolean string."""
-
- def __call__(self, value):
- """Return True, False or raise ValueError."""
- val = value.capitalize()
- if val == 'False':
- return False
- elif val == 'True':
- return True
- else:
- raise ValueError('"{}" is not True or False'.format(value))
-
-
-class BooleanAction(argparse.Action):
- """Convert and validate bool argument."""
+class ChangeAction(argparse.Action):
+ """Convert and validate change argument."""
def __init__(self,
option_strings,
@@ -40,8 +27,13 @@ class BooleanAction(argparse.Action):
choices=None,
required=False,
help=None,
- metavar='{True,False}'):
- """Create BooleanAction object."""
+ metavar='OPT=VALUE'):
+ """Create ChangeAction object."""
+ help = (help or '') + ('Apply change(s) to the new image.'
+ ' May be given multiple times.')
+ if default is None:
+ default = []
+
super().__init__(
option_strings=option_strings,
dest=dest,
@@ -56,32 +48,37 @@ class BooleanAction(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None):
"""Convert and Validate input."""
- try:
- val = BooleanValidate()(values)
- except ValueError:
- parser.error('"{}" must be True or False.'.format(option_string))
- else:
- setattr(namespace, self.dest, val)
+ items = getattr(namespace, self.dest, None) or []
+ items = copy.copy(items)
+ choices = ('CMD', 'ENTRYPOINT', 'ENV', 'EXPOSE', 'LABEL', 'ONBUILD',
+ 'STOPSIGNAL', 'USER', 'VOLUME', 'WORKDIR')
+
+ opt, _ = values.split('=', 1)
+ if opt not in choices:
+ parser.error('Option "{}" is not supported by argument "{}",'
+ ' valid options are: {}'.format(
+ opt, option_string, ', '.join(choices)))
+ items.append(values)
+ setattr(namespace, self.dest, items)
-class ChangeAction(argparse.Action):
- """Convert and validate change argument."""
+
+class SignalAction(argparse.Action):
+ """Validate input as a signal."""
def __init__(self,
option_strings,
dest,
nargs=None,
const=None,
- default=[],
- type=None,
+ default=None,
+ type=str,
choices=None,
required=False,
- help=None,
- metavar='OPT=VALUE'):
- """Create ChangeAction object."""
- help = (help or '') + ('Apply change(s) to the new image.'
- ' May be given multiple times.')
-
+ help='The signal to send.'
+ ' It may be given as a name or a number.',
+ metavar='SIGNAL'):
+ """Create SignalAction object."""
super().__init__(
option_strings=option_strings,
dest=dest,
@@ -94,21 +91,40 @@ class ChangeAction(argparse.Action):
help=help,
metavar=metavar)
- def __call__(self, parser, namespace, values, option_string=None):
- """Convert and Validate input."""
- items = getattr(namespace, self.dest, None) or []
- items = copy.copy(items)
+ if hasattr(signal, "Signals"):
- choices = ('CMD', 'ENTRYPOINT', 'ENV', 'EXPOSE', 'LABEL', 'ONBUILD',
- 'STOPSIGNAL', 'USER', 'VOLUME', 'WORKDIR')
+ def _signal_number(signame):
+ cooked = 'SIG{}'.format(signame)
+ try:
+ return signal.Signals[cooked].value
+ except ValueError:
+ pass
+ else:
- opt, val = values.split('=', 1)
- if opt not in choices:
- parser.error('Option "{}" is not supported by argument "{}",'
- ' valid options are: {}'.format(
- opt, option_string, ', '.join(choices)))
- items.append(values)
- setattr(namespace, self.dest, items)
+ def _signal_number(signame):
+ cooked = 'SIG{}'.format(signame)
+ for n, v in sorted(signal.__dict__.items()):
+ if n != cooked:
+ continue
+ if n.startswith("SIG") and not n.startswith("SIG_"):
+ return v
+
+ self._signal_number = _signal_number
+
+ def __call__(self, parser, namespace, values, option_string=None):
+ """Validate input is a signal for platform."""
+ if values.isdigit():
+ signum = int(values)
+ if signal.SIGRTMIN <= signum >= signal.SIGRTMAX:
+ raise ValueError('"{}" is not a valid signal. {}-{}'.format(
+ values, signal.SIGRTMIN, signal.SIGRTMAX))
+ else:
+ signum = self._signal_number(values)
+ if signum is None:
+ parser.error(
+ '"{}" is not a valid signal,'
+ ' see your platform documentation.'.format(values))
+ setattr(namespace, self.dest, signum)
class UnitAction(argparse.Action):
diff --git a/contrib/python/pypodman/pypodman/lib/podman_parser.py b/contrib/python/pypodman/pypodman/lib/podman_parser.py
index 412c8c8fd..913546a91 100644
--- a/contrib/python/pypodman/pypodman/lib/podman_parser.py
+++ b/contrib/python/pypodman/pypodman/lib/podman_parser.py
@@ -48,6 +48,18 @@ class PodmanArgumentParser(argparse.ArgumentParser):
super().__init__(**kwargs)
+ def add_flag(self, *args, **kwargs):
+ """Add flag to parser."""
+ flags = [a for a in args if a[0] in self.prefix_chars]
+ dest = flags[0].lstrip(self.prefix_chars)
+ no_flag = '{0}{0}no-{1}'.format(self.prefix_chars, dest)
+
+ group = self.add_mutually_exclusive_group(required=False)
+ group.add_argument(*flags, action='store_true', dest=dest, **kwargs)
+ group.add_argument(no_flag, action='store_false', dest=dest, **kwargs)
+ default = kwargs.get('default', False)
+ self.set_defaults(**{dest: default})
+
def initialize_parser(self):
"""Initialize parser without causing recursion meltdown."""
self.add_argument(
diff --git a/docs/podman-generate-kube.1.md b/docs/podman-generate-kube.1.md
new file mode 100644
index 000000000..59c3353a5
--- /dev/null
+++ b/docs/podman-generate-kube.1.md
@@ -0,0 +1,119 @@
+% podman-generate Podman Man Pages
+% Brent Baude
+% December 2018
+# NAME
+podman-generate-kube - Generate Kubernetes YAML
+
+# SYNOPSIS
+**podman generate kube **
+[**-h**|**--help**]
+[**-s**][**--service**]
+CONTAINER|POD
+
+# DESCRIPTION
+**podman generate kube** will generate Kubernetes Pod YAML (v1 specification) from a podman container or pod. Whether
+the input is for a container or pod, Podman will always generate the specification as a Pod. The input may be in the form
+of a pod or container name or ID.
+
+The **service** option can be used to generate a Service specification for the corresponding Pod ouput. In particular,
+if the object has portmap bindings, the service specification will include a NodePort declaration to expose the service. A
+random port is assigned by Podman in the specification.
+
+# OPTIONS:
+
+**s** **--service**
+Generate a service file for the resulting Pod YAML.
+
+## Examples ##
+
+Create Kubernetes Pod YAML for a container called `some-mariadb` .
+```
+$ sudo podman generate kube some-mariadb
+# Generation of Kubenetes YAML is still under development!
+#
+# Save the output of this file and use kubectl create -f to import
+# it into Kubernetes.
+#
+# Created with podman-0.11.2-dev
+apiVersion: v1
+kind: Pod
+metadata:
+ creationTimestamp: 2018-12-03T19:07:59Z
+ labels:
+ app: some-mariadb
+ name: some-mariadb-libpod
+spec:
+ containers:
+ - command:
+ - docker-entrypoint.sh
+ - mysqld
+ env:
+ - name: PATH
+ value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
+ - name: TERM
+ value: xterm
+ - name: HOSTNAME
+ - name: container
+ value: podman
+ - name: GOSU_VERSION
+ value: "1.10"
+ - name: GPG_KEYS
+ value: "199369E5404BD5FC7D2FE43BCBCB082A1BB943DB \t177F4010FE56CA3336300305F1656F24C74CD1D8
+ \t430BDF5C56E7C94E848EE60C1C4CBDCDCD2EFD2A \t4D1BB29D63D98E422B2113B19334A25F8507EFA5"
+ - name: MARIADB_MAJOR
+ value: "10.3"
+ - name: MARIADB_VERSION
+ value: 1:10.3.10+maria~bionic
+ - name: MYSQL_ROOT_PASSWORD
+ value: x
+ image: quay.io/baude/demodb:latest
+ name: some-mariadb
+ ports:
+ - containerPort: 3306
+ hostPort: 36533
+ protocol: TCP
+ resources: {}
+ securityContext:
+ allowPrivilegeEscalation: true
+ privileged: false
+ readOnlyRootFilesystem: false
+ tty: true
+ workingDir: /
+status: {}
+```
+
+Create Kubernetes service YAML for a container called `some-mariabdb`
+```
+$ sudo podman generate kube -s some-mariadb
+# Generation of Kubenetes YAML is still under development!
+#
+# Save the output of this file and use kubectl create -f to import
+# it into Kubernetes.
+#
+# Created with podman-0.11.2-dev
+apiVersion: v1
+kind: Service
+metadata:
+ creationTimestamp: 2018-12-03T19:08:24Z
+ labels:
+ app: some-mariadb
+ name: some-mariadb-libpod
+spec:
+ ports:
+ - name: "3306"
+ nodePort: 30929
+ port: 3306
+ protocol: TCP
+ targetPort: 0
+ selector:
+ app: some-mariadb
+ type: NodePort
+status:
+ loadBalancer: {}
+```
+
+## SEE ALSO
+podman(1), podman-container, podman-pod
+
+# HISTORY
+Decemeber 2018, Originally compiled by Brent Baude (bbaude at redhat dot com)
diff --git a/docs/podman-generate.1.md b/docs/podman-generate.1.md
new file mode 100644
index 000000000..f19f48511
--- /dev/null
+++ b/docs/podman-generate.1.md
@@ -0,0 +1,19 @@
+% podman-generate(1)
+
+## NAME
+podman\-container - generate structured data based for a containers and pods
+
+## SYNOPSIS
+**podman generate** *subcommand*
+
+## DESCRIPTION
+The generate command will create structured output (like YAML) based on a container or pod.
+
+## COMMANDS
+
+| Command | Man Page | Description |
+| ------- | --------------------------------------------------- | ---------------------------------------------------------------------------- |
+| kube | [podman-generate-kube(1)](podman-generate-kube.1.md) | Generate Kubernetes YAML based on a pod or container
+
+## SEE ALSO
+podman, podman-pod, podman-container
diff --git a/libpod/kube.go b/libpod/kube.go
index 1a5f80878..05a6537c4 100644
--- a/libpod/kube.go
+++ b/libpod/kube.go
@@ -2,7 +2,10 @@ package libpod
import (
"fmt"
+ "math/rand"
+ "strconv"
"strings"
+ "time"
"github.com/containers/libpod/pkg/lookup"
"github.com/containers/libpod/pkg/util"
@@ -15,23 +18,127 @@ import (
v12 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
-// InspectForKube takes a slice of libpod containers and generates
+// GenerateForKube takes a slice of libpod containers and generates
// one v1.Pod description that includes just a single container.
-func (c *Container) InspectForKube() (*v1.Pod, error) {
+func (c *Container) GenerateForKube() (*v1.Pod, error) {
// Generate the v1.Pod yaml description
return simplePodWithV1Container(c)
}
-// simplePodWithV1Container is a function used by inspect when kube yaml needs to be generated
-// for a single container. we "insert" that container description in a pod.
-func simplePodWithV1Container(ctr *Container) (*v1.Pod, error) {
- var containers []v1.Container
- result, err := containerToV1Container(ctr)
+// GenerateForKube takes a slice of libpod containers and generates
+// one v1.Pod description
+func (p *Pod) GenerateForKube() (*v1.Pod, []v1.ServicePort, error) {
+ // Generate the v1.Pod yaml description
+ var servicePorts []v1.ServicePort
+
+ allContainers, err := p.allContainers()
+ if err != nil {
+ return nil, servicePorts, err
+ }
+ // If the pod has no containers, no sense to generate YAML
+ if len(allContainers) == 0 {
+ return nil, servicePorts, errors.Errorf("pod %s has no containers", p.ID())
+ }
+ // If only an infra container is present, makes no sense to generate YAML
+ if len(allContainers) == 1 && p.HasInfraContainer() {
+ return nil, servicePorts, errors.Errorf("pod %s only has an infra container", p.ID())
+ }
+
+ if p.HasInfraContainer() {
+ infraContainer, err := p.getInfraContainer()
+ if err != nil {
+ return nil, servicePorts, err
+ }
+
+ ports, err := ocicniPortMappingToContainerPort(infraContainer.config.PortMappings)
+ if err != nil {
+ return nil, servicePorts, err
+ }
+ servicePorts = containerPortsToServicePorts(ports)
+ }
+ pod, err := p.podWithContainers(allContainers)
+ return pod, servicePorts, err
+}
+
+func (p *Pod) getInfraContainer() (*Container, error) {
+ infraID, err := p.InfraContainerID()
if err != nil {
return nil, err
}
- containers = append(containers, result)
+ return p.runtime.LookupContainer(infraID)
+}
+
+// GenerateKubeServiceFromV1Pod creates a v1 service object from a v1 pod object
+func GenerateKubeServiceFromV1Pod(pod *v1.Pod, servicePorts []v1.ServicePort) v1.Service {
+ service := v1.Service{}
+ selector := make(map[string]string)
+ selector["app"] = pod.Labels["app"]
+ ports := servicePorts
+ if len(ports) == 0 {
+ ports = containersToServicePorts(pod.Spec.Containers)
+ }
+ serviceSpec := v1.ServiceSpec{
+ Ports: ports,
+ Selector: selector,
+ Type: v1.ServiceTypeNodePort,
+ }
+ service.Spec = serviceSpec
+ service.ObjectMeta = pod.ObjectMeta
+ tm := v12.TypeMeta{
+ Kind: "Service",
+ APIVersion: pod.TypeMeta.APIVersion,
+ }
+ service.TypeMeta = tm
+ return service
+}
+// containerPortsToServicePorts takes a slice of containerports and generates a
+// slice of service ports
+func containerPortsToServicePorts(containerPorts []v1.ContainerPort) []v1.ServicePort {
+ var sps []v1.ServicePort
+ for _, cp := range containerPorts {
+ nodePort := 30000 + rand.Intn(32767-30000+1)
+ servicePort := v1.ServicePort{
+ Protocol: cp.Protocol,
+ Port: cp.ContainerPort,
+ NodePort: int32(nodePort),
+ Name: strconv.Itoa(int(cp.ContainerPort)),
+ }
+ sps = append(sps, servicePort)
+ }
+ return sps
+}
+
+// containersToServicePorts takes a slice of v1.Containers and generates an
+// inclusive list of serviceports to expose
+func containersToServicePorts(containers []v1.Container) []v1.ServicePort {
+ var sps []v1.ServicePort
+ // Without the call to rand.Seed, a program will produce the same sequence of pseudo-random numbers
+ // for each execution. Legal nodeport range is 30000-32767
+ rand.Seed(time.Now().UnixNano())
+
+ for _, ctr := range containers {
+ sps = append(sps, containerPortsToServicePorts(ctr.Ports)...)
+ }
+ return sps
+}
+
+func (p *Pod) podWithContainers(containers []*Container) (*v1.Pod, error) {
+ var podContainers []v1.Container
+ for _, ctr := range containers {
+ result, err := containerToV1Container(ctr)
+ if err != nil {
+ return nil, err
+ }
+ if !ctr.IsInfra() {
+ podContainers = append(podContainers, result)
+ }
+ }
+
+ return addContainersToPodObject(podContainers, p.Name()), nil
+}
+
+func addContainersToPodObject(containers []v1.Container, podName string) *v1.Pod {
tm := v12.TypeMeta{
Kind: "Pod",
APIVersion: "v1",
@@ -39,10 +146,10 @@ func simplePodWithV1Container(ctr *Container) (*v1.Pod, error) {
// Add a label called "app" with the containers name as a value
labels := make(map[string]string)
- labels["app"] = removeUnderscores(ctr.Name())
+ labels["app"] = removeUnderscores(podName)
om := v12.ObjectMeta{
// The name of the pod is container_name-libpod
- Name: fmt.Sprintf("%s-libpod", removeUnderscores(ctr.Name())),
+ Name: fmt.Sprintf("%s-libpod", removeUnderscores(podName)),
Labels: labels,
// CreationTimestamp seems to be required, so adding it; in doing so, the timestamp
// will reflect time this is run (not container create time) because the conversion
@@ -57,7 +164,20 @@ func simplePodWithV1Container(ctr *Container) (*v1.Pod, error) {
ObjectMeta: om,
Spec: ps,
}
- return &p, nil
+ return &p
+}
+
+// simplePodWithV1Container is a function used by inspect when kube yaml needs to be generated
+// for a single container. we "insert" that container description in a pod.
+func simplePodWithV1Container(ctr *Container) (*v1.Pod, error) {
+ var containers []v1.Container
+ result, err := containerToV1Container(ctr)
+ if err != nil {
+ return nil, err
+ }
+ containers = append(containers, result)
+ return addContainersToPodObject(containers, ctr.Name()), nil
+
}
// containerToV1Container converts information we know about a libpod container
diff --git a/test/e2e/generate_kube_test.go b/test/e2e/generate_kube_test.go
new file mode 100644
index 000000000..0ee078455
--- /dev/null
+++ b/test/e2e/generate_kube_test.go
@@ -0,0 +1,106 @@
+package integration
+
+import (
+ "fmt"
+ "os"
+
+ . "github.com/containers/libpod/test/utils"
+ "github.com/ghodss/yaml"
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+)
+
+var _ = Describe("Podman generate kube", func() {
+ var (
+ tempdir string
+ err error
+ podmanTest *PodmanTestIntegration
+ )
+
+ BeforeEach(func() {
+ tempdir, err = CreateTempDirInTempDir()
+ if err != nil {
+ os.Exit(1)
+ }
+ podmanTest = PodmanTestCreate(tempdir)
+ podmanTest.RestoreAllArtifacts()
+ })
+
+ AfterEach(func() {
+ podmanTest.Cleanup()
+ f := CurrentGinkgoTestDescription()
+ timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds())
+ GinkgoWriter.Write([]byte(timedResult))
+
+ })
+
+ It("podman generate pod kube on bogus object", func() {
+ session := podmanTest.Podman([]string{"generate", "kube", "foobar"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Not(Equal(0)))
+ })
+
+ It("podman generate service kube on bogus object", func() {
+ session := podmanTest.Podman([]string{"generate", "kube", "-s", "foobar"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Not(Equal(0)))
+ })
+
+ It("podman generate kube on container", func() {
+ session := podmanTest.RunTopContainer("top")
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ kube := podmanTest.Podman([]string{"generate", "kube", "top"})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube.ExitCode()).To(Equal(0))
+
+ _, err := yaml.Marshal(kube.OutputToString())
+ Expect(err).To(BeNil())
+ })
+
+ It("podman generate service kube on container", func() {
+ session := podmanTest.RunTopContainer("top")
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ kube := podmanTest.Podman([]string{"generate", "kube", "-s", "top"})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube.ExitCode()).To(Equal(0))
+
+ _, err := yaml.Marshal(kube.OutputToString())
+ Expect(err).To(BeNil())
+ })
+
+ It("podman generate kube on pod", func() {
+ _, rc, _ := podmanTest.CreatePod("toppod")
+ Expect(rc).To(Equal(0))
+
+ session := podmanTest.RunTopContainerInPod("topcontainer", "toppod")
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ kube := podmanTest.Podman([]string{"generate", "kube", "toppod"})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube.ExitCode()).To(Equal(0))
+
+ _, err := yaml.Marshal(kube.OutputToString())
+ Expect(err).To(BeNil())
+ })
+
+ It("podman generate service kube on pod", func() {
+ _, rc, _ := podmanTest.CreatePod("toppod")
+ Expect(rc).To(Equal(0))
+
+ session := podmanTest.RunTopContainerInPod("topcontainer", "toppod")
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ kube := podmanTest.Podman([]string{"generate", "kube", "-s", "toppod"})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube.ExitCode()).To(Equal(0))
+
+ _, err := yaml.Marshal(kube.OutputToString())
+ Expect(err).To(BeNil())
+ })
+})