From 5588f706440589d484e3f777890608c3751c1839 Mon Sep 17 00:00:00 2001 From: "Zheao.Li" Date: Sun, 11 Dec 2022 14:03:14 +0800 Subject: [PATCH 01/14] Refactor the package structure in cmd/nerdctl Signed-off-by: Zheao.Li --- .cirrus.yml | 2 +- .github/workflows/test.yml | 2 +- .gitignore | 1 + Dockerfile | 6 +- cmd/nerdctl/apparmor/apparmor_freebsd.go | 23 + .../{ => apparmor}/apparmor_inspect_linux.go | 6 +- cmd/nerdctl/{ => apparmor}/apparmor_linux.go | 14 +- .../{ => apparmor}/apparmor_load_linux.go | 6 +- .../{ => apparmor}/apparmor_ls_linux.go | 11 +- .../{ => apparmor}/apparmor_unload_linux.go | 13 +- cmd/nerdctl/apparmor/apparmor_windows.go | 23 + cmd/nerdctl/{ => build}/build.go | 38 +- cmd/nerdctl/{ => builder}/builder.go | 18 +- cmd/nerdctl/{ => client}/client.go | 16 +- cmd/nerdctl/{ => completion}/completion.go | 96 +- cmd/nerdctl/completion/completion_freebsd.go | 32 + cmd/nerdctl/completion/completion_linux.go | 71 + cmd/nerdctl/completion/completion_unix.go | 68 + cmd/nerdctl/completion/completion_windows.go | 40 + cmd/nerdctl/{ => compose}/compose.go | 15 +- cmd/nerdctl/{ => compose}/compose_build.go | 5 +- cmd/nerdctl/{ => compose}/compose_config.go | 5 +- cmd/nerdctl/{ => compose}/compose_down.go | 7 +- cmd/nerdctl/{ => compose}/compose_exec.go | 5 +- cmd/nerdctl/{ => compose}/compose_images.go | 8 +- cmd/nerdctl/{ => compose}/compose_kill.go | 5 +- cmd/nerdctl/{ => compose}/compose_logs.go | 5 +- cmd/nerdctl/{ => compose}/compose_pause.go | 12 +- cmd/nerdctl/{ => compose}/compose_port.go | 5 +- cmd/nerdctl/{ => compose}/compose_ps.go | 35 +- cmd/nerdctl/{ => compose}/compose_pull.go | 5 +- cmd/nerdctl/{ => compose}/compose_push.go | 5 +- cmd/nerdctl/{ => compose}/compose_restart.go | 5 +- cmd/nerdctl/{ => compose}/compose_rm.go | 5 +- cmd/nerdctl/{ => compose}/compose_run.go | 5 +- cmd/nerdctl/{ => compose}/compose_stop.go | 5 +- cmd/nerdctl/{ => compose}/compose_top.go | 8 +- cmd/nerdctl/{ => compose}/compose_up.go | 5 +- cmd/nerdctl/{ => compose}/compose_version.go | 2 +- cmd/nerdctl/container.go | 62 - cmd/nerdctl/{ => container}/commit.go | 13 +- cmd/nerdctl/container/container.go | 67 + .../{ => container}/container_inspect.go | 17 +- .../{ => container}/container_prune.go | 18 +- cmd/nerdctl/{ => container/cp}/cp.go | 2 +- cmd/nerdctl/container/cp/cp_freebsd.go | 23 + cmd/nerdctl/{ => container/cp}/cp_linux.go | 13 +- cmd/nerdctl/container/cp/cp_windows.go | 23 + cmd/nerdctl/{ => container}/create.go | 16 +- cmd/nerdctl/{ => container/exec}/exec.go | 16 +- .../{ => container/exec}/exec_freebsd.go | 2 +- .../{ => container/exec}/exec_linux.go | 2 +- .../{ => container/exec}/exec_windows.go | 2 +- cmd/nerdctl/{ => container}/kill.go | 12 +- cmd/nerdctl/{ => container}/logs.go | 20 +- cmd/nerdctl/{ => container}/pause.go | 51 +- cmd/nerdctl/{ => container}/port.go | 10 +- cmd/nerdctl/{ => container}/rename.go | 15 +- cmd/nerdctl/{ => container}/restart.go | 15 +- cmd/nerdctl/container/rm.go | 94 ++ cmd/nerdctl/container/run.go | 179 +++ cmd/nerdctl/container/start.go | 90 ++ cmd/nerdctl/container/stop.go | 91 ++ cmd/nerdctl/{ => container}/unpause.go | 47 +- cmd/nerdctl/{ => container}/update.go | 10 +- cmd/nerdctl/{ => container}/wait.go | 10 +- cmd/nerdctl/container_lsutil.go | 375 ----- cmd/nerdctl/{ => event}/events.go | 10 +- cmd/nerdctl/{ => history}/history.go | 18 +- cmd/nerdctl/image.go | 64 - cmd/nerdctl/image/image.go | 74 + cmd/nerdctl/{ => image}/image_convert.go | 14 +- cmd/nerdctl/{ => image}/image_cryptutil.go | 10 +- cmd/nerdctl/{ => image}/image_decrypt.go | 4 +- cmd/nerdctl/{ => image}/image_encrypt.go | 4 +- cmd/nerdctl/{ => image}/image_inspect.go | 19 +- cmd/nerdctl/{ => image}/image_prune.go | 11 +- cmd/nerdctl/{ => image}/images.go | 73 +- cmd/nerdctl/{ => inspect}/inspect.go | 18 +- cmd/nerdctl/{ => internal}/internal.go | 6 +- .../{ => internal}/internal_oci_hook.go | 7 +- cmd/nerdctl/{ => ipfs}/ipfs.go | 12 +- cmd/nerdctl/{ => ipfs}/ipfs_registry.go | 19 +- cmd/nerdctl/{ => ipfs}/ipfs_registry_down.go | 10 +- cmd/nerdctl/{ => ipfs}/ipfs_registry_serve.go | 4 +- cmd/nerdctl/{ => ipfs}/ipfs_registry_up.go | 14 +- cmd/nerdctl/{ => load}/load.go | 76 +- cmd/nerdctl/{ => login}/login.go | 4 +- cmd/nerdctl/{ => login}/login_unix.go | 2 +- cmd/nerdctl/{ => login}/login_windows.go | 2 +- cmd/nerdctl/{ => logout}/logout.go | 4 +- cmd/nerdctl/main.go | 398 ++--- cmd/nerdctl/main_freebsd.go | 12 - cmd/nerdctl/main_linux.go | 20 - cmd/nerdctl/main_unix.go | 48 - cmd/nerdctl/main_windows.go | 20 - cmd/nerdctl/{ => namespace}/namespace.go | 27 +- .../{ => namespace}/namespace_create.go | 7 +- .../{ => namespace}/namespace_freebsd.go | 2 +- .../{ => namespace}/namespace_inspect.go | 10 +- .../{ => namespace}/namespace_linux.go | 2 +- cmd/nerdctl/{ => namespace}/namespace_rm.go | 7 +- .../{ => namespace}/namespace_update.go | 7 +- .../{ => namespace}/namespace_windows.go | 2 +- cmd/nerdctl/{ => network}/network.go | 20 +- cmd/nerdctl/{ => network}/network_create.go | 7 +- .../{ => network}/network_create_unix.go | 2 +- .../{ => network}/network_create_windows.go | 2 +- cmd/nerdctl/{ => network}/network_inspect.go | 10 +- cmd/nerdctl/{ => network}/network_ls.go | 11 +- cmd/nerdctl/{ => network}/network_prune.go | 11 +- cmd/nerdctl/{ => network}/network_rm.go | 15 +- cmd/nerdctl/{ => ps}/ps.go | 124 +- cmd/nerdctl/{ => pull}/pull.go | 101 +- cmd/nerdctl/{ => push}/push.go | 17 +- cmd/nerdctl/rm.go | 225 --- cmd/nerdctl/{ => rmi}/rmi.go | 10 +- cmd/nerdctl/run.go | 1274 ----------------- cmd/nerdctl/{ => save}/save.go | 12 +- cmd/nerdctl/{ => stats}/stats.go | 28 +- cmd/nerdctl/{ => stats}/stats_freebsd.go | 2 +- cmd/nerdctl/{ => stats}/stats_linux.go | 2 +- cmd/nerdctl/{ => stats}/stats_windows.go | 2 +- cmd/nerdctl/{ => system}/info.go | 10 +- cmd/nerdctl/{ => system}/system.go | 21 +- cmd/nerdctl/{ => system}/system_prune.go | 19 +- cmd/nerdctl/{ => tag}/tag.go | 13 +- cmd/nerdctl/top/top.go | 99 ++ cmd/nerdctl/{ => utils/action}/start.go | 89 +- cmd/nerdctl/{ => utils/action}/stop.go | 80 +- cmd/nerdctl/utils/command.go | 224 +++ cmd/nerdctl/utils/common/common.go | 278 ++++ cmd/nerdctl/utils/container/container.go | 537 +++++++ .../utils/container/container_create.go | 690 +++++++++ cmd/nerdctl/{ => utils/fmtutil}/fmtutil.go | 22 +- cmd/nerdctl/utils/image.go | 113 ++ cmd/nerdctl/utils/image_encrypt.go | 71 + cmd/nerdctl/{run_mount.go => utils/mount.go} | 8 +- .../{completion_linux.go => utils/network.go} | 24 +- cmd/nerdctl/utils/pause.go | 51 + cmd/nerdctl/utils/print.go | 42 + cmd/nerdctl/utils/pull.go | 139 ++ cmd/nerdctl/utils/run/run.go | 315 ++++ .../{ => utils/run}/run_cgroup_freebsd.go | 2 +- .../{ => utils/run}/run_cgroup_linux.go | 6 +- .../{ => utils/run}/run_cgroup_windows.go | 2 +- cmd/nerdctl/{ => utils/run}/run_freebsd.go | 20 +- cmd/nerdctl/{ => utils/run}/run_gpus.go | 42 +- cmd/nerdctl/{ => utils/run}/run_linux.go | 41 +- cmd/nerdctl/{ => utils/run}/run_network.go | 74 +- cmd/nerdctl/{ => utils/run}/run_restart.go | 6 +- cmd/nerdctl/{ => utils/run}/run_runtime.go | 14 +- .../{ => utils/run}/run_security_linux.go | 2 +- cmd/nerdctl/utils/run/run_stargz_linux.go | 29 + cmd/nerdctl/{ => utils/run}/run_ulimit.go | 2 +- cmd/nerdctl/{ => utils/run}/run_user.go | 42 +- cmd/nerdctl/{ => utils/run}/run_windows.go | 24 +- .../save_linux.go} | 37 +- cmd/nerdctl/{ => utils}/top.go | 84 +- cmd/nerdctl/utils/unpause.go | 49 + cmd/nerdctl/utils/volume/volume.go | 95 ++ cmd/nerdctl/{ => version}/version.go | 10 +- cmd/nerdctl/volume.go | 55 - cmd/nerdctl/volume/volume.go | 42 + cmd/nerdctl/{ => volume}/volume_create.go | 10 +- cmd/nerdctl/{ => volume}/volume_inspect.go | 13 +- cmd/nerdctl/{ => volume}/volume_ls.go | 26 +- cmd/nerdctl/{ => volume}/volume_prune.go | 16 +- cmd/nerdctl/{ => volume}/volume_rm.go | 13 +- {cmd/nerdctl => integration}/build_test.go | 36 +- .../builder_linux_test.go | 5 +- {cmd/nerdctl => integration}/commit_test.go | 2 +- .../completion_linux_test.go | 2 +- .../compose_build_linux_test.go | 2 +- .../compose_config_test.go | 2 +- .../compose_exec_linux_test.go | 2 +- .../compose_images_linux_test.go | 2 +- .../compose_kill_linux_test.go | 2 +- .../compose_pause_linux_test.go | 2 +- .../compose_port_linux_test.go | 2 +- .../compose_ps_linux_test.go | 5 +- .../compose_pull_linux_test.go | 2 +- .../compose_restart_linux_test.go | 2 +- .../compose_rm_linux_test.go | 2 +- .../compose_run_linux_test.go | 11 +- .../compose_stop_linux_test.go | 2 +- .../compose_top_linux_test.go | 2 +- .../compose_up_linux_test.go | 80 +- .../compose_version_test.go | 2 +- .../container_inspect_linux_test.go | 2 +- .../container_prune_linux_test.go | 2 +- {cmd/nerdctl => integration}/cp_linux_test.go | 2 +- .../create_linux_test.go | 2 +- .../exec_linux_test.go | 2 +- {cmd/nerdctl => integration}/exec_test.go | 2 +- .../image_convert_linux_test.go | 2 +- .../image_convert_test.go | 2 +- .../image_encrypt_linux_test.go | 65 +- .../image_inspect_test.go | 2 +- .../image_prune_test.go | 5 +- {cmd/nerdctl => integration}/images_test.go | 5 +- {cmd/nerdctl => integration}/info_test.go | 2 +- .../ipfs_build_linux_test.go | 5 +- .../ipfs_compose_linux_test.go | 7 +- .../ipfs_linux_test.go | 24 +- .../ipfs_registry_linux_test.go | 5 +- .../load_linux_test.go | 2 +- .../login_linux_test.go | 2 +- {cmd/nerdctl => integration}/logs_test.go | 2 +- .../main_linux_test.go | 2 +- {cmd/nerdctl => integration}/main_test.go | 2 +- .../multi_platform_linux_test.go | 7 +- .../network_create_linux_test.go | 2 +- .../network_inspect_test.go | 2 +- .../network_prune_linux_test.go | 2 +- .../network_rm_linux_test.go | 2 +- {cmd/nerdctl => integration}/ps_linux_test.go | 2 +- .../pull_linux_test.go | 59 +- .../push_linux_test.go | 2 +- .../rename_linux_test.go | 2 +- .../restart_linux_test.go | 2 +- {cmd/nerdctl => integration}/rm_linux_test.go | 2 +- .../nerdctl => integration}/rmi_linux_test.go | 2 +- .../run_cgroup_linux_test.go | 5 +- {cmd/nerdctl => integration}/run_gpus_test.go | 19 +- .../nerdctl => integration}/run_linux_test.go | 5 +- .../run_log_driver_syslog_test.go | 2 +- .../run_mount_linux_test.go | 13 +- .../run_network_linux_test.go | 2 +- .../run_restart_linux_test.go | 2 +- .../run_runtime_linux_test.go | 2 +- .../run_security_linux_test.go | 2 +- .../run_stargz_linux_test.go | 15 +- {cmd/nerdctl => integration}/run_test.go | 7 +- .../run_user_linux_test.go | 2 +- .../run_user_windows_test.go | 2 +- .../run_verify_linux_test.go | 14 +- integration/save_linux_test.go | 46 + {cmd/nerdctl => integration}/start_test.go | 2 +- .../stats_linux_test.go | 2 +- .../stop_linux_test.go | 2 +- .../system_prune_linux_test.go | 2 +- .../nerdctl => integration}/top_linux_test.go | 2 +- .../volume_inspect_test.go | 2 +- .../nerdctl => integration}/volume_ls_test.go | 2 +- .../volume_prune_linux_test.go | 2 +- .../volume_rm_linux_test.go | 2 +- {cmd/nerdctl => integration}/wait_test.go | 2 +- 248 files changed, 4931 insertions(+), 4076 deletions(-) create mode 100644 cmd/nerdctl/apparmor/apparmor_freebsd.go rename cmd/nerdctl/{ => apparmor}/apparmor_inspect_linux.go (91%) rename cmd/nerdctl/{ => apparmor}/apparmor_linux.go (70%) rename cmd/nerdctl/{ => apparmor}/apparmor_load_linux.go (91%) rename cmd/nerdctl/{ => apparmor}/apparmor_ls_linux.go (91%) rename cmd/nerdctl/{ => apparmor}/apparmor_unload_linux.go (79%) create mode 100644 cmd/nerdctl/apparmor/apparmor_windows.go rename cmd/nerdctl/{ => build}/build.go (93%) rename cmd/nerdctl/{ => builder}/builder.go (88%) rename cmd/nerdctl/{ => client}/client.go (90%) rename cmd/nerdctl/{ => completion}/completion.go (51%) create mode 100644 cmd/nerdctl/completion/completion_freebsd.go create mode 100644 cmd/nerdctl/completion/completion_linux.go create mode 100644 cmd/nerdctl/completion/completion_unix.go create mode 100644 cmd/nerdctl/completion/completion_windows.go rename cmd/nerdctl/{ => compose}/compose.go (93%) rename cmd/nerdctl/{ => compose}/compose_build.go (94%) rename cmd/nerdctl/{ => compose}/compose_config.go (94%) rename cmd/nerdctl/{ => compose}/compose_down.go (85%) rename cmd/nerdctl/{ => compose}/compose_exec.go (96%) rename cmd/nerdctl/{ => compose}/compose_images.go (94%) rename cmd/nerdctl/{ => compose}/compose_kill.go (91%) rename cmd/nerdctl/{ => compose}/compose_logs.go (94%) rename cmd/nerdctl/{ => compose}/compose_pause.go (89%) rename cmd/nerdctl/{ => compose}/compose_port.go (94%) rename cmd/nerdctl/{ => compose}/compose_ps.go (85%) rename cmd/nerdctl/{ => compose}/compose_pull.go (91%) rename cmd/nerdctl/{ => compose}/compose_push.go (90%) rename cmd/nerdctl/{ => compose}/compose_restart.go (91%) rename cmd/nerdctl/{ => compose}/compose_rm.go (94%) rename cmd/nerdctl/{ => compose}/compose_run.go (98%) rename cmd/nerdctl/{ => compose}/compose_stop.go (91%) rename cmd/nerdctl/{ => compose}/compose_top.go (88%) rename cmd/nerdctl/{ => compose}/compose_up.go (96%) rename cmd/nerdctl/{ => compose}/compose_version.go (99%) delete mode 100644 cmd/nerdctl/container.go rename cmd/nerdctl/{ => container}/commit.go (92%) create mode 100644 cmd/nerdctl/container/container.go rename cmd/nerdctl/{ => container}/container_inspect.go (87%) rename cmd/nerdctl/{ => container}/container_prune.go (79%) rename cmd/nerdctl/{ => container/cp}/cp.go (99%) create mode 100644 cmd/nerdctl/container/cp/cp_freebsd.go rename cmd/nerdctl/{ => container/cp}/cp_linux.go (96%) create mode 100644 cmd/nerdctl/container/cp/cp_windows.go rename cmd/nerdctl/{ => container}/create.go (79%) rename cmd/nerdctl/{ => container/exec}/exec.go (93%) rename cmd/nerdctl/{ => container/exec}/exec_freebsd.go (98%) rename cmd/nerdctl/{ => container/exec}/exec_linux.go (99%) rename cmd/nerdctl/{ => container/exec}/exec_windows.go (98%) rename cmd/nerdctl/{ => container}/kill.go (90%) rename cmd/nerdctl/{ => container}/logs.go (91%) rename cmd/nerdctl/{ => container}/pause.go (57%) rename cmd/nerdctl/{ => container}/port.go (89%) rename cmd/nerdctl/{ => container}/rename.go (86%) rename cmd/nerdctl/{ => container}/restart.go (81%) create mode 100644 cmd/nerdctl/container/rm.go create mode 100644 cmd/nerdctl/container/run.go create mode 100644 cmd/nerdctl/container/start.go create mode 100644 cmd/nerdctl/container/stop.go rename cmd/nerdctl/{ => container}/unpause.go (61%) rename cmd/nerdctl/{ => container}/update.go (97%) rename cmd/nerdctl/{ => container}/wait.go (89%) delete mode 100644 cmd/nerdctl/container_lsutil.go rename cmd/nerdctl/{ => event}/events.go (92%) rename cmd/nerdctl/{ => history}/history.go (92%) delete mode 100644 cmd/nerdctl/image.go create mode 100644 cmd/nerdctl/image/image.go rename cmd/nerdctl/{ => image}/image_convert.go (97%) rename cmd/nerdctl/{ => image}/image_cryptutil.go (95%) rename cmd/nerdctl/{ => image}/image_decrypt.go (97%) rename cmd/nerdctl/{ => image}/image_encrypt.go (97%) rename cmd/nerdctl/{ => image}/image_inspect.go (86%) rename cmd/nerdctl/{ => image}/image_prune.go (91%) rename cmd/nerdctl/{ => image}/images.go (88%) rename cmd/nerdctl/{ => inspect}/inspect.go (86%) rename cmd/nerdctl/{ => internal}/internal.go (89%) rename cmd/nerdctl/{ => internal}/internal_oci_hook.go (89%) rename cmd/nerdctl/{ => ipfs}/ipfs.go (71%) rename cmd/nerdctl/{ => ipfs}/ipfs_registry.go (62%) rename cmd/nerdctl/{ => ipfs}/ipfs_registry_down.go (86%) rename cmd/nerdctl/{ => ipfs}/ipfs_registry_serve.go (97%) rename cmd/nerdctl/{ => ipfs}/ipfs_registry_up.go (91%) rename cmd/nerdctl/{ => load}/load.go (54%) rename cmd/nerdctl/{ => login}/login.go (99%) rename cmd/nerdctl/{ => login}/login_unix.go (98%) rename cmd/nerdctl/{ => login}/login_windows.go (98%) rename cmd/nerdctl/{ => logout}/logout.go (98%) rename cmd/nerdctl/{ => namespace}/namespace.go (79%) rename cmd/nerdctl/{ => namespace}/namespace_create.go (89%) rename cmd/nerdctl/{ => namespace}/namespace_freebsd.go (97%) rename cmd/nerdctl/{ => namespace}/namespace_inspect.go (86%) rename cmd/nerdctl/{ => namespace}/namespace_linux.go (98%) rename cmd/nerdctl/{ => namespace}/namespace_rm.go (90%) rename cmd/nerdctl/{ => namespace}/namespace_update.go (88%) rename cmd/nerdctl/{ => namespace}/namespace_windows.go (97%) rename cmd/nerdctl/{ => network}/network.go (65%) rename cmd/nerdctl/{ => network}/network_create.go (96%) rename cmd/nerdctl/{ => network}/network_create_unix.go (98%) rename cmd/nerdctl/{ => network}/network_create_windows.go (98%) rename cmd/nerdctl/{ => network}/network_inspect.go (92%) rename cmd/nerdctl/{ => network}/network_ls.go (93%) rename cmd/nerdctl/{ => network}/network_prune.go (90%) rename cmd/nerdctl/{ => network}/network_rm.go (89%) rename cmd/nerdctl/{ => ps}/ps.go (69%) rename cmd/nerdctl/{ => pull}/pull.go (52%) rename cmd/nerdctl/{ => push}/push.go (95%) delete mode 100644 cmd/nerdctl/rm.go rename cmd/nerdctl/{ => rmi}/rmi.go (93%) delete mode 100644 cmd/nerdctl/run.go rename cmd/nerdctl/{ => save}/save.go (90%) rename cmd/nerdctl/{ => stats}/stats.go (94%) rename cmd/nerdctl/{ => stats}/stats_freebsd.go (98%) rename cmd/nerdctl/{ => stats}/stats_linux.go (99%) rename cmd/nerdctl/{ => stats}/stats_windows.go (98%) rename cmd/nerdctl/{ => system}/info.go (96%) rename cmd/nerdctl/{ => system}/system.go (64%) rename cmd/nerdctl/{ => system}/system_prune.go (79%) rename cmd/nerdctl/{ => tag}/tag.go (87%) create mode 100644 cmd/nerdctl/top/top.go rename cmd/nerdctl/{ => utils/action}/start.go (65%) rename cmd/nerdctl/{ => utils/action}/stop.go (57%) create mode 100644 cmd/nerdctl/utils/command.go create mode 100644 cmd/nerdctl/utils/common/common.go create mode 100644 cmd/nerdctl/utils/container/container.go create mode 100644 cmd/nerdctl/utils/container/container_create.go rename cmd/nerdctl/{ => utils/fmtutil}/fmtutil.go (81%) create mode 100644 cmd/nerdctl/utils/image.go create mode 100644 cmd/nerdctl/utils/image_encrypt.go rename cmd/nerdctl/{run_mount.go => utils/mount.go} (98%) rename cmd/nerdctl/{completion_linux.go => utils/network.go} (58%) create mode 100644 cmd/nerdctl/utils/pause.go create mode 100644 cmd/nerdctl/utils/print.go create mode 100644 cmd/nerdctl/utils/pull.go create mode 100644 cmd/nerdctl/utils/run/run.go rename cmd/nerdctl/{ => utils/run}/run_cgroup_freebsd.go (98%) rename cmd/nerdctl/{ => utils/run}/run_cgroup_linux.go (98%) rename cmd/nerdctl/{ => utils/run}/run_cgroup_windows.go (98%) rename cmd/nerdctl/{ => utils/run}/run_freebsd.go (68%) rename cmd/nerdctl/{ => utils/run}/run_gpus.go (83%) rename cmd/nerdctl/{ => utils/run}/run_linux.go (87%) rename cmd/nerdctl/{ => utils/run}/run_network.go (87%) rename cmd/nerdctl/{ => utils/run}/run_restart.go (93%) rename cmd/nerdctl/{ => utils/run}/run_runtime.go (86%) rename cmd/nerdctl/{ => utils/run}/run_security_linux.go (99%) create mode 100644 cmd/nerdctl/utils/run/run_stargz_linux.go rename cmd/nerdctl/{ => utils/run}/run_ulimit.go (99%) rename cmd/nerdctl/{ => utils/run}/run_user.go (85%) rename cmd/nerdctl/{ => utils/run}/run_windows.go (77%) rename cmd/nerdctl/{save_linux_test.go => utils/save_linux.go} (62%) rename cmd/nerdctl/{ => utils}/top.go (71%) create mode 100644 cmd/nerdctl/utils/unpause.go create mode 100644 cmd/nerdctl/utils/volume/volume.go rename cmd/nerdctl/{ => version}/version.go (91%) delete mode 100644 cmd/nerdctl/volume.go create mode 100644 cmd/nerdctl/volume/volume.go rename cmd/nerdctl/{ => volume}/volume_create.go (85%) rename cmd/nerdctl/{ => volume}/volume_inspect.go (84%) rename cmd/nerdctl/{ => volume}/volume_ls.go (93%) rename cmd/nerdctl/{ => volume}/volume_prune.go (82%) rename cmd/nerdctl/{ => volume}/volume_rm.go (88%) rename {cmd/nerdctl => integration}/build_test.go (93%) rename {cmd/nerdctl => integration}/builder_linux_test.go (89%) rename {cmd/nerdctl => integration}/commit_test.go (98%) rename {cmd/nerdctl => integration}/completion_linux_test.go (99%) rename {cmd/nerdctl => integration}/compose_build_linux_test.go (99%) rename {cmd/nerdctl => integration}/compose_config_test.go (99%) rename {cmd/nerdctl => integration}/compose_exec_linux_test.go (99%) rename {cmd/nerdctl => integration}/compose_images_linux_test.go (99%) rename {cmd/nerdctl => integration}/compose_kill_linux_test.go (99%) rename {cmd/nerdctl => integration}/compose_pause_linux_test.go (99%) rename {cmd/nerdctl => integration}/compose_port_linux_test.go (99%) rename {cmd/nerdctl => integration}/compose_ps_linux_test.go (96%) rename {cmd/nerdctl => integration}/compose_pull_linux_test.go (98%) rename {cmd/nerdctl => integration}/compose_restart_linux_test.go (99%) rename {cmd/nerdctl => integration}/compose_rm_linux_test.go (99%) rename {cmd/nerdctl => integration}/compose_run_linux_test.go (98%) rename {cmd/nerdctl => integration}/compose_stop_linux_test.go (99%) rename {cmd/nerdctl => integration}/compose_top_linux_test.go (98%) rename {cmd/nerdctl => integration}/compose_up_linux_test.go (98%) rename {cmd/nerdctl => integration}/compose_version_test.go (98%) rename {cmd/nerdctl => integration}/container_inspect_linux_test.go (99%) rename {cmd/nerdctl => integration}/container_prune_linux_test.go (98%) rename {cmd/nerdctl => integration}/cp_linux_test.go (99%) rename {cmd/nerdctl => integration}/create_linux_test.go (99%) rename {cmd/nerdctl => integration}/exec_linux_test.go (99%) rename {cmd/nerdctl => integration}/exec_test.go (99%) rename {cmd/nerdctl => integration}/image_convert_linux_test.go (99%) rename {cmd/nerdctl => integration}/image_convert_test.go (98%) rename {cmd/nerdctl => integration}/image_encrypt_linux_test.go (51%) rename {cmd/nerdctl => integration}/image_inspect_test.go (98%) rename {cmd/nerdctl => integration}/image_prune_test.go (92%) rename {cmd/nerdctl => integration}/images_test.go (97%) rename {cmd/nerdctl => integration}/info_test.go (98%) rename {cmd/nerdctl => integration}/ipfs_build_linux_test.go (92%) rename {cmd/nerdctl => integration}/ipfs_compose_linux_test.go (96%) rename {cmd/nerdctl => integration}/ipfs_linux_test.go (91%) rename {cmd/nerdctl => integration}/ipfs_registry_linux_test.go (95%) rename {cmd/nerdctl => integration}/load_linux_test.go (98%) rename {cmd/nerdctl => integration}/login_linux_test.go (99%) rename {cmd/nerdctl => integration}/logs_test.go (99%) rename {cmd/nerdctl => integration}/main_linux_test.go (98%) rename {cmd/nerdctl => integration}/main_test.go (99%) rename {cmd/nerdctl => integration}/multi_platform_linux_test.go (96%) rename {cmd/nerdctl => integration}/network_create_linux_test.go (98%) rename {cmd/nerdctl => integration}/network_inspect_test.go (98%) rename {cmd/nerdctl => integration}/network_prune_linux_test.go (98%) rename {cmd/nerdctl => integration}/network_rm_linux_test.go (99%) rename {cmd/nerdctl => integration}/ps_linux_test.go (99%) rename {cmd/nerdctl => integration}/pull_linux_test.go (74%) rename {cmd/nerdctl => integration}/push_linux_test.go (99%) rename {cmd/nerdctl => integration}/rename_linux_test.go (99%) rename {cmd/nerdctl => integration}/restart_linux_test.go (99%) rename {cmd/nerdctl => integration}/rm_linux_test.go (98%) rename {cmd/nerdctl => integration}/rmi_linux_test.go (98%) rename {cmd/nerdctl => integration}/run_cgroup_linux_test.go (98%) rename {cmd/nerdctl => integration}/run_gpus_test.go (75%) rename {cmd/nerdctl => integration}/run_linux_test.go (98%) rename {cmd/nerdctl => integration}/run_log_driver_syslog_test.go (99%) rename {cmd/nerdctl => integration}/run_mount_linux_test.go (98%) rename {cmd/nerdctl => integration}/run_network_linux_test.go (99%) rename {cmd/nerdctl => integration}/run_restart_linux_test.go (99%) rename {cmd/nerdctl => integration}/run_runtime_linux_test.go (97%) rename {cmd/nerdctl => integration}/run_security_linux_test.go (99%) rename {cmd/nerdctl => integration}/run_stargz_linux_test.go (81%) rename {cmd/nerdctl => integration}/run_test.go (98%) rename {cmd/nerdctl => integration}/run_user_linux_test.go (99%) rename {cmd/nerdctl => integration}/run_user_windows_test.go (98%) rename {cmd/nerdctl => integration}/run_verify_linux_test.go (84%) create mode 100644 integration/save_linux_test.go rename {cmd/nerdctl => integration}/start_test.go (98%) rename {cmd/nerdctl => integration}/stats_linux_test.go (98%) rename {cmd/nerdctl => integration}/stop_linux_test.go (99%) rename {cmd/nerdctl => integration}/system_prune_linux_test.go (98%) rename {cmd/nerdctl => integration}/top_linux_test.go (98%) rename {cmd/nerdctl => integration}/volume_inspect_test.go (98%) rename {cmd/nerdctl => integration}/volume_ls_test.go (99%) rename {cmd/nerdctl => integration}/volume_prune_linux_test.go (98%) rename {cmd/nerdctl => integration}/volume_rm_linux_test.go (98%) rename {cmd/nerdctl => integration}/wait_test.go (98%) diff --git a/.cirrus.yml b/.cirrus.yml index b13f75fa6c8..9382a59ad57 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -38,4 +38,4 @@ windows_task: - powershell hack/configure-windows-ci.ps1 - refreshenv - go install .\cmd\nerdctl\ - - go test -v ./cmd/... + - go test -v ./integration/... diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a7ec7913aeb..deffe3f672f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -156,4 +156,4 @@ jobs: run: | sudo apt-get install -y expect - name: "Ensure that the integration test suite is compatible with Docker" - run: go test -timeout 20m -v -exec sudo ./cmd/nerdctl/... -args -test.target=docker -test.kill-daemon + run: go test -timeout 20m -v -exec sudo ./integration/... -args -test.target=docker -test.kill-daemon diff --git a/.gitignore b/.gitignore index 33c9733d860..5b7ac4a4682 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ build # vagrant /.vagrant +!cmd/nerdctl/build diff --git a/Dockerfile b/Dockerfile index f2612545596..8cd5575b4a3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -296,7 +296,7 @@ RUN curl -L -o nydus-static.tgz "https://github.com/dragonflyoss/image-service/r tar xzf nydus-static.tgz && \ mv nydus-static/nydus-image nydus-static/nydusd nydus-static/nydusify /usr/bin/ && \ rm nydus-static.tgz -CMD ["gotestsum", "--format=testname", "--rerun-fails=2", "--packages=github.com/containerd/nerdctl/cmd/nerdctl/...", \ +CMD ["gotestsum", "--format=testname", "--rerun-fails=2", "--packages=github.com/containerd/nerdctl/integration/...", \ "--", "-timeout=20m", "-args", "-test.kill-daemon"] FROM test-integration AS test-integration-rootless @@ -318,11 +318,11 @@ COPY ./Dockerfile.d/etc_systemd_system_user@.service.d_delegate.conf /etc/system # ipfs daemon for rootless containerd will be enabled in /test-integration-rootless.sh RUN systemctl disable test-integration-ipfs-offline VOLUME /home/rootless/.local/share -RUN go test -o /usr/local/bin/nerdctl.test -c ./cmd/nerdctl +RUN go test -o /usr/local/bin/nerdctl.test -c ./integration COPY ./Dockerfile.d/test-integration-rootless.sh / CMD ["/test-integration-rootless.sh", \ "gotestsum", "--format=testname", "--rerun-fails=2", "--raw-command", \ - "--", "/usr/local/go/bin/go", "tool", "test2json", "-t", "-p", "github.com/containerd/nerdctl/cmd/nerdctl", \ + "--", "/usr/local/go/bin/go", "tool", "test2json", "-t", "-p", "github.com/containerd/nerdctl/integration/...", \ "/usr/local/bin/nerdctl.test", "-test.v", "-test.timeout=20m", "-test.kill-daemon"] # test for CONTAINERD_ROOTLESS_ROOTLESSKIT_PORT_DRIVER=slirp4netns diff --git a/cmd/nerdctl/apparmor/apparmor_freebsd.go b/cmd/nerdctl/apparmor/apparmor_freebsd.go new file mode 100644 index 00000000000..e369b44d0e8 --- /dev/null +++ b/cmd/nerdctl/apparmor/apparmor_freebsd.go @@ -0,0 +1,23 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package apparmor + +import "github.com/spf13/cobra" + +func AddApparmorCommand(rootCmd *cobra.Command) { + // NOP +} diff --git a/cmd/nerdctl/apparmor_inspect_linux.go b/cmd/nerdctl/apparmor/apparmor_inspect_linux.go similarity index 91% rename from cmd/nerdctl/apparmor_inspect_linux.go rename to cmd/nerdctl/apparmor/apparmor_inspect_linux.go index a47f812a64c..d6235a9025e 100644 --- a/cmd/nerdctl/apparmor_inspect_linux.go +++ b/cmd/nerdctl/apparmor/apparmor_inspect_linux.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package apparmor import ( "fmt" @@ -29,14 +29,14 @@ func newApparmorInspectCommand() *cobra.Command { Use: "inspect", Short: fmt.Sprintf("Display the default AppArmor profile %q. Other profiles cannot be displayed with this command.", defaults.AppArmorProfileName), Args: cobra.NoArgs, - RunE: apparmorInspectAction, + RunE: InspectAction, SilenceUsage: true, SilenceErrors: true, } return cmd } -func apparmorInspectAction(cmd *cobra.Command, args []string) error { +func InspectAction(cmd *cobra.Command, args []string) error { b, err := apparmor.DumpDefaultProfile(defaults.AppArmorProfileName) if err != nil { return err diff --git a/cmd/nerdctl/apparmor_linux.go b/cmd/nerdctl/apparmor/apparmor_linux.go similarity index 70% rename from cmd/nerdctl/apparmor_linux.go rename to cmd/nerdctl/apparmor/apparmor_linux.go index e39985e9294..42011939177 100644 --- a/cmd/nerdctl/apparmor_linux.go +++ b/cmd/nerdctl/apparmor/apparmor_linux.go @@ -14,18 +14,20 @@ limitations under the License. */ -package main +package apparmor import ( + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" "github.com/spf13/cobra" ) -func newApparmorCommand() *cobra.Command { +func NewApparmorCommand() *cobra.Command { cmd := &cobra.Command{ - Annotations: map[string]string{Category: Management}, + Annotations: map[string]string{common.Category: common.Management}, Use: "apparmor", Short: "Manage AppArmor profiles", - RunE: unknownSubcommandAction, + RunE: completion.UnknownSubcommandAction, SilenceUsage: true, SilenceErrors: true, } @@ -37,3 +39,7 @@ func newApparmorCommand() *cobra.Command { ) return cmd } + +func AddApparmorCommand(rootCmd *cobra.Command) { + rootCmd.AddCommand(NewApparmorCommand()) +} diff --git a/cmd/nerdctl/apparmor_load_linux.go b/cmd/nerdctl/apparmor/apparmor_load_linux.go similarity index 91% rename from cmd/nerdctl/apparmor_load_linux.go rename to cmd/nerdctl/apparmor/apparmor_load_linux.go index f295faf795c..353ee6521f8 100644 --- a/cmd/nerdctl/apparmor_load_linux.go +++ b/cmd/nerdctl/apparmor/apparmor_load_linux.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package apparmor import ( "fmt" @@ -30,14 +30,14 @@ func newApparmorLoadCommand() *cobra.Command { Use: "load", Short: fmt.Sprintf("Load the default AppArmor profile %q. Requires root.", defaults.AppArmorProfileName), Args: cobra.NoArgs, - RunE: apparmorLoadAction, + RunE: LoadAction, SilenceUsage: true, SilenceErrors: true, } return cmd } -func apparmorLoadAction(cmd *cobra.Command, args []string) error { +func LoadAction(cmd *cobra.Command, args []string) error { logrus.Infof("Loading profile %q", defaults.AppArmorProfileName) return apparmor.LoadDefaultProfile(defaults.AppArmorProfileName) } diff --git a/cmd/nerdctl/apparmor_ls_linux.go b/cmd/nerdctl/apparmor/apparmor_ls_linux.go similarity index 91% rename from cmd/nerdctl/apparmor_ls_linux.go rename to cmd/nerdctl/apparmor/apparmor_ls_linux.go index 34a4ab1b92e..e802bb738fe 100644 --- a/cmd/nerdctl/apparmor_ls_linux.go +++ b/cmd/nerdctl/apparmor/apparmor_ls_linux.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package apparmor import ( "bytes" @@ -23,6 +23,7 @@ import ( "text/tabwriter" "text/template" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/fmtutil" "github.com/containerd/nerdctl/pkg/apparmorutil" "github.com/spf13/cobra" ) @@ -33,7 +34,7 @@ func newApparmorLsCommand() *cobra.Command { Aliases: []string{"list"}, Short: "List the loaded AppArmor profiles", Args: cobra.NoArgs, - RunE: apparmorLsAction, + RunE: LsAction, SilenceUsage: true, SilenceErrors: true, } @@ -46,7 +47,7 @@ func newApparmorLsCommand() *cobra.Command { return cmd } -func apparmorLsAction(cmd *cobra.Command, args []string) error { +func LsAction(cmd *cobra.Command, args []string) error { quiet, err := cmd.Flags().GetBool("quiet") if err != nil { return err @@ -70,7 +71,7 @@ func apparmorLsAction(cmd *cobra.Command, args []string) error { return errors.New("format and quiet must not be specified together") } var err error - tmpl, err = parseTemplate(format) + tmpl, err = fmtutil.ParseTemplate(format) if err != nil { return err } @@ -96,7 +97,7 @@ func apparmorLsAction(cmd *cobra.Command, args []string) error { fmt.Fprintf(w, "%s\t%s\n", f.Name, f.Mode) } } - if f, ok := w.(Flusher); ok { + if f, ok := w.(fmtutil.Flusher); ok { return f.Flush() } return nil diff --git a/cmd/nerdctl/apparmor_unload_linux.go b/cmd/nerdctl/apparmor/apparmor_unload_linux.go similarity index 79% rename from cmd/nerdctl/apparmor_unload_linux.go rename to cmd/nerdctl/apparmor/apparmor_unload_linux.go index 15154f3b95a..6b505f261d2 100644 --- a/cmd/nerdctl/apparmor_unload_linux.go +++ b/cmd/nerdctl/apparmor/apparmor_unload_linux.go @@ -14,11 +14,12 @@ limitations under the License. */ -package main +package apparmor import ( "fmt" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/pkg/apparmorutil" "github.com/containerd/nerdctl/pkg/defaults" "github.com/sirupsen/logrus" @@ -30,15 +31,15 @@ func newApparmorUnloadCommand() *cobra.Command { Use: "unload [PROFILE]", Short: fmt.Sprintf("Unload an AppArmor profile. The target profile name defaults to %q. Requires root.", defaults.AppArmorProfileName), Args: cobra.MaximumNArgs(1), - RunE: apparmorUnloadAction, - ValidArgsFunction: apparmorUnloadShellComplete, + RunE: UnloadAction, + ValidArgsFunction: completion.ApparmorUnloadShellComplete, SilenceUsage: true, SilenceErrors: true, } return cmd } -func apparmorUnloadAction(cmd *cobra.Command, args []string) error { +func UnloadAction(cmd *cobra.Command, args []string) error { target := defaults.AppArmorProfileName if len(args) > 0 { target = args[0] @@ -46,7 +47,3 @@ func apparmorUnloadAction(cmd *cobra.Command, args []string) error { logrus.Infof("Unloading profile %q", target) return apparmorutil.Unload(target) } - -func apparmorUnloadShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return shellCompleteApparmorProfiles(cmd) -} diff --git a/cmd/nerdctl/apparmor/apparmor_windows.go b/cmd/nerdctl/apparmor/apparmor_windows.go new file mode 100644 index 00000000000..e369b44d0e8 --- /dev/null +++ b/cmd/nerdctl/apparmor/apparmor_windows.go @@ -0,0 +1,23 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package apparmor + +import "github.com/spf13/cobra" + +func AddApparmorCommand(rootCmd *cobra.Command) { + // NOP +} diff --git a/cmd/nerdctl/build.go b/cmd/nerdctl/build/build.go similarity index 93% rename from cmd/nerdctl/build.go rename to cmd/nerdctl/build/build.go index b85900a5f82..db05b70880b 100644 --- a/cmd/nerdctl/build.go +++ b/cmd/nerdctl/build/build.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package build import ( "encoding/json" @@ -30,6 +30,9 @@ import ( "github.com/containerd/containerd/errdefs" dockerreference "github.com/containerd/containerd/reference/docker" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/pkg/buildkitutil" "github.com/containerd/nerdctl/pkg/defaults" "github.com/containerd/nerdctl/pkg/platformutil" @@ -39,17 +42,17 @@ import ( "github.com/spf13/cobra" ) -func newBuildCommand() *cobra.Command { +func NewBuildCommand() *cobra.Command { var buildCommand = &cobra.Command{ Use: "build [flags] PATH", Short: "Build an image from a Dockerfile. Needs buildkitd to be running.", Long: `Build an image from a Dockerfile. Needs buildkitd to be running. If Dockerfile is not present and -f is not specified, it will look for Containerfile and build with it. `, - RunE: buildAction, + RunE: RunBuildAction, SilenceUsage: true, SilenceErrors: true, } - AddStringFlag(buildCommand, "buildkit-host", nil, defaults.BuildKitHost(), "BUILDKIT_HOST", "BuildKit address") + utils.AddStringFlag(buildCommand, "buildkit-host", nil, defaults.BuildKitHost(), "BUILDKIT_HOST", "BuildKit address") buildCommand.Flags().StringArrayP("tag", "t", nil, "Name and optionally a tag in the 'name:tag' format") buildCommand.Flags().StringP("file", "f", "", "Name of the Dockerfile") buildCommand.Flags().String("target", "", "Set the target build stage to build") @@ -67,7 +70,7 @@ If Dockerfile is not present and -f is not specified, it will look for Container // #region platform flags // platform is defined as StringSlice, not StringArray, to allow specifying "--platform=amd64,arm64" buildCommand.Flags().StringSlice("platform", []string{}, "Set target platform for build (e.g., \"amd64\", \"arm64\")") - buildCommand.RegisterFlagCompletionFunc("platform", shellCompletePlatforms) + buildCommand.RegisterFlagCompletionFunc("platform", completion.ShellCompletePlatforms) // #endregion buildCommand.Flags().Bool("ipfs", false, "Allow pulling base images from IPFS") @@ -77,7 +80,7 @@ If Dockerfile is not present and -f is not specified, it will look for Container return buildCommand } -func getBuildkitHost(cmd *cobra.Command) (string, error) { +func GetBuildkitHost(cmd *cobra.Command) (string, error) { if cmd.Flags().Changed("buildkit-host") || os.Getenv("BUILDKIT_HOST") != "" { // If address is explicitly specified, use it. buildkitHost, err := cmd.Flags().GetString("buildkit-host") @@ -125,14 +128,14 @@ func isImageSharable(buildkitHost string, namespace, uuid, snapshotter string, p return executor == "containerd" && containerdUUID == uuid && containerdNamespace == namespace && workerSnapshotter == snapshotter && len(platform) == 0, nil } -func buildAction(cmd *cobra.Command, args []string) error { +func RunBuildAction(cmd *cobra.Command, args []string) error { platform, err := cmd.Flags().GetStringSlice("platform") if err != nil { return err } platform = strutil.DedupeStrSlice(platform) - buildkitHost, err := getBuildkitHost(cmd) + buildkitHost, err := GetBuildkitHost(cmd) if err != nil { return err } @@ -151,7 +154,7 @@ func buildAction(cmd *cobra.Command, args []string) error { } if runIPFSRegistry { logrus.Infof("Ensuring IPFS registry is running") - nerdctlCmd, nerdctlArgs := globalFlags(cmd) + nerdctlCmd, nerdctlArgs := utils.GlobalFlags(cmd) out, err := exec.Command(nerdctlCmd, append(nerdctlArgs, "ipfs", "registry", "up")...).CombinedOutput() if err != nil { return fmt.Errorf("failed to start IPFS registry: %v: %v", string(out), err) @@ -190,7 +193,7 @@ func buildAction(cmd *cobra.Command, args []string) error { if err != nil { return err } - if err = loadImage(buildctlStdout, cmd, platMC, quiet); err != nil { + if err = utils.LoadImage(buildctlStdout, cmd, platMC, quiet); err != nil { return err } } @@ -212,7 +215,7 @@ func buildAction(cmd *cobra.Command, args []string) error { if len(tags) > 1 { logrus.Debug("Found more than 1 tag") - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return fmt.Errorf("unable to tag images: %s", err) } @@ -257,7 +260,7 @@ func generateBuildctlArgs(cmd *cobra.Command, buildkitHost string, platform, arg return "", nil, false, "", nil, nil, err } if output == "" { - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return "", nil, false, "", nil, nil, err } @@ -499,6 +502,17 @@ func generateBuildctlArgs(cmd *cobra.Command, buildkitHost string, platform, arg return buildctlBinary, buildctlArgs, needsLoading, metaFile, tags, cleanup, nil } +func CreateBuildContext(dockerfile string) (string, error) { + tmpDir, err := os.MkdirTemp("", "nerdctl-build-test") + if err != nil { + return "", err + } + if err = os.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644); err != nil { + return "", err + } + return tmpDir, nil +} + func getDigestFromMetaFile(path string) (string, error) { data, err := os.ReadFile(path) if err != nil { diff --git a/cmd/nerdctl/builder.go b/cmd/nerdctl/builder/builder.go similarity index 88% rename from cmd/nerdctl/builder.go rename to cmd/nerdctl/builder/builder.go index ba9d265ef8b..a0a3f1c7266 100644 --- a/cmd/nerdctl/builder.go +++ b/cmd/nerdctl/builder/builder.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package builder import ( "fmt" @@ -22,18 +22,22 @@ import ( "os/exec" "strings" + "github.com/containerd/nerdctl/cmd/nerdctl/build" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/utils" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" "github.com/containerd/nerdctl/pkg/buildkitutil" "github.com/containerd/nerdctl/pkg/defaults" "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) -func newBuilderCommand() *cobra.Command { +func NewBuilderCommand() *cobra.Command { var builderCommand = &cobra.Command{ - Annotations: map[string]string{Category: Management}, + Annotations: map[string]string{common.Category: common.Management}, Use: "builder", Short: "Manage builds", - RunE: unknownSubcommandAction, + RunE: completion.UnknownSubcommandAction, SilenceUsage: true, SilenceErrors: true, } @@ -55,12 +59,12 @@ func newBuilderPruneCommand() *cobra.Command { SilenceErrors: true, } - AddStringFlag(buildPruneCommand, "buildkit-host", nil, defaults.BuildKitHost(), "BUILDKIT_HOST", "BuildKit address") + utils.AddStringFlag(buildPruneCommand, "buildkit-host", nil, defaults.BuildKitHost(), "BUILDKIT_HOST", "BuildKit address") return buildPruneCommand } func builderPruneAction(cmd *cobra.Command, _ []string) error { - buildkitHost, err := getBuildkitHost(cmd) + buildkitHost, err := build.GetBuildkitHost(cmd) if err != nil { return err } @@ -82,7 +86,7 @@ func newBuilderDebugCommand() *cobra.Command { var buildDebugCommand = &cobra.Command{ Use: "debug", Short: shortHelp, - PreRunE: checkExperimental("`nerdctl builder debug`"), + PreRunE: utils.CheckExperimental("`nerdctl builder debug`"), RunE: builderDebugAction, SilenceUsage: true, SilenceErrors: true, diff --git a/cmd/nerdctl/client.go b/cmd/nerdctl/client/client.go similarity index 90% rename from cmd/nerdctl/client.go rename to cmd/nerdctl/client/client.go index ea7f90e26ac..2c36607b29b 100644 --- a/cmd/nerdctl/client.go +++ b/cmd/nerdctl/client/client.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package client import ( "context" @@ -35,7 +35,7 @@ import ( "github.com/opencontainers/go-digest" ) -func newClient(cmd *cobra.Command, opts ...containerd.ClientOpt) (*containerd.Client, context.Context, context.CancelFunc, error) { +func NewClient(cmd *cobra.Command, opts ...containerd.ClientOpt) (*containerd.Client, context.Context, context.CancelFunc, error) { ctx := cmd.Context() namespace, err := cmd.Flags().GetString("namespace") if err != nil { @@ -65,7 +65,7 @@ func newClient(cmd *cobra.Command, opts ...containerd.ClientOpt) (*containerd.Cl return client, ctx, cancel, nil } -func newClientWithPlatform(cmd *cobra.Command, platform string, clientOpts ...containerd.ClientOpt) (*containerd.Client, context.Context, context.CancelFunc, error) { +func NewClientWithPlatform(cmd *cobra.Command, platform string, clientOpts ...containerd.ClientOpt) (*containerd.Client, context.Context, context.CancelFunc, error) { if platform != "" { if canExec, canExecErr := platformutil.CanExecProbably(platform); !canExec { warn := fmt.Sprintf("Platform %q seems incompatible with the host platform %q. If you see \"exec format error\", see https://github.com/containerd/nerdctl/blob/main/docs/multi-platform.md", @@ -83,13 +83,13 @@ func newClientWithPlatform(cmd *cobra.Command, platform string, clientOpts ...co platformM := platforms.Only(platformParsed) clientOpts = append(clientOpts, containerd.WithDefaultPlatform(platformM)) } - return newClient(cmd, clientOpts...) + return NewClient(cmd, clientOpts...) } -// getDataStore returns a string like "/var/lib/nerdctl/1935db59". +// GetDataStore returns a string like "/var/lib/nerdctl/1935db59". // "1935db9" is from `$(echo -n "/run/containerd/containerd.sock" | sha256sum | cut -c1-8)` // on Windows it will return "%PROGRAMFILES%/nerdctl/1935db59" -func getDataStore(cmd *cobra.Command) (string, error) { +func GetDataStore(cmd *cobra.Command) (string, error) { dataRoot, err := cmd.Flags().GetString("data-root") if err != nil { return "", err @@ -101,7 +101,7 @@ func getDataStore(cmd *cobra.Command) (string, error) { if err != nil { return "", err } - addrHash, err := getAddrHash(address) + addrHash, err := GetAddrHash(address) if err != nil { return "", err } @@ -112,7 +112,7 @@ func getDataStore(cmd *cobra.Command) (string, error) { return dataStore, nil } -func getAddrHash(addr string) (string, error) { +func GetAddrHash(addr string) (string, error) { const addrHashLen = 8 if runtime.GOOS != "windows" { diff --git a/cmd/nerdctl/completion.go b/cmd/nerdctl/completion/completion.go similarity index 51% rename from cmd/nerdctl/completion.go rename to cmd/nerdctl/completion/completion.go index d86ce014696..b5afa243b33 100644 --- a/cmd/nerdctl/completion.go +++ b/cmd/nerdctl/completion/completion.go @@ -14,20 +14,24 @@ limitations under the License. */ -package main +package completion import ( "context" + "errors" + "fmt" "time" "github.com/containerd/containerd" + "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/volume" "github.com/containerd/nerdctl/pkg/labels" "github.com/containerd/nerdctl/pkg/netutil" "github.com/spf13/cobra" ) -func shellCompleteImageNames(cmd *cobra.Command) ([]string, cobra.ShellCompDirective) { - client, ctx, cancel, err := newClient(cmd) +func ShellCompleteImageNames(cmd *cobra.Command) ([]string, cobra.ShellCompDirective) { + client, ctx, cancel, err := client.NewClient(cmd) if err != nil { return nil, cobra.ShellCompDirectiveError } @@ -45,8 +49,8 @@ func shellCompleteImageNames(cmd *cobra.Command) ([]string, cobra.ShellCompDirec return candidates, cobra.ShellCompDirectiveNoFileComp } -func shellCompleteContainerNames(cmd *cobra.Command, filterFunc func(containerd.ProcessStatus) bool) ([]string, cobra.ShellCompDirective) { - client, ctx, cancel, err := newClient(cmd) +func ShellCompleteContainerNames(cmd *cobra.Command, filterFunc func(containerd.ProcessStatus) bool) ([]string, cobra.ShellCompDirective) { + client, ctx, cancel, err := client.NewClient(cmd) if err != nil { return nil, cobra.ShellCompDirectiveError } @@ -89,8 +93,8 @@ func shellCompleteContainerNames(cmd *cobra.Command, filterFunc func(containerd. return candidates, cobra.ShellCompDirectiveNoFileComp } -// shellCompleteNetworkNames includes {"bridge","host","none"} -func shellCompleteNetworkNames(cmd *cobra.Command, exclude []string) ([]string, cobra.ShellCompDirective) { +// ShellCompleteNetworkNames includes {"bridge","host","none"} +func ShellCompleteNetworkNames(cmd *cobra.Command, exclude []string) ([]string, cobra.ShellCompDirective) { excludeMap := make(map[string]struct{}, len(exclude)) for _, ex := range exclude { excludeMap[ex] = struct{}{} @@ -126,8 +130,8 @@ func shellCompleteNetworkNames(cmd *cobra.Command, exclude []string) ([]string, return candidates, cobra.ShellCompDirectiveNoFileComp } -func shellCompleteVolumeNames(cmd *cobra.Command) ([]string, cobra.ShellCompDirective) { - vols, err := getVolumes(cmd) +func ShellCompleteVolumeNames(cmd *cobra.Command) ([]string, cobra.ShellCompDirective) { + vols, err := volume.GetVolumes(cmd) if err != nil { return nil, cobra.ShellCompDirectiveError } @@ -138,7 +142,7 @@ func shellCompleteVolumeNames(cmd *cobra.Command) ([]string, cobra.ShellCompDire return candidates, cobra.ShellCompDirectiveNoFileComp } -func shellCompletePlatforms(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { +func ShellCompletePlatforms(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { candidates := []string{ "amd64", "arm64", @@ -151,3 +155,75 @@ func shellCompletePlatforms(cmd *cobra.Command, args []string, toComplete string } return candidates, cobra.ShellCompDirectiveNoFileComp } + +func TopShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + // show running container names + statusFilterFn := func(st containerd.ProcessStatus) bool { + return st == containerd.Running + } + return ShellCompleteContainerNames(cmd, statusFilterFn) +} + +func PauseShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + // show running container names + statusFilterFn := func(st containerd.ProcessStatus) bool { + return st == containerd.Running + } + return ShellCompleteContainerNames(cmd, statusFilterFn) +} + +func UnpauseShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + // show paused container names + statusFilterFn := func(st containerd.ProcessStatus) bool { + return st == containerd.Paused + } + return ShellCompleteContainerNames(cmd, statusFilterFn) +} + +func LogsShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + // show container names (TODO: only show Containers with logs) + return ShellCompleteContainerNames(cmd, nil) +} + +func StartShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + // show non-running container names + statusFilterFn := func(st containerd.ProcessStatus) bool { + return st != containerd.Running && st != containerd.Unknown + } + return ShellCompleteContainerNames(cmd, statusFilterFn) +} + +func StatsShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + // show running container names + statusFilterFn := func(st containerd.ProcessStatus) bool { + return st == containerd.Running + } + return ShellCompleteContainerNames(cmd, statusFilterFn) +} + +func StopShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + // show non-stopped container names + statusFilterFn := func(st containerd.ProcessStatus) bool { + return st != containerd.Stopped && st != containerd.Created && st != containerd.Unknown + } + return ShellCompleteContainerNames(cmd, statusFilterFn) +} + +// UnknownSubcommandAction is needed to let `nerdctl system non-existent-command` fail +// https://github.com/containerd/nerdctl/issues/487 +// +// Ideally this should be implemented in Cobra itself. +func UnknownSubcommandAction(cmd *cobra.Command, args []string) error { + if len(args) == 0 { + return cmd.Help() + } + // The output mimics https://github.com/spf13/cobra/blob/v1.2.1/command.go#L647-L662 + msg := fmt.Sprintf("unknown subcommand %q for %q", args[0], cmd.Name()) + if suggestions := cmd.SuggestionsFor(args[0]); len(suggestions) > 0 { + msg += "\n\nDid you mean this?\n" + for _, s := range suggestions { + msg += fmt.Sprintf("\t%v\n", s) + } + } + return errors.New(msg) +} diff --git a/cmd/nerdctl/completion/completion_freebsd.go b/cmd/nerdctl/completion/completion_freebsd.go new file mode 100644 index 00000000000..7745811be05 --- /dev/null +++ b/cmd/nerdctl/completion/completion_freebsd.go @@ -0,0 +1,32 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package completion + +import "github.com/spf13/cobra" + +func CapShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + candidates := []string{} + return candidates, cobra.ShellCompDirectiveNoFileComp +} + +func RunShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return nil, cobra.ShellCompDirectiveNoFileComp +} + +func ShellCompleteCgroupManagerNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return nil, cobra.ShellCompDirectiveNoFileComp +} diff --git a/cmd/nerdctl/completion/completion_linux.go b/cmd/nerdctl/completion/completion_linux.go new file mode 100644 index 00000000000..65d75e3dcc9 --- /dev/null +++ b/cmd/nerdctl/completion/completion_linux.go @@ -0,0 +1,71 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package completion + +import ( + "strings" + + "github.com/containerd/containerd/pkg/cap" + "github.com/containerd/nerdctl/pkg/apparmorutil" + "github.com/containerd/nerdctl/pkg/defaults" + "github.com/containerd/nerdctl/pkg/rootlessutil" + "github.com/spf13/cobra" +) + +func ShellCompleteApparmorProfiles(cmd *cobra.Command) ([]string, cobra.ShellCompDirective) { + profiles, err := apparmorutil.Profiles() + if err != nil { + return nil, cobra.ShellCompDirectiveError + } + var names []string // nolint: prealloc + for _, f := range profiles { + names = append(names, f.Name) + } + return names, cobra.ShellCompDirectiveNoFileComp +} + +func CapShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + candidates := []string{} + for _, c := range cap.Known() { + // "CAP_SYS_ADMIN" -> "sys_admin" + s := strings.ToLower(strings.TrimPrefix(c, "CAP_")) + candidates = append(candidates, s) + } + return candidates, cobra.ShellCompDirectiveNoFileComp +} + +func RunShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + if len(args) == 0 { + return ShellCompleteImageNames(cmd) + } + return nil, cobra.ShellCompDirectiveNoFileComp +} + +func ShellCompleteCgroupManagerNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + candidates := []string{"cgroupfs"} + if defaults.IsSystemdAvailable() { + candidates = append(candidates, "systemd") + } + if rootlessutil.IsRootless() { + candidates = append(candidates, "none") + } + return candidates, cobra.ShellCompDirectiveNoFileComp +} + +func ApparmorUnloadShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return ShellCompleteApparmorProfiles(cmd) +} diff --git a/cmd/nerdctl/completion/completion_unix.go b/cmd/nerdctl/completion/completion_unix.go new file mode 100644 index 00000000000..d6f725eaf42 --- /dev/null +++ b/cmd/nerdctl/completion/completion_unix.go @@ -0,0 +1,68 @@ +//go:build freebsd || linux + +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package completion + +import ( + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/pkg/infoutil" + "github.com/containerd/nerdctl/pkg/rootlessutil" + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" +) + +func ShellCompleteNamespaceNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + if rootlessutil.IsRootlessParent() { + _ = rootlessutil.ParentMain() + return nil, cobra.ShellCompDirectiveNoFileComp + } + + client, ctx, cancel, err := nerdClient.NewClient(cmd) + if err != nil { + return nil, cobra.ShellCompDirectiveError + } + defer cancel() + nsService := client.NamespaceService() + nsList, err := nsService.List(ctx) + if err != nil { + logrus.Warn(err) + return nil, cobra.ShellCompDirectiveError + } + var candidates []string + candidates = append(candidates, nsList...) + return candidates, cobra.ShellCompDirectiveNoFileComp +} + +func ShellCompleteSnapshotterNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + if rootlessutil.IsRootlessParent() { + _ = rootlessutil.ParentMain() + return nil, cobra.ShellCompDirectiveNoFileComp + } + client, ctx, cancel, err := nerdClient.NewClient(cmd) + if err != nil { + return nil, cobra.ShellCompDirectiveError + } + defer cancel() + snapshotterPlugins, err := infoutil.GetSnapshotterNames(ctx, client.IntrospectionService()) + if err != nil { + return nil, cobra.ShellCompDirectiveError + } + var candidates []string + candidates = append(candidates, snapshotterPlugins...) + return candidates, cobra.ShellCompDirectiveNoFileComp +} diff --git a/cmd/nerdctl/completion/completion_windows.go b/cmd/nerdctl/completion/completion_windows.go new file mode 100644 index 00000000000..0cbbf5c546c --- /dev/null +++ b/cmd/nerdctl/completion/completion_windows.go @@ -0,0 +1,40 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package completion + +import "github.com/spf13/cobra" + +func CapShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + candidates := []string{} + return candidates, cobra.ShellCompDirectiveNoFileComp +} + +func RunShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return nil, cobra.ShellCompDirectiveNoFileComp +} + +func ShellCompleteNamespaceNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return nil, cobra.ShellCompDirectiveNoFileComp +} + +func ShellCompleteSnapshotterNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return nil, cobra.ShellCompDirectiveNoFileComp +} + +func ShellCompleteCgroupManagerNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return nil, cobra.ShellCompDirectiveNoFileComp +} diff --git a/cmd/nerdctl/compose.go b/cmd/nerdctl/compose/compose.go similarity index 93% rename from cmd/nerdctl/compose.go rename to cmd/nerdctl/compose/compose.go index bf78a49dc63..a51e971cfb9 100644 --- a/cmd/nerdctl/compose.go +++ b/cmd/nerdctl/compose/compose.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "context" @@ -24,6 +24,9 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/platforms" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/utils" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/volume" "github.com/containerd/nerdctl/pkg/composer" "github.com/containerd/nerdctl/pkg/composer/serviceparser" "github.com/containerd/nerdctl/pkg/cosignutil" @@ -38,17 +41,17 @@ import ( "github.com/spf13/cobra" ) -func newComposeCommand() *cobra.Command { +func NewComposeCommand() *cobra.Command { var composeCommand = &cobra.Command{ Use: "compose [flags] COMMAND", Short: "Compose", - RunE: unknownSubcommandAction, + RunE: completion.UnknownSubcommandAction, SilenceUsage: true, SilenceErrors: true, TraverseChildren: true, // required for global short hands like -f } // `-f` is a nonPersistentAlias, as it conflicts with `nerdctl compose logs --follow` - AddPersistentStringArrayFlag(composeCommand, "file", nil, []string{"f"}, nil, "", "Specify an alternate compose file") + utils.AddPersistentStringArrayFlag(composeCommand, "file", nil, []string{"f"}, nil, "", "Specify an alternate compose file") composeCommand.PersistentFlags().String("project-directory", "", "Specify an alternate working directory") composeCommand.PersistentFlags().StringP("project-name", "p", "", "Specify an alternate project name") composeCommand.PersistentFlags().String("env-file", "", "Specify an alternate environment file") @@ -80,7 +83,7 @@ func newComposeCommand() *cobra.Command { } func getComposer(cmd *cobra.Command, client *containerd.Client) (*composer.Composer, error) { - nerdctlCmd, nerdctlArgs := globalFlags(cmd) + nerdctlCmd, nerdctlArgs := utils.GlobalFlags(cmd) projectDirectory, err := cmd.Flags().GetString("project-directory") if err != nil { return nil, err @@ -155,7 +158,7 @@ func getComposer(cmd *cobra.Command, client *containerd.Client) (*composer.Compo return false, nil } - volStore, err := getVolumeStore(cmd) + volStore, err := volume.GetVolumeStore(cmd) if err != nil { return nil, err } diff --git a/cmd/nerdctl/compose_build.go b/cmd/nerdctl/compose/compose_build.go similarity index 94% rename from cmd/nerdctl/compose_build.go rename to cmd/nerdctl/compose/compose_build.go index b08032581b5..03763388e18 100644 --- a/cmd/nerdctl/compose_build.go +++ b/cmd/nerdctl/compose/compose_build.go @@ -14,9 +14,10 @@ limitations under the License. */ -package main +package compose import ( + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/pkg/composer" "github.com/spf13/cobra" ) @@ -56,7 +57,7 @@ func composeBuildAction(cmd *cobra.Command, args []string) error { return err } - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose_config.go b/cmd/nerdctl/compose/compose_config.go similarity index 94% rename from cmd/nerdctl/compose_config.go rename to cmd/nerdctl/compose/compose_config.go index 17fa15746e6..f64dfd09dcf 100644 --- a/cmd/nerdctl/compose_config.go +++ b/cmd/nerdctl/compose/compose_config.go @@ -14,11 +14,12 @@ limitations under the License. */ -package main +package compose import ( "fmt" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/pkg/composer" "github.com/spf13/cobra" ) @@ -63,7 +64,7 @@ func composeConfigAction(cmd *cobra.Command, args []string) error { return err } - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose_down.go b/cmd/nerdctl/compose/compose_down.go similarity index 85% rename from cmd/nerdctl/compose_down.go rename to cmd/nerdctl/compose/compose_down.go index b779ff13ea7..7e5d6e3ad55 100644 --- a/cmd/nerdctl/compose_down.go +++ b/cmd/nerdctl/compose/compose_down.go @@ -14,9 +14,10 @@ limitations under the License. */ -package main +package compose import ( + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/pkg/composer" "github.com/spf13/cobra" ) @@ -30,7 +31,7 @@ func newComposeDownCommand() *cobra.Command { SilenceUsage: true, SilenceErrors: true, } - composeDownCommand.Flags().BoolP("volumes", "v", false, "Remove named volumes declared in the `volumes` section of the Compose file and anonymous volumes attached to containers.") + composeDownCommand.Flags().BoolP("volumes", "v", false, "Remove named volume declared in the `volume` section of the Compose file and anonymous volume attached to containers.") return composeDownCommand } @@ -39,7 +40,7 @@ func composeDownAction(cmd *cobra.Command, args []string) error { if err != nil { return err } - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose_exec.go b/cmd/nerdctl/compose/compose_exec.go similarity index 96% rename from cmd/nerdctl/compose_exec.go rename to cmd/nerdctl/compose/compose_exec.go index 0dbcd0ebaf3..1a8ef882311 100644 --- a/cmd/nerdctl/compose_exec.go +++ b/cmd/nerdctl/compose/compose_exec.go @@ -14,11 +14,12 @@ limitations under the License. */ -package main +package compose import ( "errors" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/pkg/composer" "github.com/spf13/cobra" ) @@ -94,7 +95,7 @@ func composeExecAction(cmd *cobra.Command, args []string) error { return errors.New("currently flag -t and -d cannot be specified together (FIXME)") } - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose_images.go b/cmd/nerdctl/compose/compose_images.go similarity index 94% rename from cmd/nerdctl/compose_images.go rename to cmd/nerdctl/compose/compose_images.go index e5b52cda1a1..3724f1146dc 100644 --- a/cmd/nerdctl/compose_images.go +++ b/cmd/nerdctl/compose/compose_images.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "context" @@ -25,6 +25,8 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/pkg/progress" "github.com/containerd/containerd/snapshots" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/pkg/imgutil" "github.com/containerd/nerdctl/pkg/labels" "github.com/containerd/nerdctl/pkg/strutil" @@ -51,7 +53,7 @@ func composeImagesAction(cmd *cobra.Command, args []string) error { return err } - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } @@ -131,7 +133,7 @@ func printComposeImages(ctx context.Context, cmd *cobra.Command, containers []co return err } - size, err := unpackedImageSize(ctx, sn, image) + size, err := utils.UnpackedImageSize(ctx, sn, image) if err != nil { return err } diff --git a/cmd/nerdctl/compose_kill.go b/cmd/nerdctl/compose/compose_kill.go similarity index 91% rename from cmd/nerdctl/compose_kill.go rename to cmd/nerdctl/compose/compose_kill.go index 6ab4d152d87..14920d18d0c 100644 --- a/cmd/nerdctl/compose_kill.go +++ b/cmd/nerdctl/compose/compose_kill.go @@ -14,9 +14,10 @@ limitations under the License. */ -package main +package compose import ( + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/pkg/composer" "github.com/spf13/cobra" ) @@ -38,7 +39,7 @@ func composeKillAction(cmd *cobra.Command, args []string) error { if err != nil { return err } - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose_logs.go b/cmd/nerdctl/compose/compose_logs.go similarity index 94% rename from cmd/nerdctl/compose_logs.go rename to cmd/nerdctl/compose/compose_logs.go index 204138dcb39..2f148c46099 100644 --- a/cmd/nerdctl/compose_logs.go +++ b/cmd/nerdctl/compose/compose_logs.go @@ -14,9 +14,10 @@ limitations under the License. */ -package main +package compose import ( + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/pkg/composer" "github.com/spf13/cobra" ) @@ -59,7 +60,7 @@ func composeLogsAction(cmd *cobra.Command, args []string) error { return err } - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose_pause.go b/cmd/nerdctl/compose/compose_pause.go similarity index 89% rename from cmd/nerdctl/compose_pause.go rename to cmd/nerdctl/compose/compose_pause.go index 031746252cc..d37b3a1db02 100644 --- a/cmd/nerdctl/compose_pause.go +++ b/cmd/nerdctl/compose/compose_pause.go @@ -14,13 +14,15 @@ limitations under the License. */ -package main +package compose import ( "fmt" "sync" "github.com/containerd/containerd" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/pkg/labels" "github.com/spf13/cobra" "golang.org/x/sync/errgroup" @@ -39,7 +41,7 @@ func newComposePauseCommand() *cobra.Command { } func composePauseAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } @@ -65,7 +67,7 @@ func composePauseAction(cmd *cobra.Command, args []string) error { for _, c := range containers { c := c eg.Go(func() error { - if err := pauseContainer(ctx, client, c.ID()); err != nil { + if err := utils.PauseContainer(ctx, client, c.ID()); err != nil { return err } info, err := c.Info(ctx, containerd.WithoutRefreshedMetadata) @@ -97,7 +99,7 @@ func newComposeUnpauseCommand() *cobra.Command { } func composeUnpauseAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } @@ -123,7 +125,7 @@ func composeUnpauseAction(cmd *cobra.Command, args []string) error { for _, c := range containers { c := c eg.Go(func() error { - if err := unpauseContainer(ctx, client, c.ID()); err != nil { + if err := utils.UnpauseContainer(ctx, client, c.ID()); err != nil { return err } info, err := c.Info(ctx, containerd.WithoutRefreshedMetadata) diff --git a/cmd/nerdctl/compose_port.go b/cmd/nerdctl/compose/compose_port.go similarity index 94% rename from cmd/nerdctl/compose_port.go rename to cmd/nerdctl/compose/compose_port.go index e651eeaf6f5..e30b761be22 100644 --- a/cmd/nerdctl/compose_port.go +++ b/cmd/nerdctl/compose/compose_port.go @@ -14,12 +14,13 @@ limitations under the License. */ -package main +package compose import ( "fmt" "strconv" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/pkg/composer" "github.com/spf13/cobra" ) @@ -66,7 +67,7 @@ func composePortAction(cmd *cobra.Command, args []string) error { return fmt.Errorf("unexpected port: %d", port) } - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose_ps.go b/cmd/nerdctl/compose/compose_ps.go similarity index 85% rename from cmd/nerdctl/compose_ps.go rename to cmd/nerdctl/compose/compose_ps.go index f5fd69cbc3c..ead686a9d83 100644 --- a/cmd/nerdctl/compose_ps.go +++ b/cmd/nerdctl/compose/compose_ps.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "context" @@ -24,6 +24,7 @@ import ( "github.com/containerd/containerd" gocni "github.com/containerd/go-cni" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/pkg/formatter" "github.com/containerd/nerdctl/pkg/labels" "github.com/containerd/nerdctl/pkg/portutil" @@ -44,7 +45,7 @@ func newComposePsCommand() *cobra.Command { return composePsCommand } -type composeContainerPrintable struct { +type ContainerPrintable struct { ID string Name string Command string @@ -68,7 +69,7 @@ func composePsAction(cmd *cobra.Command, args []string) error { return fmt.Errorf("unsupported format %s, supported formats are: [json]", format) } - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } @@ -87,17 +88,17 @@ func composePsAction(cmd *cobra.Command, args []string) error { return err } - containersPrintable := make([]composeContainerPrintable, len(containers)) + containersPrintable := make([]ContainerPrintable, len(containers)) eg, ctx := errgroup.WithContext(ctx) for i, container := range containers { i, container := i, container eg.Go(func() error { - var p composeContainerPrintable + var p ContainerPrintable var err error if format == "json" { - p, err = composeContainerPrintableJSON(ctx, container) + p, err = ContainerPrintableJSON(ctx, container) } else { - p, err = composeContainerPrintableTab(ctx, container) + p, err = ContainerPrintableTab(ctx, container) } if err != nil { return err @@ -137,23 +138,23 @@ func composePsAction(cmd *cobra.Command, args []string) error { return w.Flush() } -// composeContainerPrintableTab constructs composeContainerPrintable with fields +// ContainerPrintableTab constructs ContainerPrintable with fields // only for console output. -func composeContainerPrintableTab(ctx context.Context, container containerd.Container) (composeContainerPrintable, error) { +func ContainerPrintableTab(ctx context.Context, container containerd.Container) (ContainerPrintable, error) { info, err := container.Info(ctx, containerd.WithoutRefreshedMetadata) if err != nil { - return composeContainerPrintable{}, err + return ContainerPrintable{}, err } spec, err := container.Spec(ctx) if err != nil { - return composeContainerPrintable{}, err + return ContainerPrintable{}, err } status := formatter.ContainerStatus(ctx, container) if status == "Up" { status = "running" // corresponds to Docker Compose v2.0.1 } - return composeContainerPrintable{ + return ContainerPrintable{ Name: info.Labels[labels.Name], Command: formatter.InspectContainerCommandTrunc(spec), Service: info.Labels[labels.ComposeService], @@ -162,16 +163,16 @@ func composeContainerPrintableTab(ctx context.Context, container containerd.Cont }, nil } -// composeContainerPrintableTab constructs composeContainerPrintable with fields +// ContainerPrintableTab constructs ContainerPrintable with fields // only for json output and compatible docker output. -func composeContainerPrintableJSON(ctx context.Context, container containerd.Container) (composeContainerPrintable, error) { +func ContainerPrintableJSON(ctx context.Context, container containerd.Container) (ContainerPrintable, error) { info, err := container.Info(ctx, containerd.WithoutRefreshedMetadata) if err != nil { - return composeContainerPrintable{}, err + return ContainerPrintable{}, err } spec, err := container.Spec(ctx) if err != nil { - return composeContainerPrintable{}, err + return ContainerPrintable{}, err } var ( @@ -189,7 +190,7 @@ func composeContainerPrintableJSON(ctx context.Context, container containerd.Con state = string(containerd.Unknown) } - return composeContainerPrintable{ + return ContainerPrintable{ ID: container.ID(), Name: info.Labels[labels.Name], Command: formatter.InspectContainerCommand(spec, false, false), diff --git a/cmd/nerdctl/compose_pull.go b/cmd/nerdctl/compose/compose_pull.go similarity index 91% rename from cmd/nerdctl/compose_pull.go rename to cmd/nerdctl/compose/compose_pull.go index 8976477370f..cda660c0003 100644 --- a/cmd/nerdctl/compose_pull.go +++ b/cmd/nerdctl/compose/compose_pull.go @@ -14,9 +14,10 @@ limitations under the License. */ -package main +package compose import ( + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/pkg/composer" "github.com/spf13/cobra" ) @@ -34,7 +35,7 @@ func newComposePullCommand() *cobra.Command { } func composePullAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose_push.go b/cmd/nerdctl/compose/compose_push.go similarity index 90% rename from cmd/nerdctl/compose_push.go rename to cmd/nerdctl/compose/compose_push.go index 36a2f4f2aae..9fe991e973b 100644 --- a/cmd/nerdctl/compose_push.go +++ b/cmd/nerdctl/compose/compose_push.go @@ -14,9 +14,10 @@ limitations under the License. */ -package main +package compose import ( + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/pkg/composer" "github.com/spf13/cobra" ) @@ -33,7 +34,7 @@ func newComposePushCommand() *cobra.Command { } func composePushAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose_restart.go b/cmd/nerdctl/compose/compose_restart.go similarity index 91% rename from cmd/nerdctl/compose_restart.go rename to cmd/nerdctl/compose/compose_restart.go index 7f1e3e633e1..f6880fdca0d 100644 --- a/cmd/nerdctl/compose_restart.go +++ b/cmd/nerdctl/compose/compose_restart.go @@ -14,9 +14,10 @@ limitations under the License. */ -package main +package compose import ( + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/pkg/composer" "github.com/spf13/cobra" ) @@ -44,7 +45,7 @@ func composeRestartAction(cmd *cobra.Command, args []string) error { opt.Timeout = &timeValue } - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose_rm.go b/cmd/nerdctl/compose/compose_rm.go similarity index 94% rename from cmd/nerdctl/compose_rm.go rename to cmd/nerdctl/compose/compose_rm.go index 1f718b29079..6fe62b6b968 100644 --- a/cmd/nerdctl/compose_rm.go +++ b/cmd/nerdctl/compose/compose_rm.go @@ -14,12 +14,13 @@ limitations under the License. */ -package main +package compose import ( "fmt" "strings" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/pkg/composer" "github.com/spf13/cobra" ) @@ -68,7 +69,7 @@ func composeRemoveAction(cmd *cobra.Command, args []string) error { return err } - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose_run.go b/cmd/nerdctl/compose/compose_run.go similarity index 98% rename from cmd/nerdctl/compose_run.go rename to cmd/nerdctl/compose/compose_run.go index 43413b7b69d..55f193d1167 100644 --- a/cmd/nerdctl/compose_run.go +++ b/cmd/nerdctl/compose/compose_run.go @@ -14,12 +14,13 @@ limitations under the License. */ -package main +package compose import ( "errors" "fmt" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/pkg/composer" "github.com/spf13/cobra" ) @@ -167,7 +168,7 @@ func composeRunAction(cmd *cobra.Command, args []string) error { return errors.New("currently flag -t and -d cannot be specified together (FIXME)") } - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose_stop.go b/cmd/nerdctl/compose/compose_stop.go similarity index 91% rename from cmd/nerdctl/compose_stop.go rename to cmd/nerdctl/compose/compose_stop.go index 09d2a1943c8..5526baffbc8 100644 --- a/cmd/nerdctl/compose_stop.go +++ b/cmd/nerdctl/compose/compose_stop.go @@ -14,9 +14,10 @@ limitations under the License. */ -package main +package compose import ( + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/pkg/composer" "github.com/spf13/cobra" ) @@ -44,7 +45,7 @@ func composeStopAction(cmd *cobra.Command, args []string) error { opt.Timeout = &timeValue } - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose_top.go b/cmd/nerdctl/compose/compose_top.go similarity index 88% rename from cmd/nerdctl/compose_top.go rename to cmd/nerdctl/compose/compose_top.go index e0b9d6fd4be..4e0ef0e86c2 100644 --- a/cmd/nerdctl/compose_top.go +++ b/cmd/nerdctl/compose/compose_top.go @@ -14,12 +14,14 @@ limitations under the License. */ -package main +package compose import ( "fmt" "github.com/containerd/containerd" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/pkg/labels" "github.com/spf13/cobra" ) @@ -37,7 +39,7 @@ func newComposeTopCommand() *cobra.Command { } func composeTopAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } @@ -72,7 +74,7 @@ func composeTopAction(cmd *cobra.Command, args []string) error { } fmt.Fprintf(stdout, "%s\n", info.Labels[labels.Name]) // `compose ps` uses empty ps args - err = containerTop(ctx, cmd, client, c.ID(), "") + err = utils.ContainerTop(ctx, cmd, client, c.ID(), "") if err != nil { return err } diff --git a/cmd/nerdctl/compose_up.go b/cmd/nerdctl/compose/compose_up.go similarity index 96% rename from cmd/nerdctl/compose_up.go rename to cmd/nerdctl/compose/compose_up.go index 8863711e2a7..a367c2aed7b 100644 --- a/cmd/nerdctl/compose_up.go +++ b/cmd/nerdctl/compose/compose_up.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "errors" @@ -22,6 +22,7 @@ import ( "strconv" "strings" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/pkg/composer" "github.com/spf13/cobra" ) @@ -99,7 +100,7 @@ func composeUpAction(cmd *cobra.Command, services []string) error { scale[parts[0]] = uint64(replicas) } - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose_version.go b/cmd/nerdctl/compose/compose_version.go similarity index 99% rename from cmd/nerdctl/compose_version.go rename to cmd/nerdctl/compose/compose_version.go index dbea1318ec6..48316a3d117 100644 --- a/cmd/nerdctl/compose_version.go +++ b/cmd/nerdctl/compose/compose_version.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "fmt" diff --git a/cmd/nerdctl/container.go b/cmd/nerdctl/container.go deleted file mode 100644 index 6c0a763f14b..00000000000 --- a/cmd/nerdctl/container.go +++ /dev/null @@ -1,62 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package main - -import ( - "github.com/spf13/cobra" -) - -func newContainerCommand() *cobra.Command { - containerCommand := &cobra.Command{ - Annotations: map[string]string{Category: Management}, - Use: "container", - Short: "Manage containers", - RunE: unknownSubcommandAction, - SilenceUsage: true, - SilenceErrors: true, - } - containerCommand.AddCommand( - newCreateCommand(), - newRunCommand(), - newUpdateCommand(), - newExecCommand(), - containerLsCommand(), - newContainerInspectCommand(), - newLogsCommand(), - newPortCommand(), - newRmCommand(), - newStopCommand(), - newStartCommand(), - newRestartCommand(), - newKillCommand(), - newPauseCommand(), - newWaitCommand(), - newUnpauseCommand(), - newCommitCommand(), - newRenameCommand(), - newContainerPruneCommand(), - ) - addCpCommand(containerCommand) - return containerCommand -} - -func containerLsCommand() *cobra.Command { - x := newPsCommand() - x.Use = "ls" - x.Aliases = []string{"list"} - return x -} diff --git a/cmd/nerdctl/commit.go b/cmd/nerdctl/container/commit.go similarity index 92% rename from cmd/nerdctl/commit.go rename to cmd/nerdctl/container/commit.go index 7db1853edb2..e3d9a330e74 100644 --- a/cmd/nerdctl/commit.go +++ b/cmd/nerdctl/container/commit.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "context" @@ -22,6 +22,9 @@ import ( "fmt" "strings" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" "github.com/containerd/nerdctl/pkg/imgutil/commit" "github.com/containerd/nerdctl/pkg/referenceutil" @@ -29,11 +32,11 @@ import ( "github.com/spf13/cobra" ) -func newCommitCommand() *cobra.Command { +func NewCommitCommand() *cobra.Command { var commitCommand = &cobra.Command{ Use: "commit [flags] CONTAINER REPOSITORY[:TAG]", Short: "Create a new image from a container's changes", - Args: IsExactArgs(2), + Args: utils.IsExactArgs(2), RunE: commitAction, ValidArgsFunction: commitShellComplete, SilenceUsage: true, @@ -52,7 +55,7 @@ func commitAction(cmd *cobra.Command, args []string) error { return err } - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } @@ -162,7 +165,7 @@ func newCommitOpts(cmd *cobra.Command, args []string) (*commit.Opts, error) { func commitShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if len(args) == 0 { - return shellCompleteContainerNames(cmd, nil) + return completion.ShellCompleteContainerNames(cmd, nil) } return nil, cobra.ShellCompDirectiveNoFileComp } diff --git a/cmd/nerdctl/container/container.go b/cmd/nerdctl/container/container.go new file mode 100644 index 00000000000..1db5c57f2f5 --- /dev/null +++ b/cmd/nerdctl/container/container.go @@ -0,0 +1,67 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package container + +import ( + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/container/cp" + "github.com/containerd/nerdctl/cmd/nerdctl/container/exec" + "github.com/containerd/nerdctl/cmd/nerdctl/ps" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" + "github.com/spf13/cobra" +) + +func NewContainerCommand() *cobra.Command { + containerCommand := &cobra.Command{ + Annotations: map[string]string{common.Category: common.Management}, + Use: "container", + Short: "Manage Containers", + RunE: completion.UnknownSubcommandAction, + SilenceUsage: true, + SilenceErrors: true, + } + containerCommand.AddCommand( + NewCreateCommand(), + NewRunCommand(), + NewUpdateCommand(), + exec.NewExecCommand(), + LsCommand(), + NewContainerInspectCommand(), + NewLogsCommand(), + NewPortCommand(), + NewRmCommand(), + NewStopCommand(), + NewStartCommand(), + NewRestartCommand(), + NewKillCommand(), + NewPauseCommand(), + NewWaitCommand(), + NewUnpauseCommand(), + NewCommitCommand(), + NewRenameCommand(), + NewContainerPruneCommand(), + ) + cp.AddCpCommand(containerCommand) + return containerCommand +} + +func LsCommand() *cobra.Command { + x := ps.NewPsCommand() + x.Use = "ls" + x.Aliases = []string{"list"} + return x +} diff --git a/cmd/nerdctl/container_inspect.go b/cmd/nerdctl/container/container_inspect.go similarity index 87% rename from cmd/nerdctl/container_inspect.go rename to cmd/nerdctl/container/container_inspect.go index 8580af92130..38d79882bbd 100644 --- a/cmd/nerdctl/container_inspect.go +++ b/cmd/nerdctl/container/container_inspect.go @@ -14,13 +14,16 @@ limitations under the License. */ -package main +package container import ( "context" "fmt" "time" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/fmtutil" "github.com/containerd/nerdctl/pkg/containerinspector" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" "github.com/containerd/nerdctl/pkg/inspecttypes/dockercompat" @@ -28,13 +31,13 @@ import ( "github.com/spf13/cobra" ) -func newContainerInspectCommand() *cobra.Command { +func NewContainerInspectCommand() *cobra.Command { var containerInspectCommand = &cobra.Command{ Use: "inspect [flags] CONTAINER [CONTAINER, ...]", Short: "Display detailed information on one or more containers.", Long: "Hint: set `--mode=native` for showing the full output", Args: cobra.MinimumNArgs(1), - RunE: containerInspectAction, + RunE: InspectAction, ValidArgsFunction: containerInspectShellComplete, SilenceUsage: true, SilenceErrors: true, @@ -50,8 +53,8 @@ func newContainerInspectCommand() *cobra.Command { return containerInspectCommand } -func containerInspectAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := newClient(cmd) +func InspectAction(cmd *cobra.Command, args []string) error { + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } @@ -82,7 +85,7 @@ func containerInspectAction(cmd *cobra.Command, args []string) error { return fmt.Errorf("%d errors: %v", len(errs), errs) } - return formatSlice(cmd, f.entries) + return fmtutil.FormatSlice(cmd, f.entries) } type containerInspector struct { @@ -115,5 +118,5 @@ func (x *containerInspector) Handler(ctx context.Context, found containerwalker. func containerInspectShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show container names - return shellCompleteContainerNames(cmd, nil) + return completion.ShellCompleteContainerNames(cmd, nil) } diff --git a/cmd/nerdctl/container_prune.go b/cmd/nerdctl/container/container_prune.go similarity index 79% rename from cmd/nerdctl/container_prune.go rename to cmd/nerdctl/container/container_prune.go index ab38ad8d1f2..3dd534f2f5e 100644 --- a/cmd/nerdctl/container_prune.go +++ b/cmd/nerdctl/container/container_prune.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "context" @@ -23,11 +23,15 @@ import ( "strings" "github.com/containerd/containerd" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" + containerUtils "github.com/containerd/nerdctl/cmd/nerdctl/utils/container" + "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) -func newContainerPruneCommand() *cobra.Command { +func NewContainerPruneCommand() *cobra.Command { containerPruneCommand := &cobra.Command{ Use: "prune [flags]", Short: "Remove all stopped containers", @@ -58,16 +62,16 @@ func containerPruneAction(cmd *cobra.Command, _ []string) error { } } - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } defer cancel() - return containerPrune(ctx, cmd, client) + return Prune(ctx, cmd, client) } -func containerPrune(ctx context.Context, cmd *cobra.Command, client *containerd.Client) error { +func Prune(ctx context.Context, cmd *cobra.Command, client *containerd.Client) error { containers, err := client.Containers(ctx) if err != nil { return err @@ -75,12 +79,12 @@ func containerPrune(ctx context.Context, cmd *cobra.Command, client *containerd. var deleted []string for _, container := range containers { - err = removeContainer(ctx, cmd, container, false, true) + err = containerUtils.RemoveContainer(ctx, cmd, container, false, true) if err == nil { deleted = append(deleted, container.ID()) continue } - if errors.As(err, &statusError{}) { + if errors.As(err, &common.StatusError{}) { continue } logrus.WithError(err).Warnf("failed to remove container %s", container.ID()) diff --git a/cmd/nerdctl/cp.go b/cmd/nerdctl/container/cp/cp.go similarity index 99% rename from cmd/nerdctl/cp.go rename to cmd/nerdctl/container/cp/cp.go index a80135b16bd..28623470331 100644 --- a/cmd/nerdctl/cp.go +++ b/cmd/nerdctl/container/cp/cp.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package cp import ( "errors" diff --git a/cmd/nerdctl/container/cp/cp_freebsd.go b/cmd/nerdctl/container/cp/cp_freebsd.go new file mode 100644 index 00000000000..8b82c5f5a1d --- /dev/null +++ b/cmd/nerdctl/container/cp/cp_freebsd.go @@ -0,0 +1,23 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package cp + +import "github.com/spf13/cobra" + +func AddCpCommand(rootCmd *cobra.Command) { + // NOP +} diff --git a/cmd/nerdctl/cp_linux.go b/cmd/nerdctl/container/cp/cp_linux.go similarity index 96% rename from cmd/nerdctl/cp_linux.go rename to cmd/nerdctl/container/cp/cp_linux.go index 1df784636f7..6248fb2989b 100644 --- a/cmd/nerdctl/cp_linux.go +++ b/cmd/nerdctl/container/cp/cp_linux.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package cp import ( "context" @@ -27,6 +27,7 @@ import ( "strings" "github.com/containerd/containerd" + "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/pkg/inspecttypes/native" "github.com/containerd/nerdctl/pkg/rootlessutil" "github.com/containerd/nerdctl/pkg/tarutil" @@ -35,7 +36,7 @@ import ( "github.com/spf13/cobra" ) -func newCpCommand() *cobra.Command { +func NewCpCommand() *cobra.Command { shortHelp := "Copy files/folders between a running container and the local filesystem." @@ -52,7 +53,7 @@ Using 'nerdctl cp' with untrusted or malicious containers is unsupported and may nerdctl cp [flags] SRC_PATH|- CONTAINER:DEST_PATH` var cpCommand = &cobra.Command{ Use: usage, - Args: IsExactArgs(2), + Args: utils.IsExactArgs(2), Short: shortHelp, Long: longHelp, RunE: cpAction, @@ -105,7 +106,7 @@ func cpAction(cmd *cobra.Command, args []string) error { ctx := cmd.Context() // cp works in the host namespace (for inspecting file permissions), so we can't directly use the Go client. - selfExe, inspectArgs := globalFlags(cmd) + selfExe, inspectArgs := utils.GlobalFlags(cmd) inspectArgs = append(inspectArgs, "container", "inspect", "--mode=native", "--format={{json .Process}}", container) inspectCmd := exec.CommandContext(ctx, selfExe, inspectArgs...) inspectCmd.Stderr = os.Stderr @@ -272,3 +273,7 @@ func kopy(ctx context.Context, container2host bool, pid int, dst, src string, fo } return nil } + +func AddCpCommand(rootCmd *cobra.Command) { + rootCmd.AddCommand(NewCpCommand()) +} diff --git a/cmd/nerdctl/container/cp/cp_windows.go b/cmd/nerdctl/container/cp/cp_windows.go new file mode 100644 index 00000000000..8b82c5f5a1d --- /dev/null +++ b/cmd/nerdctl/container/cp/cp_windows.go @@ -0,0 +1,23 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package cp + +import "github.com/spf13/cobra" + +func AddCpCommand(rootCmd *cobra.Command) { + // NOP +} diff --git a/cmd/nerdctl/create.go b/cmd/nerdctl/container/create.go similarity index 79% rename from cmd/nerdctl/create.go rename to cmd/nerdctl/container/create.go index b0811f17da7..15ba655cfb5 100644 --- a/cmd/nerdctl/create.go +++ b/cmd/nerdctl/container/create.go @@ -14,16 +14,20 @@ limitations under the License. */ -package main +package container import ( "fmt" "runtime" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/container" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/run" "github.com/spf13/cobra" ) -func newCreateCommand() *cobra.Command { +func NewCreateCommand() *cobra.Command { shortHelp := "Create a new container. Optionally specify \"ipfs://\" or \"ipns://\" scheme to pull image from IPFS." longHelp := shortHelp switch runtime.GOOS { @@ -40,12 +44,12 @@ func newCreateCommand() *cobra.Command { Short: shortHelp, Long: longHelp, RunE: createAction, - ValidArgsFunction: runShellComplete, + ValidArgsFunction: completion.RunShellComplete, SilenceUsage: true, SilenceErrors: true, } createCommand.Flags().SetInterspersed(false) - setCreateFlags(createCommand) + run.SetCreateFlags(createCommand) return createCommand } @@ -64,13 +68,13 @@ func createAction(cmd *cobra.Command, args []string) error { return fmt.Errorf("%s requires experimental mode to be enabled", platform) } - client, ctx, cancel, err := newClientWithPlatform(cmd, platform) + client, ctx, cancel, err := nerdClient.NewClientWithPlatform(cmd, platform) if err != nil { return err } defer cancel() - container, gc, err := createContainer(ctx, cmd, client, args, platform, false, false, true) + container, gc, err := container.CreateContainer(ctx, cmd, client, args, platform, false, false, true) if err != nil { if gc != nil { gc() diff --git a/cmd/nerdctl/exec.go b/cmd/nerdctl/container/exec/exec.go similarity index 93% rename from cmd/nerdctl/exec.go rename to cmd/nerdctl/container/exec/exec.go index 5920e4a69b7..96d23d476bb 100644 --- a/cmd/nerdctl/exec.go +++ b/cmd/nerdctl/container/exec/exec.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package exec import ( "context" @@ -28,6 +28,10 @@ import ( "github.com/containerd/containerd/cio" "github.com/containerd/containerd/cmd/ctr/commands" "github.com/containerd/containerd/cmd/ctr/commands/tasks" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + containerUtils "github.com/containerd/nerdctl/cmd/nerdctl/utils/container" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/run" "github.com/containerd/nerdctl/pkg/flagutil" "github.com/containerd/nerdctl/pkg/idgen" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" @@ -38,7 +42,7 @@ import ( "github.com/spf13/cobra" ) -func newExecCommand() *cobra.Command { +func NewExecCommand() *cobra.Command { var execCommand = &cobra.Command{ Use: "exec [flags] CONTAINER COMMAND [ARG...]", Args: cobra.MinimumNArgs(2), @@ -72,7 +76,7 @@ func execAction(cmd *cobra.Command, args []string) error { args = newArg } - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } @@ -208,7 +212,7 @@ func generateExecProcessSpec(ctx context.Context, cmd *cobra.Command, args []str if err != nil { return nil, err } - userOpts, err := generateUserOpts(cmd) + userOpts, err := run.GenerateUserOpts(cmd) if err != nil { return nil, err } @@ -247,7 +251,7 @@ func generateExecProcessSpec(ctx context.Context, cmd *cobra.Command, args []str if err != nil { return nil, err } - envs, err := generateEnvs(envFile, env) + envs, err := containerUtils.GenerateEnvs(envFile, env) if err != nil { return nil, err } @@ -273,7 +277,7 @@ func execShellComplete(cmd *cobra.Command, args []string, toComplete string) ([] statusFilterFn := func(st containerd.ProcessStatus) bool { return st == containerd.Running } - return shellCompleteContainerNames(cmd, statusFilterFn) + return completion.ShellCompleteContainerNames(cmd, statusFilterFn) } return nil, cobra.ShellCompDirectiveNoFileComp } diff --git a/cmd/nerdctl/exec_freebsd.go b/cmd/nerdctl/container/exec/exec_freebsd.go similarity index 98% rename from cmd/nerdctl/exec_freebsd.go rename to cmd/nerdctl/container/exec/exec_freebsd.go index 8d374c3b9c2..b64da690cc8 100644 --- a/cmd/nerdctl/exec_freebsd.go +++ b/cmd/nerdctl/container/exec/exec_freebsd.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package exec import ( "github.com/opencontainers/runtime-spec/specs-go" diff --git a/cmd/nerdctl/exec_linux.go b/cmd/nerdctl/container/exec/exec_linux.go similarity index 99% rename from cmd/nerdctl/exec_linux.go rename to cmd/nerdctl/container/exec/exec_linux.go index 30c9cfa9eb9..ecc08bcfb95 100644 --- a/cmd/nerdctl/exec_linux.go +++ b/cmd/nerdctl/container/exec/exec_linux.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package exec import ( "github.com/containerd/containerd/pkg/cap" diff --git a/cmd/nerdctl/exec_windows.go b/cmd/nerdctl/container/exec/exec_windows.go similarity index 98% rename from cmd/nerdctl/exec_windows.go rename to cmd/nerdctl/container/exec/exec_windows.go index 88ed1bcc369..ffd51e4c6cc 100644 --- a/cmd/nerdctl/exec_windows.go +++ b/cmd/nerdctl/container/exec/exec_windows.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package exec import ( "github.com/opencontainers/runtime-spec/specs-go" diff --git a/cmd/nerdctl/kill.go b/cmd/nerdctl/container/kill.go similarity index 90% rename from cmd/nerdctl/kill.go rename to cmd/nerdctl/container/kill.go index a354f00e9a6..a239b6659b6 100644 --- a/cmd/nerdctl/kill.go +++ b/cmd/nerdctl/container/kill.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "context" @@ -26,6 +26,8 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/cio" "github.com/containerd/containerd/errdefs" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" "github.com/moby/sys/signal" @@ -33,10 +35,10 @@ import ( "github.com/spf13/cobra" ) -func newKillCommand() *cobra.Command { +func NewKillCommand() *cobra.Command { var killCommand = &cobra.Command{ Use: "kill [flags] CONTAINER [CONTAINER, ...]", - Short: "Kill one or more running containers", + Short: "Kill one or more running Containers", Args: cobra.MinimumNArgs(1), RunE: killAction, ValidArgsFunction: killShellComplete, @@ -61,7 +63,7 @@ func killAction(cmd *cobra.Command, args []string) error { return err } - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } @@ -134,6 +136,6 @@ func killShellComplete(cmd *cobra.Command, args []string, toComplete string) ([] statusFilterFn := func(st containerd.ProcessStatus) bool { return st != containerd.Stopped && st != containerd.Created && st != containerd.Unknown } - return shellCompleteContainerNames(cmd, statusFilterFn) + return completion.ShellCompleteContainerNames(cmd, statusFilterFn) } diff --git a/cmd/nerdctl/logs.go b/cmd/nerdctl/container/logs.go similarity index 91% rename from cmd/nerdctl/logs.go rename to cmd/nerdctl/container/logs.go index b4c5ff8b593..86d30fad10d 100644 --- a/cmd/nerdctl/logs.go +++ b/cmd/nerdctl/container/logs.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "context" @@ -25,6 +25,9 @@ import ( "syscall" "github.com/containerd/containerd" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" "github.com/containerd/nerdctl/pkg/labels" "github.com/containerd/nerdctl/pkg/logging" @@ -32,13 +35,13 @@ import ( "github.com/spf13/cobra" ) -func newLogsCommand() *cobra.Command { +func NewLogsCommand() *cobra.Command { var logsCommand = &cobra.Command{ Use: "logs [flags] CONTAINER", - Args: IsExactArgs(1), + Args: utils.IsExactArgs(1), Short: "Fetch the logs of a container. Currently, only containers created with `nerdctl run -d` are supported.", RunE: logsAction, - ValidArgsFunction: logsShellComplete, + ValidArgsFunction: completion.LogsShellComplete, SilenceUsage: true, SilenceErrors: true, } @@ -51,7 +54,7 @@ func newLogsCommand() *cobra.Command { } func logsAction(cmd *cobra.Command, args []string) error { - dataStore, err := getDataStore(cmd) + dataStore, err := nerdClient.GetDataStore(cmd) if err != nil { return err } @@ -65,7 +68,7 @@ func logsAction(cmd *cobra.Command, args []string) error { logrus.Warn("Currently, `nerdctl logs` only supports containers created with `nerdctl run -d`") } - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } @@ -167,11 +170,6 @@ func logsAction(cmd *cobra.Command, args []string) error { return nil } -func logsShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - // show container names (TODO: only show containers with logs) - return shellCompleteContainerNames(cmd, nil) -} - // Attempts to parse the argument given to `-n/--tail` as a uint. func getTailArgAsUint(arg string) (uint, error) { if arg == "all" { diff --git a/cmd/nerdctl/pause.go b/cmd/nerdctl/container/pause.go similarity index 57% rename from cmd/nerdctl/pause.go rename to cmd/nerdctl/container/pause.go index aaf4d5ae860..09147f3622b 100644 --- a/cmd/nerdctl/pause.go +++ b/cmd/nerdctl/container/pause.go @@ -14,26 +14,27 @@ limitations under the License. */ -package main +package container import ( "context" "fmt" - "github.com/containerd/containerd" - "github.com/containerd/containerd/cio" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" "github.com/spf13/cobra" ) -func newPauseCommand() *cobra.Command { +func NewPauseCommand() *cobra.Command { var pauseCommand = &cobra.Command{ Use: "pause [flags] CONTAINER [CONTAINER, ...]", Args: cobra.MinimumNArgs(1), - Short: "Pause all processes within one or more containers", + Short: "Pause all processes within one or more Containers", RunE: pauseAction, - ValidArgsFunction: pauseShellComplete, + ValidArgsFunction: completion.PauseShellComplete, SilenceUsage: true, SilenceErrors: true, } @@ -41,7 +42,7 @@ func newPauseCommand() *cobra.Command { } func pauseAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } @@ -53,7 +54,7 @@ func pauseAction(cmd *cobra.Command, args []string) error { if found.MatchCount > 1 { return fmt.Errorf("multiple IDs found with provided prefix: %s", found.Req) } - if err := pauseContainer(ctx, client, found.Container.ID()); err != nil { + if err := utils.PauseContainer(ctx, client, found.Container.ID()); err != nil { return err } @@ -71,37 +72,3 @@ func pauseAction(cmd *cobra.Command, args []string) error { } return nil } - -func pauseContainer(ctx context.Context, client *containerd.Client, id string) error { - container, err := client.LoadContainer(ctx, id) - if err != nil { - return err - } - - task, err := container.Task(ctx, cio.Load) - if err != nil { - return err - } - - status, err := task.Status(ctx) - if err != nil { - return err - } - - switch status.Status { - case containerd.Paused: - return fmt.Errorf("container %s is already paused", id) - case containerd.Created, containerd.Stopped: - return fmt.Errorf("container %s is not running", id) - default: - return task.Pause(ctx) - } -} - -func pauseShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - // show running container names - statusFilterFn := func(st containerd.ProcessStatus) bool { - return st == containerd.Running - } - return shellCompleteContainerNames(cmd, statusFilterFn) -} diff --git a/cmd/nerdctl/port.go b/cmd/nerdctl/container/port.go similarity index 89% rename from cmd/nerdctl/port.go rename to cmd/nerdctl/container/port.go index ef39fa14f94..2b989836c96 100644 --- a/cmd/nerdctl/port.go +++ b/cmd/nerdctl/container/port.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "context" @@ -22,13 +22,15 @@ import ( "strconv" "strings" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/pkg/containerutil" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" "github.com/spf13/cobra" ) -func newPortCommand() *cobra.Command { +func NewPortCommand() *cobra.Command { var portCommand = &cobra.Command{ Use: "port [flags] CONTAINER [PRIVATE_PORT[/PROTO]]", Args: cobra.RangeArgs(1, 2), @@ -70,7 +72,7 @@ func portAction(cmd *cobra.Command, args []string) error { } } - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } @@ -96,5 +98,5 @@ func portAction(cmd *cobra.Command, args []string) error { } func portShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return shellCompleteContainerNames(cmd, nil) + return completion.ShellCompleteContainerNames(cmd, nil) } diff --git a/cmd/nerdctl/rename.go b/cmd/nerdctl/container/rename.go similarity index 86% rename from cmd/nerdctl/rename.go rename to cmd/nerdctl/container/rename.go index 907af2d55ab..0d682b82115 100644 --- a/cmd/nerdctl/rename.go +++ b/cmd/nerdctl/container/rename.go @@ -14,13 +14,16 @@ limitations under the License. */ -package main +package container import ( "context" "fmt" "github.com/containerd/containerd" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/pkg/dnsutil/hostsstore" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" "github.com/containerd/nerdctl/pkg/labels" @@ -28,10 +31,10 @@ import ( "github.com/spf13/cobra" ) -func newRenameCommand() *cobra.Command { +func NewRenameCommand() *cobra.Command { var renameCommand = &cobra.Command{ Use: "rename [flags] CONTAINER NEW_NAME", - Args: IsExactArgs(2), + Args: utils.IsExactArgs(2), Short: "rename a container", RunE: renameAction, ValidArgsFunction: renameShellComplete, @@ -42,7 +45,7 @@ func newRenameCommand() *cobra.Command { } func renameAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } @@ -52,7 +55,7 @@ func renameAction(cmd *cobra.Command, args []string) error { return err } - dataStore, err := getDataStore(cmd) + dataStore, err := nerdClient.GetDataStore(cmd) if err != nil { return err } @@ -105,5 +108,5 @@ func renameContainer(ctx context.Context, container containerd.Container, newNam } func renameShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return shellCompleteContainerNames(cmd, nil) + return completion.ShellCompleteContainerNames(cmd, nil) } diff --git a/cmd/nerdctl/restart.go b/cmd/nerdctl/container/restart.go similarity index 81% rename from cmd/nerdctl/restart.go rename to cmd/nerdctl/container/restart.go index b5c4dd3354e..4622a50a892 100644 --- a/cmd/nerdctl/restart.go +++ b/cmd/nerdctl/container/restart.go @@ -14,24 +14,27 @@ limitations under the License. */ -package main +package container import ( "context" "fmt" "time" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/action" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" "github.com/spf13/cobra" ) -func newRestartCommand() *cobra.Command { +func NewRestartCommand() *cobra.Command { var restartCommand = &cobra.Command{ Use: "restart [flags] CONTAINER [CONTAINER, ...]", Args: cobra.MinimumNArgs(1), Short: "Restart one or more running containers", RunE: restartAction, - ValidArgsFunction: startShellComplete, + ValidArgsFunction: completion.StartShellComplete, SilenceUsage: true, SilenceErrors: true, } @@ -51,7 +54,7 @@ func restartAction(cmd *cobra.Command, args []string) error { timeout = &t } - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } @@ -63,10 +66,10 @@ func restartAction(cmd *cobra.Command, args []string) error { if found.MatchCount > 1 { return fmt.Errorf("multiple IDs found with provided prefix: %s", found.Req) } - if err := stopContainer(ctx, found.Container, timeout); err != nil { + if err := action.StopContainer(ctx, found.Container, timeout); err != nil { return err } - if err := startContainer(ctx, found.Container, false, client); err != nil { + if err := action.StartContainer(ctx, found.Container, false, client); err != nil { return err } _, err = fmt.Fprintf(cmd.OutOrStdout(), "%s\n", found.Req) diff --git a/cmd/nerdctl/container/rm.go b/cmd/nerdctl/container/rm.go new file mode 100644 index 00000000000..41dfb66af2d --- /dev/null +++ b/cmd/nerdctl/container/rm.go @@ -0,0 +1,94 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package container + +import ( + "context" + "fmt" + + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/container" + "github.com/containerd/nerdctl/pkg/idutil/containerwalker" + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" +) + +func NewRmCommand() *cobra.Command { + var rmCommand = &cobra.Command{ + Use: "rm [flags] CONTAINER [CONTAINER, ...]", + Args: cobra.MinimumNArgs(1), + Short: "Remove one or more containers", + RunE: rmAction, + ValidArgsFunction: rmShellComplete, + SilenceUsage: true, + SilenceErrors: true, + } + rmCommand.Flags().BoolP("force", "f", false, "Force the removal of a running|paused|unknown container (uses SIGKILL)") + rmCommand.Flags().BoolP("volumes", "v", false, "Remove volume associated with the container") + return rmCommand +} + +func rmAction(cmd *cobra.Command, args []string) error { + force, err := cmd.Flags().GetBool("force") + if err != nil { + return err + } + removeAnonVolumes, err := cmd.Flags().GetBool("volumes") + if err != nil { + return err + } + + client, ctx, cancel, err := nerdClient.NewClient(cmd) + if err != nil { + return err + } + defer cancel() + + walker := &containerwalker.ContainerWalker{ + Client: client, + OnFound: func(ctx context.Context, found containerwalker.Found) error { + if found.MatchCount > 1 { + return fmt.Errorf("multiple IDs found with provided prefix: %s", found.Req) + } + if err := container.RemoveContainer(ctx, cmd, found.Container, force, removeAnonVolumes); err != nil { + return err + } + _, err = fmt.Fprintf(cmd.OutOrStdout(), "%s\n", found.Req) + return err + }, + } + for _, req := range args { + n, err := walker.Walk(ctx, req) + if err == nil && n == 0 { + err = fmt.Errorf("no such container %s", req) + } + if err != nil { + if force { + logrus.Error(err) + } else { + return err + } + } + } + return nil +} + +func rmShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + // show container names + return completion.ShellCompleteContainerNames(cmd, nil) +} diff --git a/cmd/nerdctl/container/run.go b/cmd/nerdctl/container/run.go new file mode 100644 index 00000000000..452b620c7fd --- /dev/null +++ b/cmd/nerdctl/container/run.go @@ -0,0 +1,179 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package container + +import ( + "errors" + "fmt" + "runtime" + + "github.com/containerd/console" + "github.com/containerd/containerd" + "github.com/containerd/containerd/cmd/ctr/commands" + "github.com/containerd/containerd/cmd/ctr/commands/tasks" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" + containerUtils "github.com/containerd/nerdctl/cmd/nerdctl/utils/container" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/run" + "github.com/containerd/nerdctl/pkg/labels" + "github.com/containerd/nerdctl/pkg/taskutil" + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" +) + +func NewRunCommand() *cobra.Command { + shortHelp := "Run a command in a new container. Optionally specify \"ipfs://\" or \"ipns://\" scheme to pull image from IPFS." + longHelp := shortHelp + switch runtime.GOOS { + case "windows": + longHelp += "\n" + longHelp += "WARNING: `nerdctl run` is experimental on Windows and currently broken (https://github.com/containerd/nerdctl/issues/28)" + case "freebsd": + longHelp += "\n" + longHelp += "WARNING: `nerdctl run` is experimental on FreeBSD and currently requires `--net=none` (https://github.com/containerd/nerdctl/blob/main/docs/freebsd.md)" + } + var runCommand = &cobra.Command{ + Use: "run [flags] IMAGE [COMMAND] [ARG...]", + Args: cobra.MinimumNArgs(1), + Short: shortHelp, + Long: longHelp, + RunE: runAction, + ValidArgsFunction: completion.RunShellComplete, + SilenceUsage: true, + SilenceErrors: true, + } + + runCommand.Flags().SetInterspersed(false) + run.SetCreateFlags(runCommand) + + runCommand.Flags().BoolP("detach", "d", false, "Run container in background and print container ID") + + return runCommand +} + +// runAction is heavily based on ctr implementation: +// https://github.com/containerd/containerd/blob/v1.4.3/cmd/ctr/commands/run/run.go +func runAction(cmd *cobra.Command, args []string) error { + platform, err := cmd.Flags().GetString("platform") + if err != nil { + return err + } + client, ctx, cancel, err := nerdClient.NewClientWithPlatform(cmd, platform) + if err != nil { + return err + } + defer cancel() + + flagD, err := cmd.Flags().GetBool("detach") + if err != nil { + return err + } + flagI, err := cmd.Flags().GetBool("interactive") + if err != nil { + return err + } + flagT, err := cmd.Flags().GetBool("tty") + if err != nil { + return err + } + container, gc, err := containerUtils.CreateContainer(ctx, cmd, client, args, platform, flagI, flagT, flagD) + if err != nil { + if gc != nil { + defer gc() + } + return err + } + + id := container.ID() + rm, err := cmd.Flags().GetBool("rm") + if err != nil { + return err + } + if rm { + if flagD { + return errors.New("flag -d and --rm cannot be specified together") + } + defer func() { + if err := containerUtils.RemoveContainer(ctx, cmd, container, true, true); err != nil { + logrus.WithError(err).Warnf("failed to remove container %s", id) + } + }() + } + + var con console.Console + if flagT { + con = console.Current() + defer con.Reset() + if err := con.SetRaw(); err != nil { + return err + } + } + + lab, err := container.Labels(ctx) + if err != nil { + return err + } + logURI := lab[labels.LogURI] + + task, err := taskutil.NewTask(ctx, client, container, flagI, flagT, flagD, con, logURI) + if err != nil { + return err + } + var statusC <-chan containerd.ExitStatus + if !flagD { + defer func() { + if rm { + if _, taskDeleteErr := task.Delete(ctx); taskDeleteErr != nil { + logrus.Error(taskDeleteErr) + } + } + }() + statusC, err = task.Wait(ctx) + if err != nil { + return err + } + } + + if err := task.Start(ctx); err != nil { + return err + } + + if flagD { + fmt.Fprintf(cmd.OutOrStdout(), "%s\n", id) + return nil + } + if flagT { + if err := tasks.HandleConsoleResize(ctx, task, con); err != nil { + logrus.WithError(err).Error("console resize") + } + } else { + sigc := commands.ForwardAllSignals(ctx, task) + defer commands.StopCatch(sigc) + } + status := <-statusC + code, _, err := status.Result() + if err != nil { + return err + } + if code != 0 { + return common.ExitCodeError{ + Code: int(code), + } + } + return nil +} diff --git a/cmd/nerdctl/container/start.go b/cmd/nerdctl/container/start.go new file mode 100644 index 00000000000..08e0834e333 --- /dev/null +++ b/cmd/nerdctl/container/start.go @@ -0,0 +1,90 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package container + +import ( + "context" + "fmt" + + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/action" + "github.com/containerd/nerdctl/pkg/idutil/containerwalker" + "github.com/spf13/cobra" +) + +func NewStartCommand() *cobra.Command { + var startCommand = &cobra.Command{ + Use: "start [flags] CONTAINER [CONTAINER, ...]", + Args: cobra.MinimumNArgs(1), + Short: "start one or more running containers", + RunE: startAction, + ValidArgsFunction: completion.StartShellComplete, + SilenceUsage: true, + SilenceErrors: true, + } + + startCommand.Flags().SetInterspersed(false) + startCommand.Flags().BoolP("attach", "a", false, "Attach STDOUT/STDERR and forward signals") + + return startCommand +} + +func startAction(cmd *cobra.Command, args []string) error { + client, ctx, cancel, err := nerdClient.NewClient(cmd) + if err != nil { + return err + } + defer cancel() + + flagA, err := cmd.Flags().GetBool("attach") + if err != nil { + return err + } + + if flagA && len(args) > 1 { + return fmt.Errorf("you cannot start and attach multiple containers at once") + } + + walker := &containerwalker.ContainerWalker{ + Client: client, + OnFound: func(ctx context.Context, found containerwalker.Found) error { + if found.MatchCount > 1 { + return fmt.Errorf("multiple IDs found with provided prefix: %s", found.Req) + } + if err := action.StartContainer(ctx, found.Container, flagA, client); err != nil { + return err + } + if !flagA { + _, err := fmt.Fprintf(cmd.OutOrStdout(), "%s\n", found.Req) + if err != nil { + return err + } + } + return err + }, + } + for _, req := range args { + n, err := walker.Walk(ctx, req) + if err != nil { + return err + } else if n == 0 { + return fmt.Errorf("no such container %s", req) + } + } + return nil +} diff --git a/cmd/nerdctl/container/stop.go b/cmd/nerdctl/container/stop.go new file mode 100644 index 00000000000..34a6262ebc5 --- /dev/null +++ b/cmd/nerdctl/container/stop.go @@ -0,0 +1,91 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package container + +import ( + "context" + "fmt" + "time" + + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/action" + "github.com/spf13/cobra" + + "github.com/containerd/containerd/errdefs" + "github.com/containerd/nerdctl/pkg/idutil/containerwalker" +) + +func NewStopCommand() *cobra.Command { + var stopCommand = &cobra.Command{ + Use: "stop [flags] CONTAINER [CONTAINER, ...]", + Args: cobra.MinimumNArgs(1), + Short: "Stop one or more running containers", + RunE: stopAction, + ValidArgsFunction: completion.StopShellComplete, + SilenceUsage: true, + SilenceErrors: true, + } + stopCommand.Flags().IntP("time", "t", 10, "Seconds to wait for stop before killing it") + return stopCommand +} + +func stopAction(cmd *cobra.Command, args []string) error { + // Time to wait after sending a SIGTERM and before sending a SIGKILL. + var timeout *time.Duration + if cmd.Flags().Changed("time") { + timeValue, err := cmd.Flags().GetInt("time") + if err != nil { + return err + } + t := time.Duration(timeValue) * time.Second + timeout = &t + } + + client, ctx, cancel, err := nerdClient.NewClient(cmd) + if err != nil { + return err + } + defer cancel() + + walker := &containerwalker.ContainerWalker{ + Client: client, + OnFound: func(ctx context.Context, found containerwalker.Found) error { + if found.MatchCount > 1 { + return fmt.Errorf("multiple IDs found with provided prefix: %s", found.Req) + } + if err := action.StopContainer(ctx, found.Container, timeout); err != nil { + if errdefs.IsNotFound(err) { + fmt.Fprintf(cmd.ErrOrStderr(), "No such container: %s\n", found.Req) + return nil + } + return err + } + _, err := fmt.Fprintf(cmd.OutOrStdout(), "%s\n", found.Req) + return err + }, + } + for _, req := range args { + n, err := walker.Walk(ctx, req) + if err != nil { + return err + } else if n == 0 { + return fmt.Errorf("no such container %s", req) + } + } + return nil +} diff --git a/cmd/nerdctl/unpause.go b/cmd/nerdctl/container/unpause.go similarity index 61% rename from cmd/nerdctl/unpause.go rename to cmd/nerdctl/container/unpause.go index 4af00fd80b1..6bebe6dd743 100644 --- a/cmd/nerdctl/unpause.go +++ b/cmd/nerdctl/container/unpause.go @@ -14,26 +14,27 @@ limitations under the License. */ -package main +package container import ( "context" "fmt" - "github.com/containerd/containerd" - "github.com/containerd/containerd/cio" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" "github.com/spf13/cobra" ) -func newUnpauseCommand() *cobra.Command { +func NewUnpauseCommand() *cobra.Command { var unpauseCommand = &cobra.Command{ Use: "unpause [flags] CONTAINER [CONTAINER, ...]", Args: cobra.MinimumNArgs(1), Short: "Unpause all processes within one or more containers", RunE: unpauseAction, - ValidArgsFunction: unpauseShellComplete, + ValidArgsFunction: completion.UnpauseShellComplete, SilenceUsage: true, SilenceErrors: true, } @@ -41,7 +42,7 @@ func newUnpauseCommand() *cobra.Command { } func unpauseAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } @@ -53,7 +54,7 @@ func unpauseAction(cmd *cobra.Command, args []string) error { if found.MatchCount > 1 { return fmt.Errorf("multiple IDs found with provided prefix: %s", found.Req) } - if err := unpauseContainer(ctx, client, found.Container.ID()); err != nil { + if err := utils.UnpauseContainer(ctx, client, found.Container.ID()); err != nil { return err } @@ -71,35 +72,3 @@ func unpauseAction(cmd *cobra.Command, args []string) error { } return nil } - -func unpauseContainer(ctx context.Context, client *containerd.Client, id string) error { - container, err := client.LoadContainer(ctx, id) - if err != nil { - return err - } - - task, err := container.Task(ctx, cio.Load) - if err != nil { - return err - } - - status, err := task.Status(ctx) - if err != nil { - return err - } - - switch status.Status { - case containerd.Paused: - return task.Resume(ctx) - default: - return fmt.Errorf("container %s is not paused", id) - } -} - -func unpauseShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - // show paused container names - statusFilterFn := func(st containerd.ProcessStatus) bool { - return st == containerd.Paused - } - return shellCompleteContainerNames(cmd, statusFilterFn) -} diff --git a/cmd/nerdctl/update.go b/cmd/nerdctl/container/update.go similarity index 97% rename from cmd/nerdctl/update.go rename to cmd/nerdctl/container/update.go index 1ca73dc14b2..84a407034b1 100644 --- a/cmd/nerdctl/update.go +++ b/cmd/nerdctl/container/update.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "context" @@ -27,6 +27,8 @@ import ( "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/log" "github.com/containerd/containerd/pkg/cri/util" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/pkg/formatter" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" "github.com/containerd/nerdctl/pkg/infoutil" @@ -50,7 +52,7 @@ type updateResourceOptions struct { BlkioWeight uint16 } -func newUpdateCommand() *cobra.Command { +func NewUpdateCommand() *cobra.Command { var updateCommand = &cobra.Command{ Use: "update [flags] CONTAINER [CONTAINER, ...]", Args: cobra.MinimumNArgs(1), @@ -81,7 +83,7 @@ func setUpdateFlags(cmd *cobra.Command) { } func updateAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } @@ -385,5 +387,5 @@ func copySpec(spec *runtimespec.Spec) (*runtimespec.Spec, error) { } func updateShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return shellCompleteContainerNames(cmd, nil) + return completion.ShellCompleteContainerNames(cmd, nil) } diff --git a/cmd/nerdctl/wait.go b/cmd/nerdctl/container/wait.go similarity index 89% rename from cmd/nerdctl/wait.go rename to cmd/nerdctl/container/wait.go index 64dc02ff102..c4bfbc41856 100644 --- a/cmd/nerdctl/wait.go +++ b/cmd/nerdctl/container/wait.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "context" @@ -22,12 +22,14 @@ import ( "io" "github.com/containerd/containerd" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" "github.com/hashicorp/go-multierror" "github.com/spf13/cobra" ) -func newWaitCommand() *cobra.Command { +func NewWaitCommand() *cobra.Command { var waitCommand = &cobra.Command{ Use: "wait [flags] CONTAINER [CONTAINER, ...]", Args: cobra.MinimumNArgs(1), @@ -41,7 +43,7 @@ func newWaitCommand() *cobra.Command { } func containerWaitAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } @@ -103,5 +105,5 @@ func waitShellComplete(cmd *cobra.Command, args []string, toComplete string) ([] statusFilterFn := func(st containerd.ProcessStatus) bool { return st == containerd.Running } - return shellCompleteContainerNames(cmd, statusFilterFn) + return completion.ShellCompleteContainerNames(cmd, statusFilterFn) } diff --git a/cmd/nerdctl/container_lsutil.go b/cmd/nerdctl/container_lsutil.go deleted file mode 100644 index 314e940d9e6..00000000000 --- a/cmd/nerdctl/container_lsutil.go +++ /dev/null @@ -1,375 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package main - -import ( - "context" - "fmt" - "strconv" - "strings" - "time" - - "github.com/containerd/containerd" - "github.com/containerd/containerd/containers" - "github.com/sirupsen/logrus" -) - -func foldContainerFilters(ctx context.Context, containers []containerd.Container, filters []string) (*containerFilterContext, error) { - filterCtx := &containerFilterContext{containers: containers} - err := filterCtx.foldFilters(ctx, filters) - return filterCtx, err -} - -type containerFilterContext struct { - containers []containerd.Container - - idFilterFuncs []func(string) bool - nameFilterFuncs []func(string) bool - exitedFilterFuncs []func(int) bool - beforeFilterFuncs []func(t time.Time) bool - sinceFilterFuncs []func(t time.Time) bool - statusFilterFuncs []func(containerd.ProcessStatus) bool - labelFilterFuncs []func(map[string]string) bool - volumeFilterFuncs []func([]*containerVolume) bool - networkFilterFuncs []func([]string) bool -} - -func (cl *containerFilterContext) MatchesFilters(ctx context.Context) []containerd.Container { - matchesContainers := make([]containerd.Container, 0, len(cl.containers)) - for _, container := range cl.containers { - if !cl.matchesInfoFilters(ctx, container) { - continue - } - if !cl.matchesTaskFilters(ctx, container) { - continue - } - matchesContainers = append(matchesContainers, container) - } - cl.containers = matchesContainers - return cl.containers -} - -func (cl *containerFilterContext) foldFilters(ctx context.Context, filters []string) error { - folders := []struct { - filterType string - foldFunc func(context.Context, string, string) error - }{ - {"id", cl.foldIDFilter}, {"name", cl.foldNameFilter}, - {"before", cl.foldBeforeFilter}, {"since", cl.foldSinceFilter}, - {"network", cl.foldNetworkFilter}, {"label", cl.foldLabelFilter}, - {"volume", cl.foldVolumeFilter}, {"status", cl.foldStatusFilter}, - {"exited", cl.foldExitedFilter}, - } - for _, filter := range filters { - invalidFilter := true - for _, folder := range folders { - if !strings.HasPrefix(filter, folder.filterType) { - continue - } - splited := strings.SplitN(filter, "=", 2) - if len(splited) != 2 { - return fmt.Errorf("invalid argument \"%s\" for \"-f, --filter\": bad format of filter (expected name=value)", folder.filterType) - } - if err := folder.foldFunc(ctx, filter, splited[1]); err != nil { - return err - } - invalidFilter = false - break - } - if invalidFilter { - return fmt.Errorf("invalid filter '%s'", filter) - } - } - return nil -} - -func (cl *containerFilterContext) foldExitedFilter(_ context.Context, filter, value string) error { - exited, err := strconv.Atoi(value) - if err != nil { - return err - } - cl.exitedFilterFuncs = append(cl.exitedFilterFuncs, func(exitStatus int) bool { - return exited == exitStatus - }) - return nil -} - -func (cl *containerFilterContext) foldStatusFilter(_ context.Context, filter, value string) error { - status := containerd.ProcessStatus(value) - switch status { - case containerd.Running, containerd.Created, containerd.Stopped, containerd.Paused, containerd.Pausing, containerd.Unknown: - cl.statusFilterFuncs = append(cl.statusFilterFuncs, func(stats containerd.ProcessStatus) bool { - return status == stats - }) - case containerd.ProcessStatus("exited"): - cl.statusFilterFuncs = append(cl.statusFilterFuncs, func(stats containerd.ProcessStatus) bool { - return containerd.Stopped == stats - }) - case containerd.ProcessStatus("restarting"), containerd.ProcessStatus("removing"), containerd.ProcessStatus("dead"): - logrus.Warnf("%s is not supported and is ignored", filter) - default: - return fmt.Errorf("invalid filter '%s'", filter) - } - return nil -} - -func (cl *containerFilterContext) foldBeforeFilter(ctx context.Context, filter, value string) error { - beforeC, err := idOrNameFilter(ctx, cl.containers, value) - if err == nil { - cl.beforeFilterFuncs = append(cl.beforeFilterFuncs, func(t time.Time) bool { - return t.Before(beforeC.CreatedAt) - }) - } - return err -} - -func (cl *containerFilterContext) foldSinceFilter(ctx context.Context, filter, value string) error { - sinceC, err := idOrNameFilter(ctx, cl.containers, value) - if err == nil { - cl.sinceFilterFuncs = append(cl.sinceFilterFuncs, func(t time.Time) bool { - return t.After(sinceC.CreatedAt) - }) - } - return err -} - -func (cl *containerFilterContext) foldIDFilter(_ context.Context, filter, value string) error { - cl.idFilterFuncs = append(cl.idFilterFuncs, func(id string) bool { - if value == "" { - return false - } - return strings.HasPrefix(id, value) - }) - return nil -} - -func (cl *containerFilterContext) foldNameFilter(_ context.Context, filter, value string) error { - cl.nameFilterFuncs = append(cl.nameFilterFuncs, func(name string) bool { - if value == "" { - return true - } - return strings.Contains(name, value) - }) - return nil -} - -func (cl *containerFilterContext) foldLabelFilter(_ context.Context, filter, value string) error { - k, v, hasValue := value, "", false - if subs := strings.SplitN(value, "=", 2); len(subs) == 2 { - hasValue = true - k, v = subs[0], subs[1] - } - cl.labelFilterFuncs = append(cl.labelFilterFuncs, func(labels map[string]string) bool { - if labels == nil { - return false - } - val, ok := labels[k] - if !ok || (hasValue && val != v) { - return false - } - return true - }) - return nil -} - -func (cl *containerFilterContext) foldVolumeFilter(_ context.Context, filter, value string) error { - cl.volumeFilterFuncs = append(cl.volumeFilterFuncs, func(vols []*containerVolume) bool { - for _, vol := range vols { - if (vol.Source != "" && vol.Source == value) || - (vol.Destination != "" && vol.Destination == value) || - (vol.Name != "" && vol.Name == value) { - return true - } - } - return false - }) - return nil -} - -func (cl *containerFilterContext) foldNetworkFilter(_ context.Context, filter, value string) error { - cl.networkFilterFuncs = append(cl.networkFilterFuncs, func(networks []string) bool { - for _, network := range networks { - if network == value { - return true - } - } - return false - }) - return nil -} - -func (cl *containerFilterContext) matchesInfoFilters(ctx context.Context, container containerd.Container) bool { - if len(cl.idFilterFuncs)+len(cl.nameFilterFuncs)+len(cl.beforeFilterFuncs)+ - len(cl.sinceFilterFuncs)+len(cl.labelFilterFuncs)+len(cl.volumeFilterFuncs)+len(cl.networkFilterFuncs) == 0 { - return true - } - info, _ := container.Info(ctx, containerd.WithoutRefreshedMetadata) - return cl.matchesIDFilter(info) && cl.matchesNameFilter(info) && cl.matchesBeforeFilter(info) && - cl.matchesSinceFilter(info) && cl.matchesLabelFilter(info) && cl.matchesVolumeFilter(info) && - cl.matchesNetworkFilter(info) -} - -func (cl *containerFilterContext) matchesTaskFilters(ctx context.Context, container containerd.Container) bool { - if len(cl.exitedFilterFuncs)+len(cl.statusFilterFuncs) == 0 { - return true - } - ctx, cancel := context.WithTimeout(ctx, 5*time.Second) - defer cancel() - task, err := container.Task(ctx, nil) - if err != nil { - logrus.Warn(err) - return false - } - status, err := task.Status(ctx) - if err != nil { - logrus.Warn(err) - return false - } - return cl.matchesExitedFilter(status) && cl.matchesStatusFilter(status) -} - -func (cl *containerFilterContext) matchesExitedFilter(status containerd.Status) bool { - if len(cl.exitedFilterFuncs) == 0 { - return true - } - if status.Status != containerd.Stopped { - return false - } - for _, exitedFilterFunc := range cl.exitedFilterFuncs { - if !exitedFilterFunc(int(status.ExitStatus)) { - continue - } - return true - } - return false -} - -func (cl *containerFilterContext) matchesStatusFilter(status containerd.Status) bool { - if len(cl.statusFilterFuncs) == 0 { - return true - } - for _, statusFilterFunc := range cl.statusFilterFuncs { - if !statusFilterFunc(status.Status) { - continue - } - return true - } - return false -} - -func (cl *containerFilterContext) matchesIDFilter(info containers.Container) bool { - if len(cl.idFilterFuncs) == 0 { - return true - } - for _, idFilterFunc := range cl.idFilterFuncs { - if !idFilterFunc(info.ID) { - continue - } - return true - } - return false -} - -func (cl *containerFilterContext) matchesNameFilter(info containers.Container) bool { - if len(cl.nameFilterFuncs) == 0 { - return true - } - cName := getPrintableContainerName(info.Labels) - for _, nameFilterFunc := range cl.nameFilterFuncs { - if !nameFilterFunc(cName) { - continue - } - return true - } - return false -} - -func (cl *containerFilterContext) matchesSinceFilter(info containers.Container) bool { - if len(cl.sinceFilterFuncs) == 0 { - return true - } - for _, sinceFilterFunc := range cl.sinceFilterFuncs { - if !sinceFilterFunc(info.CreatedAt) { - continue - } - return true - } - return false -} - -func (cl *containerFilterContext) matchesBeforeFilter(info containers.Container) bool { - if len(cl.beforeFilterFuncs) == 0 { - return true - } - for _, beforeFilterFunc := range cl.beforeFilterFuncs { - if !beforeFilterFunc(info.CreatedAt) { - continue - } - return true - } - return false -} - -func (cl *containerFilterContext) matchesLabelFilter(info containers.Container) bool { - for _, labelFilterFunc := range cl.labelFilterFuncs { - if !labelFilterFunc(info.Labels) { - return false - } - } - return true -} - -func (cl *containerFilterContext) matchesVolumeFilter(info containers.Container) bool { - if len(cl.volumeFilterFuncs) == 0 { - return true - } - vols := getContainerVolumes(info.Labels) - for _, volumeFilterFunc := range cl.volumeFilterFuncs { - if !volumeFilterFunc(vols) { - continue - } - return true - } - return false -} - -func (cl *containerFilterContext) matchesNetworkFilter(info containers.Container) bool { - if len(cl.networkFilterFuncs) == 0 { - return true - } - networks := getContainerNetworks(info.Labels) - for _, networkFilterFunc := range cl.networkFilterFuncs { - if !networkFilterFunc(networks) { - continue - } - return true - } - return false -} - -func idOrNameFilter(ctx context.Context, containers []containerd.Container, value string) (*containers.Container, error) { - for _, container := range containers { - info, err := container.Info(ctx, containerd.WithoutRefreshedMetadata) - if err != nil { - return nil, err - } - if strings.HasPrefix(info.ID, value) || strings.Contains(getPrintableContainerName(info.Labels), value) { - return &info, nil - } - } - return nil, fmt.Errorf("no such container %s", value) -} diff --git a/cmd/nerdctl/events.go b/cmd/nerdctl/event/events.go similarity index 92% rename from cmd/nerdctl/events.go rename to cmd/nerdctl/event/events.go index 916dcb4e82d..cb842d859e3 100644 --- a/cmd/nerdctl/events.go +++ b/cmd/nerdctl/event/events.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package event import ( "bytes" @@ -26,6 +26,8 @@ import ( "github.com/containerd/containerd/events" "github.com/containerd/containerd/log" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/fmtutil" "github.com/containerd/typeurl" "github.com/spf13/cobra" @@ -34,7 +36,7 @@ import ( _ "github.com/containerd/containerd/api/events" ) -func newEventsCommand() *cobra.Command { +func NewEventsCommand() *cobra.Command { shortHelp := `Get real time events from the server` longHelp := shortHelp + "\nNOTE: The output format is not compatible with Docker." var eventsCommand = &cobra.Command{ @@ -62,7 +64,7 @@ type Out struct { // eventsActions is from https://github.com/containerd/containerd/blob/v1.4.3/cmd/ctr/commands/events/events.go func eventsAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } @@ -81,7 +83,7 @@ func eventsAction(cmd *cobra.Command, args []string) error { case "raw", "table", "wide": return errors.New("unsupported format: \"raw\", \"table\", and \"wide\"") default: - tmpl, err = parseTemplate(format) + tmpl, err = fmtutil.ParseTemplate(format) if err != nil { return err } diff --git a/cmd/nerdctl/history.go b/cmd/nerdctl/history/history.go similarity index 92% rename from cmd/nerdctl/history.go rename to cmd/nerdctl/history/history.go index 27f1ff58b22..61f74aeaa79 100644 --- a/cmd/nerdctl/history.go +++ b/cmd/nerdctl/history/history.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package history import ( "bytes" @@ -29,6 +29,10 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/pkg/progress" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/utils" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/fmtutil" "github.com/containerd/nerdctl/pkg/formatter" "github.com/containerd/nerdctl/pkg/idutil/imagewalker" "github.com/containerd/nerdctl/pkg/imgutil" @@ -37,11 +41,11 @@ import ( "github.com/spf13/cobra" ) -func newHistoryCommand() *cobra.Command { +func NewHistoryCommand() *cobra.Command { var historyCommand = &cobra.Command{ Use: "history [flags] IMAGE", Short: "Show the history of an image", - Args: IsExactArgs(1), + Args: utils.IsExactArgs(1), RunE: historyAction, ValidArgsFunction: historyShellComplete, SilenceUsage: true, @@ -69,7 +73,7 @@ type historyPrintable struct { } func historyAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } @@ -195,7 +199,7 @@ func printHistory(cmd *cobra.Command, historys []historyPrintable) error { return errors.New("format and quiet must not be specified together") } var err error - tmpl, err = parseTemplate(format) + tmpl, err = fmtutil.ParseTemplate(format) if err != nil { return err } @@ -214,7 +218,7 @@ func printHistory(cmd *cobra.Command, historys []historyPrintable) error { } } - if f, ok := w.(Flusher); ok { + if f, ok := w.(fmtutil.Flusher); ok { return f.Flush() } return nil @@ -254,5 +258,5 @@ func (x *historyPrinter) printHistory(p historyPrintable) error { func historyShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show image names - return shellCompleteImageNames(cmd) + return completion.ShellCompleteImageNames(cmd) } diff --git a/cmd/nerdctl/image.go b/cmd/nerdctl/image.go deleted file mode 100644 index afae1936335..00000000000 --- a/cmd/nerdctl/image.go +++ /dev/null @@ -1,64 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package main - -import ( - "github.com/spf13/cobra" -) - -func newImageCommand() *cobra.Command { - cmd := &cobra.Command{ - Annotations: map[string]string{Category: Management}, - Use: "image", - Short: "Manage images", - RunE: unknownSubcommandAction, - SilenceUsage: true, - SilenceErrors: true, - } - cmd.AddCommand( - newBuildCommand(), - // commitCommand is in "container", not in "image" - imageLsCommand(), - newHistoryCommand(), - newPullCommand(), - newPushCommand(), - newLoadCommand(), - newSaveCommand(), - newTagCommand(), - imageRmCommand(), - newImageConvertCommand(), - newImageInspectCommand(), - newImageEncryptCommand(), - newImageDecryptCommand(), - newImagePruneCommand(), - ) - return cmd -} - -func imageLsCommand() *cobra.Command { - x := newImagesCommand() - x.Use = "ls" - x.Aliases = []string{"list"} - return x -} - -func imageRmCommand() *cobra.Command { - x := newRmiCommand() - x.Use = "rm" - x.Aliases = []string{"remove"} - return x -} diff --git a/cmd/nerdctl/image/image.go b/cmd/nerdctl/image/image.go new file mode 100644 index 00000000000..489771764bf --- /dev/null +++ b/cmd/nerdctl/image/image.go @@ -0,0 +1,74 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package image + +import ( + "github.com/containerd/nerdctl/cmd/nerdctl/build" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/history" + "github.com/containerd/nerdctl/cmd/nerdctl/load" + "github.com/containerd/nerdctl/cmd/nerdctl/pull" + "github.com/containerd/nerdctl/cmd/nerdctl/push" + "github.com/containerd/nerdctl/cmd/nerdctl/rmi" + "github.com/containerd/nerdctl/cmd/nerdctl/save" + "github.com/containerd/nerdctl/cmd/nerdctl/tag" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" + "github.com/spf13/cobra" +) + +func NewImageCommand() *cobra.Command { + cmd := &cobra.Command{ + Annotations: map[string]string{common.Category: common.Management}, + Use: "image", + Short: "Manage images", + RunE: completion.UnknownSubcommandAction, + SilenceUsage: true, + SilenceErrors: true, + } + cmd.AddCommand( + build.NewBuildCommand(), + // commitCommand is in "container", not in "image" + LsCommand(), + history.NewHistoryCommand(), + pull.NewPullCommand(), + push.NewPushCommand(), + load.NewLoadCommand(), + save.NewSaveCommand(), + tag.NewTagCommand(), + RmCommand(), + NewImageConvertCommand(), + NewImageInspectCommand(), + NewImageEncryptCommand(), + NewImageDecryptCommand(), + NewImagePruneCommand(), + ) + return cmd +} + +func LsCommand() *cobra.Command { + x := NewImagesCommand() + x.Use = "ls" + x.Aliases = []string{"list"} + return x +} + +func RmCommand() *cobra.Command { + x := rmi.NewRmiCommand() + x.Use = "rm" + x.Aliases = []string{"remove"} + return x +} diff --git a/cmd/nerdctl/image_convert.go b/cmd/nerdctl/image/image_convert.go similarity index 97% rename from cmd/nerdctl/image_convert.go rename to cmd/nerdctl/image/image_convert.go index 33a37bcb2fe..513a5275291 100644 --- a/cmd/nerdctl/image_convert.go +++ b/cmd/nerdctl/image/image_convert.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package image import ( "compress/gzip" @@ -30,6 +30,8 @@ import ( "github.com/containerd/containerd/images" "github.com/containerd/containerd/images/converter" "github.com/containerd/containerd/images/converter/uncompress" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" converterutil "github.com/containerd/nerdctl/pkg/imgutil/converter" "github.com/containerd/nerdctl/pkg/platformutil" "github.com/containerd/nerdctl/pkg/referenceutil" @@ -57,7 +59,7 @@ For encryption and decryption, use 'nerdctl image (encrypt|decrypt)' command. ` // imageConvertCommand is from https://github.com/containerd/stargz-snapshotter/blob/d58f43a8235e46da73fb94a1a35280cb4d607b2c/cmd/ctr-remote/commands/convert.go -func newImageConvertCommand() *cobra.Command { +func NewImageConvertCommand() *cobra.Command { imageConvertCommand := &cobra.Command{ Use: "convert [flags] ...", Short: "convert an image", @@ -110,7 +112,7 @@ func newImageConvertCommand() *cobra.Command { // #region platform flags // platform is defined as StringSlice, not StringArray, to allow specifying "--platform=amd64,arm64" imageConvertCommand.Flags().StringSlice("platform", []string{}, "Convert content for a specific platform") - imageConvertCommand.RegisterFlagCompletionFunc("platform", shellCompletePlatforms) + imageConvertCommand.RegisterFlagCompletionFunc("platform", completion.ShellCompletePlatforms) imageConvertCommand.Flags().Bool("all-platforms", false, "Convert content for all platforms") // #endregion @@ -178,7 +180,7 @@ func imageConvertAction(cmd *cobra.Command, args []string) error { return err } - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } @@ -458,7 +460,7 @@ func getNydusConvertOpts(cmd *cobra.Command) (*nydusconvert.PackOption, error) { return nil, err } if workDir == "" { - workDir, err = getDataStore(cmd) + workDir, err = nerdClient.GetDataStore(cmd) if err != nil { return nil, err } @@ -524,7 +526,7 @@ func readPathsFromRecordFile(filename string) ([]string, error) { func imageConvertShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show image names - return shellCompleteImageNames(cmd) + return completion.ShellCompleteImageNames(cmd) } func printConvertedImage(cmd *cobra.Command, img converterutil.ConvertedImageInfo) error { diff --git a/cmd/nerdctl/image_cryptutil.go b/cmd/nerdctl/image/image_cryptutil.go similarity index 95% rename from cmd/nerdctl/image_cryptutil.go rename to cmd/nerdctl/image/image_cryptutil.go index 18d232ebb82..1a6bfac5c25 100644 --- a/cmd/nerdctl/image_cryptutil.go +++ b/cmd/nerdctl/image/image_cryptutil.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package image import ( "context" @@ -25,6 +25,8 @@ import ( "github.com/containerd/containerd/images/converter" "github.com/containerd/imgcrypt/images/encryption" "github.com/containerd/imgcrypt/images/encryption/parsehelpers" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/pkg/platformutil" "github.com/containerd/nerdctl/pkg/referenceutil" ocispec "github.com/opencontainers/image-spec/specs-go/v1" @@ -43,7 +45,7 @@ func registerImgcryptFlags(cmd *cobra.Command, encrypt bool) { // #region platform flags // platform is defined as StringSlice, not StringArray, to allow specifying "--platform=amd64,arm64" flags.StringSlice("platform", []string{}, "Convert content for a specific platform") - cmd.RegisterFlagCompletionFunc("platform", shellCompletePlatforms) + cmd.RegisterFlagCompletionFunc("platform", completion.ShellCompletePlatforms) flags.Bool("all-platforms", false, "Convert content for all platforms") // #endregion @@ -136,7 +138,7 @@ func getImgcryptAction(encrypt bool) func(cmd *cobra.Command, args []string) err return err } - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } @@ -196,5 +198,5 @@ func composeConvertFunc(a, b converter.ConvertFunc) converter.ConvertFunc { func imgcryptShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show image names - return shellCompleteImageNames(cmd) + return completion.ShellCompleteImageNames(cmd) } diff --git a/cmd/nerdctl/image_decrypt.go b/cmd/nerdctl/image/image_decrypt.go similarity index 97% rename from cmd/nerdctl/image_decrypt.go rename to cmd/nerdctl/image/image_decrypt.go index fa6faf46629..9dedc9a3d93 100644 --- a/cmd/nerdctl/image_decrypt.go +++ b/cmd/nerdctl/image/image_decrypt.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package image import ( "github.com/spf13/cobra" @@ -45,7 +45,7 @@ Example (decrypt): nerdctl image decrypt --key=mykey.pem example.com/foo:encrypted foo:decrypted ` -func newImageDecryptCommand() *cobra.Command { +func NewImageDecryptCommand() *cobra.Command { cmd := &cobra.Command{ Use: "decrypt [flags] ...", Short: "decrypt an image", diff --git a/cmd/nerdctl/image_encrypt.go b/cmd/nerdctl/image/image_encrypt.go similarity index 97% rename from cmd/nerdctl/image_encrypt.go rename to cmd/nerdctl/image/image_encrypt.go index 39ee30659f3..92e9c6ea91a 100644 --- a/cmd/nerdctl/image_encrypt.go +++ b/cmd/nerdctl/image/image_encrypt.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package image import ( "github.com/spf13/cobra" @@ -45,7 +45,7 @@ CAUTION: This command only encrypts image layers, but does NOT encrypt container To see non-encrypted information, run 'nerdctl image inspect --mode=native --platform=PLATFORM example.com/foo:encrypted' . ` -func newImageEncryptCommand() *cobra.Command { +func NewImageEncryptCommand() *cobra.Command { cmd := &cobra.Command{ Use: "encrypt [flags] ...", Short: "encrypt image layers", diff --git a/cmd/nerdctl/image_inspect.go b/cmd/nerdctl/image/image_inspect.go similarity index 86% rename from cmd/nerdctl/image_inspect.go rename to cmd/nerdctl/image/image_inspect.go index 15e5bf912fa..ba8f4d25f83 100644 --- a/cmd/nerdctl/image_inspect.go +++ b/cmd/nerdctl/image/image_inspect.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package image import ( "context" @@ -23,6 +23,9 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/platforms" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/fmtutil" "github.com/containerd/nerdctl/pkg/idutil/imagewalker" "github.com/containerd/nerdctl/pkg/imageinspector" "github.com/containerd/nerdctl/pkg/inspecttypes/dockercompat" @@ -30,7 +33,7 @@ import ( "github.com/spf13/cobra" ) -func newImageInspectCommand() *cobra.Command { +func NewImageInspectCommand() *cobra.Command { var imageInspectCommand = &cobra.Command{ Use: "inspect [flags] IMAGE [IMAGE...]", Args: cobra.MinimumNArgs(1), @@ -52,7 +55,7 @@ func newImageInspectCommand() *cobra.Command { // #region platform flags imageInspectCommand.Flags().String("platform", "", "Inspect a specific platform") // not a slice, and there is no --all-platforms - imageInspectCommand.RegisterFlagCompletionFunc("platform", shellCompletePlatforms) + imageInspectCommand.RegisterFlagCompletionFunc("platform", completion.ShellCompletePlatforms) // #endregion return imageInspectCommand @@ -63,10 +66,10 @@ func imageInspectAction(cmd *cobra.Command, args []string) error { if err != nil { return err } - return imageInspectActionWithPlatform(cmd, args, platform) + return InspectActionWithPlatform(cmd, args, platform) } -func imageInspectActionWithPlatform(cmd *cobra.Command, args []string, platform string) error { +func InspectActionWithPlatform(cmd *cobra.Command, args []string, platform string) error { var clientOpts []containerd.ClientOpt if platform != "" { platformParsed, err := platforms.Parse(platform) @@ -76,7 +79,7 @@ func imageInspectActionWithPlatform(cmd *cobra.Command, args []string, platform platformM := platforms.Only(platformParsed) clientOpts = append(clientOpts, containerd.WithDefaultPlatform(platformM)) } - client, ctx, cancel, err := newClient(cmd, clientOpts...) + client, ctx, cancel, err := nerdClient.NewClient(cmd, clientOpts...) if err != nil { return err } @@ -129,7 +132,7 @@ func imageInspectActionWithPlatform(cmd *cobra.Command, args []string, platform return fmt.Errorf("%d errors: %v", len(errs), errs) } - return formatSlice(cmd, f.entries) + return fmtutil.FormatSlice(cmd, f.entries) } type imageInspector struct { @@ -139,5 +142,5 @@ type imageInspector struct { func imageInspectShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show image names - return shellCompleteImageNames(cmd) + return completion.ShellCompleteImageNames(cmd) } diff --git a/cmd/nerdctl/image_prune.go b/cmd/nerdctl/image/image_prune.go similarity index 91% rename from cmd/nerdctl/image_prune.go rename to cmd/nerdctl/image/image_prune.go index ee869a183e0..f127e50032b 100644 --- a/cmd/nerdctl/image_prune.go +++ b/cmd/nerdctl/image/image_prune.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package image import ( "context" @@ -24,12 +24,13 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/images" "github.com/containerd/containerd/platforms" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/opencontainers/go-digest" "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) -func newImagePruneCommand() *cobra.Command { +func NewImagePruneCommand() *cobra.Command { imagePruneCommand := &cobra.Command{ Use: "prune [flags]", Short: "Remove unused images", @@ -74,16 +75,16 @@ func imagePruneAction(cmd *cobra.Command, _ []string) error { } } - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } defer cancel() - return imagePrune(ctx, cmd, client) + return Prune(ctx, cmd, client) } -func imagePrune(ctx context.Context, cmd *cobra.Command, client *containerd.Client) error { +func Prune(ctx context.Context, cmd *cobra.Command, client *containerd.Client) error { var ( imageStore = client.ImageService() contentStore = client.ContentStore() diff --git a/cmd/nerdctl/images.go b/cmd/nerdctl/image/images.go similarity index 88% rename from cmd/nerdctl/images.go rename to cmd/nerdctl/image/images.go index 60ffd9165e6..2b136732ecb 100644 --- a/cmd/nerdctl/images.go +++ b/cmd/nerdctl/image/images.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package image import ( "bytes" @@ -31,22 +31,24 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/content" - "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/images" "github.com/containerd/containerd/pkg/progress" "github.com/containerd/containerd/platforms" dockerreference "github.com/containerd/containerd/reference/docker" "github.com/containerd/containerd/snapshots" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/utils" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/fmtutil" "github.com/containerd/nerdctl/pkg/formatter" "github.com/containerd/nerdctl/pkg/imgutil" "github.com/containerd/nerdctl/pkg/referenceutil" - "github.com/opencontainers/image-spec/identity" v1 "github.com/opencontainers/image-spec/specs-go/v1" "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) -func newImagesCommand() *cobra.Command { +func NewImagesCommand() *cobra.Command { shortHelp := "List images" longHelp := shortHelp + ` @@ -98,7 +100,7 @@ func imagesAction(cmd *cobra.Command, args []string) error { filters = append(filters, fmt.Sprintf("name==%s", canonicalRef.String())) filters = append(filters, fmt.Sprintf("name==%s", args[0])) } - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } @@ -267,7 +269,7 @@ func printImages(ctx context.Context, cmd *cobra.Command, client *containerd.Cli return errors.New("format and quiet must not be specified together") } var err error - tmpl, err = parseTemplate(format) + tmpl, err = fmtutil.ParseTemplate(format) if err != nil { return err } @@ -295,7 +297,7 @@ func printImages(ctx context.Context, cmd *cobra.Command, client *containerd.Cli logrus.Warn(err) } } - if f, ok := w.(Flusher); ok { + if f, ok := w.(fmtutil.Flusher); ok { return f.Flush() } return nil @@ -350,7 +352,7 @@ func (x *imagePrinter) printImageSinglePlatform(ctx context.Context, img images. logrus.WithError(err).Warnf("failed to get blob size of image %q for platform %q", img.Name, platforms.Format(ociPlatform)) } - size, err := unpackedImageSize(ctx, x.snapshotter, image) + size, err := utils.UnpackedImageSize(ctx, x.snapshotter, image) if err != nil { logrus.WithError(err).Warnf("failed to get unpacked size of image %q for platform %q", img.Name, platforms.Format(ociPlatform)) } @@ -416,60 +418,7 @@ func (x *imagePrinter) printImageSinglePlatform(ctx context.Context, img images. func imagesShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if len(args) == 0 { // show image names - return shellCompleteImageNames(cmd) + return completion.ShellCompleteImageNames(cmd) } return nil, cobra.ShellCompDirectiveNoFileComp } - -type snapshotKey string - -// recursive function to calculate total usage of key's parent -func (key snapshotKey) add(ctx context.Context, s snapshots.Snapshotter, usage *snapshots.Usage) error { - if key == "" { - return nil - } - u, err := s.Usage(ctx, string(key)) - if err != nil { - return err - } - - usage.Add(u) - - info, err := s.Stat(ctx, string(key)) - if err != nil { - return err - } - - key = snapshotKey(info.Parent) - return key.add(ctx, s, usage) -} - -// unpackedImageSize is the size of the unpacked snapshots. -// Does not contain the size of the blobs in the content store. (Corresponds to Docker). -func unpackedImageSize(ctx context.Context, s snapshots.Snapshotter, img containerd.Image) (int64, error) { - diffIDs, err := img.RootFS(ctx) - if err != nil { - return 0, err - } - - chainID := identity.ChainID(diffIDs).String() - usage, err := s.Usage(ctx, chainID) - if err != nil { - if errdefs.IsNotFound(err) { - logrus.WithError(err).Debugf("image %q seems not unpacked", img.Name()) - return 0, nil - } - return 0, err - } - - info, err := s.Stat(ctx, chainID) - if err != nil { - return 0, err - } - - //add ChainID's parent usage to the total usage - if err := snapshotKey(info.Parent).add(ctx, s, &usage); err != nil { - return 0, err - } - return usage.Size, nil -} diff --git a/cmd/nerdctl/inspect.go b/cmd/nerdctl/inspect/inspect.go similarity index 86% rename from cmd/nerdctl/inspect.go rename to cmd/nerdctl/inspect/inspect.go index 0bb29b7939e..a4d8b763241 100644 --- a/cmd/nerdctl/inspect.go +++ b/cmd/nerdctl/inspect/inspect.go @@ -14,19 +14,23 @@ limitations under the License. */ -package main +package inspect import ( "context" "fmt" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/container" + "github.com/containerd/nerdctl/cmd/nerdctl/image" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" "github.com/containerd/nerdctl/pkg/idutil/imagewalker" "github.com/spf13/cobra" ) -func newInspectCommand() *cobra.Command { +func NewInspectCommand() *cobra.Command { var inspectCommand = &cobra.Command{ Use: "inspect", Short: "Return low-level information on objects.", @@ -72,7 +76,7 @@ func inspectAction(cmd *cobra.Command, args []string) error { return fmt.Errorf("%q is not a valid value for --type", inspectType) } - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } @@ -115,13 +119,13 @@ func inspectAction(cmd *cobra.Command, args []string) error { return fmt.Errorf("no such object %s", req) } if nc != 0 { - if err := containerInspectAction(cmd, []string{req}); err != nil { + if err := container.InspectAction(cmd, []string{req}); err != nil { errs = append(errs, err) } continue } if ni != 0 { - if err := imageInspectActionWithPlatform(cmd, []string{req}, ""); err != nil { + if err := image.InspectActionWithPlatform(cmd, []string{req}, ""); err != nil { errs = append(errs, err) } continue @@ -137,8 +141,8 @@ func inspectAction(cmd *cobra.Command, args []string) error { func inspectShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show container names - containers, _ := shellCompleteContainerNames(cmd, nil) + containers, _ := completion.ShellCompleteContainerNames(cmd, nil) // show image names - images, _ := shellCompleteImageNames(cmd) + images, _ := completion.ShellCompleteImageNames(cmd) return append(containers, images...), cobra.ShellCompDirectiveNoFileComp } diff --git a/cmd/nerdctl/internal.go b/cmd/nerdctl/internal/internal.go similarity index 89% rename from cmd/nerdctl/internal.go rename to cmd/nerdctl/internal/internal.go index 9f62d1ea2ae..644be4c6db2 100644 --- a/cmd/nerdctl/internal.go +++ b/cmd/nerdctl/internal/internal.go @@ -14,13 +14,13 @@ limitations under the License. */ -package main +package internal import ( "github.com/spf13/cobra" ) -func newInternalCommand() *cobra.Command { +func NewInternalCommand() *cobra.Command { var internalCommand = &cobra.Command{ Use: "internal", Short: "DO NOT EXECUTE MANUALLY", @@ -30,7 +30,7 @@ func newInternalCommand() *cobra.Command { } internalCommand.AddCommand( - newInternalOCIHookCommandCommand(), + NewInternalOCIHookCommandCommand(), ) return internalCommand diff --git a/cmd/nerdctl/internal_oci_hook.go b/cmd/nerdctl/internal/internal_oci_hook.go similarity index 89% rename from cmd/nerdctl/internal_oci_hook.go rename to cmd/nerdctl/internal/internal_oci_hook.go index 486c11664c7..a81b3150614 100644 --- a/cmd/nerdctl/internal_oci_hook.go +++ b/cmd/nerdctl/internal/internal_oci_hook.go @@ -14,18 +14,19 @@ limitations under the License. */ -package main +package internal import ( "errors" "os" + "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/pkg/ocihook" "github.com/spf13/cobra" ) -func newInternalOCIHookCommandCommand() *cobra.Command { +func NewInternalOCIHookCommandCommand() *cobra.Command { var internalOCIHookCommand = &cobra.Command{ Use: "oci-hook", Short: "OCI hook", @@ -44,7 +45,7 @@ func internalOCIHookAction(cmd *cobra.Command, args []string) error { if event == "" { return errors.New("event type needs to be passed") } - dataStore, err := getDataStore(cmd) + dataStore, err := client.GetDataStore(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/ipfs.go b/cmd/nerdctl/ipfs/ipfs.go similarity index 71% rename from cmd/nerdctl/ipfs.go rename to cmd/nerdctl/ipfs/ipfs.go index 871077e1e5f..3c6f20ada1e 100644 --- a/cmd/nerdctl/ipfs.go +++ b/cmd/nerdctl/ipfs/ipfs.go @@ -14,23 +14,25 @@ limitations under the License. */ -package main +package ipfs import ( + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" "github.com/spf13/cobra" ) -func newIPFSCommand() *cobra.Command { +func NewIPFSCommand() *cobra.Command { cmd := &cobra.Command{ - Annotations: map[string]string{Category: Management}, + Annotations: map[string]string{common.Category: common.Management}, Use: "ipfs", Short: "Distributing images on IPFS", - RunE: unknownSubcommandAction, + RunE: completion.UnknownSubcommandAction, SilenceUsage: true, SilenceErrors: true, } cmd.AddCommand( - newIPFSRegistryCommand(), + NewIPFSRegistryCommand(), ) return cmd } diff --git a/cmd/nerdctl/ipfs_registry.go b/cmd/nerdctl/ipfs/ipfs_registry.go similarity index 62% rename from cmd/nerdctl/ipfs_registry.go rename to cmd/nerdctl/ipfs/ipfs_registry.go index c5d72d08569..d5829315afd 100644 --- a/cmd/nerdctl/ipfs_registry.go +++ b/cmd/nerdctl/ipfs/ipfs_registry.go @@ -14,26 +14,29 @@ limitations under the License. */ -package main +package ipfs import ( + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/utils" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" "github.com/spf13/cobra" ) -func newIPFSRegistryCommand() *cobra.Command { +func NewIPFSRegistryCommand() *cobra.Command { cmd := &cobra.Command{ - Annotations: map[string]string{Category: Management}, + Annotations: map[string]string{common.Category: common.Management}, Use: "registry", Short: "Manage read-only registry backed by IPFS", - PreRunE: checkExperimental("ipfs"), - RunE: unknownSubcommandAction, + PreRunE: utils.CheckExperimental("ipfs"), + RunE: completion.UnknownSubcommandAction, SilenceUsage: true, SilenceErrors: true, } cmd.AddCommand( - newIPFSRegistryServeCommand(), - newIPFSRegistryUpCommand(), - newIPFSRegistryDownCommand(), + NewIPFSRegistryServeCommand(), + NewIPFSRegistryUpCommand(), + NewIPFSRegistryDownCommand(), ) return cmd } diff --git a/cmd/nerdctl/ipfs_registry_down.go b/cmd/nerdctl/ipfs/ipfs_registry_down.go similarity index 86% rename from cmd/nerdctl/ipfs_registry_down.go rename to cmd/nerdctl/ipfs/ipfs_registry_down.go index 5ccecda4d05..48f25c64bd2 100644 --- a/cmd/nerdctl/ipfs_registry_down.go +++ b/cmd/nerdctl/ipfs/ipfs_registry_down.go @@ -14,18 +14,20 @@ limitations under the License. */ -package main +package ipfs import ( "context" "fmt" "os/exec" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" "github.com/spf13/cobra" ) -func newIPFSRegistryDownCommand() *cobra.Command { +func NewIPFSRegistryDownCommand() *cobra.Command { var ipfsRegistryDownCommand = &cobra.Command{ Use: "down", Short: "stop registry as a background container \"ipfs-registry\".", @@ -38,7 +40,7 @@ func newIPFSRegistryDownCommand() *cobra.Command { } func ipfsRegistryDownAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } @@ -56,7 +58,7 @@ func ipfsRegistryDownAction(cmd *cobra.Command, args []string) error { if nc == 0 { return fmt.Errorf("ipfs registry %q doesn't exist", ipfsRegistryContainerName) } - nerdctlCmd, nerdctlArgs := globalFlags(cmd) + nerdctlCmd, nerdctlArgs := utils.GlobalFlags(cmd) if out, err := exec.Command(nerdctlCmd, append(nerdctlArgs, "stop", ipfsRegistryContainerName)...).CombinedOutput(); err != nil { return fmt.Errorf("failed to stop registry: %v: %v", string(out), err) } diff --git a/cmd/nerdctl/ipfs_registry_serve.go b/cmd/nerdctl/ipfs/ipfs_registry_serve.go similarity index 97% rename from cmd/nerdctl/ipfs_registry_serve.go rename to cmd/nerdctl/ipfs/ipfs_registry_serve.go index 51214d10fbf..fa191b91bf1 100644 --- a/cmd/nerdctl/ipfs_registry_serve.go +++ b/cmd/nerdctl/ipfs/ipfs_registry_serve.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package ipfs import ( "fmt" @@ -33,7 +33,7 @@ const ( defaultIPFSReadTimeoutDuration = 0 ) -func newIPFSRegistryServeCommand() *cobra.Command { +func NewIPFSRegistryServeCommand() *cobra.Command { var ipfsRegistryServeCommand = &cobra.Command{ Use: "serve", Short: "serve read-only registry backed by IPFS on localhost. Use \"nerdctl ipfs registry up\".", diff --git a/cmd/nerdctl/ipfs_registry_up.go b/cmd/nerdctl/ipfs/ipfs_registry_up.go similarity index 91% rename from cmd/nerdctl/ipfs_registry_up.go rename to cmd/nerdctl/ipfs/ipfs_registry_up.go index d6085027cf6..4aa73a2bd64 100644 --- a/cmd/nerdctl/ipfs_registry_up.go +++ b/cmd/nerdctl/ipfs/ipfs_registry_up.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package ipfs import ( "context" @@ -25,6 +25,8 @@ import ( "path/filepath" "time" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" "github.com/hashicorp/go-multierror" httpapi "github.com/ipfs/go-ipfs-http-client" @@ -34,10 +36,10 @@ import ( const ipfsRegistryContainerName = "ipfs-registry" -func newIPFSRegistryUpCommand() *cobra.Command { +func NewIPFSRegistryUpCommand() *cobra.Command { var ipfsRegistryUpCommand = &cobra.Command{ Use: "up", - Short: "start registry as a background container \"ipfs-registry\", backed by the current user's IPFS API", + Short: "Start registry as a background container \"ipfs-registry\", backed by the current user's IPFS API", RunE: ipfsRegistryUpAction, SilenceUsage: true, SilenceErrors: true, @@ -51,7 +53,7 @@ func newIPFSRegistryUpCommand() *cobra.Command { } func ipfsRegistryUpAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } @@ -92,11 +94,11 @@ func runRegistryAsContainer(cmd *cobra.Command) error { if err != nil { return err } - dataStore, err := getDataStore(cmd) + dataStore, err := nerdClient.GetDataStore(cmd) if err != nil { return err } - nerdctlCmd, nerdctlArgs := globalFlags(cmd) + nerdctlCmd, nerdctlArgs := utils.GlobalFlags(cmd) registryRoot := filepath.Join(dataStore, "ipfs-registry", "rootfs") if err := os.RemoveAll(registryRoot); err != nil { return err diff --git a/cmd/nerdctl/load.go b/cmd/nerdctl/load/load.go similarity index 54% rename from cmd/nerdctl/load.go rename to cmd/nerdctl/load/load.go index 02e43d559c3..6e2ce07ae0f 100644 --- a/cmd/nerdctl/load.go +++ b/cmd/nerdctl/load/load.go @@ -14,24 +14,20 @@ limitations under the License. */ -package main +package load import ( "errors" - "fmt" - "io" "os" - "github.com/containerd/containerd" "github.com/containerd/containerd/archive/compression" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/images/archive" - "github.com/containerd/containerd/platforms" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/pkg/platformutil" "github.com/spf13/cobra" ) -func newLoadCommand() *cobra.Command { +func NewLoadCommand() *cobra.Command { var loadCommand = &cobra.Command{ Use: "load", Args: cobra.NoArgs, @@ -47,7 +43,7 @@ func newLoadCommand() *cobra.Command { // #region platform flags // platform is defined as StringSlice, not StringArray, to allow specifying "--platform=amd64,arm64" loadCommand.Flags().StringSlice("platform", []string{}, "Import content for a specific platform") - loadCommand.RegisterFlagCompletionFunc("platform", shellCompletePlatforms) + loadCommand.RegisterFlagCompletionFunc("platform", completion.ShellCompletePlatforms) loadCommand.Flags().Bool("all-platforms", false, "Import content for all platforms") // #endregion @@ -95,65 +91,5 @@ func loadAction(cmd *cobra.Command, _ []string) error { return err } - return loadImage(decompressor, cmd, platMC, false) -} - -func loadImage(in io.Reader, cmd *cobra.Command, platMC platforms.MatchComparer, quiet bool) error { - // In addition to passing WithImagePlatform() to client.Import(), we also need to pass WithDefaultPlatform() to newClient(). - // Otherwise unpacking may fail. - client, ctx, cancel, err := newClient(cmd, containerd.WithDefaultPlatform(platMC)) - if err != nil { - return err - } - defer cancel() - - sn, err := cmd.Flags().GetString("snapshotter") - if err != nil { - return err - } - - r := &readCounter{Reader: in} - imgs, err := client.Import(ctx, r, containerd.WithDigestRef(archive.DigestTranslator(sn)), containerd.WithSkipDigestRef(func(name string) bool { return name != "" }), containerd.WithImportPlatform(platMC)) - if err != nil { - if r.N == 0 { - // Avoid confusing "unrecognized image format" - return errors.New("no image was built") - } - if errors.Is(err, images.ErrEmptyWalk) { - err = fmt.Errorf("%w (Hint: set `--platform=PLATFORM` or `--all-platforms`)", err) - } - return err - } - for _, img := range imgs { - image := containerd.NewImageWithPlatform(client, img, platMC) - - // TODO: Show unpack status - if !quiet { - fmt.Fprintf(cmd.OutOrStdout(), "unpacking %s (%s)...\n", img.Name, img.Target.Digest) - } - err = image.Unpack(ctx, sn) - if err != nil { - return err - } - if quiet { - fmt.Fprintln(cmd.OutOrStdout(), img.Target.Digest) - } else { - fmt.Fprintf(cmd.OutOrStdout(), "Loaded image: %s\n", img.Name) - } - } - - return nil -} - -type readCounter struct { - io.Reader - N int -} - -func (r *readCounter) Read(p []byte) (int, error) { - n, err := r.Reader.Read(p) - if n > 0 { - r.N += n - } - return n, err + return utils.LoadImage(decompressor, cmd, platMC, false) } diff --git a/cmd/nerdctl/login.go b/cmd/nerdctl/login/login.go similarity index 99% rename from cmd/nerdctl/login.go rename to cmd/nerdctl/login/login.go index 78d954411eb..41274d59a4b 100644 --- a/cmd/nerdctl/login.go +++ b/cmd/nerdctl/login/login.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package login import ( "bufio" @@ -56,7 +56,7 @@ https://docs.docker.com/engine/reference/commandline/login/#credentials-store var options = new(loginOptions) -func newLoginCommand() *cobra.Command { +func NewLoginCommand() *cobra.Command { var loginCommand = &cobra.Command{ Use: "login [flags] [SERVER]", Args: cobra.MaximumNArgs(1), diff --git a/cmd/nerdctl/login_unix.go b/cmd/nerdctl/login/login_unix.go similarity index 98% rename from cmd/nerdctl/login_unix.go rename to cmd/nerdctl/login/login_unix.go index c117a330961..ee536be1721 100644 --- a/cmd/nerdctl/login_unix.go +++ b/cmd/nerdctl/login/login_unix.go @@ -16,7 +16,7 @@ limitations under the License. */ -package main +package login import ( "fmt" diff --git a/cmd/nerdctl/login_windows.go b/cmd/nerdctl/login/login_windows.go similarity index 98% rename from cmd/nerdctl/login_windows.go rename to cmd/nerdctl/login/login_windows.go index 236ac17213b..89c3834fb92 100644 --- a/cmd/nerdctl/login_windows.go +++ b/cmd/nerdctl/login/login_windows.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package login import ( "fmt" diff --git a/cmd/nerdctl/logout.go b/cmd/nerdctl/logout/logout.go similarity index 98% rename from cmd/nerdctl/logout.go rename to cmd/nerdctl/logout/logout.go index 09b4ee43179..c7c03048289 100644 --- a/cmd/nerdctl/logout.go +++ b/cmd/nerdctl/logout/logout.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package logout import ( "fmt" @@ -24,7 +24,7 @@ import ( "github.com/spf13/cobra" ) -func newLogoutCommand() *cobra.Command { +func NewLogoutCommand() *cobra.Command { var logoutCommand = &cobra.Command{ Use: "logout [flags] [SERVER]", Args: cobra.MaximumNArgs(1), diff --git a/cmd/nerdctl/main.go b/cmd/nerdctl/main.go index dd192ebd958..48414984afd 100644 --- a/cmd/nerdctl/main.go +++ b/cmd/nerdctl/main.go @@ -21,12 +21,43 @@ import ( "fmt" "os" "runtime" - "strconv" "strings" "github.com/containerd/containerd" "github.com/containerd/containerd/defaults" "github.com/containerd/containerd/namespaces" + "github.com/containerd/nerdctl/cmd/nerdctl/apparmor" + "github.com/containerd/nerdctl/cmd/nerdctl/build" + "github.com/containerd/nerdctl/cmd/nerdctl/builder" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/compose" + "github.com/containerd/nerdctl/cmd/nerdctl/container" + "github.com/containerd/nerdctl/cmd/nerdctl/container/cp" + "github.com/containerd/nerdctl/cmd/nerdctl/container/exec" + "github.com/containerd/nerdctl/cmd/nerdctl/event" + "github.com/containerd/nerdctl/cmd/nerdctl/history" + "github.com/containerd/nerdctl/cmd/nerdctl/image" + "github.com/containerd/nerdctl/cmd/nerdctl/inspect" + "github.com/containerd/nerdctl/cmd/nerdctl/internal" + "github.com/containerd/nerdctl/cmd/nerdctl/ipfs" + "github.com/containerd/nerdctl/cmd/nerdctl/load" + "github.com/containerd/nerdctl/cmd/nerdctl/login" + "github.com/containerd/nerdctl/cmd/nerdctl/logout" + "github.com/containerd/nerdctl/cmd/nerdctl/namespace" + "github.com/containerd/nerdctl/cmd/nerdctl/network" + "github.com/containerd/nerdctl/cmd/nerdctl/ps" + "github.com/containerd/nerdctl/cmd/nerdctl/pull" + "github.com/containerd/nerdctl/cmd/nerdctl/push" + "github.com/containerd/nerdctl/cmd/nerdctl/rmi" + "github.com/containerd/nerdctl/cmd/nerdctl/save" + "github.com/containerd/nerdctl/cmd/nerdctl/stats" + "github.com/containerd/nerdctl/cmd/nerdctl/system" + "github.com/containerd/nerdctl/cmd/nerdctl/tag" + "github.com/containerd/nerdctl/cmd/nerdctl/top" + "github.com/containerd/nerdctl/cmd/nerdctl/utils" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" + version2 "github.com/containerd/nerdctl/cmd/nerdctl/version" + "github.com/containerd/nerdctl/cmd/nerdctl/volume" ncdefaults "github.com/containerd/nerdctl/pkg/defaults" "github.com/containerd/nerdctl/pkg/logging" "github.com/containerd/nerdctl/pkg/rootlessutil" @@ -38,11 +69,6 @@ import ( "github.com/spf13/pflag" ) -const ( - Category = "category" - Management = "management" -) - // usage was derived from https://github.com/spf13/cobra/blob/v1.2.1/command.go#L491-L514 func usage(c *cobra.Command) error { s := "Usage: " @@ -63,7 +89,7 @@ func usage(c *cobra.Command) error { var managementCommands, nonManagementCommands []*cobra.Command for _, f := range c.Commands() { f := f - if f.Annotations[Category] == Management { + if f.Annotations[common.Category] == common.Management { managementCommands = append(managementCommands, f) } else { nonManagementCommands = append(nonManagementCommands, f) @@ -106,7 +132,7 @@ func usage(c *cobra.Command) error { func main() { if err := xmain(); err != nil { - HandleExitCoder(err) + common.HandleExitCoder(err) logrus.Fatal(err) } } @@ -182,23 +208,23 @@ func initRootCmdFlags(rootCmd *cobra.Command, tomlPath string) (*pflag.FlagSet, rootCmd.PersistentFlags().Bool("debug", cfg.Debug, "debug mode") rootCmd.PersistentFlags().Bool("debug-full", cfg.DebugFull, "debug mode (with full output)") // -a is aliases (conflicts with nerdctl images -a) - AddPersistentStringFlag(rootCmd, "address", []string{"a", "H"}, nil, []string{"host"}, aliasToBeInherited, cfg.Address, "CONTAINERD_ADDRESS", `containerd address, optionally with "unix://" prefix`) + utils.AddPersistentStringFlag(rootCmd, "address", []string{"a", "H"}, nil, []string{"host"}, aliasToBeInherited, cfg.Address, "CONTAINERD_ADDRESS", `containerd address, optionally with "unix://" prefix`) // -n is aliases (conflicts with nerdctl logs -n) - AddPersistentStringFlag(rootCmd, "namespace", []string{"n"}, nil, nil, aliasToBeInherited, cfg.Namespace, "CONTAINERD_NAMESPACE", `containerd namespace, such as "moby" for Docker, "k8s.io" for Kubernetes`) - rootCmd.RegisterFlagCompletionFunc("namespace", shellCompleteNamespaceNames) - AddPersistentStringFlag(rootCmd, "snapshotter", nil, nil, []string{"storage-driver"}, aliasToBeInherited, cfg.Snapshotter, "CONTAINERD_SNAPSHOTTER", "containerd snapshotter") - rootCmd.RegisterFlagCompletionFunc("snapshotter", shellCompleteSnapshotterNames) - rootCmd.RegisterFlagCompletionFunc("storage-driver", shellCompleteSnapshotterNames) - AddPersistentStringFlag(rootCmd, "cni-path", nil, nil, nil, aliasToBeInherited, cfg.CNIPath, "CNI_PATH", "cni plugins binary directory") - AddPersistentStringFlag(rootCmd, "cni-netconfpath", nil, nil, nil, aliasToBeInherited, cfg.CNINetConfPath, "NETCONFPATH", "cni config directory") + utils.AddPersistentStringFlag(rootCmd, "namespace", []string{"n"}, nil, nil, aliasToBeInherited, cfg.Namespace, "CONTAINERD_NAMESPACE", `containerd namespace, such as "moby" for Docker, "k8s.io" for Kubernetes`) + rootCmd.RegisterFlagCompletionFunc("namespace", completion.ShellCompleteNamespaceNames) + utils.AddPersistentStringFlag(rootCmd, "snapshotter", nil, nil, []string{"storage-driver"}, aliasToBeInherited, cfg.Snapshotter, "CONTAINERD_SNAPSHOTTER", "containerd snapshotter") + rootCmd.RegisterFlagCompletionFunc("snapshotter", completion.ShellCompleteSnapshotterNames) + rootCmd.RegisterFlagCompletionFunc("storage-driver", completion.ShellCompleteSnapshotterNames) + utils.AddPersistentStringFlag(rootCmd, "cni-path", nil, nil, nil, aliasToBeInherited, cfg.CNIPath, "CNI_PATH", "cni plugins binary directory") + utils.AddPersistentStringFlag(rootCmd, "cni-netconfpath", nil, nil, nil, aliasToBeInherited, cfg.CNINetConfPath, "NETCONFPATH", "cni config directory") rootCmd.PersistentFlags().String("data-root", cfg.DataRoot, "Root directory of persistent nerdctl state (managed by nerdctl, not by containerd)") rootCmd.PersistentFlags().String("cgroup-manager", cfg.CgroupManager, `Cgroup manager to use ("cgroupfs"|"systemd")`) - rootCmd.RegisterFlagCompletionFunc("cgroup-manager", shellCompleteCgroupManagerNames) + rootCmd.RegisterFlagCompletionFunc("cgroup-manager", completion.ShellCompleteCgroupManagerNames) rootCmd.PersistentFlags().Bool("insecure-registry", cfg.InsecureRegistry, "skips verifying HTTPS certs, and allows falling back to plain HTTP") // hosts-dir is defined as StringSlice, not StringArray, to allow specifying "--hosts-dir=/etc/containerd/certs.d,/etc/docker/certs.d" rootCmd.PersistentFlags().StringSlice("hosts-dir", cfg.HostsDir, "A directory that contains /hosts.toml (containerd style) or /{ca.cert, cert.pem, key.pem} (docker style)") // Experimental enable experimental feature, see in https://github.com/containerd/nerdctl/blob/main/docs/experimental.md - AddPersistentBoolFlag(rootCmd, "experimental", nil, nil, cfg.Experimental, "NERDCTL_EXPERIMENTAL", "Control experimental: https://github.com/containerd/nerdctl/blob/main/docs/experimental.md") + utils.AddPersistentBoolFlag(rootCmd, "experimental", nil, nil, cfg.Experimental, "NERDCTL_EXPERIMENTAL", "Control experimental: https://github.com/containerd/nerdctl/blob/main/docs/experimental.md") return aliasToBeInherited, nil } @@ -264,329 +290,89 @@ Config file ($NERDCTL_TOML): %s } return nil } - rootCmd.RunE = unknownSubcommandAction + rootCmd.RunE = completion.UnknownSubcommandAction rootCmd.AddCommand( - newCreateCommand(), + container.NewCreateCommand(), // #region Run & Exec - newRunCommand(), - newUpdateCommand(), - newExecCommand(), + container.NewRunCommand(), + container.NewUpdateCommand(), + exec.NewExecCommand(), // #endregion // #region Container management - newPsCommand(), - newLogsCommand(), - newPortCommand(), - newStopCommand(), - newStartCommand(), - newRestartCommand(), - newKillCommand(), - newRmCommand(), - newPauseCommand(), - newUnpauseCommand(), - newCommitCommand(), - newWaitCommand(), - newRenameCommand(), + ps.NewPsCommand(), + container.NewLogsCommand(), + container.NewPortCommand(), + container.NewStopCommand(), + container.NewStartCommand(), + container.NewRestartCommand(), + container.NewKillCommand(), + container.NewRmCommand(), + container.NewPauseCommand(), + container.NewUnpauseCommand(), + container.NewCommitCommand(), + container.NewWaitCommand(), + container.NewRenameCommand(), // #endregion // Build - newBuildCommand(), + build.NewBuildCommand(), // #region Image management - newImagesCommand(), - newPullCommand(), - newPushCommand(), - newLoadCommand(), - newSaveCommand(), - newTagCommand(), - newRmiCommand(), - newHistoryCommand(), + image.NewImagesCommand(), + pull.NewPullCommand(), + push.NewPushCommand(), + load.NewLoadCommand(), + save.NewSaveCommand(), + tag.NewTagCommand(), + rmi.NewRmiCommand(), + history.NewHistoryCommand(), // #endregion // #region System - newEventsCommand(), - newInfoCommand(), - newVersionCommand(), + event.NewEventsCommand(), + system.NewInfoCommand(), + version2.NewVersionCommand(), // #endregion // Inspect - newInspectCommand(), + inspect.NewInspectCommand(), // stats - newTopCommand(), - newStatsCommand(), + top.NewTopCommand(), + stats.NewStatsCommand(), // #region Management - newContainerCommand(), - newImageCommand(), - newNetworkCommand(), - newVolumeCommand(), - newSystemCommand(), - newNamespaceCommand(), - newBuilderCommand(), + container.NewContainerCommand(), + image.NewImageCommand(), + network.NewNetworkCommand(), + volume.NewVolumeCommand(), + system.NewSystemCommand(), + namespace.NewNamespaceCommand(), + builder.NewBuilderCommand(), // #endregion // Internal - newInternalCommand(), + internal.NewInternalCommand(), // login - newLoginCommand(), + login.NewLoginCommand(), // Logout - newLogoutCommand(), + logout.NewLogoutCommand(), // Compose - newComposeCommand(), + compose.NewComposeCommand(), // IPFS - newIPFSCommand(), + ipfs.NewIPFSCommand(), ) - addApparmorCommand(rootCmd) - addCpCommand(rootCmd) + apparmor.AddApparmorCommand(rootCmd) + cp.AddCpCommand(rootCmd) - // add aliasToBeInherited to subCommand(s) InheritedFlags + // Add aliasToBeInherited to subCommand(s) InheritedFlags for _, subCmd := range rootCmd.Commands() { subCmd.InheritedFlags().AddFlagSet(aliasToBeInherited) } return rootCmd, nil } - -func globalFlags(cmd *cobra.Command) (string, []string) { - args0, err := os.Executable() - if err != nil { - logrus.WithError(err).Warnf("cannot call os.Executable(), assuming the executable to be %q", os.Args[0]) - args0 = os.Args[0] - } - if len(os.Args) < 2 { - return args0, nil - } - - rootCmd := cmd.Root() - flagSet := rootCmd.Flags() - args := []string{} - flagSet.VisitAll(func(f *pflag.Flag) { - key := f.Name - val := f.Value.String() - if f.Changed { - args = append(args, "--"+key+"="+val) - } - }) - return args0, args -} - -type ExitCoder interface { - error - ExitCode() int -} - -type ExitCodeError struct { - error - exitCode int -} - -func (e ExitCodeError) ExitCode() int { - return e.exitCode -} - -func HandleExitCoder(err error) { - if err == nil { - return - } - - if exitErr, ok := err.(ExitCoder); ok { - os.Exit(exitErr.ExitCode()) - } -} - -// unknownSubcommandAction is needed to let `nerdctl system non-existent-command` fail -// https://github.com/containerd/nerdctl/issues/487 -// -// Ideally this should be implemented in Cobra itself. -func unknownSubcommandAction(cmd *cobra.Command, args []string) error { - if len(args) == 0 { - return cmd.Help() - } - // The output mimics https://github.com/spf13/cobra/blob/v1.2.1/command.go#L647-L662 - msg := fmt.Sprintf("unknown subcommand %q for %q", args[0], cmd.Name()) - if suggestions := cmd.SuggestionsFor(args[0]); len(suggestions) > 0 { - msg += "\n\nDid you mean this?\n" - for _, s := range suggestions { - msg += fmt.Sprintf("\t%v\n", s) - } - } - return errors.New(msg) -} - -// AddStringFlag is similar to cmd.Flags().String but supports aliases and env var -func AddStringFlag(cmd *cobra.Command, name string, aliases []string, value string, env, usage string) { - if env != "" { - usage = fmt.Sprintf("%s [$%s]", usage, env) - } - if envV, ok := os.LookupEnv(env); ok { - value = envV - } - aliasesUsage := fmt.Sprintf("Alias of --%s", name) - p := new(string) - flags := cmd.Flags() - flags.StringVar(p, name, value, usage) - for _, a := range aliases { - if len(a) == 1 { - // pflag doesn't support short-only flags, so we have to register long one as well here - flags.StringVarP(p, a, a, value, aliasesUsage) - } else { - flags.StringVar(p, a, value, aliasesUsage) - } - } -} - -// AddPersistentStringFlag is similar to AddStringFlag but persistent. -// See https://github.com/spf13/cobra/blob/main/user_guide.md#persistent-flags to learn what is "persistent". -func AddPersistentStringFlag(cmd *cobra.Command, name string, aliases, localAliases, persistentAliases []string, aliasToBeInherited *pflag.FlagSet, value string, env, usage string) { - if env != "" { - usage = fmt.Sprintf("%s [$%s]", usage, env) - } - if envV, ok := os.LookupEnv(env); ok { - value = envV - } - aliasesUsage := fmt.Sprintf("Alias of --%s", name) - p := new(string) - - // flags is full set of flag(s) - // flags can redefine alias already used in subcommands - flags := cmd.Flags() - for _, a := range aliases { - if len(a) == 1 { - // pflag doesn't support short-only flags, so we have to register long one as well here - flags.StringVarP(p, a, a, value, aliasesUsage) - } else { - flags.StringVar(p, a, value, aliasesUsage) - } - // non-persistent flags are not added to the InheritedFlags, so we should add them manually - f := flags.Lookup(a) - aliasToBeInherited.AddFlag(f) - } - - // localFlags are local to the rootCmd - localFlags := cmd.LocalFlags() - for _, a := range localAliases { - if len(a) == 1 { - // pflag doesn't support short-only flags, so we have to register long one as well here - localFlags.StringVarP(p, a, a, value, aliasesUsage) - } else { - localFlags.StringVar(p, a, value, aliasesUsage) - } - } - - // persistentFlags cannot redefine alias already used in subcommands - persistentFlags := cmd.PersistentFlags() - persistentFlags.StringVar(p, name, value, usage) - for _, a := range persistentAliases { - if len(a) == 1 { - // pflag doesn't support short-only flags, so we have to register long one as well here - persistentFlags.StringVarP(p, a, a, value, aliasesUsage) - } else { - persistentFlags.StringVar(p, a, value, aliasesUsage) - } - } -} - -// AddPersistentBoolFlag is similar to AddBoolFlag but persistent. -// See https://github.com/spf13/cobra/blob/main/user_guide.md#persistent-flags to learn what is "persistent". -func AddPersistentBoolFlag(cmd *cobra.Command, name string, aliases, nonPersistentAliases []string, value bool, env, usage string) { - if env != "" { - usage = fmt.Sprintf("%s [$%s]", usage, env) - } - if envV, ok := os.LookupEnv(env); ok { - var err error - value, err = strconv.ParseBool(envV) - if err != nil { - logrus.WithError(err).Warnf("Invalid boolean value for `%s`", env) - } - } - aliasesUsage := fmt.Sprintf("Alias of --%s", name) - p := new(bool) - flags := cmd.Flags() - for _, a := range nonPersistentAliases { - if len(a) == 1 { - // pflag doesn't support short-only flags, so we have to register long one as well here - flags.BoolVarP(p, a, a, value, aliasesUsage) - } else { - flags.BoolVar(p, a, value, aliasesUsage) - } - } - - persistentFlags := cmd.PersistentFlags() - persistentFlags.BoolVar(p, name, value, usage) - for _, a := range aliases { - if len(a) == 1 { - // pflag doesn't support short-only flags, so we have to register long one as well here - persistentFlags.BoolVarP(p, a, a, value, aliasesUsage) - } else { - persistentFlags.BoolVar(p, a, value, aliasesUsage) - } - } -} - -// AddPersistentStringArrayFlag is similar to cmd.Flags().StringArray but supports aliases and env var and persistent. -// See https://github.com/spf13/cobra/blob/main/user_guide.md#persistent-flags to learn what is "persistent". -func AddPersistentStringArrayFlag(cmd *cobra.Command, name string, aliases, nonPersistentAliases []string, value []string, env string, usage string) { - if env != "" { - usage = fmt.Sprintf("%s [$%s]", usage, env) - } - if envV, ok := os.LookupEnv(env); ok { - value = []string{envV} - } - aliasesUsage := fmt.Sprintf("Alias of --%s", name) - p := new([]string) - flags := cmd.Flags() - for _, a := range nonPersistentAliases { - if len(a) == 1 { - // pflag doesn't support short-only flags, so we have to register long one as well here - flags.StringArrayVarP(p, a, a, value, aliasesUsage) - } else { - flags.StringArrayVar(p, a, value, aliasesUsage) - } - } - - persistentFlags := cmd.PersistentFlags() - persistentFlags.StringArrayVar(p, name, value, usage) - for _, a := range aliases { - if len(a) == 1 { - // pflag doesn't support short-only flags, so we have to register long one as well here - persistentFlags.StringArrayVarP(p, a, a, value, aliasesUsage) - } else { - persistentFlags.StringArrayVar(p, a, value, aliasesUsage) - } - } -} - -func checkExperimental(feature string) func(cmd *cobra.Command, args []string) error { - return func(cmd *cobra.Command, args []string) error { - experimental, err := cmd.Flags().GetBool("experimental") - if err != nil { - return err - } - if !experimental { - return fmt.Errorf("%s is experimental feature, you should enable experimental config", feature) - } - return nil - } -} - -// IsExactArgs returns an error if there is not the exact number of args -func IsExactArgs(number int) cobra.PositionalArgs { - return func(cmd *cobra.Command, args []string) error { - if len(args) == number { - return nil - } - return fmt.Errorf( - "%q requires exactly %d %s.\nSee '%s --help'.\n\nUsage: %s\n\n%s", - cmd.CommandPath(), - number, - "argument(s)", - cmd.CommandPath(), - cmd.UseLine(), - cmd.Short, - ) - } -} diff --git a/cmd/nerdctl/main_freebsd.go b/cmd/nerdctl/main_freebsd.go index 30ed7a9c1ea..9cb97aaf29e 100644 --- a/cmd/nerdctl/main_freebsd.go +++ b/cmd/nerdctl/main_freebsd.go @@ -23,15 +23,3 @@ import ( func appNeedsRootlessParentMain(cmd *cobra.Command, args []string) bool { return false } - -func shellCompleteCgroupManagerNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return nil, cobra.ShellCompDirectiveNoFileComp -} - -func addApparmorCommand(rootCmd *cobra.Command) { - // NOP -} - -func addCpCommand(rootCmd *cobra.Command) { - // NOP -} diff --git a/cmd/nerdctl/main_linux.go b/cmd/nerdctl/main_linux.go index a20cb00dbb6..bf01eba808c 100644 --- a/cmd/nerdctl/main_linux.go +++ b/cmd/nerdctl/main_linux.go @@ -17,7 +17,6 @@ package main import ( - ncdefaults "github.com/containerd/nerdctl/pkg/defaults" "github.com/containerd/nerdctl/pkg/rootlessutil" "github.com/containerd/nerdctl/pkg/strutil" "github.com/spf13/cobra" @@ -53,22 +52,3 @@ func appNeedsRootlessParentMain(cmd *cobra.Command, args []string) bool { } return true } - -func shellCompleteCgroupManagerNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - candidates := []string{"cgroupfs"} - if ncdefaults.IsSystemdAvailable() { - candidates = append(candidates, "systemd") - } - if rootlessutil.IsRootless() { - candidates = append(candidates, "none") - } - return candidates, cobra.ShellCompDirectiveNoFileComp -} - -func addApparmorCommand(rootCmd *cobra.Command) { - rootCmd.AddCommand(newApparmorCommand()) -} - -func addCpCommand(rootCmd *cobra.Command) { - rootCmd.AddCommand(newCpCommand()) -} diff --git a/cmd/nerdctl/main_unix.go b/cmd/nerdctl/main_unix.go index 3fe1f41105a..a6cad93d6d7 100644 --- a/cmd/nerdctl/main_unix.go +++ b/cmd/nerdctl/main_unix.go @@ -17,51 +17,3 @@ */ package main - -import ( - "github.com/containerd/nerdctl/pkg/infoutil" - "github.com/containerd/nerdctl/pkg/rootlessutil" - "github.com/sirupsen/logrus" - "github.com/spf13/cobra" -) - -func shellCompleteNamespaceNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - if rootlessutil.IsRootlessParent() { - _ = rootlessutil.ParentMain() - return nil, cobra.ShellCompDirectiveNoFileComp - } - - client, ctx, cancel, err := newClient(cmd) - if err != nil { - return nil, cobra.ShellCompDirectiveError - } - defer cancel() - nsService := client.NamespaceService() - nsList, err := nsService.List(ctx) - if err != nil { - logrus.Warn(err) - return nil, cobra.ShellCompDirectiveError - } - var candidates []string - candidates = append(candidates, nsList...) - return candidates, cobra.ShellCompDirectiveNoFileComp -} - -func shellCompleteSnapshotterNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - if rootlessutil.IsRootlessParent() { - _ = rootlessutil.ParentMain() - return nil, cobra.ShellCompDirectiveNoFileComp - } - client, ctx, cancel, err := newClient(cmd) - if err != nil { - return nil, cobra.ShellCompDirectiveError - } - defer cancel() - snapshotterPlugins, err := infoutil.GetSnapshotterNames(ctx, client.IntrospectionService()) - if err != nil { - return nil, cobra.ShellCompDirectiveError - } - var candidates []string - candidates = append(candidates, snapshotterPlugins...) - return candidates, cobra.ShellCompDirectiveNoFileComp -} diff --git a/cmd/nerdctl/main_windows.go b/cmd/nerdctl/main_windows.go index e8c48782a20..9cb97aaf29e 100644 --- a/cmd/nerdctl/main_windows.go +++ b/cmd/nerdctl/main_windows.go @@ -23,23 +23,3 @@ import ( func appNeedsRootlessParentMain(cmd *cobra.Command, args []string) bool { return false } - -func shellCompleteNamespaceNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return nil, cobra.ShellCompDirectiveNoFileComp -} - -func shellCompleteSnapshotterNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return nil, cobra.ShellCompDirectiveNoFileComp -} - -func shellCompleteCgroupManagerNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return nil, cobra.ShellCompDirectiveNoFileComp -} - -func addApparmorCommand(rootCmd *cobra.Command) { - // NOP -} - -func addCpCommand(rootCmd *cobra.Command) { - // NOP -} diff --git a/cmd/nerdctl/namespace.go b/cmd/nerdctl/namespace/namespace.go similarity index 79% rename from cmd/nerdctl/namespace.go rename to cmd/nerdctl/namespace/namespace.go index 0d05926c69e..762b7ba68a2 100644 --- a/cmd/nerdctl/namespace.go +++ b/cmd/nerdctl/namespace/namespace.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package namespace import ( "fmt" @@ -24,31 +24,34 @@ import ( "text/tabwriter" "github.com/containerd/containerd/namespaces" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" "github.com/containerd/nerdctl/pkg/mountutil/volumestore" "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) -func newNamespaceCommand() *cobra.Command { +func NewNamespaceCommand() *cobra.Command { namespaceCommand := &cobra.Command{ - Annotations: map[string]string{Category: Management}, + Annotations: map[string]string{common.Category: common.Management}, Use: "namespace", Aliases: []string{"ns"}, Short: "Manage containerd namespaces", Long: "Unrelated to Linux namespaces and Kubernetes namespaces", - RunE: unknownSubcommandAction, + RunE: completion.UnknownSubcommandAction, SilenceUsage: true, SilenceErrors: true, } - namespaceCommand.AddCommand(newNamespaceLsCommand()) - namespaceCommand.AddCommand(newNamespaceRmCommand()) - namespaceCommand.AddCommand(newNamespaceCreateCommand()) - namespaceCommand.AddCommand(newNamespacelabelUpdateCommand()) - namespaceCommand.AddCommand(newNamespaceInspectCommand()) + namespaceCommand.AddCommand(NewNamespaceLsCommand()) + namespaceCommand.AddCommand(NewNamespaceRmCommand()) + namespaceCommand.AddCommand(NewNamespaceCreateCommand()) + namespaceCommand.AddCommand(NewNamespacelabelUpdateCommand()) + namespaceCommand.AddCommand(NewNamespaceInspectCommand()) return namespaceCommand } -func newNamespaceLsCommand() *cobra.Command { +func NewNamespaceLsCommand() *cobra.Command { namespaceLsCommand := &cobra.Command{ Use: "ls", Aliases: []string{"list"}, @@ -62,7 +65,7 @@ func newNamespaceLsCommand() *cobra.Command { } func namespaceLsAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } @@ -84,7 +87,7 @@ func namespaceLsAction(cmd *cobra.Command, args []string) error { return nil } - dataStore, err := getDataStore(cmd) + dataStore, err := nerdClient.GetDataStore(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/namespace_create.go b/cmd/nerdctl/namespace/namespace_create.go similarity index 89% rename from cmd/nerdctl/namespace_create.go rename to cmd/nerdctl/namespace/namespace_create.go index 481f41e6c69..9aca9ee77bc 100644 --- a/cmd/nerdctl/namespace_create.go +++ b/cmd/nerdctl/namespace/namespace_create.go @@ -14,14 +14,15 @@ limitations under the License. */ -package main +package namespace import ( "github.com/containerd/containerd/cmd/ctr/commands" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/spf13/cobra" ) -func newNamespaceCreateCommand() *cobra.Command { +func NewNamespaceCreateCommand() *cobra.Command { namespaceCreateCommand := &cobra.Command{ Use: "create NAMESPACE", Short: "Create a new namespace", @@ -41,7 +42,7 @@ func namespaceCreateAction(cmd *cobra.Command, args []string) error { return err } - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/namespace_freebsd.go b/cmd/nerdctl/namespace/namespace_freebsd.go similarity index 97% rename from cmd/nerdctl/namespace_freebsd.go rename to cmd/nerdctl/namespace/namespace_freebsd.go index 688ea349d77..d13c19c6f9e 100644 --- a/cmd/nerdctl/namespace_freebsd.go +++ b/cmd/nerdctl/namespace/namespace_freebsd.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package namespace import ( "github.com/containerd/containerd/namespaces" diff --git a/cmd/nerdctl/namespace_inspect.go b/cmd/nerdctl/namespace/namespace_inspect.go similarity index 86% rename from cmd/nerdctl/namespace_inspect.go rename to cmd/nerdctl/namespace/namespace_inspect.go index 408164082bb..a7fd10fb3f7 100644 --- a/cmd/nerdctl/namespace_inspect.go +++ b/cmd/nerdctl/namespace/namespace_inspect.go @@ -14,15 +14,17 @@ limitations under the License. */ -package main +package namespace import ( "github.com/containerd/containerd/namespaces" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/fmtutil" "github.com/containerd/nerdctl/pkg/inspecttypes/native" "github.com/spf13/cobra" ) -func newNamespaceInspectCommand() *cobra.Command { +func NewNamespaceInspectCommand() *cobra.Command { namespaceInspectCommand := &cobra.Command{ Use: "inspect NAMESPACE", Short: "Display detailed information on one or more namespaces.", @@ -39,7 +41,7 @@ func newNamespaceInspectCommand() *cobra.Command { } func labelInspectAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } @@ -58,5 +60,5 @@ func labelInspectAction(cmd *cobra.Command, args []string) error { } result[index] = nsInspect } - return formatSlice(cmd, result) + return fmtutil.FormatSlice(cmd, result) } diff --git a/cmd/nerdctl/namespace_linux.go b/cmd/nerdctl/namespace/namespace_linux.go similarity index 98% rename from cmd/nerdctl/namespace_linux.go rename to cmd/nerdctl/namespace/namespace_linux.go index 46f2c1958bd..da9852418b9 100644 --- a/cmd/nerdctl/namespace_linux.go +++ b/cmd/nerdctl/namespace/namespace_linux.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package namespace import ( "github.com/containerd/containerd/namespaces" diff --git a/cmd/nerdctl/namespace_rm.go b/cmd/nerdctl/namespace/namespace_rm.go similarity index 90% rename from cmd/nerdctl/namespace_rm.go rename to cmd/nerdctl/namespace/namespace_rm.go index 68bfeaa913b..9ab2ba30c4a 100644 --- a/cmd/nerdctl/namespace_rm.go +++ b/cmd/nerdctl/namespace/namespace_rm.go @@ -14,17 +14,18 @@ limitations under the License. */ -package main +package namespace import ( "fmt" "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/log" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/spf13/cobra" ) -func newNamespaceRmCommand() *cobra.Command { +func NewNamespaceRmCommand() *cobra.Command { namespaceRmCommand := &cobra.Command{ Use: "remove [flags] NAMESPACE [NAMESPACE...]", Aliases: []string{"rm"}, @@ -40,7 +41,7 @@ func newNamespaceRmCommand() *cobra.Command { func namespaceRmAction(cmd *cobra.Command, args []string) error { var exitErr error - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/namespace_update.go b/cmd/nerdctl/namespace/namespace_update.go similarity index 88% rename from cmd/nerdctl/namespace_update.go rename to cmd/nerdctl/namespace/namespace_update.go index b5127e28bfb..f6eb166ad19 100644 --- a/cmd/nerdctl/namespace_update.go +++ b/cmd/nerdctl/namespace/namespace_update.go @@ -14,13 +14,14 @@ limitations under the License. */ -package main +package namespace import ( + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/spf13/cobra" ) -func newNamespacelabelUpdateCommand() *cobra.Command { +func NewNamespacelabelUpdateCommand() *cobra.Command { namespaceLableCommand := &cobra.Command{ Use: "update [flags] NAMESPACE", Short: "Update labels for a namespace", @@ -39,7 +40,7 @@ func labelUpdateAction(cmd *cobra.Command, args []string) error { return err } - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/namespace_windows.go b/cmd/nerdctl/namespace/namespace_windows.go similarity index 97% rename from cmd/nerdctl/namespace_windows.go rename to cmd/nerdctl/namespace/namespace_windows.go index 688ea349d77..d13c19c6f9e 100644 --- a/cmd/nerdctl/namespace_windows.go +++ b/cmd/nerdctl/namespace/namespace_windows.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package namespace import ( "github.com/containerd/containerd/namespaces" diff --git a/cmd/nerdctl/network.go b/cmd/nerdctl/network/network.go similarity index 65% rename from cmd/nerdctl/network.go rename to cmd/nerdctl/network/network.go index cc9b38d5f51..903e63becf9 100644 --- a/cmd/nerdctl/network.go +++ b/cmd/nerdctl/network/network.go @@ -14,27 +14,29 @@ limitations under the License. */ -package main +package network import ( + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" "github.com/spf13/cobra" ) -func newNetworkCommand() *cobra.Command { +func NewNetworkCommand() *cobra.Command { networkCommand := &cobra.Command{ - Annotations: map[string]string{Category: Management}, + Annotations: map[string]string{common.Category: common.Management}, Use: "network", Short: "Manage networks", - RunE: unknownSubcommandAction, + RunE: completion.UnknownSubcommandAction, SilenceUsage: true, SilenceErrors: true, } networkCommand.AddCommand( - newNetworkLsCommand(), - newNetworkInspectCommand(), - newNetworkCreateCommand(), - newNetworkRmCommand(), - newNetworkPruneCommand(), + NewNetworkLsCommand(), + NewNetworkInspectCommand(), + NewNetworkCreateCommand(), + NewNetworkRmCommand(), + NewNetworkPruneCommand(), ) return networkCommand } diff --git a/cmd/nerdctl/network_create.go b/cmd/nerdctl/network/network_create.go similarity index 96% rename from cmd/nerdctl/network_create.go rename to cmd/nerdctl/network/network_create.go index 9d7328fc3f6..c9127e07f89 100644 --- a/cmd/nerdctl/network_create.go +++ b/cmd/nerdctl/network/network_create.go @@ -14,25 +14,26 @@ limitations under the License. */ -package main +package network import ( "fmt" "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/identifiers" + "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/pkg/netutil" "github.com/containerd/nerdctl/pkg/strutil" "github.com/spf13/cobra" ) -func newNetworkCreateCommand() *cobra.Command { +func NewNetworkCreateCommand() *cobra.Command { var networkCreateCommand = &cobra.Command{ Use: "create [flags] NETWORK", Short: "Create a network", Long: `NOTE: To isolate CNI bridge, CNI plugin "firewall" (>= v1.1.0) is needed.`, - Args: IsExactArgs(1), + Args: utils.IsExactArgs(1), RunE: networkCreateAction, SilenceUsage: true, SilenceErrors: true, diff --git a/cmd/nerdctl/network_create_unix.go b/cmd/nerdctl/network/network_create_unix.go similarity index 98% rename from cmd/nerdctl/network_create_unix.go rename to cmd/nerdctl/network/network_create_unix.go index 298030ba5bc..b2c8c062f33 100644 --- a/cmd/nerdctl/network_create_unix.go +++ b/cmd/nerdctl/network/network_create_unix.go @@ -16,7 +16,7 @@ limitations under the License. */ -package main +package network import "github.com/spf13/cobra" diff --git a/cmd/nerdctl/network_create_windows.go b/cmd/nerdctl/network/network_create_windows.go similarity index 98% rename from cmd/nerdctl/network_create_windows.go rename to cmd/nerdctl/network/network_create_windows.go index 2d6acf7e92b..3cb69b7a938 100644 --- a/cmd/nerdctl/network_create_windows.go +++ b/cmd/nerdctl/network/network_create_windows.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package network import "github.com/spf13/cobra" diff --git a/cmd/nerdctl/network_inspect.go b/cmd/nerdctl/network/network_inspect.go similarity index 92% rename from cmd/nerdctl/network_inspect.go rename to cmd/nerdctl/network/network_inspect.go index 06facf36d93..30cda74f999 100644 --- a/cmd/nerdctl/network_inspect.go +++ b/cmd/nerdctl/network/network_inspect.go @@ -14,12 +14,14 @@ limitations under the License. */ -package main +package network import ( "encoding/json" "fmt" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/fmtutil" "github.com/containerd/nerdctl/pkg/inspecttypes/dockercompat" "github.com/containerd/nerdctl/pkg/inspecttypes/native" "github.com/containerd/nerdctl/pkg/netutil" @@ -27,7 +29,7 @@ import ( "github.com/spf13/cobra" ) -func newNetworkInspectCommand() *cobra.Command { +func NewNetworkInspectCommand() *cobra.Command { networkInspectCommand := &cobra.Command{ Use: "inspect [flags] NETWORK [NETWORK, ...]", Short: "Display detailed information on one or more networks", @@ -101,11 +103,11 @@ func networkInspectAction(cmd *cobra.Command, args []string) error { } } - return formatSlice(cmd, result) + return fmtutil.FormatSlice(cmd, result) } func networkInspectShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show network names, including "bridge" exclude := []string{"host", "none"} - return shellCompleteNetworkNames(cmd, exclude) + return completion.ShellCompleteNetworkNames(cmd, exclude) } diff --git a/cmd/nerdctl/network_ls.go b/cmd/nerdctl/network/network_ls.go similarity index 93% rename from cmd/nerdctl/network_ls.go rename to cmd/nerdctl/network/network_ls.go index 26933333f33..b1b7a70998a 100644 --- a/cmd/nerdctl/network_ls.go +++ b/cmd/nerdctl/network/network_ls.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package network import ( "bytes" @@ -23,12 +23,13 @@ import ( "text/tabwriter" "text/template" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/fmtutil" "github.com/containerd/nerdctl/pkg/netutil" "github.com/spf13/cobra" ) -func newNetworkLsCommand() *cobra.Command { +func NewNetworkLsCommand() *cobra.Command { cmd := &cobra.Command{ Use: "ls", Aliases: []string{"list"}, @@ -79,7 +80,7 @@ func networkLsAction(cmd *cobra.Command, args []string) error { return errors.New("format and quiet must not be specified together") } var err error - tmpl, err = parseTemplate(format) + tmpl, err = fmtutil.ParseTemplate(format) if err != nil { return err } @@ -114,7 +115,7 @@ func networkLsAction(cmd *cobra.Command, args []string) error { } } if n.NerdctlLabels != nil { - p.Labels = formatLabels(*n.NerdctlLabels) + p.Labels = fmtutil.FormatLabels(*n.NerdctlLabels) } pp[i] = p } @@ -146,7 +147,7 @@ func networkLsAction(cmd *cobra.Command, args []string) error { fmt.Fprintf(w, "%s\t%s\t%s\n", p.ID, p.Name, p.file) } } - if f, ok := w.(Flusher); ok { + if f, ok := w.(fmtutil.Flusher); ok { return f.Flush() } return nil diff --git a/cmd/nerdctl/network_prune.go b/cmd/nerdctl/network/network_prune.go similarity index 90% rename from cmd/nerdctl/network_prune.go rename to cmd/nerdctl/network/network_prune.go index 30426d9f22d..abea9fb3fc7 100644 --- a/cmd/nerdctl/network_prune.go +++ b/cmd/nerdctl/network/network_prune.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package network import ( "context" @@ -22,6 +22,7 @@ import ( "strings" "github.com/containerd/containerd" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/pkg/netutil" "github.com/containerd/nerdctl/pkg/strutil" "github.com/sirupsen/logrus" @@ -30,7 +31,7 @@ import ( var networkDriversToKeep = []string{"host", "none", DefaultNetworkDriver} -func newNetworkPruneCommand() *cobra.Command { +func NewNetworkPruneCommand() *cobra.Command { networkPruneCommand := &cobra.Command{ Use: "prune [flags]", Short: "Remove all unused networks", @@ -62,16 +63,16 @@ func networkPruneAction(cmd *cobra.Command, _ []string) error { } } - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } defer cancel() - return networkPrune(ctx, cmd, client) + return Prune(ctx, cmd, client) } -func networkPrune(ctx context.Context, cmd *cobra.Command, client *containerd.Client) error { +func Prune(ctx context.Context, cmd *cobra.Command, client *containerd.Client) error { cniPath, err := cmd.Flags().GetString("cni-path") if err != nil { return err diff --git a/cmd/nerdctl/network_rm.go b/cmd/nerdctl/network/network_rm.go similarity index 89% rename from cmd/nerdctl/network_rm.go rename to cmd/nerdctl/network/network_rm.go index 41beb2d668b..d1cf988c9b7 100644 --- a/cmd/nerdctl/network_rm.go +++ b/cmd/nerdctl/network/network_rm.go @@ -14,12 +14,15 @@ limitations under the License. */ -package main +package network import ( "context" "fmt" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" "github.com/containerd/nerdctl/pkg/idutil/netwalker" "github.com/containerd/nerdctl/pkg/netutil" "github.com/sirupsen/logrus" @@ -27,7 +30,7 @@ import ( "github.com/spf13/cobra" ) -func newNetworkRmCommand() *cobra.Command { +func NewNetworkRmCommand() *cobra.Command { networkRmCommand := &cobra.Command{ Use: "rm [flags] NETWORK [NETWORK, ...]", Aliases: []string{"remove"}, @@ -43,7 +46,7 @@ func newNetworkRmCommand() *cobra.Command { } func networkRmAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } @@ -113,8 +116,8 @@ func networkRmAction(cmd *cobra.Command, args []string) error { // compatible with docker // ExitCodeError is to allow the program to exit with status code 1 without outputting an error message. if code != 0 { - return ExitCodeError{ - exitCode: code, + return common.ExitCodeError{ + Code: code, } } return nil @@ -123,5 +126,5 @@ func networkRmAction(cmd *cobra.Command, args []string) error { func networkRmShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show network names, including "bridge" exclude := []string{netutil.DefaultNetworkName, "host", "none"} - return shellCompleteNetworkNames(cmd, exclude) + return completion.ShellCompleteNetworkNames(cmd, exclude) } diff --git a/cmd/nerdctl/ps.go b/cmd/nerdctl/ps/ps.go similarity index 69% rename from cmd/nerdctl/ps.go rename to cmd/nerdctl/ps/ps.go index b377263d82b..2e643b2ac82 100644 --- a/cmd/nerdctl/ps.go +++ b/cmd/nerdctl/ps/ps.go @@ -14,12 +14,11 @@ limitations under the License. */ -package main +package ps import ( "bytes" "context" - "encoding/json" "errors" "fmt" "io" @@ -31,22 +30,23 @@ import ( "time" "github.com/containerd/containerd" - "github.com/containerd/containerd/containers" "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/pkg/progress" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/utils" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/container" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/fmtutil" "github.com/containerd/nerdctl/pkg/formatter" "github.com/containerd/nerdctl/pkg/labels" - "github.com/containerd/nerdctl/pkg/labels/k8slabels" "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) -func newPsCommand() *cobra.Command { +func NewPsCommand() *cobra.Command { var psCommand = &cobra.Command{ Use: "ps", Args: cobra.NoArgs, - Short: "List containers", + Short: "List Containers", RunE: psAction, SilenceUsage: true, SilenceErrors: true, @@ -68,7 +68,7 @@ func newPsCommand() *cobra.Command { } func psAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } @@ -96,7 +96,7 @@ func psAction(cmd *cobra.Command, args []string) error { if err != nil { return err } - filterCtx, err := foldContainerFilters(ctx, containers, filters) + filterCtx, err := container.FoldContainerFilters(ctx, containers, filters) if err != nil { return err } @@ -182,7 +182,7 @@ func printContainers(ctx context.Context, client *containerd.Client, cmd *cobra. return errors.New("format and quiet must not be specified together") } var err error - tmpl, err = parseTemplate(format) + tmpl, err = fmtutil.ParseTemplate(format) if err != nil { return err } @@ -224,7 +224,7 @@ func printContainers(ctx context.Context, client *containerd.Client, cmd *cobra. ID: id, Image: imageName, Platform: info.Labels[labels.Platform], - Names: getPrintableContainerName(info.Labels), + Names: utils.GetPrintableContainerName(info.Labels), Ports: formatter.FormatPorts(info.Labels), Status: cStatus, Runtime: info.Runtime.Name, @@ -232,7 +232,7 @@ func printContainers(ctx context.Context, client *containerd.Client, cmd *cobra. } if size || wide { - containerSize, err := getContainerSize(ctx, client, c, info) + containerSize, err := container.GetContainerSize(ctx, client, c, info) if err != nil { return err } @@ -277,106 +277,8 @@ func printContainers(ctx context.Context, client *containerd.Client, cmd *cobra. } } - if f, ok := w.(Flusher); ok { + if f, ok := w.(fmtutil.Flusher); ok { return f.Flush() } return nil } - -func getPrintableContainerName(containerLabels map[string]string) string { - if name, ok := containerLabels[labels.Name]; ok { - return name - } - - if ns, ok := containerLabels[k8slabels.PodNamespace]; ok { - if podName, ok := containerLabels[k8slabels.PodName]; ok { - if containerName, ok := containerLabels[k8slabels.ContainerName]; ok { - // Container - return fmt.Sprintf("k8s://%s/%s/%s", ns, podName, containerName) - } - // Pod sandbox - return fmt.Sprintf("k8s://%s/%s", ns, podName) - } - } - return "" -} - -type containerVolume struct { - Type string - Name string - Source string - Destination string - Mode string - RW bool - Propagation string -} - -func getContainerVolumes(containerLabels map[string]string) []*containerVolume { - var vols []*containerVolume - volLabels := []string{labels.AnonymousVolumes, labels.Mounts} - for _, volLabel := range volLabels { - names, ok := containerLabels[volLabel] - if !ok { - continue - } - var ( - volumes []*containerVolume - err error - ) - if volLabel == labels.Mounts { - err = json.Unmarshal([]byte(names), &volumes) - } - if volLabel == labels.AnonymousVolumes { - var anonymous []string - err = json.Unmarshal([]byte(names), &anonymous) - for _, anony := range anonymous { - volumes = append(volumes, &containerVolume{Name: anony}) - } - - } - if err != nil { - logrus.Warn(err) - } - vols = append(vols, volumes...) - } - return vols -} - -func getContainerNetworks(containerLables map[string]string) []string { - var networks []string - if names, ok := containerLables[labels.Networks]; ok { - if err := json.Unmarshal([]byte(names), &networks); err != nil { - logrus.Warn(err) - } - } - return networks -} - -func getContainerSize(ctx context.Context, client *containerd.Client, c containerd.Container, info containers.Container) (string, error) { - // get container snapshot size - snapshotKey := info.SnapshotKey - var containerSize int64 - - if snapshotKey != "" { - usage, err := client.SnapshotService(info.Snapshotter).Usage(ctx, snapshotKey) - if err != nil { - return "", err - } - containerSize = usage.Size - } - - // get the image interface - image, err := c.Image(ctx) - if err != nil { - return "", err - } - - sn := client.SnapshotService(info.Snapshotter) - - imageSize, err := unpackedImageSize(ctx, sn, image) - if err != nil { - return "", err - } - - return fmt.Sprintf("%s (virtual %s)", progress.Bytes(containerSize).String(), progress.Bytes(imageSize).String()), nil -} diff --git a/cmd/nerdctl/pull.go b/cmd/nerdctl/pull/pull.go similarity index 52% rename from cmd/nerdctl/pull.go rename to cmd/nerdctl/pull/pull.go index c3ea62b9956..67071eb2f22 100644 --- a/cmd/nerdctl/pull.go +++ b/cmd/nerdctl/pull/pull.go @@ -14,32 +14,22 @@ limitations under the License. */ -package main +package pull import ( - "context" - "errors" - "fmt" - - "github.com/containerd/containerd" - "github.com/containerd/nerdctl/pkg/cosignutil" - "github.com/containerd/nerdctl/pkg/imgutil" - "github.com/containerd/nerdctl/pkg/ipfs" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/pkg/platformutil" - "github.com/containerd/nerdctl/pkg/referenceutil" "github.com/containerd/nerdctl/pkg/strutil" - httpapi "github.com/ipfs/go-ipfs-http-client" - v1 "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/sirupsen/logrus" - "github.com/spf13/cobra" ) -func newPullCommand() *cobra.Command { +func NewPullCommand() *cobra.Command { var pullCommand = &cobra.Command{ Use: "pull [flags] NAME[:TAG]", Short: "Pull an image from a registry. Optionally specify \"ipfs://\" or \"ipns://\" scheme to pull image from IPFS.", - Args: IsExactArgs(1), + Args: utils.IsExactArgs(1), RunE: pullAction, SilenceUsage: true, SilenceErrors: true, @@ -52,7 +42,7 @@ func newPullCommand() *cobra.Command { // #region platform flags // platform is defined as StringSlice, not StringArray, to allow specifying "--platform=amd64,arm64" pullCommand.Flags().StringSlice("platform", nil, "Pull content for a specific platform") - pullCommand.RegisterFlagCompletionFunc("platform", shellCompletePlatforms) + pullCommand.RegisterFlagCompletionFunc("platform", completion.ShellCompletePlatforms) pullCommand.Flags().Bool("all-platforms", false, "Pull content for all platforms") // #endregion @@ -71,7 +61,7 @@ func newPullCommand() *cobra.Command { func pullAction(cmd *cobra.Command, args []string) error { rawRef := args[0] - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } @@ -102,83 +92,10 @@ func pullAction(cmd *cobra.Command, args []string) error { return err } - _, err = ensureImage(ctx, cmd, client, rawRef, ocispecPlatforms, "always", unpack, quiet) + _, err = utils.EnsureImage(ctx, cmd, client, rawRef, ocispecPlatforms, "always", unpack, quiet) if err != nil { return err } return nil } - -func ensureImage(ctx context.Context, cmd *cobra.Command, client *containerd.Client, rawRef string, ocispecPlatforms []v1.Platform, - pull string, unpack *bool, quiet bool) (*imgutil.EnsuredImage, error) { - - var ensured *imgutil.EnsuredImage - snapshotter, err := cmd.Flags().GetString("snapshotter") - if err != nil { - return nil, err - } - insecureRegistry, err := cmd.Flags().GetBool("insecure-registry") - if err != nil { - return nil, err - } - hostsDirs, err := cmd.Flags().GetStringSlice("hosts-dir") - if err != nil { - return nil, err - } - verifier, err := cmd.Flags().GetString("verify") - if err != nil { - return nil, err - } - - if scheme, ref, err := referenceutil.ParseIPFSRefWithScheme(rawRef); err == nil { - if verifier != "none" { - return nil, errors.New("--verify flag is not supported on IPFS as of now") - } - - ipfsClient, err := httpapi.NewLocalApi() - if err != nil { - return nil, err - } - ensured, err = ipfs.EnsureImage(ctx, client, ipfsClient, cmd.OutOrStdout(), cmd.ErrOrStderr(), snapshotter, scheme, ref, - pull, ocispecPlatforms, unpack, quiet) - if err != nil { - return nil, err - } - return ensured, nil - } - - ref := rawRef - switch verifier { - case "cosign": - experimental, err := cmd.Flags().GetBool("experimental") - if err != nil { - return nil, err - } - - if !experimental { - return nil, fmt.Errorf("cosign only work with enable experimental feature") - } - - keyRef, err := cmd.Flags().GetString("cosign-key") - if err != nil { - return nil, err - } - - ref, err = cosignutil.VerifyCosign(ctx, rawRef, keyRef, hostsDirs) - if err != nil { - return nil, err - } - case "none": - logrus.Debugf("verification process skipped") - default: - return nil, fmt.Errorf("no verifier found: %s", verifier) - } - - ensured, err = imgutil.EnsureImage(ctx, client, cmd.OutOrStdout(), cmd.ErrOrStderr(), snapshotter, ref, - pull, insecureRegistry, hostsDirs, ocispecPlatforms, unpack, quiet) - if err != nil { - return nil, err - } - return ensured, err -} diff --git a/cmd/nerdctl/push.go b/cmd/nerdctl/push/push.go similarity index 95% rename from cmd/nerdctl/push.go rename to cmd/nerdctl/push/push.go index c467014a243..2e246186dce 100644 --- a/cmd/nerdctl/push.go +++ b/cmd/nerdctl/push/push.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package push import ( "context" @@ -26,6 +26,9 @@ import ( "github.com/containerd/containerd/images/converter" refdocker "github.com/containerd/containerd/reference/docker" "github.com/containerd/containerd/remotes" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/pkg/cosignutil" "github.com/containerd/nerdctl/pkg/errutil" "github.com/containerd/nerdctl/pkg/imgutil/dockerconfigresolver" @@ -38,7 +41,7 @@ import ( estargzconvert "github.com/containerd/stargz-snapshotter/nativeconverter/estargz" httpapi "github.com/ipfs/go-ipfs-http-client" "github.com/multiformats/go-multiaddr" - digest "github.com/opencontainers/go-digest" + "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -48,11 +51,11 @@ const ( allowNonDistFlag = "allow-nondistributable-artifacts" ) -func newPushCommand() *cobra.Command { +func NewPushCommand() *cobra.Command { var pushCommand = &cobra.Command{ Use: "push [flags] NAME[:TAG]", Short: "Push an image or a repository to a registry. Optionally specify \"ipfs://\" or \"ipns://\" scheme to push image to IPFS.", - Args: IsExactArgs(1), + Args: utils.IsExactArgs(1), RunE: pushAction, ValidArgsFunction: pushShellComplete, SilenceUsage: true, @@ -61,7 +64,7 @@ func newPushCommand() *cobra.Command { // #region platform flags // platform is defined as StringSlice, not StringArray, to allow specifying "--platform=amd64,arm64" pushCommand.Flags().StringSlice("platform", []string{}, "Push content for a specific platform") - pushCommand.RegisterFlagCompletionFunc("platform", shellCompletePlatforms) + pushCommand.RegisterFlagCompletionFunc("platform", completion.ShellCompletePlatforms) pushCommand.Flags().Bool("all-platforms", false, "Push content for all platforms") // #endregion @@ -85,7 +88,7 @@ func newPushCommand() *cobra.Command { func pushAction(cmd *cobra.Command, args []string) error { rawRef := args[0] - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } @@ -267,7 +270,7 @@ func pushAction(cmd *cobra.Command, args []string) error { func pushShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show image names - return shellCompleteImageNames(cmd) + return completion.ShellCompleteImageNames(cmd) } func eStargzConvertFunc() converter.ConvertFunc { diff --git a/cmd/nerdctl/rm.go b/cmd/nerdctl/rm.go deleted file mode 100644 index 46d588a4678..00000000000 --- a/cmd/nerdctl/rm.go +++ /dev/null @@ -1,225 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package main - -import ( - "context" - "encoding/json" - "fmt" - "os" - "syscall" - - "github.com/containerd/containerd" - "github.com/containerd/containerd/cio" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/namespaces" - "github.com/containerd/nerdctl/pkg/dnsutil/hostsstore" - "github.com/containerd/nerdctl/pkg/idutil/containerwalker" - "github.com/containerd/nerdctl/pkg/labels" - "github.com/containerd/nerdctl/pkg/namestore" - - "github.com/sirupsen/logrus" - "github.com/spf13/cobra" -) - -func newRmCommand() *cobra.Command { - var rmCommand = &cobra.Command{ - Use: "rm [flags] CONTAINER [CONTAINER, ...]", - Args: cobra.MinimumNArgs(1), - Short: "Remove one or more containers", - RunE: rmAction, - ValidArgsFunction: rmShellComplete, - SilenceUsage: true, - SilenceErrors: true, - } - rmCommand.Flags().BoolP("force", "f", false, "Force the removal of a running|paused|unknown container (uses SIGKILL)") - rmCommand.Flags().BoolP("volumes", "v", false, "Remove volumes associated with the container") - return rmCommand -} - -// removing a non-stoped/non-created container without force, will cause a error -type statusError struct { - error -} - -func rmAction(cmd *cobra.Command, args []string) error { - force, err := cmd.Flags().GetBool("force") - if err != nil { - return err - } - removeAnonVolumes, err := cmd.Flags().GetBool("volumes") - if err != nil { - return err - } - - client, ctx, cancel, err := newClient(cmd) - if err != nil { - return err - } - defer cancel() - - walker := &containerwalker.ContainerWalker{ - Client: client, - OnFound: func(ctx context.Context, found containerwalker.Found) error { - if found.MatchCount > 1 { - return fmt.Errorf("multiple IDs found with provided prefix: %s", found.Req) - } - if err := removeContainer(ctx, cmd, found.Container, force, removeAnonVolumes); err != nil { - return err - } - _, err = fmt.Fprintf(cmd.OutOrStdout(), "%s\n", found.Req) - return err - }, - } - for _, req := range args { - n, err := walker.Walk(ctx, req) - if err == nil && n == 0 { - err = fmt.Errorf("no such container %s", req) - } - if err != nil { - if force { - logrus.Error(err) - } else { - return err - } - } - } - return nil -} - -func removeContainer(ctx context.Context, cmd *cobra.Command, container containerd.Container, force bool, removeAnonVolumes bool) (retErr error) { - ns, err := namespaces.NamespaceRequired(ctx) - if err != nil { - return err - } - - id := container.ID() - l, err := container.Labels(ctx) - if err != nil { - return err - } - stateDir := l[labels.StateDir] - name := l[labels.Name] - - dataStore, err := getDataStore(cmd) - if err != nil { - return err - } - namst, err := namestore.New(dataStore, ns) - if err != nil { - return err - } - - defer func() { - if errdefs.IsNotFound(retErr) { - retErr = nil - } - if retErr != nil { - return - } - - if err := os.RemoveAll(stateDir); err != nil { - logrus.WithError(retErr).Warnf("failed to remove container state dir %s", stateDir) - } - if name != "" { - if err := namst.Release(name, id); err != nil { - logrus.WithError(retErr).Warnf("failed to release container name %s", name) - } - } - if err := hostsstore.DeallocHostsFile(dataStore, ns, id); err != nil { - logrus.WithError(retErr).Warnf("failed to remove hosts file for container %q", id) - } - }() - if anonVolumesJSON, ok := l[labels.AnonymousVolumes]; ok && removeAnonVolumes { - var anonVolumes []string - if err := json.Unmarshal([]byte(anonVolumesJSON), &anonVolumes); err != nil { - return err - } - volStore, err := getVolumeStore(cmd) - if err != nil { - return err - } - defer func() { - if _, err := volStore.Remove(anonVolumes); err != nil { - logrus.WithError(err).Warnf("failed to remove anonymous volumes %v", anonVolumes) - } - }() - } - - task, err := container.Task(ctx, cio.Load) - if err != nil { - if errdefs.IsNotFound(err) { - if container.Delete(ctx, containerd.WithSnapshotCleanup) != nil { - return container.Delete(ctx) - } - } - return err - } - - status, err := task.Status(ctx) - if err != nil { - if errdefs.IsNotFound(err) { - return nil - } - return err - } - - switch status.Status { - case containerd.Created, containerd.Stopped: - if _, err := task.Delete(ctx); err != nil && !errdefs.IsNotFound(err) { - return fmt.Errorf("failed to delete task %v: %w", id, err) - } - case containerd.Paused: - if !force { - return statusError{fmt.Errorf("you cannot remove a %v container %v. Unpause the container before attempting removal or force remove", status.Status, id)} - } - _, err := task.Delete(ctx, containerd.WithProcessKill) - if err != nil && !errdefs.IsNotFound(err) { - return fmt.Errorf("failed to delete task %v: %w", id, err) - } - // default is the case, when status.Status = containerd.Running - default: - if !force { - return statusError{fmt.Errorf("you cannot remove a %v container %v. Stop the container before attempting removal or force remove", status.Status, id)} - } - if err := task.Kill(ctx, syscall.SIGKILL); err != nil { - logrus.WithError(err).Warnf("failed to send SIGKILL") - } - es, err := task.Wait(ctx) - if err == nil { - <-es - } - _, err = task.Delete(ctx, containerd.WithProcessKill) - if err != nil && !errdefs.IsNotFound(err) { - logrus.WithError(err).Warnf("failed to delete task %v", id) - } - } - var delOpts []containerd.DeleteOpts - if _, err := container.Image(ctx); err == nil { - delOpts = append(delOpts, containerd.WithSnapshotCleanup) - } - - if err := container.Delete(ctx, delOpts...); err != nil { - return err - } - return err -} - -func rmShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - // show container names - return shellCompleteContainerNames(cmd, nil) -} diff --git a/cmd/nerdctl/rmi.go b/cmd/nerdctl/rmi/rmi.go similarity index 93% rename from cmd/nerdctl/rmi.go rename to cmd/nerdctl/rmi/rmi.go index 4bbf1e26499..d3e5118734a 100644 --- a/cmd/nerdctl/rmi.go +++ b/cmd/nerdctl/rmi/rmi.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package rmi import ( "context" @@ -23,13 +23,15 @@ import ( "github.com/containerd/containerd/images" "github.com/containerd/containerd/platforms" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/pkg/formatter" "github.com/containerd/nerdctl/pkg/idutil/imagewalker" "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) -func newRmiCommand() *cobra.Command { +func NewRmiCommand() *cobra.Command { var rmiCommand = &cobra.Command{ Use: "rmi [flags] IMAGE [IMAGE, ...]", Short: "Remove one or more images", @@ -58,7 +60,7 @@ func rmiAction(cmd *cobra.Command, args []string) error { delOpts = append(delOpts, images.SynchronousDelete()) } - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } @@ -133,5 +135,5 @@ func rmiAction(cmd *cobra.Command, args []string) error { func rmiShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show image names - return shellCompleteImageNames(cmd) + return completion.ShellCompleteImageNames(cmd) } diff --git a/cmd/nerdctl/run.go b/cmd/nerdctl/run.go deleted file mode 100644 index 20aa7761b73..00000000000 --- a/cmd/nerdctl/run.go +++ /dev/null @@ -1,1274 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package main - -import ( - "bufio" - "context" - "encoding/json" - "errors" - "fmt" - "net/url" - "os" - "os/exec" - "path" - "path/filepath" - "runtime" - "strconv" - "strings" - - "github.com/containerd/console" - "github.com/containerd/containerd" - "github.com/containerd/containerd/cio" - "github.com/containerd/containerd/cmd/ctr/commands" - "github.com/containerd/containerd/cmd/ctr/commands/tasks" - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/oci" - gocni "github.com/containerd/go-cni" - "github.com/containerd/nerdctl/pkg/defaults" - "github.com/containerd/nerdctl/pkg/idgen" - "github.com/containerd/nerdctl/pkg/imgutil" - "github.com/containerd/nerdctl/pkg/inspecttypes/dockercompat" - "github.com/containerd/nerdctl/pkg/labels" - "github.com/containerd/nerdctl/pkg/logging" - "github.com/containerd/nerdctl/pkg/mountutil" - "github.com/containerd/nerdctl/pkg/namestore" - "github.com/containerd/nerdctl/pkg/netutil" - "github.com/containerd/nerdctl/pkg/platformutil" - "github.com/containerd/nerdctl/pkg/referenceutil" - "github.com/containerd/nerdctl/pkg/rootlessutil" - "github.com/containerd/nerdctl/pkg/strutil" - "github.com/containerd/nerdctl/pkg/taskutil" - dopts "github.com/docker/cli/opts" - "github.com/opencontainers/runtime-spec/specs-go" - "github.com/sirupsen/logrus" - "github.com/spf13/cobra" -) - -const ( - tiniInitBinary = "tini" -) - -func newRunCommand() *cobra.Command { - shortHelp := "Run a command in a new container. Optionally specify \"ipfs://\" or \"ipns://\" scheme to pull image from IPFS." - longHelp := shortHelp - switch runtime.GOOS { - case "windows": - longHelp += "\n" - longHelp += "WARNING: `nerdctl run` is experimental on Windows and currently broken (https://github.com/containerd/nerdctl/issues/28)" - case "freebsd": - longHelp += "\n" - longHelp += "WARNING: `nerdctl run` is experimental on FreeBSD and currently requires `--net=none` (https://github.com/containerd/nerdctl/blob/main/docs/freebsd.md)" - } - var runCommand = &cobra.Command{ - Use: "run [flags] IMAGE [COMMAND] [ARG...]", - Args: cobra.MinimumNArgs(1), - Short: shortHelp, - Long: longHelp, - RunE: runAction, - ValidArgsFunction: runShellComplete, - SilenceUsage: true, - SilenceErrors: true, - } - - runCommand.Flags().SetInterspersed(false) - setCreateFlags(runCommand) - - runCommand.Flags().BoolP("detach", "d", false, "Run container in background and print container ID") - - return runCommand -} - -func setCreateFlags(cmd *cobra.Command) { - - // No "-h" alias for "--help", because "-h" for "--hostname". - cmd.Flags().Bool("help", false, "show help") - - cmd.Flags().BoolP("tty", "t", false, "(Currently -t needs to correspond to -i)") - cmd.Flags().BoolP("interactive", "i", false, "Keep STDIN open even if not attached") - cmd.Flags().String("restart", "no", `Restart policy to apply when a container exits (implemented values: "no"|"always")`) - cmd.RegisterFlagCompletionFunc("restart", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return []string{"no", "always", "on-failure", "unless-stopped"}, cobra.ShellCompDirectiveNoFileComp - }) - cmd.Flags().Bool("rm", false, "Automatically remove the container when it exits") - cmd.Flags().String("pull", "missing", `Pull image before running ("always"|"missing"|"never")`) - cmd.RegisterFlagCompletionFunc("pull", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return []string{"always", "missing", "never"}, cobra.ShellCompDirectiveNoFileComp - }) - cmd.Flags().String("stop-signal", "SIGTERM", "Signal to stop a container") - cmd.Flags().Int("stop-timeout", 0, "Timeout (in seconds) to stop a container") - - // #region for init process - cmd.Flags().Bool("init", false, "Run an init process inside the container, Default to use tini") - cmd.Flags().String("init-binary", tiniInitBinary, "The custom binary to use as the init process") - // #endregion - - // #region platform flags - cmd.Flags().String("platform", "", "Set platform (e.g. \"amd64\", \"arm64\")") // not a slice, and there is no --all-platforms - cmd.RegisterFlagCompletionFunc("platform", shellCompletePlatforms) - // #endregion - - // #region network flags - // network (net) is defined as StringSlice, not StringArray, to allow specifying "--network=cni1,cni2" - cmd.Flags().StringSlice("network", []string{netutil.DefaultNetworkName}, `Connect a container to a network ("bridge"|"host"|"none"|"container:"|)`) - cmd.RegisterFlagCompletionFunc("network", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return shellCompleteNetworkNames(cmd, []string{}) - }) - cmd.Flags().StringSlice("net", []string{netutil.DefaultNetworkName}, `Connect a container to a network ("bridge"|"host"|"none"|)`) - cmd.RegisterFlagCompletionFunc("net", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return shellCompleteNetworkNames(cmd, []string{}) - }) - // dns is defined as StringSlice, not StringArray, to allow specifying "--dns=1.1.1.1,8.8.8.8" (compatible with Podman) - cmd.Flags().StringSlice("dns", nil, "Set custom DNS servers") - cmd.Flags().StringSlice("dns-search", nil, "Set custom DNS search domains") - // We allow for both "--dns-opt" and "--dns-option", although the latter is the recommended way. - cmd.Flags().StringSlice("dns-opt", nil, "Set DNS options") - cmd.Flags().StringSlice("dns-option", nil, "Set DNS options") - // publish is defined as StringSlice, not StringArray, to allow specifying "--publish=80:80,443:443" (compatible with Podman) - cmd.Flags().StringSliceP("publish", "p", nil, "Publish a container's port(s) to the host") - // FIXME: not support IPV6 yet - cmd.Flags().String("ip", "", "IPv4 address to assign to the container") - cmd.Flags().StringP("hostname", "h", "", "Container host name") - cmd.Flags().String("mac-address", "", "MAC address to assign to the container") - // #endregion - - cmd.Flags().String("ipc", "", `IPC namespace to use ("host"|"private")`) - cmd.RegisterFlagCompletionFunc("ipc", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return []string{"host", "private"}, cobra.ShellCompDirectiveNoFileComp - }) - // #region cgroups, namespaces, and ulimits flags - cmd.Flags().Float64("cpus", 0.0, "Number of CPUs") - cmd.Flags().StringP("memory", "m", "", "Memory limit") - cmd.Flags().String("memory-reservation", "", "Memory soft limit") - cmd.Flags().String("memory-swap", "", "Swap limit equal to memory plus swap: '-1' to enable unlimited swap") - cmd.Flags().Int64("memory-swappiness", -1, "Tune container memory swappiness (0 to 100) (default -1)") - cmd.Flags().String("kernel-memory", "", "Kernel memory limit (deprecated)") - cmd.Flags().Bool("oom-kill-disable", false, "Disable OOM Killer") - cmd.Flags().Int("oom-score-adj", 0, "Tune container’s OOM preferences (-1000 to 1000, rootless: 100 to 1000)") - cmd.Flags().String("pid", "", "PID namespace to use") - cmd.RegisterFlagCompletionFunc("pid", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return []string{"host"}, cobra.ShellCompDirectiveNoFileComp - }) - cmd.Flags().Int64("pids-limit", -1, "Tune container pids limit (set -1 for unlimited)") - cmd.Flags().StringSlice("cgroup-conf", nil, "Configure cgroup v2 (key=value)") - cmd.Flags().Uint16("blkio-weight", 0, "Block IO (relative weight), between 10 and 1000, or 0 to disable (default 0)") - cmd.Flags().String("cgroupns", defaults.CgroupnsMode(), `Cgroup namespace to use, the default depends on the cgroup version ("host"|"private")`) - cmd.RegisterFlagCompletionFunc("cgroupns", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return []string{"host", "private"}, cobra.ShellCompDirectiveNoFileComp - }) - cmd.Flags().String("cpuset-cpus", "", "CPUs in which to allow execution (0-3, 0,1)") - cmd.Flags().String("cpuset-mems", "", "MEMs in which to allow execution (0-3, 0,1)") - cmd.Flags().Uint64("cpu-shares", 0, "CPU shares (relative weight)") - cmd.Flags().Int64("cpu-quota", -1, "Limit CPU CFS (Completely Fair Scheduler) quota") - cmd.Flags().Uint64("cpu-period", 0, "Limit CPU CFS (Completely Fair Scheduler) period") - // device is defined as StringSlice, not StringArray, to allow specifying "--device=DEV1,DEV2" (compatible with Podman) - cmd.Flags().StringSlice("device", nil, "Add a host device to the container") - // ulimit is defined as StringSlice, not StringArray, to allow specifying "--ulimit=ULIMIT1,ULIMIT2" (compatible with Podman) - cmd.Flags().StringSlice("ulimit", nil, "Ulimit options") - cmd.Flags().String("rdt-class", "", "Name of the RDT class (or CLOS) to associate the container with") - // #endregion - - // user flags - cmd.Flags().StringP("user", "u", "", "Username or UID (format: [:])") - cmd.Flags().String("umask", "", "Set the umask inside the container. Defaults to 0022") - cmd.Flags().StringSlice("group-add", []string{}, "Add additional groups to join") - - // #region security flags - cmd.Flags().StringArray("security-opt", []string{}, "Security options") - cmd.RegisterFlagCompletionFunc("security-opt", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return []string{"seccomp=", "seccomp=unconfined", "apparmor=", "apparmor=" + defaults.AppArmorProfileName, "apparmor=unconfined", "no-new-privileges", "privileged-without-host-devices"}, cobra.ShellCompDirectiveNoFileComp - }) - // cap-add and cap-drop are defined as StringSlice, not StringArray, to allow specifying "--cap-add=CAP_SYS_ADMIN,CAP_NET_ADMIN" (compatible with Podman) - cmd.Flags().StringSlice("cap-add", []string{}, "Add Linux capabilities") - cmd.RegisterFlagCompletionFunc("cap-add", capShellComplete) - cmd.Flags().StringSlice("cap-drop", []string{}, "Drop Linux capabilities") - cmd.RegisterFlagCompletionFunc("cap-drop", capShellComplete) - cmd.Flags().Bool("privileged", false, "Give extended privileges to this container") - // #endregion - - // #region runtime flags - cmd.Flags().String("runtime", defaults.Runtime, "Runtime to use for this container, e.g. \"crun\", or \"io.containerd.runsc.v1\"") - // sysctl needs to be StringArray, not StringSlice, to prevent "foo=foo1,foo2" from being split to {"foo=foo1", "foo2"} - cmd.Flags().StringArray("sysctl", nil, "Sysctl options") - // gpus needs to be StringArray, not StringSlice, to prevent "capabilities=utility,device=DEV" from being split to {"capabilities=utility", "device=DEV"} - cmd.Flags().StringArray("gpus", nil, "GPU devices to add to the container ('all' to pass all GPUs)") - cmd.RegisterFlagCompletionFunc("gpus", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return []string{"all"}, cobra.ShellCompDirectiveNoFileComp - }) - // #endregion - - // #region mount flags - // volume needs to be StringArray, not StringSlice, to prevent "/foo:/foo:ro,Z" from being split to {"/foo:/foo:ro", "Z"} - cmd.Flags().StringArrayP("volume", "v", nil, "Bind mount a volume") - // tmpfs needs to be StringArray, not StringSlice, to prevent "/foo:size=64m,exec" from being split to {"/foo:size=64m", "exec"} - cmd.Flags().StringArray("tmpfs", nil, "Mount a tmpfs directory") - cmd.Flags().StringArray("mount", nil, "Attach a filesystem mount to the container") - // #endregion - - // rootfs flags - cmd.Flags().Bool("read-only", false, "Mount the container's root filesystem as read only") - // rootfs flags (from Podman) - cmd.Flags().Bool("rootfs", false, "The first argument is not an image but the rootfs to the exploded container") - - // #region env flags - // entrypoint needs to be StringArray, not StringSlice, to prevent "FOO=foo1,foo2" from being split to {"FOO=foo1", "foo2"} - // entrypoint StringArray is an internal implementation to support `nerdctl compose` entrypoint yaml filed with multiple strings - // users are not expected to specify multiple --entrypoint flags manually. - cmd.Flags().StringArray("entrypoint", nil, "Overwrite the default ENTRYPOINT of the image") - cmd.Flags().StringP("workdir", "w", "", "Working directory inside the container") - // env needs to be StringArray, not StringSlice, to prevent "FOO=foo1,foo2" from being split to {"FOO=foo1", "foo2"} - cmd.Flags().StringArrayP("env", "e", nil, "Set environment variables") - // add-host is defined as StringSlice, not StringArray, to allow specifying "--add-host=HOST1:IP1,HOST2:IP2" (compatible with Podman) - cmd.Flags().StringSlice("add-host", nil, "Add a custom host-to-IP mapping (host:ip)") - // env-file is defined as StringSlice, not StringArray, to allow specifying "--env-file=FILE1,FILE2" (compatible with Podman) - cmd.Flags().StringSlice("env-file", nil, "Set environment variables from file") - - // #region metadata flags - cmd.Flags().String("name", "", "Assign a name to the container") - // label needs to be StringArray, not StringSlice, to prevent "foo=foo1,foo2" from being split to {"foo=foo1", "foo2"} - cmd.Flags().StringArrayP("label", "l", nil, "Set metadata on container") - cmd.RegisterFlagCompletionFunc("label", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return labels.ShellCompletions, cobra.ShellCompDirectiveNoFileComp - }) - - // label-file is defined as StringSlice, not StringArray, to allow specifying "--env-file=FILE1,FILE2" (compatible with Podman) - cmd.Flags().StringSlice("label-file", nil, "Set metadata on container from file") - cmd.Flags().String("cidfile", "", "Write the container ID to the file") - // #endregion - - // #region logging flags - // log-opt needs to be StringArray, not StringSlice, to prevent "env=os,customer" from being split to {"env=os", "customer"} - cmd.Flags().String("log-driver", "json-file", "Logging driver for the container. Default is json-file. It also supports logURI (eg: --log-driver binary://)") - cmd.RegisterFlagCompletionFunc("log-driver", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return logging.Drivers(), cobra.ShellCompDirectiveNoFileComp - }) - cmd.Flags().StringArray("log-opt", nil, "Log driver options") - // #endregion - - // shared memory flags - cmd.Flags().String("shm-size", "", "Size of /dev/shm") - cmd.Flags().String("pidfile", "", "file path to write the task's pid") - - // #region verify flags - cmd.Flags().String("verify", "none", "Verify the image (none|cosign)") - cmd.RegisterFlagCompletionFunc("verify", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return []string{"none", "cosign"}, cobra.ShellCompDirectiveNoFileComp - }) - cmd.Flags().String("cosign-key", "", "Path to the public key file, KMS, URI or Kubernetes Secret for --verify=cosign") - // #endregion -} - -// runAction is heavily based on ctr implementation: -// https://github.com/containerd/containerd/blob/v1.4.3/cmd/ctr/commands/run/run.go -func runAction(cmd *cobra.Command, args []string) error { - platform, err := cmd.Flags().GetString("platform") - if err != nil { - return err - } - client, ctx, cancel, err := newClientWithPlatform(cmd, platform) - if err != nil { - return err - } - defer cancel() - - flagD, err := cmd.Flags().GetBool("detach") - if err != nil { - return err - } - flagI, err := cmd.Flags().GetBool("interactive") - if err != nil { - return err - } - flagT, err := cmd.Flags().GetBool("tty") - if err != nil { - return err - } - container, gc, err := createContainer(ctx, cmd, client, args, platform, flagI, flagT, flagD) - if err != nil { - if gc != nil { - defer gc() - } - return err - } - - id := container.ID() - rm, err := cmd.Flags().GetBool("rm") - if err != nil { - return err - } - if rm { - if flagD { - return errors.New("flag -d and --rm cannot be specified together") - } - defer func() { - if err := removeContainer(ctx, cmd, container, true, true); err != nil { - logrus.WithError(err).Warnf("failed to remove container %s", id) - } - }() - } - - var con console.Console - if flagT { - con = console.Current() - defer con.Reset() - if err := con.SetRaw(); err != nil { - return err - } - } - - lab, err := container.Labels(ctx) - if err != nil { - return err - } - logURI := lab[labels.LogURI] - - task, err := taskutil.NewTask(ctx, client, container, flagI, flagT, flagD, con, logURI) - if err != nil { - return err - } - var statusC <-chan containerd.ExitStatus - if !flagD { - defer func() { - if rm { - if _, taskDeleteErr := task.Delete(ctx); taskDeleteErr != nil { - logrus.Error(taskDeleteErr) - } - } - }() - statusC, err = task.Wait(ctx) - if err != nil { - return err - } - } - - if err := task.Start(ctx); err != nil { - return err - } - - if flagD { - fmt.Fprintf(cmd.OutOrStdout(), "%s\n", id) - return nil - } - if flagT { - if err := tasks.HandleConsoleResize(ctx, task, con); err != nil { - logrus.WithError(err).Error("console resize") - } - } else { - sigc := commands.ForwardAllSignals(ctx, task) - defer commands.StopCatch(sigc) - } - status := <-statusC - code, _, err := status.Result() - if err != nil { - return err - } - if code != 0 { - return ExitCodeError{ - exitCode: int(code), - } - } - return nil -} - -// FIXME: split to smaller functions -func createContainer(ctx context.Context, cmd *cobra.Command, client *containerd.Client, args []string, platform string, flagI, flagT, flagD bool) (containerd.Container, func(), error) { - // simulate the behavior of double dash - newArg := []string{} - if len(args) >= 2 && args[1] == "--" { - newArg = append(newArg, args[:1]...) - newArg = append(newArg, args[2:]...) - args = newArg - } - var internalLabels internalLabels - internalLabels.platform = platform - - ns, err := cmd.Flags().GetString("namespace") - if err != nil { - return nil, nil, err - } - internalLabels.namespace = ns - - var ( - opts []oci.SpecOpts - cOpts []containerd.NewContainerOpts - id = idgen.GenerateID() - ) - - cidfile, err := cmd.Flags().GetString("cidfile") - if err != nil { - return nil, nil, err - } - if cidfile != "" { - if err := writeCIDFile(cidfile, id); err != nil { - return nil, nil, err - } - } - - dataStore, err := getDataStore(cmd) - if err != nil { - return nil, nil, err - } - - stateDir, err := getContainerStateDirPath(cmd, dataStore, id) - if err != nil { - return nil, nil, err - } - if err := os.MkdirAll(stateDir, 0700); err != nil { - return nil, nil, err - } - internalLabels.stateDir = stateDir - - opts = append(opts, - oci.WithDefaultSpec(), - ) - - opts, internalLabels, err = setPlatformOptions(ctx, opts, cmd, client, id, internalLabels) - if err != nil { - return nil, nil, err - } - - rootfsOpts, rootfsCOpts, ensuredImage, err := generateRootfsOpts(ctx, client, platform, cmd, args, id) - if err != nil { - return nil, nil, err - } - opts = append(opts, rootfsOpts...) - cOpts = append(cOpts, rootfsCOpts...) - - wd, err := cmd.Flags().GetString("workdir") - if err != nil { - return nil, nil, err - } - if wd != "" { - opts = append(opts, oci.WithProcessCwd(wd)) - } - - envFile, err := cmd.Flags().GetStringSlice("env-file") - if err != nil { - return nil, nil, err - } - env, err := cmd.Flags().GetStringArray("env") - if err != nil { - return nil, nil, err - } - envs, err := generateEnvs(envFile, env) - if err != nil { - return nil, nil, err - } - opts = append(opts, oci.WithEnv(envs)) - - if flagI { - if flagD { - return nil, nil, errors.New("currently flag -i and -d cannot be specified together (FIXME)") - } - } - - if flagT { - if flagD { - return nil, nil, errors.New("currently flag -t and -d cannot be specified together (FIXME)") - } - opts = append(opts, oci.WithTTY) - } - - mountOpts, anonVolumes, mountPoints, err := generateMountOpts(ctx, cmd, client, ensuredImage) - if err != nil { - return nil, nil, err - } - internalLabels.anonVolumes = anonVolumes - internalLabels.mountPoints = mountPoints - opts = append(opts, mountOpts...) - - var logURI string - if flagD { - // json-file is the built-in and default log driver for nerdctl - logDriver, err := cmd.Flags().GetString("log-driver") - if err != nil { - return nil, nil, err - } - - // check if log driver is a valid uri. If it is a valid uri and scheme is not - if u, err := url.Parse(logDriver); err == nil && u.Scheme != "" { - logURI = logDriver - } else { - logOptMap, err := parseKVStringsMapFromLogOpt(cmd, logDriver) - if err != nil { - return nil, nil, err - } - logDriverInst, err := logging.GetDriver(logDriver, logOptMap) - if err != nil { - return nil, nil, err - } - if err := logDriverInst.Init(dataStore, ns, id); err != nil { - return nil, nil, err - } - logConfig := &logging.LogConfig{ - Driver: logDriver, - Opts: logOptMap, - } - logConfigB, err := json.Marshal(logConfig) - if err != nil { - return nil, nil, err - } - logConfigFilePath := logging.LogConfigFilePath(dataStore, ns, id) - if err = os.WriteFile(logConfigFilePath, logConfigB, 0600); err != nil { - return nil, nil, err - } - if lu, err := generateLogURI(dataStore); err != nil { - return nil, nil, err - } else if lu != nil { - logrus.Debugf("generated log driver: %s", lu.String()) - - logURI = lu.String() - } - } - } - internalLabels.logURI = logURI - - restartValue, err := cmd.Flags().GetString("restart") - if err != nil { - return nil, nil, err - } - restartOpts, err := generateRestartOpts(ctx, client, restartValue, logURI) - if err != nil { - return nil, nil, err - } - cOpts = append(cOpts, restartOpts...) - - stopSignal, err := cmd.Flags().GetString("stop-signal") - if err != nil { - return nil, nil, err - } - stopTimeout, err := cmd.Flags().GetInt("stop-timeout") - if err != nil { - return nil, nil, err - } - cOpts = append(cOpts, withStop(stopSignal, stopTimeout, ensuredImage)) - - hostname := id[0:12] - customHostname, err := cmd.Flags().GetString("hostname") - if err != nil { - return nil, nil, err - } - if customHostname != "" { - hostname = customHostname - } - opts = append(opts, oci.WithHostname(hostname)) - internalLabels.hostname = hostname - // `/etc/hostname` does not exist on FreeBSD - if runtime.GOOS == "linux" { - hostnamePath := filepath.Join(stateDir, "hostname") - if err := os.WriteFile(hostnamePath, []byte(hostname+"\n"), 0644); err != nil { - return nil, nil, err - } - opts = append(opts, withCustomEtcHostname(hostnamePath)) - } - - netOpts, netSlice, ipAddress, ports, macAddress, err := generateNetOpts(cmd, dataStore, stateDir, ns, id) - if err != nil { - return nil, nil, err - } - internalLabels.networks = netSlice - internalLabels.ipAddress = ipAddress - internalLabels.ports = ports - internalLabels.macAddress = macAddress - opts = append(opts, netOpts...) - - hookOpt, err := withNerdctlOCIHook(cmd, id) - if err != nil { - return nil, nil, err - } - opts = append(opts, hookOpt) - - uOpts, err := generateUserOpts(cmd) - if err != nil { - return nil, nil, err - } - opts = append(opts, uOpts...) - - gOpts, err := generateGroupsOpts(cmd) - if err != nil { - return nil, nil, err - } - opts = append(opts, gOpts...) - - umaskOpts, err := generateUmaskOpts(cmd) - if err != nil { - return nil, nil, err - } - opts = append(opts, umaskOpts...) - - rtCOpts, err := generateRuntimeCOpts(cmd) - if err != nil { - return nil, nil, err - } - cOpts = append(cOpts, rtCOpts...) - - lCOpts, err := withContainerLabels(cmd) - if err != nil { - return nil, nil, err - } - cOpts = append(cOpts, lCOpts...) - - var containerNameStore namestore.NameStore - name, err := cmd.Flags().GetString("name") - if err != nil { - return nil, nil, err - } - if name == "" && !cmd.Flags().Changed("name") { - // Automatically set the container name, unless `--name=""` was explicitly specified. - var imageRef string - if ensuredImage != nil { - imageRef = ensuredImage.Ref - } - name = referenceutil.SuggestContainerName(imageRef, id) - } - if name != "" { - containerNameStore, err = namestore.New(dataStore, ns) - if err != nil { - return nil, nil, err - } - if err := containerNameStore.Acquire(name, id); err != nil { - return nil, nil, err - } - } - internalLabels.name = name - - var pidFile string - if cmd.Flags().Lookup("pidfile").Changed { - pidFile, err = cmd.Flags().GetString("pidfile") - if err != nil { - return nil, nil, err - } - } - internalLabels.pidFile = pidFile - - extraHosts, err := cmd.Flags().GetStringSlice("add-host") - if err != nil { - return nil, nil, err - } - extraHosts = strutil.DedupeStrSlice(extraHosts) - for _, host := range extraHosts { - if _, err := dopts.ValidateExtraHost(host); err != nil { - return nil, nil, err - } - } - internalLabels.extraHosts = extraHosts - - ilOpt, err := withInternalLabels(internalLabels) - if err != nil { - return nil, nil, err - } - cOpts = append(cOpts, ilOpt) - - opts = append(opts, propagateContainerdLabelsToOCIAnnotations()) - - var s specs.Spec - spec := containerd.WithSpec(&s, opts...) - cOpts = append(cOpts, spec) - - container, err := client.NewContainer(ctx, id, cOpts...) - if err != nil { - gcContainer := func() { - var isErr bool - if errE := os.RemoveAll(stateDir); errE != nil { - isErr = true - } - if name != "" { - var errE error - if containerNameStore, errE = namestore.New(dataStore, ns); errE != nil { - isErr = true - } - if errE = containerNameStore.Release(name, id); errE != nil { - isErr = true - } - - } - if isErr { - logrus.Warnf("failed to remove container %q", id) - } - } - return nil, gcContainer, err - } - return container, nil, nil -} - -func generateRootfsOpts(ctx context.Context, client *containerd.Client, platform string, cmd *cobra.Command, args []string, id string) ([]oci.SpecOpts, []containerd.NewContainerOpts, *imgutil.EnsuredImage, error) { - var ( - ensured *imgutil.EnsuredImage - err error - ) - imageless, err := cmd.Flags().GetBool("rootfs") - if err != nil { - return nil, nil, nil, err - } - if !imageless { - pull, err := cmd.Flags().GetString("pull") - if err != nil { - return nil, nil, nil, err - } - var platformSS []string // len: 0 or 1 - if platform != "" { - platformSS = append(platformSS, platform) - } - ocispecPlatforms, err := platformutil.NewOCISpecPlatformSlice(false, platformSS) - if err != nil { - return nil, nil, nil, err - } - rawRef := args[0] - ensured, err = ensureImage(ctx, cmd, client, rawRef, ocispecPlatforms, pull, nil, false) - if err != nil { - return nil, nil, nil, err - } - } - var ( - opts []oci.SpecOpts - cOpts []containerd.NewContainerOpts - ) - if !imageless { - cOpts = append(cOpts, - containerd.WithImage(ensured.Image), - containerd.WithSnapshotter(ensured.Snapshotter), - containerd.WithNewSnapshot(id, ensured.Image), - containerd.WithImageStopSignal(ensured.Image, "SIGTERM"), - ) - - if len(ensured.ImageConfig.Env) == 0 { - opts = append(opts, oci.WithDefaultPathEnv) - } - for ind, env := range ensured.ImageConfig.Env { - if strings.HasPrefix(env, "PATH=") { - break - } else { - if ind == len(ensured.ImageConfig.Env)-1 { - opts = append(opts, oci.WithDefaultPathEnv) - } - } - } - } else { - absRootfs, err := filepath.Abs(args[0]) - if err != nil { - return nil, nil, nil, err - } - opts = append(opts, oci.WithRootFSPath(absRootfs), oci.WithDefaultPathEnv) - } - - // NOTE: "--entrypoint" can be set to an empty string, see TestRunEntrypoint* in run_test.go . - entrypoint, err := cmd.Flags().GetStringArray("entrypoint") - if err != nil { - return nil, nil, nil, err - } - - if !imageless && !cmd.Flag("entrypoint").Changed { - opts = append(opts, oci.WithImageConfigArgs(ensured.Image, args[1:])) - } else { - if !imageless { - opts = append(opts, oci.WithImageConfig(ensured.Image)) - } - var processArgs []string - if len(entrypoint) != 0 { - processArgs = append(processArgs, entrypoint...) - } - if len(args) > 1 { - processArgs = append(processArgs, args[1:]...) - } - if len(processArgs) == 0 { - // error message is from Podman - return nil, nil, nil, errors.New("no command or entrypoint provided, and no CMD or ENTRYPOINT from image") - } - opts = append(opts, oci.WithProcessArgs(processArgs...)) - } - - initProcessFlag, err := cmd.Flags().GetBool("init") - if err != nil { - return nil, nil, nil, err - } - initBinary, err := cmd.Flags().GetString("init-binary") - if err != nil { - return nil, nil, nil, err - } - if cmd.Flags().Changed("init-binary") { - initProcessFlag = true - } - if initProcessFlag { - binaryPath, err := exec.LookPath(initBinary) - if err != nil { - if errors.Is(err, exec.ErrNotFound) { - return nil, nil, nil, fmt.Errorf(`init binary %q not found`, initBinary) - } - return nil, nil, nil, err - } - inContainerPath := filepath.Join("/sbin", filepath.Base(initBinary)) - opts = append(opts, func(_ context.Context, _ oci.Client, _ *containers.Container, spec *oci.Spec) error { - spec.Process.Args = append([]string{inContainerPath, "--"}, spec.Process.Args...) - spec.Mounts = append([]specs.Mount{{ - Destination: inContainerPath, - Type: "bind", - Source: binaryPath, - Options: []string{"bind", "ro"}, - }}, spec.Mounts...) - return nil - }) - } - - readonly, err := cmd.Flags().GetBool("read-only") - if err != nil { - return nil, nil, nil, err - } - if readonly { - opts = append(opts, oci.WithRootFSReadonly()) - } - return opts, cOpts, ensured, nil -} - -// withBindMountHostIPC replaces /dev/shm and /dev/mqueue mount with rbind. -// Required for --ipc=host on rootless. -func withBindMountHostIPC(_ context.Context, _ oci.Client, _ *containers.Container, s *oci.Spec) error { - for i, m := range s.Mounts { - if path.Clean(m.Destination) == "/dev/shm" { - newM := specs.Mount{ - Destination: "/dev/shm", - Type: "bind", - Source: "/dev/shm", - Options: []string{"rbind", "nosuid", "noexec", "nodev"}, - } - s.Mounts[i] = newM - } - if path.Clean(m.Destination) == "/dev/mqueue" { - newM := specs.Mount{ - Destination: "/dev/mqueue", - Type: "bind", - Source: "/dev/mqueue", - Options: []string{"rbind", "nosuid", "noexec", "nodev"}, - } - s.Mounts[i] = newM - } - } - return nil -} - -// withBindMountHostProcfs replaces procfs mount with rbind. -// Required for --pid=host on rootless. -// -// https://github.com/moby/moby/pull/41893/files -// https://github.com/containers/podman/blob/v3.0.0-rc1/pkg/specgen/generate/oci.go#L248-L257 -func withBindMountHostProcfs(_ context.Context, _ oci.Client, _ *containers.Container, s *oci.Spec) error { - for i, m := range s.Mounts { - if path.Clean(m.Destination) == "/proc" { - newM := specs.Mount{ - Destination: "/proc", - Type: "bind", - Source: "/proc", - Options: []string{"rbind", "nosuid", "noexec", "nodev"}, - } - s.Mounts[i] = newM - } - } - - // Remove ReadonlyPaths for /proc/* - newROP := s.Linux.ReadonlyPaths[:0] - for _, x := range s.Linux.ReadonlyPaths { - x = path.Clean(x) - if !strings.HasPrefix(x, "/proc/") { - newROP = append(newROP, x) - } - } - s.Linux.ReadonlyPaths = newROP - return nil -} - -func generateLogURI(dataStore string) (*url.URL, error) { - selfExe, err := os.Executable() - if err != nil { - return nil, err - } - args := map[string]string{ - logging.MagicArgv1: dataStore, - } - - return cio.LogURIGenerator("binary", selfExe, args) -} - -func withNerdctlOCIHook(cmd *cobra.Command, id string) (oci.SpecOpts, error) { - selfExe, f := globalFlags(cmd) - args := append([]string{selfExe}, append(f, "internal", "oci-hook")...) - return func(_ context.Context, _ oci.Client, _ *containers.Container, s *specs.Spec) error { - if s.Hooks == nil { - s.Hooks = &specs.Hooks{} - } - crArgs := append(args, "createRuntime") - s.Hooks.CreateRuntime = append(s.Hooks.CreateRuntime, specs.Hook{ - Path: selfExe, - Args: crArgs, - Env: os.Environ(), - }) - argsCopy := append([]string(nil), args...) - psArgs := append(argsCopy, "postStop") - s.Hooks.Poststop = append(s.Hooks.Poststop, specs.Hook{ - Path: selfExe, - Args: psArgs, - Env: os.Environ(), - }) - return nil - }, nil -} - -func getContainerStateDirPath(cmd *cobra.Command, dataStore, id string) (string, error) { - ns, err := cmd.Flags().GetString("namespace") - if err != nil { - return "", err - } - if ns == "" { - return "", errors.New("namespace is required") - } - if strings.Contains(ns, "/") { - return "", errors.New("namespace with '/' is unsupported") - } - return filepath.Join(dataStore, "containers", ns, id), nil -} - -func withContainerLabels(cmd *cobra.Command) ([]containerd.NewContainerOpts, error) { - labelMap, err := readKVStringsMapfFromLabel(cmd) - if err != nil { - return nil, err - } - o := containerd.WithAdditionalContainerLabels(labelMap) - return []containerd.NewContainerOpts{o}, nil -} - -func readKVStringsMapfFromLabel(cmd *cobra.Command) (map[string]string, error) { - labelsMap, err := cmd.Flags().GetStringArray("label") - if err != nil { - return nil, err - } - labelsMap = strutil.DedupeStrSlice(labelsMap) - labelsFilePath, err := cmd.Flags().GetStringSlice("label-file") - if err != nil { - return nil, err - } - labelsFilePath = strutil.DedupeStrSlice(labelsFilePath) - labels, err := dopts.ReadKVStrings(labelsFilePath, labelsMap) - if err != nil { - return nil, err - } - - return strutil.ConvertKVStringsToMap(labels), nil -} - -// parseKVStringsMapFromLogOpt parse log options KV entries and convert to Map -func parseKVStringsMapFromLogOpt(cmd *cobra.Command, logDriver string) (map[string]string, error) { - logOptArray, err := cmd.Flags().GetStringArray("log-opt") - if err != nil { - return nil, err - } - logOptArray = strutil.DedupeStrSlice(logOptArray) - logOptMap := strutil.ConvertKVStringsToMap(logOptArray) - if logDriver == "json-file" { - if _, ok := logOptMap[logging.MaxSize]; !ok { - delete(logOptMap, logging.MaxFile) - } - } - if err := logging.ValidateLogOpts(logDriver, logOptMap); err != nil { - return nil, err - } - return logOptMap, nil -} - -func withStop(stopSignal string, stopTimeout int, ensuredImage *imgutil.EnsuredImage) containerd.NewContainerOpts { - return func(ctx context.Context, _ *containerd.Client, c *containers.Container) error { - if c.Labels == nil { - c.Labels = make(map[string]string) - } - var err error - if ensuredImage != nil { - stopSignal, err = containerd.GetOCIStopSignal(ctx, ensuredImage.Image, stopSignal) - if err != nil { - return err - } - } - c.Labels[containerd.StopSignalLabel] = stopSignal - if stopTimeout != 0 { - c.Labels[labels.StopTimout] = strconv.Itoa(stopTimeout) - } - return nil - } -} - -type internalLabels struct { - // labels from cmd options - namespace string - platform string - extraHosts []string - pidFile string - // labels from cmd options or automatically set - name string - hostname string - // automatically generated - stateDir string - // network - networks []string - ipAddress string - ports []gocni.PortMapping - macAddress string - // volumn - mountPoints []*mountutil.Processed - anonVolumes []string - // pid namespace - pidContainer string - // log - logURI string -} - -func withInternalLabels(internalLabels internalLabels) (containerd.NewContainerOpts, error) { - m := make(map[string]string) - m[labels.Namespace] = internalLabels.namespace - if internalLabels.name != "" { - m[labels.Name] = internalLabels.name - } - m[labels.Hostname] = internalLabels.hostname - extraHostsJSON, err := json.Marshal(internalLabels.extraHosts) - if err != nil { - return nil, err - } - m[labels.ExtraHosts] = string(extraHostsJSON) - m[labels.StateDir] = internalLabels.stateDir - networksJSON, err := json.Marshal(internalLabels.networks) - if err != nil { - return nil, err - } - m[labels.Networks] = string(networksJSON) - if len(internalLabels.ports) > 0 { - portsJSON, err := json.Marshal(internalLabels.ports) - if err != nil { - return nil, err - } - m[labels.Ports] = string(portsJSON) - } - if internalLabels.logURI != "" { - m[labels.LogURI] = internalLabels.logURI - } - if len(internalLabels.anonVolumes) > 0 { - anonVolumeJSON, err := json.Marshal(internalLabels.anonVolumes) - if err != nil { - return nil, err - } - m[labels.AnonymousVolumes] = string(anonVolumeJSON) - } - - if internalLabels.pidFile != "" { - m[labels.PIDFile] = internalLabels.pidFile - } - - if internalLabels.ipAddress != "" { - m[labels.IPAddress] = internalLabels.ipAddress - } - - m[labels.Platform], err = platformutil.NormalizeString(internalLabels.platform) - if err != nil { - return nil, err - } - - if len(internalLabels.mountPoints) > 0 { - mounts := dockercompatMounts(internalLabels.mountPoints) - mountPointsJSON, err := json.Marshal(mounts) - if err != nil { - return nil, err - } - m[labels.Mounts] = string(mountPointsJSON) - } - - if internalLabels.macAddress != "" { - m[labels.MACAddress] = internalLabels.macAddress - } - - if internalLabels.pidContainer != "" { - m[labels.PIDContainer] = internalLabels.pidContainer - } - - return containerd.WithAdditionalContainerLabels(m), nil -} - -func dockercompatMounts(mountPoints []*mountutil.Processed) []dockercompat.MountPoint { - reuslt := make([]dockercompat.MountPoint, len(mountPoints)) - for i := range mountPoints { - mp := mountPoints[i] - reuslt[i] = dockercompat.MountPoint{ - Type: mp.Type, - Name: mp.Name, - Source: mp.Mount.Source, - Destination: mp.Mount.Destination, - Driver: "", - Mode: mp.Mode, - } - - // it's a anonymous volume - if mp.AnonymousVolume != "" { - reuslt[i].Name = mp.AnonymousVolume - } - - // volume only support local driver - if mp.Type == "volume" { - reuslt[i].Driver = "local" - } - } - return reuslt -} - -func propagateContainerdLabelsToOCIAnnotations() oci.SpecOpts { - return func(ctx context.Context, oc oci.Client, c *containers.Container, s *oci.Spec) error { - return oci.WithAnnotations(c.Labels)(ctx, oc, c, s) - } -} - -func writeCIDFile(path, id string) error { - if _, err := os.Stat(path); err == nil { - return fmt.Errorf("container ID file found, make sure the other container isn't running or delete %s", path) - } else if errors.Is(err, os.ErrNotExist) { - f, err := os.Create(path) - if err != nil { - return err - } - defer f.Close() - if err != nil { - return fmt.Errorf("failed to create the container ID file: %s", err) - } - if _, err := f.WriteString(id); err != nil { - return err - } - return nil - } else { - return err - } -} - -func parseEnvVars(paths []string) ([]string, error) { - vars := make([]string, 0) - for _, path := range paths { - f, err := os.Open(path) - if err != nil { - return nil, fmt.Errorf("failed to open env file %s: %w", path, err) - } - defer f.Close() - - sc := bufio.NewScanner(f) - for sc.Scan() { - line := strings.TrimSpace(sc.Text()) - // skip comment lines - if strings.HasPrefix(line, "#") { - continue - } - vars = append(vars, line) - } - if err = sc.Err(); err != nil { - return nil, err - } - } - return vars, nil -} - -func withOSEnv(envs []string) ([]string, error) { - newEnvs := make([]string, len(envs)) - - // from https://github.com/docker/cli/blob/v22.06.0-beta.0/opts/env.go#L18 - getEnv := func(val string) (string, error) { - arr := strings.SplitN(val, "=", 2) - if arr[0] == "" { - return "", errors.New("invalid environment variable: " + val) - } - if len(arr) > 1 { - return val, nil - } - if envVal, ok := os.LookupEnv(arr[0]); ok { - return arr[0] + "=" + envVal, nil - } - return val, nil - } - for i := range envs { - env, err := getEnv(envs[i]) - if err != nil { - return nil, err - } - newEnvs[i] = env - } - - return newEnvs, nil -} - -func generateSharingPIDOpts(ctx context.Context, targetCon containerd.Container) ([]oci.SpecOpts, error) { - opts := make([]oci.SpecOpts, 0) - - task, err := targetCon.Task(ctx, nil) - if err != nil { - return nil, err - } - status, err := task.Status(ctx) - if err != nil { - return nil, err - } - - if status.Status != containerd.Running { - return nil, fmt.Errorf("shared container is not running") - } - - spec, err := targetCon.Spec(ctx) - if err != nil { - return nil, err - } - - isHost := true - for _, n := range spec.Linux.Namespaces { - if n.Type == specs.PIDNamespace { - isHost = false - } - } - if isHost { - opts = append(opts, oci.WithHostNamespace(specs.PIDNamespace)) - if rootlessutil.IsRootless() { - opts = append(opts, withBindMountHostProcfs) - } - } else { - ns := specs.LinuxNamespace{ - Type: specs.PIDNamespace, - Path: fmt.Sprintf("/proc/%d/ns/pid", task.Pid()), - } - opts = append(opts, oci.WithLinuxNamespace(ns)) - } - - return opts, nil -} - -// generateEnvs combines environment variables from `--env-file` and `--env`. -// Pass an empty slice if any arg is not used. -func generateEnvs(envFile []string, env []string) ([]string, error) { - var envs []string - var err error - - if envFiles := strutil.DedupeStrSlice(envFile); len(envFiles) > 0 { - envs, err = parseEnvVars(envFiles) - if err != nil { - return nil, err - } - } - - if env := strutil.DedupeStrSlice(env); len(env) > 0 { - envs = append(envs, env...) - } - - if envs, err = withOSEnv(envs); err != nil { - return nil, err - } - - return envs, nil -} diff --git a/cmd/nerdctl/save.go b/cmd/nerdctl/save/save.go similarity index 90% rename from cmd/nerdctl/save.go rename to cmd/nerdctl/save/save.go index b7623e1e55e..1739693373f 100644 --- a/cmd/nerdctl/save.go +++ b/cmd/nerdctl/save/save.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package save import ( "fmt" @@ -22,6 +22,8 @@ import ( "os" "github.com/containerd/containerd/images/archive" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/pkg/platformutil" "github.com/containerd/nerdctl/pkg/referenceutil" "github.com/mattn/go-isatty" @@ -29,7 +31,7 @@ import ( "github.com/spf13/cobra" ) -func newSaveCommand() *cobra.Command { +func NewSaveCommand() *cobra.Command { var saveCommand = &cobra.Command{ Use: "save", Args: cobra.MinimumNArgs(1), @@ -45,7 +47,7 @@ func newSaveCommand() *cobra.Command { // #region platform flags // platform is defined as StringSlice, not StringArray, to allow specifying "--platform=amd64,arm64" saveCommand.Flags().StringSlice("platform", []string{}, "Export content for a specific platform") - saveCommand.RegisterFlagCompletionFunc("platform", shellCompletePlatforms) + saveCommand.RegisterFlagCompletionFunc("platform", completion.ShellCompletePlatforms) saveCommand.Flags().Bool("all-platforms", false, "Export content for all platforms") // #endregion @@ -83,7 +85,7 @@ func saveAction(cmd *cobra.Command, args []string) error { } func saveImage(images []string, out io.Writer, saveOpts []archive.ExportOpt, cmd *cobra.Command) error { - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } @@ -118,5 +120,5 @@ func saveImage(images []string, out io.Writer, saveOpts []archive.ExportOpt, cmd func saveShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show image names - return shellCompleteImageNames(cmd) + return completion.ShellCompleteImageNames(cmd) } diff --git a/cmd/nerdctl/stats.go b/cmd/nerdctl/stats/stats.go similarity index 94% rename from cmd/nerdctl/stats.go rename to cmd/nerdctl/stats/stats.go index e843aefc3b7..c831dcac175 100644 --- a/cmd/nerdctl/stats.go +++ b/cmd/nerdctl/stats/stats.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package stats import ( "bytes" @@ -27,10 +27,12 @@ import ( "text/template" "time" - "github.com/containerd/containerd" eventstypes "github.com/containerd/containerd/api/events" "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/events" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/fmtutil" "github.com/containerd/nerdctl/pkg/containerinspector" "github.com/containerd/nerdctl/pkg/eventutil" "github.com/containerd/nerdctl/pkg/formatter" @@ -44,12 +46,12 @@ import ( "github.com/spf13/cobra" ) -func newStatsCommand() *cobra.Command { +func NewStatsCommand() *cobra.Command { var statsCommand = &cobra.Command{ Use: "stats", Short: "Display a live stream of container(s) resource usage statistics.", RunE: statsAction, - ValidArgsFunction: statsShellComplete, + ValidArgsFunction: completion.StatsShellComplete, SilenceUsage: true, SilenceErrors: true, } @@ -134,7 +136,7 @@ func statsAction(cmd *cobra.Command, args []string) error { case "raw": return errors.New("unsupported format: \"raw\"") default: - tmpl, err = parseTemplate(format) + tmpl, err = fmtutil.ParseTemplate(format) if err != nil { return err } @@ -149,7 +151,7 @@ func statsAction(cmd *cobra.Command, args []string) error { waitFirst := &sync.WaitGroup{} cStats := stats{} - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } @@ -253,7 +255,7 @@ func statsAction(cmd *cobra.Command, args []string) error { defer close(eventChan) <-started - // Start a goroutine to retrieve the initial list of containers stats. + // Start a goroutine to retrieve the initial list of Containers stats. getContainerList() // make sure each container get at least one valid stat data @@ -348,7 +350,7 @@ func statsAction(cmd *cobra.Command, args []string) error { } } } - if f, ok := w.(Flusher); ok { + if f, ok := w.(fmtutil.Flusher); ok { f.Flush() } @@ -390,7 +392,7 @@ func collect(cmd *cobra.Command, s *statsutil.Stats, waitFirst *sync.WaitGroup, } }() - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { s.SetError(err) return @@ -482,11 +484,3 @@ func collect(cmd *cobra.Command, s *statsutil.Stats, waitFirst *sync.WaitGroup, } } } - -func statsShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - // show running container names - statusFilterFn := func(st containerd.ProcessStatus) bool { - return st == containerd.Running - } - return shellCompleteContainerNames(cmd, statusFilterFn) -} diff --git a/cmd/nerdctl/stats_freebsd.go b/cmd/nerdctl/stats/stats_freebsd.go similarity index 98% rename from cmd/nerdctl/stats_freebsd.go rename to cmd/nerdctl/stats/stats_freebsd.go index a6460b3218a..44f233c2a75 100644 --- a/cmd/nerdctl/stats_freebsd.go +++ b/cmd/nerdctl/stats/stats_freebsd.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package stats import ( "github.com/containerd/nerdctl/pkg/inspecttypes/native" diff --git a/cmd/nerdctl/stats_linux.go b/cmd/nerdctl/stats/stats_linux.go similarity index 99% rename from cmd/nerdctl/stats_linux.go rename to cmd/nerdctl/stats/stats_linux.go index 8f6ddbbee36..0b6b4ba39f5 100644 --- a/cmd/nerdctl/stats_linux.go +++ b/cmd/nerdctl/stats/stats_linux.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package stats import ( "errors" diff --git a/cmd/nerdctl/stats_windows.go b/cmd/nerdctl/stats/stats_windows.go similarity index 98% rename from cmd/nerdctl/stats_windows.go rename to cmd/nerdctl/stats/stats_windows.go index a6460b3218a..44f233c2a75 100644 --- a/cmd/nerdctl/stats_windows.go +++ b/cmd/nerdctl/stats/stats_windows.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package stats import ( "github.com/containerd/nerdctl/pkg/inspecttypes/native" diff --git a/cmd/nerdctl/info.go b/cmd/nerdctl/system/info.go similarity index 96% rename from cmd/nerdctl/info.go rename to cmd/nerdctl/system/info.go index 9268492e500..7574c3eada4 100644 --- a/cmd/nerdctl/info.go +++ b/cmd/nerdctl/system/info.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package system import ( "fmt" @@ -23,6 +23,8 @@ import ( "strings" "text/template" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/fmtutil" "golang.org/x/text/cases" "golang.org/x/text/language" @@ -37,7 +39,7 @@ import ( "github.com/spf13/cobra" ) -func newInfoCommand() *cobra.Command { +func NewInfoCommand() *cobra.Command { var infoCommand = &cobra.Command{ Use: "info", Args: cobra.NoArgs, @@ -67,13 +69,13 @@ func infoAction(cmd *cobra.Command, args []string) error { return err } if format != "" { - tmpl, err = parseTemplate(format) + tmpl, err = fmtutil.ParseTemplate(format) if err != nil { return err } } - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/system.go b/cmd/nerdctl/system/system.go similarity index 64% rename from cmd/nerdctl/system.go rename to cmd/nerdctl/system/system.go index bb9635be295..5142dfb86cf 100644 --- a/cmd/nerdctl/system.go +++ b/cmd/nerdctl/system/system.go @@ -14,24 +14,29 @@ limitations under the License. */ -package main +package system -import "github.com/spf13/cobra" +import ( + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/event" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" + "github.com/spf13/cobra" +) -func newSystemCommand() *cobra.Command { +func NewSystemCommand() *cobra.Command { var systemCommand = &cobra.Command{ - Annotations: map[string]string{Category: Management}, + Annotations: map[string]string{common.Category: common.Management}, Use: "system", Short: "Manage containerd", - RunE: unknownSubcommandAction, + RunE: completion.UnknownSubcommandAction, SilenceUsage: true, SilenceErrors: true, } // versionCommand is not here systemCommand.AddCommand( - newEventsCommand(), - newInfoCommand(), - newSystemPruneCommand(), + event.NewEventsCommand(), + NewInfoCommand(), + NewSystemPruneCommand(), ) return systemCommand } diff --git a/cmd/nerdctl/system_prune.go b/cmd/nerdctl/system/system_prune.go similarity index 79% rename from cmd/nerdctl/system_prune.go rename to cmd/nerdctl/system/system_prune.go index 544c6a271f1..4388c561dab 100644 --- a/cmd/nerdctl/system_prune.go +++ b/cmd/nerdctl/system/system_prune.go @@ -14,17 +14,22 @@ limitations under the License. */ -package main +package system import ( "fmt" "strings" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/container" + "github.com/containerd/nerdctl/cmd/nerdctl/image" + "github.com/containerd/nerdctl/cmd/nerdctl/network" + "github.com/containerd/nerdctl/cmd/nerdctl/volume" "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) -func newSystemPruneCommand() *cobra.Command { +func NewSystemPruneCommand() *cobra.Command { systemPruneCommand := &cobra.Command{ Use: "prune [flags]", Short: "Remove unused data", @@ -82,22 +87,22 @@ func systemPruneAction(cmd *cobra.Command, args []string) error { } } - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } defer cancel() - if err := containerPrune(ctx, cmd, client); err != nil { + if err := container.Prune(ctx, cmd, client); err != nil { return err } - if err := networkPrune(ctx, cmd, client); err != nil { + if err := network.Prune(ctx, cmd, client); err != nil { return err } if vFlag { - if err := volumePrune(ctx, cmd, client); err != nil { + if err := volume.Prune(ctx, cmd, client); err != nil { return err } } - return imagePrune(ctx, cmd, client) + return image.Prune(ctx, cmd, client) } diff --git a/cmd/nerdctl/tag.go b/cmd/nerdctl/tag/tag.go similarity index 87% rename from cmd/nerdctl/tag.go rename to cmd/nerdctl/tag/tag.go index d8a8bbd909b..d2304684eef 100644 --- a/cmd/nerdctl/tag.go +++ b/cmd/nerdctl/tag/tag.go @@ -14,24 +14,27 @@ limitations under the License. */ -package main +package tag import ( "context" "fmt" "github.com/containerd/containerd/errdefs" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/pkg/idutil/imagewalker" "github.com/containerd/nerdctl/pkg/referenceutil" "github.com/spf13/cobra" ) -func newTagCommand() *cobra.Command { +func NewTagCommand() *cobra.Command { var tagCommand = &cobra.Command{ Use: "tag [flags] SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]", Short: "Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE", - Args: IsExactArgs(2), + Args: utils.IsExactArgs(2), RunE: tagAction, ValidArgsFunction: tagShellComplete, SilenceUsage: true, @@ -41,7 +44,7 @@ func newTagCommand() *cobra.Command { } func tagAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } @@ -100,7 +103,7 @@ func tagAction(cmd *cobra.Command, args []string) error { func tagShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if len(args) < 2 { // show image names - return shellCompleteImageNames(cmd) + return completion.ShellCompleteImageNames(cmd) } return nil, cobra.ShellCompDirectiveNoFileComp } diff --git a/cmd/nerdctl/top/top.go b/cmd/nerdctl/top/top.go new file mode 100644 index 00000000000..dfb16ea7007 --- /dev/null +++ b/cmd/nerdctl/top/top.go @@ -0,0 +1,99 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* + Portions from: + - https://github.com/moby/moby/blob/v20.10.6/api/types/container/container_top.go + - https://github.com/moby/moby/blob/v20.10.6/daemon/top_unix.go + Copyright (C) The Moby authors. + Licensed under the Apache License, Version 2.0 + NOTICE: https://github.com/moby/moby/blob/v20.10.6/NOTICE +*/ + +package top + +import ( + "context" + "errors" + "fmt" + "strings" + + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/utils" + "github.com/containerd/nerdctl/pkg/idutil/containerwalker" + "github.com/containerd/nerdctl/pkg/infoutil" + "github.com/containerd/nerdctl/pkg/rootlessutil" + + "github.com/spf13/cobra" +) + +func NewTopCommand() *cobra.Command { + var topCommand = &cobra.Command{ + Use: "top CONTAINER [ps OPTIONS]", + Args: cobra.MinimumNArgs(1), + Short: "Display the running processes of a container", + RunE: topAction, + ValidArgsFunction: completion.TopShellComplete, + SilenceUsage: true, + SilenceErrors: true, + } + topCommand.Flags().SetInterspersed(false) + return topCommand +} + +func topAction(cmd *cobra.Command, args []string) error { + // NOTE: rootless container does not rely on cgroupv1. + // more details about possible ways to resolve this concern: #223 + if rootlessutil.IsRootless() && infoutil.CgroupsVersion() == "1" { + return fmt.Errorf("top requires cgroup v2 for rootless containers, see https://rootlesscontaine.rs/getting-started/common/cgroup2/") + } + + cgroupManager, err := cmd.Flags().GetString("cgroup-manager") + if err != nil { + return err + } + if cgroupManager == "none" { + return errors.New("cgroup manager must not be \"none\"") + } + + client, ctx, cancel, err := nerdClient.NewClient(cmd) + if err != nil { + return err + } + defer cancel() + + walker := &containerwalker.ContainerWalker{ + Client: client, + OnFound: func(ctx context.Context, found containerwalker.Found) error { + if found.MatchCount > 1 { + return fmt.Errorf("multiple IDs found with provided prefix: %s", found.Req) + } + if err := utils.ContainerTop(ctx, cmd, client, found.Container.ID(), strings.Join(args[1:], " ")); err != nil { + return err + } + return nil + }, + } + + n, err := walker.Walk(ctx, args[0]) + if err != nil { + return err + } else if n == 0 { + return fmt.Errorf("no such container %s", args[0]) + } + return nil +} diff --git a/cmd/nerdctl/start.go b/cmd/nerdctl/utils/action/start.go similarity index 65% rename from cmd/nerdctl/start.go rename to cmd/nerdctl/utils/action/start.go index 147ca221d31..d769ae636d0 100644 --- a/cmd/nerdctl/start.go +++ b/cmd/nerdctl/utils/action/start.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package action import ( "context" @@ -30,79 +30,16 @@ import ( "github.com/containerd/containerd/cio" "github.com/containerd/containerd/cmd/ctr/commands" "github.com/containerd/containerd/oci" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/run" "github.com/containerd/nerdctl/pkg/formatter" - "github.com/containerd/nerdctl/pkg/idutil/containerwalker" "github.com/containerd/nerdctl/pkg/labels" "github.com/containerd/nerdctl/pkg/netutil/nettype" "github.com/opencontainers/runtime-spec/specs-go" - "github.com/sirupsen/logrus" - "github.com/spf13/cobra" ) -func newStartCommand() *cobra.Command { - var startCommand = &cobra.Command{ - Use: "start [flags] CONTAINER [CONTAINER, ...]", - Args: cobra.MinimumNArgs(1), - Short: "Start one or more running containers", - RunE: startAction, - ValidArgsFunction: startShellComplete, - SilenceUsage: true, - SilenceErrors: true, - } - - startCommand.Flags().SetInterspersed(false) - startCommand.Flags().BoolP("attach", "a", false, "Attach STDOUT/STDERR and forward signals") - - return startCommand -} - -func startAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := newClient(cmd) - if err != nil { - return err - } - defer cancel() - - flagA, err := cmd.Flags().GetBool("attach") - if err != nil { - return err - } - - if flagA && len(args) > 1 { - return fmt.Errorf("you cannot start and attach multiple containers at once") - } - - walker := &containerwalker.ContainerWalker{ - Client: client, - OnFound: func(ctx context.Context, found containerwalker.Found) error { - if found.MatchCount > 1 { - return fmt.Errorf("multiple IDs found with provided prefix: %s", found.Req) - } - if err := startContainer(ctx, found.Container, flagA, client); err != nil { - return err - } - if !flagA { - _, err := fmt.Fprintf(cmd.OutOrStdout(), "%s\n", found.Req) - if err != nil { - return err - } - } - return err - }, - } - for _, req := range args { - n, err := walker.Walk(ctx, req) - if err != nil { - return err - } else if n == 0 { - return fmt.Errorf("no such container %s", req) - } - } - return nil -} - -func startContainer(ctx context.Context, container containerd.Container, flagA bool, client *containerd.Client) error { +func StartContainer(ctx context.Context, container containerd.Container, flagA bool, client *containerd.Client) error { lab, err := container.Labels(ctx) if err != nil { return err @@ -139,7 +76,7 @@ func startContainer(ctx context.Context, container containerd.Container, flagA b logrus.Warnf("container %s is already running", container.ID()) return nil } - if err := updateContainerStoppedLabel(ctx, container, false); err != nil { + if err := run.UpdateContainerStoppedLabel(ctx, container, false); err != nil { return err } if oldTask, err := container.Task(ctx, nil); err == nil { @@ -176,8 +113,8 @@ func startContainer(ctx context.Context, container containerd.Container, flagA b return err } if code != 0 { - return ExitCodeError{ - exitCode: int(code), + return common.ExitCodeError{ + Code: int(code), } } return nil @@ -205,7 +142,7 @@ func reconfigNetContainer(ctx context.Context, c containerd.Container, client *c if err != nil { return err } - netNSPath, err := getContainerNetNSPath(ctx, targetCon) + netNSPath, err := run.GetContainerNetNSPath(ctx, targetCon) if err != nil { return err } @@ -242,7 +179,7 @@ func reconfigPIDContainer(ctx context.Context, c containerd.Container, client *c return err } - opts, err := generateSharingPIDOpts(ctx, targetCon) + opts, err := run.GenerateSharingPIDOpts(ctx, targetCon) if err != nil { return err } @@ -261,11 +198,3 @@ func reconfigPIDContainer(ctx context.Context, c containerd.Container, client *c return nil } - -func startShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - // show non-running container names - statusFilterFn := func(st containerd.ProcessStatus) bool { - return st != containerd.Running && st != containerd.Unknown - } - return shellCompleteContainerNames(cmd, statusFilterFn) -} diff --git a/cmd/nerdctl/stop.go b/cmd/nerdctl/utils/action/stop.go similarity index 57% rename from cmd/nerdctl/stop.go rename to cmd/nerdctl/utils/action/stop.go index 21227bef1fc..5985f3253a2 100644 --- a/cmd/nerdctl/stop.go +++ b/cmd/nerdctl/utils/action/stop.go @@ -14,87 +14,23 @@ limitations under the License. */ -package main +package action import ( "context" "fmt" "time" - "github.com/spf13/cobra" - "github.com/containerd/containerd" "github.com/containerd/containerd/cio" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/nerdctl/pkg/idutil/containerwalker" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/run" "github.com/containerd/nerdctl/pkg/labels" - "github.com/moby/sys/signal" "github.com/sirupsen/logrus" ) -func newStopCommand() *cobra.Command { - var stopCommand = &cobra.Command{ - Use: "stop [flags] CONTAINER [CONTAINER, ...]", - Args: cobra.MinimumNArgs(1), - Short: "Stop one or more running containers", - RunE: stopAction, - ValidArgsFunction: stopShellComplete, - SilenceUsage: true, - SilenceErrors: true, - } - stopCommand.Flags().IntP("time", "t", 10, "Seconds to wait for stop before killing it") - return stopCommand -} - -func stopAction(cmd *cobra.Command, args []string) error { - // Time to wait after sending a SIGTERM and before sending a SIGKILL. - var timeout *time.Duration - if cmd.Flags().Changed("time") { - timeValue, err := cmd.Flags().GetInt("time") - if err != nil { - return err - } - t := time.Duration(timeValue) * time.Second - timeout = &t - } - - client, ctx, cancel, err := newClient(cmd) - if err != nil { - return err - } - defer cancel() - - walker := &containerwalker.ContainerWalker{ - Client: client, - OnFound: func(ctx context.Context, found containerwalker.Found) error { - if found.MatchCount > 1 { - return fmt.Errorf("multiple IDs found with provided prefix: %s", found.Req) - } - if err := stopContainer(ctx, found.Container, timeout); err != nil { - if errdefs.IsNotFound(err) { - fmt.Fprintf(cmd.ErrOrStderr(), "No such container: %s\n", found.Req) - return nil - } - return err - } - _, err := fmt.Fprintf(cmd.OutOrStdout(), "%s\n", found.Req) - return err - }, - } - for _, req := range args { - n, err := walker.Walk(ctx, req) - if err != nil { - return err - } else if n == 0 { - return fmt.Errorf("no such container %s", req) - } - } - return nil -} - -func stopContainer(ctx context.Context, container containerd.Container, timeout *time.Duration) error { - if err := updateContainerStoppedLabel(ctx, container, true); err != nil { +func StopContainer(ctx context.Context, container containerd.Container, timeout *time.Duration) error { + if err := run.UpdateContainerStoppedLabel(ctx, container, true); err != nil { return err } @@ -210,11 +146,3 @@ func waitContainerStop(ctx context.Context, exitCh <-chan containerd.ExitStatus, return status.Error() } } - -func stopShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - // show non-stopped container names - statusFilterFn := func(st containerd.ProcessStatus) bool { - return st != containerd.Stopped && st != containerd.Created && st != containerd.Unknown - } - return shellCompleteContainerNames(cmd, statusFilterFn) -} diff --git a/cmd/nerdctl/utils/command.go b/cmd/nerdctl/utils/command.go new file mode 100644 index 00000000000..1ae62decfe6 --- /dev/null +++ b/cmd/nerdctl/utils/command.go @@ -0,0 +1,224 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package utils + +import ( + "fmt" + "os" + "strconv" + + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + "github.com/spf13/pflag" +) + +// AddStringFlag is similar to cmd.Flags().String but supports aliases and env var +func AddStringFlag(cmd *cobra.Command, name string, aliases []string, value string, env, usage string) { + if env != "" { + usage = fmt.Sprintf("%s [$%s]", usage, env) + } + if envV, ok := os.LookupEnv(env); ok { + value = envV + } + aliasesUsage := fmt.Sprintf("Alias of --%s", name) + p := new(string) + flags := cmd.Flags() + flags.StringVar(p, name, value, usage) + for _, a := range aliases { + if len(a) == 1 { + // pflag doesn't support short-only flags, so we have to register long one as well here + flags.StringVarP(p, a, a, value, aliasesUsage) + } else { + flags.StringVar(p, a, value, aliasesUsage) + } + } +} + +// AddPersistentStringFlag is similar to AddStringFlag but persistent. +// See https://github.com/spf13/cobra/blob/main/user_guide.md#persistent-flags to learn what is "persistent". +func AddPersistentStringFlag(cmd *cobra.Command, name string, aliases, localAliases, persistentAliases []string, aliasToBeInherited *pflag.FlagSet, value string, env, usage string) { + if env != "" { + usage = fmt.Sprintf("%s [$%s]", usage, env) + } + if envV, ok := os.LookupEnv(env); ok { + value = envV + } + aliasesUsage := fmt.Sprintf("Alias of --%s", name) + p := new(string) + + // flags is full set of flag(s) + // flags can redefine alias already used in subcommands + flags := cmd.Flags() + for _, a := range aliases { + if len(a) == 1 { + // pflag doesn't support short-only flags, so we have to register long one as well here + flags.StringVarP(p, a, a, value, aliasesUsage) + } else { + flags.StringVar(p, a, value, aliasesUsage) + } + // non-persistent flags are not added to the InheritedFlags, so we should add them manually + f := flags.Lookup(a) + aliasToBeInherited.AddFlag(f) + } + + // localFlags are local to the rootCmd + localFlags := cmd.LocalFlags() + for _, a := range localAliases { + if len(a) == 1 { + // pflag doesn't support short-only flags, so we have to register long one as well here + localFlags.StringVarP(p, a, a, value, aliasesUsage) + } else { + localFlags.StringVar(p, a, value, aliasesUsage) + } + } + + // persistentFlags cannot redefine alias already used in subcommands + persistentFlags := cmd.PersistentFlags() + persistentFlags.StringVar(p, name, value, usage) + for _, a := range persistentAliases { + if len(a) == 1 { + // pflag doesn't support short-only flags, so we have to register long one as well here + persistentFlags.StringVarP(p, a, a, value, aliasesUsage) + } else { + persistentFlags.StringVar(p, a, value, aliasesUsage) + } + } +} + +// AddPersistentBoolFlag is similar to AddBoolFlag but persistent. +// See https://github.com/spf13/cobra/blob/main/user_guide.md#persistent-flags to learn what is "persistent". +func AddPersistentBoolFlag(cmd *cobra.Command, name string, aliases, nonPersistentAliases []string, value bool, env, usage string) { + if env != "" { + usage = fmt.Sprintf("%s [$%s]", usage, env) + } + if envV, ok := os.LookupEnv(env); ok { + var err error + value, err = strconv.ParseBool(envV) + if err != nil { + logrus.WithError(err).Warnf("Invalid boolean value for `%s`", env) + } + } + aliasesUsage := fmt.Sprintf("Alias of --%s", name) + p := new(bool) + flags := cmd.Flags() + for _, a := range nonPersistentAliases { + if len(a) == 1 { + // pflag doesn't support short-only flags, so we have to register long one as well here + flags.BoolVarP(p, a, a, value, aliasesUsage) + } else { + flags.BoolVar(p, a, value, aliasesUsage) + } + } + + persistentFlags := cmd.PersistentFlags() + persistentFlags.BoolVar(p, name, value, usage) + for _, a := range aliases { + if len(a) == 1 { + // pflag doesn't support short-only flags, so we have to register long one as well here + persistentFlags.BoolVarP(p, a, a, value, aliasesUsage) + } else { + persistentFlags.BoolVar(p, a, value, aliasesUsage) + } + } +} + +// AddPersistentStringArrayFlag is similar to cmd.Flags().StringArray but supports aliases and env var and persistent. +// See https://github.com/spf13/cobra/blob/main/user_guide.md#persistent-flags to learn what is "persistent". +func AddPersistentStringArrayFlag(cmd *cobra.Command, name string, aliases, nonPersistentAliases []string, value []string, env string, usage string) { + if env != "" { + usage = fmt.Sprintf("%s [$%s]", usage, env) + } + if envV, ok := os.LookupEnv(env); ok { + value = []string{envV} + } + aliasesUsage := fmt.Sprintf("Alias of --%s", name) + p := new([]string) + flags := cmd.Flags() + for _, a := range nonPersistentAliases { + if len(a) == 1 { + // pflag doesn't support short-only flags, so we have to register long one as well here + flags.StringArrayVarP(p, a, a, value, aliasesUsage) + } else { + flags.StringArrayVar(p, a, value, aliasesUsage) + } + } + + persistentFlags := cmd.PersistentFlags() + persistentFlags.StringArrayVar(p, name, value, usage) + for _, a := range aliases { + if len(a) == 1 { + // pflag doesn't support short-only flags, so we have to register long one as well here + persistentFlags.StringArrayVarP(p, a, a, value, aliasesUsage) + } else { + persistentFlags.StringArrayVar(p, a, value, aliasesUsage) + } + } +} + +func CheckExperimental(feature string) func(cmd *cobra.Command, args []string) error { + return func(cmd *cobra.Command, args []string) error { + experimental, err := cmd.Flags().GetBool("experimental") + if err != nil { + return err + } + if !experimental { + return fmt.Errorf("%s is experimental feature, you should enable experimental config", feature) + } + return nil + } +} + +// IsExactArgs returns an error if there is not the exact number of args +func IsExactArgs(number int) cobra.PositionalArgs { + return func(cmd *cobra.Command, args []string) error { + if len(args) == number { + return nil + } + return fmt.Errorf( + "%q requires exactly %d %s.\nSee '%s --help'.\n\nUsage: %s\n\n%s", + cmd.CommandPath(), + number, + "argument(s)", + cmd.CommandPath(), + cmd.UseLine(), + cmd.Short, + ) + } +} + +func GlobalFlags(cmd *cobra.Command) (string, []string) { + args0, err := os.Executable() + if err != nil { + logrus.WithError(err).Warnf("cannot call os.Executable(), assuming the executable to be %q", os.Args[0]) + args0 = os.Args[0] + } + if len(os.Args) < 2 { + return args0, nil + } + + rootCmd := cmd.Root() + flagSet := rootCmd.Flags() + args := []string{} + flagSet.VisitAll(func(f *pflag.Flag) { + key := f.Name + val := f.Value.String() + if f.Changed { + args = append(args, "--"+key+"="+val) + } + }) + return args0, args +} diff --git a/cmd/nerdctl/utils/common/common.go b/cmd/nerdctl/utils/common/common.go new file mode 100644 index 00000000000..5df318b4ac2 --- /dev/null +++ b/cmd/nerdctl/utils/common/common.go @@ -0,0 +1,278 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package common + +import ( + "context" + "encoding/json" + "errors" + "io" + "os" + "path/filepath" + "strings" + + "github.com/containerd/containerd" + "github.com/containerd/containerd/snapshots" + "github.com/containerd/go-cni" + "github.com/containerd/nerdctl/pkg/inspecttypes/dockercompat" + "github.com/containerd/nerdctl/pkg/labels" + "github.com/containerd/nerdctl/pkg/mountutil" + "github.com/containerd/nerdctl/pkg/platformutil" + "github.com/containerd/nerdctl/pkg/strutil" + "github.com/docker/cli/opts" + "github.com/spf13/cobra" +) + +const ( + Category = "category" + Management = "management" + TiniInitBinary = "tini" +) + +type ReadCounter struct { + io.Reader + N int +} + +func (r *ReadCounter) Read(p []byte) (int, error) { + n, err := r.Reader.Read(p) + if n > 0 { + r.N += n + } + return n, err +} + +type SnapshotKey string + +type DockerArchiveManifestJSONEntry struct { + Config string + RepoTags []string + Layers []string +} + +type DockerArchiveManifestJSON []DockerArchiveManifestJSONEntry + +// recursive function to calculate total usage of key's parent +func (key SnapshotKey) Add(ctx context.Context, s snapshots.Snapshotter, usage *snapshots.Usage) error { + if key == "" { + return nil + } + u, err := s.Usage(ctx, string(key)) + if err != nil { + return err + } + + usage.Add(u) + + info, err := s.Stat(ctx, string(key)) + if err != nil { + return err + } + + key = SnapshotKey(info.Parent) + return key.Add(ctx, s, usage) +} + +// removing a non-stoped/non-created container without force, will cause a error +type StatusError struct { + error +} + +func NewStatusError(err error) StatusError { + return StatusError{err} +} + +func (e StatusError) Error() string { + return e.error.Error() +} + +type ExitCoder interface { + error + ExitCode() int +} + +type ExitCodeError struct { + error + Code int +} + +func (e ExitCodeError) ExitCode() int { + return e.Code +} + +func HandleExitCoder(err error) { + if err == nil { + return + } + + if exitErr, ok := err.(ExitCoder); ok { + os.Exit(exitErr.ExitCode()) + } +} + +type InternalLabels struct { + // labels from cmd options + Namespace string + Platform string + ExtraHosts []string + PidFile string + // labels from cmd options or automatically set + Name string + Hostname string + // automatically generated + StateDir string + // network + Networks []string + IPAddress string + Ports []cni.PortMapping + MacAddress string + // volumn + MountPoints []*mountutil.Processed + AnonVolumes []string + // pid Namespace + PidContainer string + // log + LogURI string +} + +func WithInternalLabels(internalLabels InternalLabels) (containerd.NewContainerOpts, error) { + m := make(map[string]string) + m[labels.Namespace] = internalLabels.Namespace + if internalLabels.Name != "" { + m[labels.Name] = internalLabels.Name + } + m[labels.Hostname] = internalLabels.Hostname + extraHostsJSON, err := json.Marshal(internalLabels.ExtraHosts) + if err != nil { + return nil, err + } + m[labels.ExtraHosts] = string(extraHostsJSON) + m[labels.StateDir] = internalLabels.StateDir + networksJSON, err := json.Marshal(internalLabels.Networks) + if err != nil { + return nil, err + } + m[labels.Networks] = string(networksJSON) + if len(internalLabels.Ports) > 0 { + portsJSON, err := json.Marshal(internalLabels.Ports) + if err != nil { + return nil, err + } + m[labels.Ports] = string(portsJSON) + } + if internalLabels.LogURI != "" { + m[labels.LogURI] = internalLabels.LogURI + } + if len(internalLabels.AnonVolumes) > 0 { + anonVolumeJSON, err := json.Marshal(internalLabels.AnonVolumes) + if err != nil { + return nil, err + } + m[labels.AnonymousVolumes] = string(anonVolumeJSON) + } + + if internalLabels.PidFile != "" { + m[labels.PIDFile] = internalLabels.PidFile + } + + if internalLabels.IPAddress != "" { + m[labels.IPAddress] = internalLabels.IPAddress + } + + m[labels.Platform], err = platformutil.NormalizeString(internalLabels.Platform) + if err != nil { + return nil, err + } + + if len(internalLabels.MountPoints) > 0 { + mounts := DockercompatMounts(internalLabels.MountPoints) + mountPointsJSON, err := json.Marshal(mounts) + if err != nil { + return nil, err + } + m[labels.Mounts] = string(mountPointsJSON) + } + + if internalLabels.MacAddress != "" { + m[labels.MACAddress] = internalLabels.MacAddress + } + + if internalLabels.PidContainer != "" { + m[labels.PIDContainer] = internalLabels.PidContainer + } + + return containerd.WithAdditionalContainerLabels(m), nil +} + +func DockercompatMounts(mountPoints []*mountutil.Processed) []dockercompat.MountPoint { + reuslt := make([]dockercompat.MountPoint, len(mountPoints)) + for i := range mountPoints { + mp := mountPoints[i] + reuslt[i] = dockercompat.MountPoint{ + Type: mp.Type, + Name: mp.Name, + Source: mp.Mount.Source, + Destination: mp.Mount.Destination, + Driver: "", + Mode: mp.Mode, + } + + // it's a anonymous volume + if mp.AnonymousVolume != "" { + reuslt[i].Name = mp.AnonymousVolume + } + + // volume only support local driver + if mp.Type == "volume" { + reuslt[i].Driver = "local" + } + } + return reuslt +} + +func ReadKVStringsMapfFromLabel(cmd *cobra.Command) (map[string]string, error) { + labelsMap, err := cmd.Flags().GetStringArray("label") + if err != nil { + return nil, err + } + labelsMap = strutil.DedupeStrSlice(labelsMap) + labelsFilePath, err := cmd.Flags().GetStringSlice("label-file") + if err != nil { + return nil, err + } + labelsFilePath = strutil.DedupeStrSlice(labelsFilePath) + labels, err := opts.ReadKVStrings(labelsFilePath, labelsMap) + if err != nil { + return nil, err + } + + return strutil.ConvertKVStringsToMap(labels), nil +} + +func GetContainerStateDirPath(cmd *cobra.Command, dataStore, id string) (string, error) { + ns, err := cmd.Flags().GetString("namespace") + if err != nil { + return "", err + } + if ns == "" { + return "", errors.New("namespace is required") + } + if strings.Contains(ns, "/") { + return "", errors.New("namespace with '/' is unsupported") + } + return filepath.Join(dataStore, "containers", ns, id), nil +} diff --git a/cmd/nerdctl/utils/container/container.go b/cmd/nerdctl/utils/container/container.go new file mode 100644 index 00000000000..ea1060f65f4 --- /dev/null +++ b/cmd/nerdctl/utils/container/container.go @@ -0,0 +1,537 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package container + +import ( + "context" + "encoding/json" + "fmt" + "os" + "strconv" + "strings" + "syscall" + "time" + + "github.com/containerd/containerd" + "github.com/containerd/containerd/cio" + "github.com/containerd/containerd/containers" + "github.com/containerd/containerd/errdefs" + "github.com/containerd/containerd/namespaces" + "github.com/containerd/containerd/pkg/progress" + "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/utils" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/volume" + "github.com/containerd/nerdctl/pkg/dnsutil/hostsstore" + "github.com/containerd/nerdctl/pkg/labels" + "github.com/containerd/nerdctl/pkg/namestore" + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" +) + +func FoldContainerFilters(ctx context.Context, containers []containerd.Container, filters []string) (*FilterContext, error) { + filterCtx := &FilterContext{Containers: containers} + err := filterCtx.foldFilters(ctx, filters) + return filterCtx, err +} + +type FilterContext struct { + Containers []containerd.Container + + IDFilterFuncs []func(string) bool + NameFilterFuncs []func(string) bool + ExitedFilterFuncs []func(int) bool + BeforeFilterFuncs []func(t time.Time) bool + SinceFilterFuncs []func(t time.Time) bool + StatusFilterFuncs []func(containerd.ProcessStatus) bool + LabelFilterFuncs []func(map[string]string) bool + VolumeFilterFuncs []func([]*volume.ContainerVolume) bool + NetworkFilterFuncs []func([]string) bool +} + +func (cl *FilterContext) MatchesFilters(ctx context.Context) []containerd.Container { + matchesContainers := make([]containerd.Container, 0, len(cl.Containers)) + for _, container := range cl.Containers { + if !cl.matchesInfoFilters(ctx, container) { + continue + } + if !cl.matchesTaskFilters(ctx, container) { + continue + } + matchesContainers = append(matchesContainers, container) + } + cl.Containers = matchesContainers + return cl.Containers +} + +func (cl *FilterContext) foldFilters(ctx context.Context, filters []string) error { + folders := []struct { + filterType string + foldFunc func(context.Context, string, string) error + }{ + {"id", cl.foldIDFilter}, {"name", cl.foldNameFilter}, + {"before", cl.foldBeforeFilter}, {"since", cl.foldSinceFilter}, + {"network", cl.foldNetworkFilter}, {"label", cl.foldLabelFilter}, + {"volume", cl.foldVolumeFilter}, {"status", cl.foldStatusFilter}, + {"exited", cl.foldExitedFilter}, + } + for _, filter := range filters { + invalidFilter := true + for _, folder := range folders { + if !strings.HasPrefix(filter, folder.filterType) { + continue + } + splited := strings.SplitN(filter, "=", 2) + if len(splited) != 2 { + return fmt.Errorf("invalid argument \"%s\" for \"-f, --filter\": bad format of filter (expected Name=value)", folder.filterType) + } + if err := folder.foldFunc(ctx, filter, splited[1]); err != nil { + return err + } + invalidFilter = false + break + } + if invalidFilter { + return fmt.Errorf("invalid filter '%s'", filter) + } + } + return nil +} + +func (cl *FilterContext) foldExitedFilter(_ context.Context, filter, value string) error { + exited, err := strconv.Atoi(value) + if err != nil { + return err + } + cl.ExitedFilterFuncs = append(cl.ExitedFilterFuncs, func(exitStatus int) bool { + return exited == exitStatus + }) + return nil +} + +func (cl *FilterContext) foldStatusFilter(_ context.Context, filter, value string) error { + status := containerd.ProcessStatus(value) + switch status { + case containerd.Running, containerd.Created, containerd.Stopped, containerd.Paused, containerd.Pausing, containerd.Unknown: + cl.StatusFilterFuncs = append(cl.StatusFilterFuncs, func(stats containerd.ProcessStatus) bool { + return status == stats + }) + case containerd.ProcessStatus("exited"): + cl.StatusFilterFuncs = append(cl.StatusFilterFuncs, func(stats containerd.ProcessStatus) bool { + return containerd.Stopped == stats + }) + case containerd.ProcessStatus("restarting"), containerd.ProcessStatus("removing"), containerd.ProcessStatus("dead"): + logrus.Warnf("%s is not supported and is ignored", filter) + default: + return fmt.Errorf("invalid filter '%s'", filter) + } + return nil +} + +func (cl *FilterContext) foldBeforeFilter(ctx context.Context, filter, value string) error { + beforeC, err := IDOrNameFilter(ctx, cl.Containers, value) + if err == nil { + cl.BeforeFilterFuncs = append(cl.BeforeFilterFuncs, func(t time.Time) bool { + return t.Before(beforeC.CreatedAt) + }) + } + return err +} + +func (cl *FilterContext) foldSinceFilter(ctx context.Context, filter, value string) error { + sinceC, err := IDOrNameFilter(ctx, cl.Containers, value) + if err == nil { + cl.SinceFilterFuncs = append(cl.SinceFilterFuncs, func(t time.Time) bool { + return t.After(sinceC.CreatedAt) + }) + } + return err +} + +func (cl *FilterContext) foldIDFilter(_ context.Context, filter, value string) error { + cl.IDFilterFuncs = append(cl.IDFilterFuncs, func(id string) bool { + if value == "" { + return false + } + return strings.HasPrefix(id, value) + }) + return nil +} + +func (cl *FilterContext) foldNameFilter(_ context.Context, filter, value string) error { + cl.NameFilterFuncs = append(cl.NameFilterFuncs, func(name string) bool { + if value == "" { + return true + } + return strings.Contains(name, value) + }) + return nil +} + +func (cl *FilterContext) foldLabelFilter(_ context.Context, filter, value string) error { + k, v, hasValue := value, "", false + if subs := strings.SplitN(value, "=", 2); len(subs) == 2 { + hasValue = true + k, v = subs[0], subs[1] + } + cl.LabelFilterFuncs = append(cl.LabelFilterFuncs, func(labels map[string]string) bool { + if labels == nil { + return false + } + val, ok := labels[k] + if !ok || (hasValue && val != v) { + return false + } + return true + }) + return nil +} + +func (cl *FilterContext) foldVolumeFilter(_ context.Context, filter, value string) error { + cl.VolumeFilterFuncs = append(cl.VolumeFilterFuncs, func(vols []*volume.ContainerVolume) bool { + for _, vol := range vols { + if (vol.Source != "" && vol.Source == value) || + (vol.Destination != "" && vol.Destination == value) || + (vol.Name != "" && vol.Name == value) { + return true + } + } + return false + }) + return nil +} + +func (cl *FilterContext) foldNetworkFilter(_ context.Context, filter, value string) error { + cl.NetworkFilterFuncs = append(cl.NetworkFilterFuncs, func(networks []string) bool { + for _, network := range networks { + if network == value { + return true + } + } + return false + }) + return nil +} + +func (cl *FilterContext) matchesInfoFilters(ctx context.Context, container containerd.Container) bool { + if len(cl.IDFilterFuncs)+len(cl.NameFilterFuncs)+len(cl.BeforeFilterFuncs)+ + len(cl.SinceFilterFuncs)+len(cl.LabelFilterFuncs)+len(cl.VolumeFilterFuncs)+len(cl.NetworkFilterFuncs) == 0 { + return true + } + info, _ := container.Info(ctx, containerd.WithoutRefreshedMetadata) + return cl.matchesIDFilter(info) && cl.matchesNameFilter(info) && cl.matchesBeforeFilter(info) && + cl.matchesSinceFilter(info) && cl.matchesLabelFilter(info) && cl.matchesVolumeFilter(info) && + cl.matchesNetworkFilter(info) +} + +func (cl *FilterContext) matchesTaskFilters(ctx context.Context, container containerd.Container) bool { + if len(cl.ExitedFilterFuncs)+len(cl.StatusFilterFuncs) == 0 { + return true + } + ctx, cancel := context.WithTimeout(ctx, 5*time.Second) + defer cancel() + task, err := container.Task(ctx, nil) + if err != nil { + logrus.Warn(err) + return false + } + status, err := task.Status(ctx) + if err != nil { + logrus.Warn(err) + return false + } + return cl.matchesExitedFilter(status) && cl.matchesStatusFilter(status) +} + +func (cl *FilterContext) matchesExitedFilter(status containerd.Status) bool { + if len(cl.ExitedFilterFuncs) == 0 { + return true + } + if status.Status != containerd.Stopped { + return false + } + for _, exitedFilterFunc := range cl.ExitedFilterFuncs { + if !exitedFilterFunc(int(status.ExitStatus)) { + continue + } + return true + } + return false +} + +func (cl *FilterContext) matchesStatusFilter(status containerd.Status) bool { + if len(cl.StatusFilterFuncs) == 0 { + return true + } + for _, statusFilterFunc := range cl.StatusFilterFuncs { + if !statusFilterFunc(status.Status) { + continue + } + return true + } + return false +} + +func (cl *FilterContext) matchesIDFilter(info containers.Container) bool { + if len(cl.IDFilterFuncs) == 0 { + return true + } + for _, idFilterFunc := range cl.IDFilterFuncs { + if !idFilterFunc(info.ID) { + continue + } + return true + } + return false +} + +func (cl *FilterContext) matchesNameFilter(info containers.Container) bool { + if len(cl.NameFilterFuncs) == 0 { + return true + } + cName := utils.GetPrintableContainerName(info.Labels) + for _, nameFilterFunc := range cl.NameFilterFuncs { + if !nameFilterFunc(cName) { + continue + } + return true + } + return false +} + +func (cl *FilterContext) matchesSinceFilter(info containers.Container) bool { + if len(cl.SinceFilterFuncs) == 0 { + return true + } + for _, sinceFilterFunc := range cl.SinceFilterFuncs { + if !sinceFilterFunc(info.CreatedAt) { + continue + } + return true + } + return false +} + +func (cl *FilterContext) matchesBeforeFilter(info containers.Container) bool { + if len(cl.BeforeFilterFuncs) == 0 { + return true + } + for _, beforeFilterFunc := range cl.BeforeFilterFuncs { + if !beforeFilterFunc(info.CreatedAt) { + continue + } + return true + } + return false +} + +func (cl *FilterContext) matchesLabelFilter(info containers.Container) bool { + for _, labelFilterFunc := range cl.LabelFilterFuncs { + if !labelFilterFunc(info.Labels) { + return false + } + } + return true +} + +func (cl *FilterContext) matchesVolumeFilter(info containers.Container) bool { + if len(cl.VolumeFilterFuncs) == 0 { + return true + } + vols := volume.GetContainerVolumes(info.Labels) + for _, volumeFilterFunc := range cl.VolumeFilterFuncs { + if !volumeFilterFunc(vols) { + continue + } + return true + } + return false +} + +func (cl *FilterContext) matchesNetworkFilter(info containers.Container) bool { + if len(cl.NetworkFilterFuncs) == 0 { + return true + } + networks := utils.GetContainerNetworks(info.Labels) + for _, networkFilterFunc := range cl.NetworkFilterFuncs { + if !networkFilterFunc(networks) { + continue + } + return true + } + return false +} + +func IDOrNameFilter(ctx context.Context, containers []containerd.Container, value string) (*containers.Container, error) { + for _, container := range containers { + info, err := container.Info(ctx, containerd.WithoutRefreshedMetadata) + if err != nil { + return nil, err + } + if strings.HasPrefix(info.ID, value) || strings.Contains(utils.GetPrintableContainerName(info.Labels), value) { + return &info, nil + } + } + return nil, fmt.Errorf("no such container %s", value) +} + +func GetContainerSize(ctx context.Context, client *containerd.Client, c containerd.Container, info containers.Container) (string, error) { + // get container snapshot size + snapshotKey := info.SnapshotKey + var containerSize int64 + + if snapshotKey != "" { + usage, err := client.SnapshotService(info.Snapshotter).Usage(ctx, snapshotKey) + if err != nil { + return "", err + } + containerSize = usage.Size + } + + // get the image interface + image, err := c.Image(ctx) + if err != nil { + return "", err + } + + sn := client.SnapshotService(info.Snapshotter) + + imageSize, err := utils.UnpackedImageSize(ctx, sn, image) + if err != nil { + return "", err + } + + return fmt.Sprintf("%s (virtual %s)", progress.Bytes(containerSize).String(), progress.Bytes(imageSize).String()), nil +} + +func RemoveContainer(ctx context.Context, cmd *cobra.Command, container containerd.Container, force bool, removeAnonVolumes bool) (retErr error) { + ns, err := namespaces.NamespaceRequired(ctx) + if err != nil { + return err + } + + id := container.ID() + l, err := container.Labels(ctx) + if err != nil { + return err + } + stateDir := l[labels.StateDir] + name := l[labels.Name] + + dataStore, err := client.GetDataStore(cmd) + if err != nil { + return err + } + namst, err := namestore.New(dataStore, ns) + if err != nil { + return err + } + + defer func() { + if errdefs.IsNotFound(retErr) { + retErr = nil + } + if retErr != nil { + return + } + + if err := os.RemoveAll(stateDir); err != nil { + logrus.WithError(retErr).Warnf("failed to remove container state dir %s", stateDir) + } + if name != "" { + if err := namst.Release(name, id); err != nil { + logrus.WithError(retErr).Warnf("failed to release container Name %s", name) + } + } + if err := hostsstore.DeallocHostsFile(dataStore, ns, id); err != nil { + logrus.WithError(retErr).Warnf("failed to remove hosts file for container %q", id) + } + }() + if anonVolumesJSON, ok := l[labels.AnonymousVolumes]; ok && removeAnonVolumes { + var anonVolumes []string + if err := json.Unmarshal([]byte(anonVolumesJSON), &anonVolumes); err != nil { + return err + } + volStore, err := volume.GetVolumeStore(cmd) + if err != nil { + return err + } + defer func() { + if _, err := volStore.Remove(anonVolumes); err != nil { + logrus.WithError(err).Warnf("failed to remove anonymous volume %v", anonVolumes) + } + }() + } + + task, err := container.Task(ctx, cio.Load) + if err != nil { + if errdefs.IsNotFound(err) { + if container.Delete(ctx, containerd.WithSnapshotCleanup) != nil { + return container.Delete(ctx) + } + } + return err + } + + status, err := task.Status(ctx) + if err != nil { + if errdefs.IsNotFound(err) { + return nil + } + return err + } + + switch status.Status { + case containerd.Created, containerd.Stopped: + if _, err := task.Delete(ctx); err != nil && !errdefs.IsNotFound(err) { + return fmt.Errorf("failed to delete task %v: %w", id, err) + } + case containerd.Paused: + if !force { + return common.NewStatusError(fmt.Errorf("you cannot remove a %v container %v. Unpause the container before attempting removal or force remove", status.Status, id)) + } + _, err := task.Delete(ctx, containerd.WithProcessKill) + if err != nil && !errdefs.IsNotFound(err) { + return fmt.Errorf("failed to delete task %v: %w", id, err) + } + // default is the case, when status.Status = containerd.Running + default: + if !force { + return common.NewStatusError(fmt.Errorf("you cannot remove a %v container %v. Stop the container before attempting removal or force remove", status.Status, id)) + } + if err := task.Kill(ctx, syscall.SIGKILL); err != nil { + logrus.WithError(err).Warnf("failed to send SIGKILL") + } + es, err := task.Wait(ctx) + if err == nil { + <-es + } + _, err = task.Delete(ctx, containerd.WithProcessKill) + if err != nil && !errdefs.IsNotFound(err) { + logrus.WithError(err).Warnf("failed to delete task %v", id) + } + } + var delOpts []containerd.DeleteOpts + if _, err := container.Image(ctx); err == nil { + delOpts = append(delOpts, containerd.WithSnapshotCleanup) + } + + if err := container.Delete(ctx, delOpts...); err != nil { + return err + } + return err +} diff --git a/cmd/nerdctl/utils/container/container_create.go b/cmd/nerdctl/utils/container/container_create.go new file mode 100644 index 00000000000..2d95d5be030 --- /dev/null +++ b/cmd/nerdctl/utils/container/container_create.go @@ -0,0 +1,690 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package container + +import ( + "bufio" + "context" + "encoding/json" + "errors" + "fmt" + "net/url" + "os" + "os/exec" + "path/filepath" + "runtime" + "strconv" + "strings" + + "github.com/containerd/containerd" + "github.com/containerd/containerd/cio" + "github.com/containerd/containerd/containers" + "github.com/containerd/containerd/oci" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/utils" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/run" + "github.com/containerd/nerdctl/pkg/idgen" + "github.com/containerd/nerdctl/pkg/imgutil" + "github.com/containerd/nerdctl/pkg/labels" + "github.com/containerd/nerdctl/pkg/logging" + "github.com/containerd/nerdctl/pkg/namestore" + "github.com/containerd/nerdctl/pkg/platformutil" + "github.com/containerd/nerdctl/pkg/referenceutil" + "github.com/containerd/nerdctl/pkg/strutil" + opts2 "github.com/docker/cli/opts" + "github.com/opencontainers/runtime-spec/specs-go" + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" +) + +// FIXME: split to smaller functions +func CreateContainer(ctx context.Context, cmd *cobra.Command, client *containerd.Client, args []string, platform string, flagI, flagT, flagD bool) (containerd.Container, func(), error) { + // simulate the behavior of double dash + newArg := []string{} + if len(args) >= 2 && args[1] == "--" { + newArg = append(newArg, args[:1]...) + newArg = append(newArg, args[2:]...) + args = newArg + } + var internalLabels common.InternalLabels + internalLabels.Platform = platform + + ns, err := cmd.Flags().GetString("namespace") + if err != nil { + return nil, nil, err + } + internalLabels.Namespace = ns + + var ( + opts []oci.SpecOpts + cOpts []containerd.NewContainerOpts + id = idgen.GenerateID() + ) + + cidfile, err := cmd.Flags().GetString("cidfile") + if err != nil { + return nil, nil, err + } + if cidfile != "" { + if err := WriteCIDFile(cidfile, id); err != nil { + return nil, nil, err + } + } + + dataStore, err := nerdClient.GetDataStore(cmd) + if err != nil { + return nil, nil, err + } + + stateDir, err := common.GetContainerStateDirPath(cmd, dataStore, id) + if err != nil { + return nil, nil, err + } + if err := os.MkdirAll(stateDir, 0700); err != nil { + return nil, nil, err + } + internalLabels.StateDir = stateDir + + opts = append(opts, + oci.WithDefaultSpec(), + ) + + opts, internalLabels, err = run.SetPlatformOptions(ctx, opts, cmd, client, id, internalLabels) + if err != nil { + return nil, nil, err + } + + rootfsOpts, rootfsCOpts, ensuredImage, err := GenerateRootfsOpts(ctx, client, platform, cmd, args, id) + if err != nil { + return nil, nil, err + } + opts = append(opts, rootfsOpts...) + cOpts = append(cOpts, rootfsCOpts...) + + wd, err := cmd.Flags().GetString("workdir") + if err != nil { + return nil, nil, err + } + if wd != "" { + opts = append(opts, oci.WithProcessCwd(wd)) + } + + envFile, err := cmd.Flags().GetStringSlice("env-file") + if err != nil { + return nil, nil, err + } + env, err := cmd.Flags().GetStringArray("env") + if err != nil { + return nil, nil, err + } + envs, err := GenerateEnvs(envFile, env) + if err != nil { + return nil, nil, err + } + opts = append(opts, oci.WithEnv(envs)) + + if flagI { + if flagD { + return nil, nil, errors.New("currently flag -i and -d cannot be specified together (FIXME)") + } + } + + if flagT { + if flagD { + return nil, nil, errors.New("currently flag -t and -d cannot be specified together (FIXME)") + } + opts = append(opts, oci.WithTTY) + } + + mountOpts, anonVolumes, mountPoints, err := utils.GenerateMountOpts(ctx, cmd, client, ensuredImage) + if err != nil { + return nil, nil, err + } + internalLabels.AnonVolumes = anonVolumes + internalLabels.MountPoints = mountPoints + opts = append(opts, mountOpts...) + + var logURI string + if flagD { + // json-file is the built-in and default log driver for nerdctl + logDriver, err := cmd.Flags().GetString("log-driver") + if err != nil { + return nil, nil, err + } + + // check if log driver is a valid uri. If it is a valid uri and scheme is not + if u, err := url.Parse(logDriver); err == nil && u.Scheme != "" { + logURI = logDriver + } else { + logOptMap, err := ParseKVStringsMapFromLogOpt(cmd, logDriver) + if err != nil { + return nil, nil, err + } + logDriverInst, err := logging.GetDriver(logDriver, logOptMap) + if err != nil { + return nil, nil, err + } + if err := logDriverInst.Init(dataStore, ns, id); err != nil { + return nil, nil, err + } + logConfig := &logging.LogConfig{ + Driver: logDriver, + Opts: logOptMap, + } + logConfigB, err := json.Marshal(logConfig) + if err != nil { + return nil, nil, err + } + logConfigFilePath := logging.LogConfigFilePath(dataStore, ns, id) + if err = os.WriteFile(logConfigFilePath, logConfigB, 0600); err != nil { + return nil, nil, err + } + if lu, err := GenerateLogURI(dataStore); err != nil { + return nil, nil, err + } else if lu != nil { + logrus.Debugf("generated log driver: %s", lu.String()) + + logURI = lu.String() + } + } + } + internalLabels.LogURI = logURI + + restartValue, err := cmd.Flags().GetString("restart") + if err != nil { + return nil, nil, err + } + restartOpts, err := run.GenerateRestartOpts(ctx, client, restartValue, logURI) + if err != nil { + return nil, nil, err + } + cOpts = append(cOpts, restartOpts...) + + stopSignal, err := cmd.Flags().GetString("stop-signal") + if err != nil { + return nil, nil, err + } + stopTimeout, err := cmd.Flags().GetInt("stop-timeout") + if err != nil { + return nil, nil, err + } + cOpts = append(cOpts, WithStop(stopSignal, stopTimeout, ensuredImage)) + + hostname := id[0:12] + customHostname, err := cmd.Flags().GetString("hostname") + if err != nil { + return nil, nil, err + } + if customHostname != "" { + hostname = customHostname + } + opts = append(opts, oci.WithHostname(hostname)) + internalLabels.Hostname = hostname + // `/etc/hostname` does not exist on FreeBSD + if runtime.GOOS == "linux" { + hostnamePath := filepath.Join(stateDir, "hostname") + if err := os.WriteFile(hostnamePath, []byte(hostname+"\n"), 0644); err != nil { + return nil, nil, err + } + opts = append(opts, run.WithCustomEtcHostname(hostnamePath)) + } + + netOpts, netSlice, ipAddress, ports, macAddress, err := run.GenerateNetOpts(cmd, dataStore, stateDir, ns, id) + if err != nil { + return nil, nil, err + } + internalLabels.Networks = netSlice + internalLabels.IPAddress = ipAddress + internalLabels.Ports = ports + internalLabels.MacAddress = macAddress + opts = append(opts, netOpts...) + + hookOpt, err := WithNerdctlOCIHook(cmd, id) + if err != nil { + return nil, nil, err + } + opts = append(opts, hookOpt) + + uOpts, err := run.GenerateUserOpts(cmd) + if err != nil { + return nil, nil, err + } + opts = append(opts, uOpts...) + + gOpts, err := run.GenerateGroupsOpts(cmd) + if err != nil { + return nil, nil, err + } + opts = append(opts, gOpts...) + + umaskOpts, err := run.GenerateUmaskOpts(cmd) + if err != nil { + return nil, nil, err + } + opts = append(opts, umaskOpts...) + + rtCOpts, err := run.GenerateRuntimeCOpts(cmd) + if err != nil { + return nil, nil, err + } + cOpts = append(cOpts, rtCOpts...) + + lCOpts, err := WithContainerLabels(cmd) + if err != nil { + return nil, nil, err + } + cOpts = append(cOpts, lCOpts...) + + var containerNameStore namestore.NameStore + name, err := cmd.Flags().GetString("name") + if err != nil { + return nil, nil, err + } + if name == "" && !cmd.Flags().Changed("name") { + // Automatically set the container Name, unless `--Name=""` was explicitly specified. + var imageRef string + if ensuredImage != nil { + imageRef = ensuredImage.Ref + } + name = referenceutil.SuggestContainerName(imageRef, id) + } + if name != "" { + containerNameStore, err = namestore.New(dataStore, ns) + if err != nil { + return nil, nil, err + } + if err := containerNameStore.Acquire(name, id); err != nil { + return nil, nil, err + } + } + internalLabels.Name = name + + var pidFile string + if cmd.Flags().Lookup("pidfile").Changed { + pidFile, err = cmd.Flags().GetString("pidfile") + if err != nil { + return nil, nil, err + } + } + internalLabels.PidFile = pidFile + + extraHosts, err := cmd.Flags().GetStringSlice("add-host") + if err != nil { + return nil, nil, err + } + extraHosts = strutil.DedupeStrSlice(extraHosts) + for _, host := range extraHosts { + if _, err := opts2.ValidateExtraHost(host); err != nil { + return nil, nil, err + } + } + internalLabels.ExtraHosts = extraHosts + + ilOpt, err := common.WithInternalLabels(internalLabels) + if err != nil { + return nil, nil, err + } + cOpts = append(cOpts, ilOpt) + + opts = append(opts, PropagateContainerdLabelsToOCIAnnotations()) + + var s specs.Spec + spec := containerd.WithSpec(&s, opts...) + cOpts = append(cOpts, spec) + + container, err := client.NewContainer(ctx, id, cOpts...) + if err != nil { + gcContainer := func() { + var isErr bool + if errE := os.RemoveAll(stateDir); errE != nil { + isErr = true + } + if name != "" { + var errE error + if containerNameStore, errE = namestore.New(dataStore, ns); errE != nil { + isErr = true + } + if errE = containerNameStore.Release(name, id); errE != nil { + isErr = true + } + + } + if isErr { + logrus.Warnf("failed to remove container %q", id) + } + } + return nil, gcContainer, err + } + return container, nil, nil +} + +func GenerateRootfsOpts(ctx context.Context, client *containerd.Client, platform string, cmd *cobra.Command, args []string, id string) ([]oci.SpecOpts, []containerd.NewContainerOpts, *imgutil.EnsuredImage, error) { + var ( + ensured *imgutil.EnsuredImage + err error + ) + imageless, err := cmd.Flags().GetBool("rootfs") + if err != nil { + return nil, nil, nil, err + } + if !imageless { + pull, err := cmd.Flags().GetString("pull") + if err != nil { + return nil, nil, nil, err + } + var platformSS []string // len: 0 or 1 + if platform != "" { + platformSS = append(platformSS, platform) + } + ocispecPlatforms, err := platformutil.NewOCISpecPlatformSlice(false, platformSS) + if err != nil { + return nil, nil, nil, err + } + rawRef := args[0] + ensured, err = utils.EnsureImage(ctx, cmd, client, rawRef, ocispecPlatforms, pull, nil, false) + if err != nil { + return nil, nil, nil, err + } + } + var ( + opts []oci.SpecOpts + cOpts []containerd.NewContainerOpts + ) + if !imageless { + cOpts = append(cOpts, + containerd.WithImage(ensured.Image), + containerd.WithSnapshotter(ensured.Snapshotter), + containerd.WithNewSnapshot(id, ensured.Image), + containerd.WithImageStopSignal(ensured.Image, "SIGTERM"), + ) + + if len(ensured.ImageConfig.Env) == 0 { + opts = append(opts, oci.WithDefaultPathEnv) + } + for ind, env := range ensured.ImageConfig.Env { + if strings.HasPrefix(env, "PATH=") { + break + } else { + if ind == len(ensured.ImageConfig.Env)-1 { + opts = append(opts, oci.WithDefaultPathEnv) + } + } + } + } else { + absRootfs, err := filepath.Abs(args[0]) + if err != nil { + return nil, nil, nil, err + } + opts = append(opts, oci.WithRootFSPath(absRootfs), oci.WithDefaultPathEnv) + } + + // NOTE: "--entrypoint" can be set to an empty string, see TestRunEntrypoint* in run_test.go . + entrypoint, err := cmd.Flags().GetStringArray("entrypoint") + if err != nil { + return nil, nil, nil, err + } + + if !imageless && !cmd.Flag("entrypoint").Changed { + opts = append(opts, oci.WithImageConfigArgs(ensured.Image, args[1:])) + } else { + if !imageless { + opts = append(opts, oci.WithImageConfig(ensured.Image)) + } + var processArgs []string + if len(entrypoint) != 0 { + processArgs = append(processArgs, entrypoint...) + } + if len(args) > 1 { + processArgs = append(processArgs, args[1:]...) + } + if len(processArgs) == 0 { + // error message is from Podman + return nil, nil, nil, errors.New("no command or entrypoint provided, and no CMD or ENTRYPOINT from image") + } + opts = append(opts, oci.WithProcessArgs(processArgs...)) + } + + initProcessFlag, err := cmd.Flags().GetBool("init") + if err != nil { + return nil, nil, nil, err + } + initBinary, err := cmd.Flags().GetString("init-binary") + if err != nil { + return nil, nil, nil, err + } + if cmd.Flags().Changed("init-binary") { + initProcessFlag = true + } + if initProcessFlag { + binaryPath, err := exec.LookPath(initBinary) + if err != nil { + if errors.Is(err, exec.ErrNotFound) { + return nil, nil, nil, fmt.Errorf(`init binary %q not found`, initBinary) + } + return nil, nil, nil, err + } + inContainerPath := filepath.Join("/sbin", filepath.Base(initBinary)) + opts = append(opts, func(_ context.Context, _ oci.Client, _ *containers.Container, spec *oci.Spec) error { + spec.Process.Args = append([]string{inContainerPath, "--"}, spec.Process.Args...) + spec.Mounts = append([]specs.Mount{{ + Destination: inContainerPath, + Type: "bind", + Source: binaryPath, + Options: []string{"bind", "ro"}, + }}, spec.Mounts...) + return nil + }) + } + + readonly, err := cmd.Flags().GetBool("read-only") + if err != nil { + return nil, nil, nil, err + } + if readonly { + opts = append(opts, oci.WithRootFSReadonly()) + } + return opts, cOpts, ensured, nil +} + +func GenerateLogURI(dataStore string) (*url.URL, error) { + selfExe, err := os.Executable() + if err != nil { + return nil, err + } + args := map[string]string{ + logging.MagicArgv1: dataStore, + } + + return cio.LogURIGenerator("binary", selfExe, args) +} + +func WithNerdctlOCIHook(cmd *cobra.Command, id string) (oci.SpecOpts, error) { + selfExe, f := utils.GlobalFlags(cmd) + args := append([]string{selfExe}, append(f, "internal", "oci-hook")...) + return func(_ context.Context, _ oci.Client, _ *containers.Container, s *specs.Spec) error { + if s.Hooks == nil { + s.Hooks = &specs.Hooks{} + } + crArgs := append(args, "createRuntime") + s.Hooks.CreateRuntime = append(s.Hooks.CreateRuntime, specs.Hook{ + Path: selfExe, + Args: crArgs, + Env: os.Environ(), + }) + argsCopy := append([]string(nil), args...) + psArgs := append(argsCopy, "postStop") + s.Hooks.Poststop = append(s.Hooks.Poststop, specs.Hook{ + Path: selfExe, + Args: psArgs, + Env: os.Environ(), + }) + return nil + }, nil +} + +func WithContainerLabels(cmd *cobra.Command) ([]containerd.NewContainerOpts, error) { + labelMap, err := common.ReadKVStringsMapfFromLabel(cmd) + if err != nil { + return nil, err + } + o := containerd.WithAdditionalContainerLabels(labelMap) + return []containerd.NewContainerOpts{o}, nil +} + +// parseKVStringsMapFromLogOpt parse log options KV entries and convert to Map +func ParseKVStringsMapFromLogOpt(cmd *cobra.Command, logDriver string) (map[string]string, error) { + logOptArray, err := cmd.Flags().GetStringArray("log-opt") + if err != nil { + return nil, err + } + logOptArray = strutil.DedupeStrSlice(logOptArray) + logOptMap := strutil.ConvertKVStringsToMap(logOptArray) + if logDriver == "json-file" { + if _, ok := logOptMap[logging.MaxSize]; !ok { + delete(logOptMap, logging.MaxFile) + } + } + if err := logging.ValidateLogOpts(logDriver, logOptMap); err != nil { + return nil, err + } + return logOptMap, nil +} + +func WithStop(stopSignal string, stopTimeout int, ensuredImage *imgutil.EnsuredImage) containerd.NewContainerOpts { + return func(ctx context.Context, _ *containerd.Client, c *containers.Container) error { + if c.Labels == nil { + c.Labels = make(map[string]string) + } + var err error + if ensuredImage != nil { + stopSignal, err = containerd.GetOCIStopSignal(ctx, ensuredImage.Image, stopSignal) + if err != nil { + return err + } + } + c.Labels[containerd.StopSignalLabel] = stopSignal + if stopTimeout != 0 { + c.Labels[labels.StopTimout] = strconv.Itoa(stopTimeout) + } + return nil + } +} + +func PropagateContainerdLabelsToOCIAnnotations() oci.SpecOpts { + return func(ctx context.Context, oc oci.Client, c *containers.Container, s *oci.Spec) error { + return oci.WithAnnotations(c.Labels)(ctx, oc, c, s) + } +} + +func WriteCIDFile(path, id string) error { + if _, err := os.Stat(path); err == nil { + return fmt.Errorf("container ID file found, make sure the other container isn't running or delete %s", path) + } else if errors.Is(err, os.ErrNotExist) { + f, err := os.Create(path) + if err != nil { + return err + } + defer f.Close() + if err != nil { + return fmt.Errorf("failed to create the container ID file: %s", err) + } + if _, err := f.WriteString(id); err != nil { + return err + } + return nil + } else { + return err + } +} + +func ParseEnvVars(paths []string) ([]string, error) { + vars := make([]string, 0) + for _, path := range paths { + f, err := os.Open(path) + if err != nil { + return nil, fmt.Errorf("failed to open env file %s: %w", path, err) + } + defer f.Close() + + sc := bufio.NewScanner(f) + for sc.Scan() { + line := strings.TrimSpace(sc.Text()) + // skip comment lines + if strings.HasPrefix(line, "#") { + continue + } + vars = append(vars, line) + } + if err = sc.Err(); err != nil { + return nil, err + } + } + return vars, nil +} + +func WithOSEnv(envs []string) ([]string, error) { + newEnvs := make([]string, len(envs)) + + // from https://github.com/docker/cli/blob/v22.06.0-beta.0/opts/env.go#L18 + getEnv := func(val string) (string, error) { + arr := strings.SplitN(val, "=", 2) + if arr[0] == "" { + return "", errors.New("invalid environment variable: " + val) + } + if len(arr) > 1 { + return val, nil + } + if envVal, ok := os.LookupEnv(arr[0]); ok { + return arr[0] + "=" + envVal, nil + } + return val, nil + } + for i := range envs { + env, err := getEnv(envs[i]) + if err != nil { + return nil, err + } + newEnvs[i] = env + } + + return newEnvs, nil +} + +// generateEnvs combines environment variables from `--env-file` and `--env`. +// Pass an empty slice if any arg is not used. +func GenerateEnvs(envFile []string, env []string) ([]string, error) { + var envs []string + var err error + + if envFiles := strutil.DedupeStrSlice(envFile); len(envFiles) > 0 { + envs, err = ParseEnvVars(envFiles) + if err != nil { + return nil, err + } + } + + if env := strutil.DedupeStrSlice(env); len(env) > 0 { + envs = append(envs, env...) + } + + if envs, err = WithOSEnv(envs); err != nil { + return nil, err + } + + return envs, nil +} diff --git a/cmd/nerdctl/fmtutil.go b/cmd/nerdctl/utils/fmtutil/fmtutil.go similarity index 81% rename from cmd/nerdctl/fmtutil.go rename to cmd/nerdctl/utils/fmtutil/fmtutil.go index cb52442f2e0..5bbd1d8b135 100644 --- a/cmd/nerdctl/fmtutil.go +++ b/cmd/nerdctl/utils/fmtutil/fmtutil.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package fmtutil import ( "bytes" @@ -32,7 +32,7 @@ type Flusher interface { Flush() error } -func formatLabels(labels map[string]string) string { +func FormatLabels(labels map[string]string) string { var res string for k, v := range labels { s := k + "=" + v @@ -45,13 +45,13 @@ func formatLabels(labels map[string]string) string { return res } -// formatSlice formats the slice with `--format` flag. +// FormatSlice formats the slice with `--format` flag. // // --format="" (default): JSON // --format='{{json .}}': JSON lines // -// formatSlice is expected to be only used for `nerdctl OBJECT inspect` commands. -func formatSlice(cmd *cobra.Command, x []interface{}) error { +// FormatSlice is expected to be only used for `nerdctl OBJECT inspect` commands. +func FormatSlice(cmd *cobra.Command, x []interface{}) error { var tmpl *template.Template format, err := cmd.Flags().GetString("format") if err != nil { @@ -68,7 +68,7 @@ func formatSlice(cmd *cobra.Command, x []interface{}) error { return errors.New("unsupported format: \"raw\", \"table\", and \"wide\"") default: var err error - tmpl, err = parseTemplate(format) + tmpl, err = ParseTemplate(format) if err != nil { return err } @@ -77,7 +77,7 @@ func formatSlice(cmd *cobra.Command, x []interface{}) error { if err := tmpl.Execute(&b, f); err != nil { if _, ok := err.(template.ExecError); ok { // FallBack to Raw Format - if err = tryRawFormat(&b, f, tmpl); err != nil { + if err = TryRawFormat(&b, f, tmpl); err != nil { return err } } @@ -90,7 +90,7 @@ func formatSlice(cmd *cobra.Command, x []interface{}) error { return nil } -func tryRawFormat(b *bytes.Buffer, f interface{}, tmpl *template.Template) error { +func TryRawFormat(b *bytes.Buffer, f interface{}, tmpl *template.Template) error { m, err := json.MarshalIndent(f, "", " ") if err != nil { return err @@ -113,9 +113,9 @@ func tryRawFormat(b *bytes.Buffer, f interface{}, tmpl *template.Template) error return nil } -// parseTemplate wraps github.com/docker/cli/templates.Parse() to allow `json` as an alias of `{{json .}}`. -// parseTemplate can be removed when https://github.com/docker/cli/pull/3355 gets merged and tagged (Docker 22.XX). -func parseTemplate(format string) (*template.Template, error) { +// ParseTemplate wraps github.com/docker/cli/templates.Parse() to allow `json` as an alias of `{{json .}}`. +// ParseTemplate can be removed when https://github.com/docker/cli/pull/3355 gets merged and tagged (Docker 22.XX). +func ParseTemplate(format string) (*template.Template, error) { aliases := map[string]string{ "json": "{{json .}}", } diff --git a/cmd/nerdctl/utils/image.go b/cmd/nerdctl/utils/image.go new file mode 100644 index 00000000000..8b2edb70700 --- /dev/null +++ b/cmd/nerdctl/utils/image.go @@ -0,0 +1,113 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package utils + +import ( + "context" + "errors" + "fmt" + "io" + + "github.com/containerd/containerd" + "github.com/containerd/containerd/errdefs" + "github.com/containerd/containerd/images" + "github.com/containerd/containerd/images/archive" + "github.com/containerd/containerd/platforms" + "github.com/containerd/containerd/snapshots" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" + "github.com/opencontainers/image-spec/identity" + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" +) + +func LoadImage(in io.Reader, cmd *cobra.Command, platMC platforms.MatchComparer, quiet bool) error { + // In addition to passing WithImagePlatform() to client.Import(), we also need to pass WithDefaultPlatform() to NewClient(). + // Otherwise unpacking may fail. + client, ctx, cancel, err := nerdClient.NewClient(cmd, containerd.WithDefaultPlatform(platMC)) + if err != nil { + return err + } + defer cancel() + + sn, err := cmd.Flags().GetString("snapshotter") + if err != nil { + return err + } + + r := &common.ReadCounter{Reader: in} + imgs, err := client.Import(ctx, r, containerd.WithDigestRef(archive.DigestTranslator(sn)), containerd.WithSkipDigestRef(func(name string) bool { return name != "" }), containerd.WithImportPlatform(platMC)) + if err != nil { + if r.N == 0 { + // Avoid confusing "unrecognized image format" + return errors.New("no image was built") + } + if errors.Is(err, images.ErrEmptyWalk) { + err = fmt.Errorf("%w (Hint: set `--platform=PLATFORM` or `--all-platforms`)", err) + } + return err + } + for _, img := range imgs { + image := containerd.NewImageWithPlatform(client, img, platMC) + + // TODO: Show unpack status + if !quiet { + fmt.Fprintf(cmd.OutOrStdout(), "unpacking %s (%s)...\n", img.Name, img.Target.Digest) + } + err = image.Unpack(ctx, sn) + if err != nil { + return err + } + if quiet { + fmt.Fprintln(cmd.OutOrStdout(), img.Target.Digest) + } else { + fmt.Fprintf(cmd.OutOrStdout(), "Loaded image: %s\n", img.Name) + } + } + + return nil +} + +// UnpackedImageSize is the size of the unpacked snapshots. +// Does not contain the size of the blobs in the content store. (Corresponds to Docker). +func UnpackedImageSize(ctx context.Context, s snapshots.Snapshotter, img containerd.Image) (int64, error) { + diffIDs, err := img.RootFS(ctx) + if err != nil { + return 0, err + } + + chainID := identity.ChainID(diffIDs).String() + usage, err := s.Usage(ctx, chainID) + if err != nil { + if errdefs.IsNotFound(err) { + logrus.WithError(err).Debugf("image %q seems not unpacked", img.Name()) + return 0, nil + } + return 0, err + } + + info, err := s.Stat(ctx, chainID) + if err != nil { + return 0, err + } + + //Add ChainID's parent usage to the total usage + if err := common.SnapshotKey(info.Parent).Add(ctx, s, &usage); err != nil { + return 0, err + } + return usage.Size, nil +} diff --git a/cmd/nerdctl/utils/image_encrypt.go b/cmd/nerdctl/utils/image_encrypt.go new file mode 100644 index 00000000000..80b7f47277f --- /dev/null +++ b/cmd/nerdctl/utils/image_encrypt.go @@ -0,0 +1,71 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package utils + +import ( + "os" + "os/exec" + "path/filepath" + "testing" + + "github.com/containerd/nerdctl/pkg/buildkitutil" + "github.com/containerd/nerdctl/pkg/testutil" + "gotest.tools/v3/assert" +) + +type JweKeyPair struct { + Prv string + Pub string + Cleanup func() +} + +func NewJWEKeyPair(t testing.TB) *JweKeyPair { + if _, err := exec.LookPath("openssl"); err != nil { + t.Skip(err) + } + td, err := os.MkdirTemp(t.TempDir(), "jwe-key-pair") + assert.NilError(t, err) + prv := filepath.Join(td, "mykey.pem") + pub := filepath.Join(td, "mypubkey.pem") + cmds := [][]string{ + // Exec openssl commands to ensure that nerdctl is compatible with the output of openssl commands. + // Do NOT refactor this function to use "crypto/rsa" stdlib. + {"openssl", "genrsa", "-out", prv}, + {"openssl", "rsa", "-in", prv, "-pubout", "-out", pub}, + } + for _, f := range cmds { + cmd := exec.Command(f[0], f[1:]...) + if out, err := cmd.CombinedOutput(); err != nil { + t.Fatalf("failed to run %v: %v (%q)", cmd.Args, err, string(out)) + } + } + return &JweKeyPair{ + Prv: prv, + Pub: pub, + Cleanup: func() { + _ = os.RemoveAll(td) + }, + } +} + +func RmiAll(base *testutil.Base) { + imageIDs := base.Cmd("images", "--no-trunc", "-a", "-q").OutLines() + base.Cmd(append([]string{"rmi", "-f"}, imageIDs...)...).AssertOK() + if _, err := buildkitutil.GetBuildkitHost(testutil.Namespace); err == nil { + base.Cmd("builder", "prune").AssertOK() + } +} diff --git a/cmd/nerdctl/run_mount.go b/cmd/nerdctl/utils/mount.go similarity index 98% rename from cmd/nerdctl/run_mount.go rename to cmd/nerdctl/utils/mount.go index d9837a131ea..f7595b95f24 100644 --- a/cmd/nerdctl/run_mount.go +++ b/cmd/nerdctl/utils/mount.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package utils import ( "context" @@ -30,6 +30,7 @@ import ( "github.com/containerd/containerd/mount" "github.com/containerd/containerd/oci" "github.com/containerd/continuity/fs" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/volume" "github.com/containerd/nerdctl/pkg/idgen" "github.com/containerd/nerdctl/pkg/imgutil" "github.com/containerd/nerdctl/pkg/mountutil" @@ -38,7 +39,6 @@ import ( securejoin "github.com/cyphar/filepath-securejoin" "github.com/opencontainers/image-spec/identity" "github.com/opencontainers/runtime-spec/specs-go" - "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -120,8 +120,8 @@ func parseMountFlags(cmd *cobra.Command, volStore volumestore.VolumeStore) ([]*m // generateMountOpts generates volume-related mount opts. // Other mounts such as procfs mount are not handled here. -func generateMountOpts(ctx context.Context, cmd *cobra.Command, client *containerd.Client, ensuredImage *imgutil.EnsuredImage) ([]oci.SpecOpts, []string, []*mountutil.Processed, error) { - volStore, err := getVolumeStore(cmd) +func GenerateMountOpts(ctx context.Context, cmd *cobra.Command, client *containerd.Client, ensuredImage *imgutil.EnsuredImage) ([]oci.SpecOpts, []string, []*mountutil.Processed, error) { + volStore, err := volume.GetVolumeStore(cmd) if err != nil { return nil, nil, nil, err } diff --git a/cmd/nerdctl/completion_linux.go b/cmd/nerdctl/utils/network.go similarity index 58% rename from cmd/nerdctl/completion_linux.go rename to cmd/nerdctl/utils/network.go index e89d5e40960..ba359e0495b 100644 --- a/cmd/nerdctl/completion_linux.go +++ b/cmd/nerdctl/utils/network.go @@ -14,21 +14,21 @@ limitations under the License. */ -package main +package utils import ( - "github.com/containerd/nerdctl/pkg/apparmorutil" - "github.com/spf13/cobra" + "encoding/json" + + "github.com/containerd/nerdctl/pkg/labels" + "github.com/sirupsen/logrus" ) -func shellCompleteApparmorProfiles(cmd *cobra.Command) ([]string, cobra.ShellCompDirective) { - profiles, err := apparmorutil.Profiles() - if err != nil { - return nil, cobra.ShellCompDirectiveError - } - var names []string // nolint: prealloc - for _, f := range profiles { - names = append(names, f.Name) +func GetContainerNetworks(containerLables map[string]string) []string { + var networks []string + if names, ok := containerLables[labels.Networks]; ok { + if err := json.Unmarshal([]byte(names), &networks); err != nil { + logrus.Warn(err) + } } - return names, cobra.ShellCompDirectiveNoFileComp + return networks } diff --git a/cmd/nerdctl/utils/pause.go b/cmd/nerdctl/utils/pause.go new file mode 100644 index 00000000000..759191e4e33 --- /dev/null +++ b/cmd/nerdctl/utils/pause.go @@ -0,0 +1,51 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package utils + +import ( + "context" + "fmt" + + "github.com/containerd/containerd" + "github.com/containerd/containerd/cio" +) + +func PauseContainer(ctx context.Context, client *containerd.Client, id string) error { + container, err := client.LoadContainer(ctx, id) + if err != nil { + return err + } + + task, err := container.Task(ctx, cio.Load) + if err != nil { + return err + } + + status, err := task.Status(ctx) + if err != nil { + return err + } + + switch status.Status { + case containerd.Paused: + return fmt.Errorf("container %s is already paused", id) + case containerd.Created, containerd.Stopped: + return fmt.Errorf("container %s is not running", id) + default: + return task.Pause(ctx) + } +} diff --git a/cmd/nerdctl/utils/print.go b/cmd/nerdctl/utils/print.go new file mode 100644 index 00000000000..bd14d11033b --- /dev/null +++ b/cmd/nerdctl/utils/print.go @@ -0,0 +1,42 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package utils + +import ( + "fmt" + + "github.com/containerd/nerdctl/pkg/labels" + "github.com/containerd/nerdctl/pkg/labels/k8slabels" +) + +func GetPrintableContainerName(containerLabels map[string]string) string { + if name, ok := containerLabels[labels.Name]; ok { + return name + } + + if ns, ok := containerLabels[k8slabels.PodNamespace]; ok { + if podName, ok := containerLabels[k8slabels.PodName]; ok { + if containerName, ok := containerLabels[k8slabels.ContainerName]; ok { + // Container + return fmt.Sprintf("k8s://%s/%s/%s", ns, podName, containerName) + } + // Pod sandbox + return fmt.Sprintf("k8s://%s/%s", ns, podName) + } + } + return "" +} diff --git a/cmd/nerdctl/utils/pull.go b/cmd/nerdctl/utils/pull.go new file mode 100644 index 00000000000..30386d34995 --- /dev/null +++ b/cmd/nerdctl/utils/pull.go @@ -0,0 +1,139 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package utils + +import ( + "context" + "errors" + "fmt" + "os" + "os/exec" + "path/filepath" + "testing" + + "github.com/containerd/containerd" + "github.com/containerd/nerdctl/pkg/cosignutil" + "github.com/containerd/nerdctl/pkg/imgutil" + "github.com/containerd/nerdctl/pkg/ipfs" + "github.com/containerd/nerdctl/pkg/referenceutil" + httpapi "github.com/ipfs/go-ipfs-http-client" + v1 "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + "gotest.tools/v3/assert" +) + +type CosignKeyPair struct { + PublicKey string + PrivateKey string + Cleanup func() +} + +func NewCosignKeyPair(t testing.TB, path string) *CosignKeyPair { + td, err := os.MkdirTemp(t.TempDir(), path) + assert.NilError(t, err) + + cmd := exec.Command("cosign", "generate-key-pair") + cmd.Dir = td + if out, err := cmd.CombinedOutput(); err != nil { + t.Fatalf("failed to run %v: %v (%q)", cmd.Args, err, string(out)) + } + + publicKey := filepath.Join(td, "cosign.pub") + privateKey := filepath.Join(td, "cosign.key") + + return &CosignKeyPair{ + PublicKey: publicKey, + PrivateKey: privateKey, + Cleanup: func() { + _ = os.RemoveAll(td) + }, + } +} + +func EnsureImage(ctx context.Context, cmd *cobra.Command, client *containerd.Client, rawRef string, ocispecPlatforms []v1.Platform, + pull string, unpack *bool, quiet bool) (*imgutil.EnsuredImage, error) { + + var ensured *imgutil.EnsuredImage + snapshotter, err := cmd.Flags().GetString("snapshotter") + if err != nil { + return nil, err + } + insecureRegistry, err := cmd.Flags().GetBool("insecure-registry") + if err != nil { + return nil, err + } + hostsDirs, err := cmd.Flags().GetStringSlice("hosts-dir") + if err != nil { + return nil, err + } + verifier, err := cmd.Flags().GetString("verify") + if err != nil { + return nil, err + } + + if scheme, ref, err := referenceutil.ParseIPFSRefWithScheme(rawRef); err == nil { + if verifier != "none" { + return nil, errors.New("--verify flag is not supported on IPFS as of now") + } + + ipfsClient, err := httpapi.NewLocalApi() + if err != nil { + return nil, err + } + ensured, err = ipfs.EnsureImage(ctx, client, ipfsClient, cmd.OutOrStdout(), cmd.ErrOrStderr(), snapshotter, scheme, ref, + pull, ocispecPlatforms, unpack, quiet) + if err != nil { + return nil, err + } + return ensured, nil + } + + ref := rawRef + switch verifier { + case "cosign": + experimental, err := cmd.Flags().GetBool("experimental") + if err != nil { + return nil, err + } + + if !experimental { + return nil, fmt.Errorf("cosign only work with enable experimental feature") + } + + keyRef, err := cmd.Flags().GetString("cosign-key") + if err != nil { + return nil, err + } + + ref, err = cosignutil.VerifyCosign(ctx, rawRef, keyRef, hostsDirs) + if err != nil { + return nil, err + } + case "none": + logrus.Debugf("verification process skipped") + default: + return nil, fmt.Errorf("no verifier found: %s", verifier) + } + + ensured, err = imgutil.EnsureImage(ctx, client, cmd.OutOrStdout(), cmd.ErrOrStderr(), snapshotter, ref, + pull, insecureRegistry, hostsDirs, ocispecPlatforms, unpack, quiet) + if err != nil { + return nil, err + } + return ensured, err +} diff --git a/cmd/nerdctl/utils/run/run.go b/cmd/nerdctl/utils/run/run.go new file mode 100644 index 00000000000..3fff372da4d --- /dev/null +++ b/cmd/nerdctl/utils/run/run.go @@ -0,0 +1,315 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package run + +import ( + "context" + "fmt" + "path" + "strings" + + "github.com/containerd/containerd" + "github.com/containerd/containerd/containers" + "github.com/containerd/containerd/oci" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" + "github.com/containerd/nerdctl/pkg/defaults" + "github.com/containerd/nerdctl/pkg/labels" + "github.com/containerd/nerdctl/pkg/logging" + "github.com/containerd/nerdctl/pkg/netutil" + "github.com/containerd/nerdctl/pkg/rootlessutil" + "github.com/opencontainers/runtime-spec/specs-go" + "github.com/spf13/cobra" +) + +func SetCreateFlags(cmd *cobra.Command) { + + // No "-h" alias for "--help", because "-h" for "--hostname". + cmd.Flags().Bool("help", false, "show help") + + cmd.Flags().BoolP("tty", "t", false, "(Currently -t needs to correspond to -i)") + cmd.Flags().BoolP("interactive", "i", false, "Keep STDIN open even if not attached") + cmd.Flags().String("restart", "no", `Restart policy to apply when a container exits (implemented values: "no"|"always")`) + cmd.RegisterFlagCompletionFunc("restart", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return []string{"no", "always", "on-failure", "unless-stopped"}, cobra.ShellCompDirectiveNoFileComp + }) + cmd.Flags().Bool("rm", false, "Automatically remove the container when it exits") + cmd.Flags().String("pull", "missing", `Pull image before running ("always"|"missing"|"never")`) + cmd.RegisterFlagCompletionFunc("pull", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return []string{"always", "missing", "never"}, cobra.ShellCompDirectiveNoFileComp + }) + cmd.Flags().String("stop-signal", "SIGTERM", "Signal to stop a container") + cmd.Flags().Int("stop-timeout", 0, "Timeout (in seconds) to stop a container") + + // #region for init process + cmd.Flags().Bool("init", false, "Run an init process inside the container, Default to use tini") + cmd.Flags().String("init-binary", common.TiniInitBinary, "The custom binary to use as the init process") + // #endregion + + // #region platform flags + cmd.Flags().String("platform", "", "Set platform (e.g. \"amd64\", \"arm64\")") // not a slice, and there is no --all-platforms + cmd.RegisterFlagCompletionFunc("platform", completion.ShellCompletePlatforms) + // #endregion + + // #region network flags + // network (net) is defined as StringSlice, not StringArray, to allow specifying "--network=cni1,cni2" + cmd.Flags().StringSlice("network", []string{netutil.DefaultNetworkName}, `Connect a container to a network ("bridge"|"host"|"none"|"container:"|)`) + cmd.RegisterFlagCompletionFunc("network", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return completion.ShellCompleteNetworkNames(cmd, []string{}) + }) + cmd.Flags().StringSlice("net", []string{netutil.DefaultNetworkName}, `Connect a container to a network ("bridge"|"host"|"none"|)`) + cmd.RegisterFlagCompletionFunc("net", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return completion.ShellCompleteNetworkNames(cmd, []string{}) + }) + // dns is defined as StringSlice, not StringArray, to allow specifying "--dns=1.1.1.1,8.8.8.8" (compatible with Podman) + cmd.Flags().StringSlice("dns", nil, "Set custom DNS servers") + cmd.Flags().StringSlice("dns-search", nil, "Set custom DNS search domains") + // We allow for both "--dns-opt" and "--dns-option", although the latter is the recommended way. + cmd.Flags().StringSlice("dns-opt", nil, "Set DNS options") + cmd.Flags().StringSlice("dns-option", nil, "Set DNS options") + // publish is defined as StringSlice, not StringArray, to allow specifying "--publish=80:80,443:443" (compatible with Podman) + cmd.Flags().StringSliceP("publish", "p", nil, "Publish a container's port(s) to the host") + // FIXME: not support IPV6 yet + cmd.Flags().String("ip", "", "IPv4 address to assign to the container") + cmd.Flags().StringP("hostname", "h", "", "Container host name") + cmd.Flags().String("mac-address", "", "MAC address to assign to the container") + // #endregion + + cmd.Flags().String("ipc", "", `IPC namespace to use ("host"|"private")`) + cmd.RegisterFlagCompletionFunc("ipc", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return []string{"host", "private"}, cobra.ShellCompDirectiveNoFileComp + }) + // #region cgroups, namespaces, and ulimits flags + cmd.Flags().Float64("cpus", 0.0, "Number of CPUs") + cmd.Flags().StringP("memory", "m", "", "Memory limit") + cmd.Flags().String("memory-reservation", "", "Memory soft limit") + cmd.Flags().String("memory-swap", "", "Swap limit equal to memory plus swap: '-1' to enable unlimited swap") + cmd.Flags().Int64("memory-swappiness", -1, "Tune container memory swappiness (0 to 100) (default -1)") + cmd.Flags().String("kernel-memory", "", "Kernel memory limit (deprecated)") + cmd.Flags().Bool("oom-kill-disable", false, "Disable OOM Killer") + cmd.Flags().Int("oom-score-adj", 0, "Tune container’s OOM preferences (-1000 to 1000, rootless: 100 to 1000)") + cmd.Flags().String("pid", "", "PID namespace to use") + cmd.RegisterFlagCompletionFunc("pid", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return []string{"host"}, cobra.ShellCompDirectiveNoFileComp + }) + cmd.Flags().Int64("pids-limit", -1, "Tune container pids limit (set -1 for unlimited)") + cmd.Flags().StringSlice("cgroup-conf", nil, "Configure cgroup v2 (key=value)") + cmd.Flags().Uint16("blkio-weight", 0, "Block IO (relative weight), between 10 and 1000, or 0 to disable (default 0)") + cmd.Flags().String("cgroupns", defaults.CgroupnsMode(), `Cgroup namespace to use, the default depends on the cgroup version ("host"|"private")`) + cmd.RegisterFlagCompletionFunc("cgroupns", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return []string{"host", "private"}, cobra.ShellCompDirectiveNoFileComp + }) + cmd.Flags().String("cpuset-cpus", "", "CPUs in which to allow execution (0-3, 0,1)") + cmd.Flags().String("cpuset-mems", "", "MEMs in which to allow execution (0-3, 0,1)") + cmd.Flags().Uint64("cpu-shares", 0, "CPU shares (relative weight)") + cmd.Flags().Int64("cpu-quota", -1, "Limit CPU CFS (Completely Fair Scheduler) quota") + cmd.Flags().Uint64("cpu-period", 0, "Limit CPU CFS (Completely Fair Scheduler) period") + // device is defined as StringSlice, not StringArray, to allow specifying "--device=DEV1,DEV2" (compatible with Podman) + cmd.Flags().StringSlice("device", nil, "Add a host device to the container") + // ulimit is defined as StringSlice, not StringArray, to allow specifying "--ulimit=ULIMIT1,ULIMIT2" (compatible with Podman) + cmd.Flags().StringSlice("ulimit", nil, "Ulimit options") + cmd.Flags().String("rdt-class", "", "Name of the RDT class (or CLOS) to associate the container with") + // #endregion + + // user flags + cmd.Flags().StringP("user", "u", "", "Username or UID (format: [:])") + cmd.Flags().String("umask", "", "Set the umask inside the container. Defaults to 0022") + cmd.Flags().StringSlice("group-add", []string{}, "Add additional groups to join") + + // #region security flags + cmd.Flags().StringArray("security-opt", []string{}, "Security options") + cmd.RegisterFlagCompletionFunc("security-opt", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return []string{"seccomp=", "seccomp=unconfined", "apparmor=", "apparmor=" + defaults.AppArmorProfileName, "apparmor=unconfined", "no-new-privileges", "privileged-without-host-devices"}, cobra.ShellCompDirectiveNoFileComp + }) + // cap-add and cap-drop are defined as StringSlice, not StringArray, to allow specifying "--cap-add=CAP_SYS_ADMIN,CAP_NET_ADMIN" (compatible with Podman) + cmd.Flags().StringSlice("cap-add", []string{}, "Add Linux Capabilities") + cmd.RegisterFlagCompletionFunc("cap-add", completion.CapShellComplete) + cmd.Flags().StringSlice("cap-drop", []string{}, "Drop Linux Capabilities") + cmd.RegisterFlagCompletionFunc("cap-drop", completion.CapShellComplete) + cmd.Flags().Bool("privileged", false, "Give extended privileges to this container") + // #endregion + + // #region runtime flags + cmd.Flags().String("runtime", defaults.Runtime, "Runtime to use for this container, e.g. \"crun\", or \"io.containerd.runsc.v1\"") + // sysctl needs to be StringArray, not StringSlice, to prevent "foo=foo1,foo2" from being split to {"foo=foo1", "foo2"} + cmd.Flags().StringArray("sysctl", nil, "Sysctl options") + // gpus needs to be StringArray, not StringSlice, to prevent "Capabilities=utility,device=DEV" from being split to {"Capabilities=utility", "device=DEV"} + cmd.Flags().StringArray("gpus", nil, "GPU devices to Add to the container ('all' to pass all GPUs)") + cmd.RegisterFlagCompletionFunc("gpus", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return []string{"all"}, cobra.ShellCompDirectiveNoFileComp + }) + // #endregion + + // #region mount flags + // volume needs to be StringArray, not StringSlice, to prevent "/foo:/foo:ro,Z" from being split to {"/foo:/foo:ro", "Z"} + cmd.Flags().StringArrayP("volume", "v", nil, "Bind mount a volume") + // tmpfs needs to be StringArray, not StringSlice, to prevent "/foo:size=64m,exec" from being split to {"/foo:size=64m", "exec"} + cmd.Flags().StringArray("tmpfs", nil, "Mount a tmpfs directory") + cmd.Flags().StringArray("mount", nil, "Attach a filesystem mount to the container") + // #endregion + + // rootfs flags + cmd.Flags().Bool("read-only", false, "Mount the container's root filesystem as read only") + // rootfs flags (from Podman) + cmd.Flags().Bool("rootfs", false, "The first argument is not an image but the rootfs to the exploded container") + + // #region env flags + // entrypoint needs to be StringArray, not StringSlice, to prevent "FOO=foo1,foo2" from being split to {"FOO=foo1", "foo2"} + // entrypoint StringArray is an internal implementation to support `nerdctl compose` entrypoint yaml filed with multiple strings + // users are not expected to specify multiple --entrypoint flags manually. + cmd.Flags().StringArray("entrypoint", nil, "Overwrite the default ENTRYPOINT of the image") + cmd.Flags().StringP("workdir", "w", "", "Working directory inside the container") + // env needs to be StringArray, not StringSlice, to prevent "FOO=foo1,foo2" from being split to {"FOO=foo1", "foo2"} + cmd.Flags().StringArrayP("env", "e", nil, "Set environment variables") + // add-host is defined as StringSlice, not StringArray, to allow specifying "--add-host=HOST1:IP1,HOST2:IP2" (compatible with Podman) + cmd.Flags().StringSlice("add-host", nil, "Add a custom host-to-IP mapping (host:ip)") + // env-file is defined as StringSlice, not StringArray, to allow specifying "--env-file=FILE1,FILE2" (compatible with Podman) + cmd.Flags().StringSlice("env-file", nil, "Set environment variables from file") + + // #region metadata flags + cmd.Flags().String("name", "", "Assign a name to the container") + // label needs to be StringArray, not StringSlice, to prevent "foo=foo1,foo2" from being split to {"foo=foo1", "foo2"} + cmd.Flags().StringArrayP("label", "l", nil, "Set metadata on container") + cmd.RegisterFlagCompletionFunc("label", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return labels.ShellCompletions, cobra.ShellCompDirectiveNoFileComp + }) + + // label-file is defined as StringSlice, not StringArray, to allow specifying "--env-file=FILE1,FILE2" (compatible with Podman) + cmd.Flags().StringSlice("label-file", nil, "Set metadata on container from file") + cmd.Flags().String("cidfile", "", "Write the container ID to the file") + // #endregion + + // #region logging flags + // log-opt needs to be StringArray, not StringSlice, to prevent "env=os,customer" from being split to {"env=os", "customer"} + cmd.Flags().String("log-driver", "json-file", "Logging driver for the container. Default is json-file. It also supports logURI (eg: --log-driver binary://)") + cmd.RegisterFlagCompletionFunc("log-driver", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return logging.Drivers(), cobra.ShellCompDirectiveNoFileComp + }) + cmd.Flags().StringArray("log-opt", nil, "Log driver options") + // #endregion + + // shared memory flags + cmd.Flags().String("shm-size", "", "Size of /dev/shm") + cmd.Flags().String("pidfile", "", "file path to write the task's pid") + + // #region verify flags + cmd.Flags().String("verify", "none", "Verify the image (none|cosign)") + cmd.RegisterFlagCompletionFunc("verify", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return []string{"none", "cosign"}, cobra.ShellCompDirectiveNoFileComp + }) + cmd.Flags().String("cosign-key", "", "Path to the public key file, KMS, URI or Kubernetes Secret for --verify=cosign") + // #endregion +} + +// WithBindMountHostIPC replaces /dev/shm and /dev/mqueue mount with rbind. +// Required for --ipc=host on rootless. +func WithBindMountHostIPC(_ context.Context, _ oci.Client, _ *containers.Container, s *oci.Spec) error { + for i, m := range s.Mounts { + if path.Clean(m.Destination) == "/dev/shm" { + newM := specs.Mount{ + Destination: "/dev/shm", + Type: "bind", + Source: "/dev/shm", + Options: []string{"rbind", "nosuid", "noexec", "nodev"}, + } + s.Mounts[i] = newM + } + if path.Clean(m.Destination) == "/dev/mqueue" { + newM := specs.Mount{ + Destination: "/dev/mqueue", + Type: "bind", + Source: "/dev/mqueue", + Options: []string{"rbind", "nosuid", "noexec", "nodev"}, + } + s.Mounts[i] = newM + } + } + return nil +} + +// withBindMountHostProcfs replaces procfs mount with rbind. +// Required for --pid=host on rootless. +// +// https://github.com/moby/moby/pull/41893/files +// https://github.com/containers/podman/blob/v3.0.0-rc1/pkg/specgen/generate/oci.go#L248-L257 +func WithBindMountHostProcfs(_ context.Context, _ oci.Client, _ *containers.Container, s *oci.Spec) error { + for i, m := range s.Mounts { + if path.Clean(m.Destination) == "/proc" { + newM := specs.Mount{ + Destination: "/proc", + Type: "bind", + Source: "/proc", + Options: []string{"rbind", "nosuid", "noexec", "nodev"}, + } + s.Mounts[i] = newM + } + } + + // Remove ReadonlyPaths for /proc/* + newROP := s.Linux.ReadonlyPaths[:0] + for _, x := range s.Linux.ReadonlyPaths { + x = path.Clean(x) + if !strings.HasPrefix(x, "/proc/") { + newROP = append(newROP, x) + } + } + s.Linux.ReadonlyPaths = newROP + return nil +} + +func GenerateSharingPIDOpts(ctx context.Context, targetCon containerd.Container) ([]oci.SpecOpts, error) { + opts := make([]oci.SpecOpts, 0) + + task, err := targetCon.Task(ctx, nil) + if err != nil { + return nil, err + } + status, err := task.Status(ctx) + if err != nil { + return nil, err + } + + if status.Status != containerd.Running { + return nil, fmt.Errorf("shared container is not running") + } + + spec, err := targetCon.Spec(ctx) + if err != nil { + return nil, err + } + + isHost := true + for _, n := range spec.Linux.Namespaces { + if n.Type == specs.PIDNamespace { + isHost = false + } + } + if isHost { + opts = append(opts, oci.WithHostNamespace(specs.PIDNamespace)) + if rootlessutil.IsRootless() { + opts = append(opts, WithBindMountHostProcfs) + } + } else { + ns := specs.LinuxNamespace{ + Type: specs.PIDNamespace, + Path: fmt.Sprintf("/proc/%d/ns/pid", task.Pid()), + } + opts = append(opts, oci.WithLinuxNamespace(ns)) + } + + return opts, nil +} diff --git a/cmd/nerdctl/run_cgroup_freebsd.go b/cmd/nerdctl/utils/run/run_cgroup_freebsd.go similarity index 98% rename from cmd/nerdctl/run_cgroup_freebsd.go rename to cmd/nerdctl/utils/run/run_cgroup_freebsd.go index bb0fe0f6213..37fcddd1de8 100644 --- a/cmd/nerdctl/run_cgroup_freebsd.go +++ b/cmd/nerdctl/utils/run/run_cgroup_freebsd.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package run import ( "github.com/containerd/containerd/oci" diff --git a/cmd/nerdctl/run_cgroup_linux.go b/cmd/nerdctl/utils/run/run_cgroup_linux.go similarity index 98% rename from cmd/nerdctl/run_cgroup_linux.go rename to cmd/nerdctl/utils/run/run_cgroup_linux.go index 2c964f46c0a..a30620508b6 100644 --- a/cmd/nerdctl/run_cgroup_linux.go +++ b/cmd/nerdctl/utils/run/run_cgroup_linux.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package run import ( "context" @@ -271,7 +271,7 @@ func generateCgroupOpts(cmd *cobra.Command, id string) ([]oci.SpecOpts, error) { return nil, err } for _, f := range device { - devPath, mode, err := parseDevice(f) + devPath, mode, err := ParseDevice(f) if err != nil { return nil, fmt.Errorf("failed to parse device %q: %w", f, err) } @@ -280,7 +280,7 @@ func generateCgroupOpts(cmd *cobra.Command, id string) ([]oci.SpecOpts, error) { return opts, nil } -func parseDevice(s string) (hostDevPath string, mode string, err error) { +func ParseDevice(s string) (hostDevPath string, mode string, err error) { mode = "rwm" split := strings.Split(s, ":") var containerDevPath string diff --git a/cmd/nerdctl/run_cgroup_windows.go b/cmd/nerdctl/utils/run/run_cgroup_windows.go similarity index 98% rename from cmd/nerdctl/run_cgroup_windows.go rename to cmd/nerdctl/utils/run/run_cgroup_windows.go index bb0fe0f6213..37fcddd1de8 100644 --- a/cmd/nerdctl/run_cgroup_windows.go +++ b/cmd/nerdctl/utils/run/run_cgroup_windows.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package run import ( "github.com/containerd/containerd/oci" diff --git a/cmd/nerdctl/run_freebsd.go b/cmd/nerdctl/utils/run/run_freebsd.go similarity index 68% rename from cmd/nerdctl/run_freebsd.go rename to cmd/nerdctl/utils/run/run_freebsd.go index eef282e940c..53116ade585 100644 --- a/cmd/nerdctl/run_freebsd.go +++ b/cmd/nerdctl/utils/run/run_freebsd.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package run import ( "context" @@ -22,23 +22,15 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/containers" "github.com/containerd/containerd/oci" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" "github.com/spf13/cobra" ) +func SetPlatformOptions(ctx context.Context, opts []oci.SpecOpts, cmd *cobra.Command, client *containerd.Client, id string, internalLabels common.InternalLabels) ([]oci.SpecOpts, common.InternalLabels, error) { + return opts, internalLabels, nil +} + func WithoutRunMount() func(ctx context.Context, client oci.Client, c *containers.Container, s *oci.Spec) error { // not valid on freebsd return func(_ context.Context, _ oci.Client, _ *containers.Container, s *oci.Spec) error { return nil } } - -func capShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - candidates := []string{} - return candidates, cobra.ShellCompDirectiveNoFileComp -} - -func runShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return nil, cobra.ShellCompDirectiveNoFileComp -} - -func setPlatformOptions(ctx context.Context, opts []oci.SpecOpts, cmd *cobra.Command, client *containerd.Client, id string, internalLabels internalLabels) ([]oci.SpecOpts, internalLabels, error) { - return opts, internalLabels, nil -} diff --git a/cmd/nerdctl/run_gpus.go b/cmd/nerdctl/utils/run/run_gpus.go similarity index 83% rename from cmd/nerdctl/run_gpus.go rename to cmd/nerdctl/utils/run/run_gpus.go index 7b656fc6d64..2c3e23855fc 100644 --- a/cmd/nerdctl/run_gpus.go +++ b/cmd/nerdctl/utils/run/run_gpus.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package run import ( "encoding/csv" @@ -28,10 +28,10 @@ import ( "github.com/containerd/nerdctl/pkg/rootlessutil" ) -type gpuReq struct { - count int - deviceIDs []string - capabilities []string +type GpuReq struct { + Count int + DeviceIDs []string + Capabilities []string } func parseGPUOpts(value []string) (res []oci.SpecOpts, _ error) { @@ -46,22 +46,22 @@ func parseGPUOpts(value []string) (res []oci.SpecOpts, _ error) { } func parseGPUOpt(value string) (oci.SpecOpts, error) { - req, err := parseGPUOptCSV(value) + req, err := ParseGPUOptCSV(value) if err != nil { return nil, err } var gpuOpts []nvidia.Opts - if len(req.deviceIDs) > 0 { - gpuOpts = append(gpuOpts, nvidia.WithDeviceUUIDs(req.deviceIDs...)) - } else if req.count > 0 { + if len(req.DeviceIDs) > 0 { + gpuOpts = append(gpuOpts, nvidia.WithDeviceUUIDs(req.DeviceIDs...)) + } else if req.Count > 0 { var devices []int - for i := 0; i < req.count; i++ { + for i := 0; i < req.Count; i++ { devices = append(devices, i) } gpuOpts = append(gpuOpts, nvidia.WithDevices(devices...)) - } else if req.count < 0 { + } else if req.Count < 0 { gpuOpts = append(gpuOpts, nvidia.WithAllDevices) } @@ -70,7 +70,7 @@ func parseGPUOpt(value string) (oci.SpecOpts, error) { str2cap[string(c)] = c } var nvidiaCaps []nvidia.Capability - for _, c := range req.capabilities { + for _, c := range req.Capabilities { if cap, isNvidiaCap := str2cap[c]; isNvidiaCap { nvidiaCaps = append(nvidiaCaps, cap) } @@ -92,7 +92,7 @@ func parseGPUOpt(value string) (oci.SpecOpts, error) { return nvidia.WithGPUs(gpuOpts...), nil } -func parseGPUOptCSV(value string) (*gpuReq, error) { +func ParseGPUOptCSV(value string) (*GpuReq, error) { csvReader := csv.NewReader(strings.NewReader(value)) fields, err := csvReader.Read() if err != nil { @@ -100,7 +100,7 @@ func parseGPUOptCSV(value string) (*gpuReq, error) { } var ( - req gpuReq + req GpuReq seen = map[string]struct{}{} ) for _, field := range fields { @@ -113,7 +113,7 @@ func parseGPUOptCSV(value string) (*gpuReq, error) { if len(parts) == 1 { seen["count"] = struct{}{} - req.count, err = parseCount(key) + req.Count, err = parseCount(key) if err != nil { return nil, err } @@ -127,14 +127,14 @@ func parseGPUOptCSV(value string) (*gpuReq, error) { return nil, fmt.Errorf("invalid driver %q: \"nvidia\" is only supported", value) } case "count": - req.count, err = parseCount(value) + req.Count, err = parseCount(value) if err != nil { return nil, err } case "device": - req.deviceIDs = strings.Split(value, ",") + req.DeviceIDs = strings.Split(value, ",") case "capabilities": - req.capabilities = strings.Split(value, ",") + req.Capabilities = strings.Split(value, ",") case "options": // This option is allowed but not used for gpus. // Please see also: https://github.com/moby/moby/pull/38828 @@ -143,11 +143,11 @@ func parseGPUOptCSV(value string) (*gpuReq, error) { } } - if req.count != 0 && len(req.deviceIDs) > 0 { + if req.Count != 0 && len(req.DeviceIDs) > 0 { return nil, errors.New("cannot set both Count and DeviceIDs on device request") } - if _, ok := seen["count"]; !ok && len(req.deviceIDs) == 0 { - req.count = 1 + if _, ok := seen["count"]; !ok && len(req.DeviceIDs) == 0 { + req.Count = 1 } return &req, nil diff --git a/cmd/nerdctl/run_linux.go b/cmd/nerdctl/utils/run/run_linux.go similarity index 87% rename from cmd/nerdctl/run_linux.go rename to cmd/nerdctl/utils/run/run_linux.go index 94b4b2938a0..1b09c2387e2 100644 --- a/cmd/nerdctl/run_linux.go +++ b/cmd/nerdctl/utils/run/run_linux.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package run import ( "context" @@ -24,8 +24,8 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/containers" "github.com/containerd/containerd/oci" - "github.com/containerd/containerd/pkg/cap" "github.com/containerd/containerd/pkg/userns" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" "github.com/containerd/nerdctl/pkg/bypass4netnsutil" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" "github.com/containerd/nerdctl/pkg/rootlessutil" @@ -36,28 +36,7 @@ import ( "github.com/spf13/cobra" ) -func WithoutRunMount() func(ctx context.Context, client oci.Client, c *containers.Container, s *oci.Spec) error { - return oci.WithoutRunMount -} - -func capShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - candidates := []string{} - for _, c := range cap.Known() { - // "CAP_SYS_ADMIN" -> "sys_admin" - s := strings.ToLower(strings.TrimPrefix(c, "CAP_")) - candidates = append(candidates, s) - } - return candidates, cobra.ShellCompDirectiveNoFileComp -} - -func runShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - if len(args) == 0 { - return shellCompleteImageNames(cmd) - } - return nil, cobra.ShellCompDirectiveNoFileComp -} - -func setPlatformOptions(ctx context.Context, opts []oci.SpecOpts, cmd *cobra.Command, client *containerd.Client, id string, internalLabels internalLabels) ([]oci.SpecOpts, internalLabels, error) { +func SetPlatformOptions(ctx context.Context, opts []oci.SpecOpts, cmd *cobra.Command, client *containerd.Client, id string, internalLabels common.InternalLabels) ([]oci.SpecOpts, common.InternalLabels, error) { opts = append(opts, oci.WithDefaultUnixDevices, WithoutRunMount(), // unmount default tmpfs on "/run": https://github.com/containerd/nerdctl/issues/157) @@ -74,7 +53,7 @@ func setPlatformOptions(ctx context.Context, opts []oci.SpecOpts, cmd *cobra.Com } opts = append(opts, cgOpts...) - labelsMap, err := readKVStringsMapfFromLabel(cmd) + labelsMap, err := common.ReadKVStringsMapfFromLabel(cmd) if err != nil { return nil, internalLabels, err } @@ -137,7 +116,7 @@ func setPlatformOptions(ctx context.Context, opts []oci.SpecOpts, cmd *cobra.Com if err != nil { return nil, internalLabels, err } - internalLabels.pidContainer = pidInternalLabel + internalLabels.PidContainer = pidInternalLabel opts = append(opts, pidOpts...) ulimitOpts, err := generateUlimitsOpts(cmd) @@ -175,7 +154,7 @@ func setPlatformOptions(ctx context.Context, opts []oci.SpecOpts, cmd *cobra.Com // if nothing is specified, or if private, default to normal behavior if ipc == "host" { opts = append(opts, oci.WithHostNamespace(specs.IPCNamespace)) - opts = append(opts, withBindMountHostIPC) + opts = append(opts, WithBindMountHostIPC) } else if ipc != "" && ipc != "private" { return nil, internalLabels, fmt.Errorf("error: %v", "invalid ipc value, supported values are 'private' or 'host'") } @@ -239,7 +218,7 @@ func generatePIDOpts(ctx context.Context, client *containerd.Client, pid string) case "host": opts = append(opts, oci.WithHostNamespace(specs.PIDNamespace)) if rootlessutil.IsRootless() { - opts = append(opts, withBindMountHostProcfs) + opts = append(opts, WithBindMountHostProcfs) } default: // container: parsed := strings.Split(pid, ":") @@ -255,7 +234,7 @@ func generatePIDOpts(ctx context.Context, client *containerd.Client, pid string) return fmt.Errorf("multiple IDs found with provided prefix: %s", found.Req) } - o, err := generateSharingPIDOpts(ctx, found.Container) + o, err := GenerateSharingPIDOpts(ctx, found.Container) if err != nil { return err } @@ -276,3 +255,7 @@ func generatePIDOpts(ctx context.Context, client *containerd.Client, pid string) return opts, pidInternalLabel, nil } + +func WithoutRunMount() func(ctx context.Context, client oci.Client, c *containers.Container, s *oci.Spec) error { + return oci.WithoutRunMount +} diff --git a/cmd/nerdctl/run_network.go b/cmd/nerdctl/utils/run/run_network.go similarity index 87% rename from cmd/nerdctl/run_network.go rename to cmd/nerdctl/utils/run/run_network.go index fe41fa46c3e..2c1024d75cf 100644 --- a/cmd/nerdctl/run_network.go +++ b/cmd/nerdctl/utils/run/run_network.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package run import ( "context" @@ -29,7 +29,9 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/containers" "github.com/containerd/containerd/oci" - gocni "github.com/containerd/go-cni" + "github.com/containerd/go-cni" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" "github.com/containerd/nerdctl/pkg/dnsutil" "github.com/containerd/nerdctl/pkg/dnsutil/hostsstore" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" @@ -45,7 +47,19 @@ import ( "github.com/spf13/cobra" ) -func getNetworkSlice(cmd *cobra.Command) ([]string, error) { +func WithCustomEtcHostname(src string) func(context.Context, oci.Client, *containers.Container, *oci.Spec) error { + return func(_ context.Context, _ oci.Client, _ *containers.Container, s *oci.Spec) error { + s.Mounts = append(s.Mounts, specs.Mount{ + Destination: "/etc/hostname", + Type: "bind", + Source: src, + Options: []string{"bind", mountutil.DefaultPropagationMode}, // writable + }) + return nil + } +} + +func GetNetworkSlice(cmd *cobra.Command) ([]string, error) { var netSlice = []string{} var networkSet = false if cmd.Flags().Lookup("network").Changed { @@ -75,7 +89,7 @@ func getNetworkSlice(cmd *cobra.Command) ([]string, error) { return netSlice, nil } -func withCustomResolvConf(src string) func(context.Context, oci.Client, *containers.Container, *oci.Spec) error { +func WithCustomResolvConf(src string) func(context.Context, oci.Client, *containers.Container, *oci.Spec) error { return func(_ context.Context, _ oci.Client, _ *containers.Container, s *oci.Spec) error { s.Mounts = append(s.Mounts, specs.Mount{ Destination: "/etc/resolv.conf", @@ -87,19 +101,7 @@ func withCustomResolvConf(src string) func(context.Context, oci.Client, *contain } } -func withCustomEtcHostname(src string) func(context.Context, oci.Client, *containers.Container, *oci.Spec) error { - return func(_ context.Context, _ oci.Client, _ *containers.Container, s *oci.Spec) error { - s.Mounts = append(s.Mounts, specs.Mount{ - Destination: "/etc/hostname", - Type: "bind", - Source: src, - Options: []string{"bind", mountutil.DefaultPropagationMode}, // writable - }) - return nil - } -} - -func withCustomHosts(src string) func(context.Context, oci.Client, *containers.Container, *oci.Spec) error { +func WithCustomHosts(src string) func(context.Context, oci.Client, *containers.Container, *oci.Spec) error { return func(_ context.Context, _ oci.Client, _ *containers.Container, s *oci.Spec) error { s.Mounts = append(s.Mounts, specs.Mount{ Destination: "/etc/hosts", @@ -111,7 +113,7 @@ func withCustomHosts(src string) func(context.Context, oci.Client, *containers.C } } -func generateNetOpts(cmd *cobra.Command, dataStore, stateDir, ns, id string) ([]oci.SpecOpts, []string, string, []gocni.PortMapping, string, error) { +func GenerateNetOpts(cmd *cobra.Command, dataStore, stateDir, ns, id string) ([]oci.SpecOpts, []string, string, []cni.PortMapping, string, error) { opts := []oci.SpecOpts{} portSlice, err := cmd.Flags().GetStringSlice("publish") if err != nil { @@ -121,7 +123,7 @@ func generateNetOpts(cmd *cobra.Command, dataStore, stateDir, ns, id string) ([] if err != nil { return nil, nil, "", nil, "", err } - netSlice, err := getNetworkSlice(cmd) + netSlice, err := GetNetworkSlice(cmd) if err != nil { return nil, nil, "", nil, "", err } @@ -130,12 +132,12 @@ func generateNetOpts(cmd *cobra.Command, dataStore, stateDir, ns, id string) ([] logrus.Warnf("You have assign an IP address %s but no network, So we will use the default network", ipAddress) } - macAddress, err := getMACAddress(cmd, netSlice) + macAddress, err := GetMACAddress(cmd, netSlice) if err != nil { return nil, nil, "", nil, "", err } - ports := make([]gocni.PortMapping, 0) + ports := make([]cni.PortMapping, 0) netType, err := nettype.Detect(netSlice) if err != nil { return nil, nil, "", nil, "", err @@ -154,13 +156,13 @@ func generateNetOpts(cmd *cobra.Command, dataStore, stateDir, ns, id string) ([] case nettype.CNI: // We only verify flags and generate resolv.conf here. // The actual network is configured in the oci hook. - if err := verifyCNINetwork(cmd, netSlice, macAddress); err != nil { + if err := VerifyCNINetwork(cmd, netSlice, macAddress); err != nil { return nil, nil, "", nil, "", err } if runtime.GOOS == "linux" { resolvConfPath := filepath.Join(stateDir, "resolv.conf") - if err := buildResolvConf(cmd, resolvConfPath); err != nil { + if err := BuildResolvConf(cmd, resolvConfPath); err != nil { return nil, nil, "", nil, "", err } @@ -169,7 +171,7 @@ func generateNetOpts(cmd *cobra.Command, dataStore, stateDir, ns, id string) ([] if err != nil { return nil, nil, "", nil, "", err } - opts = append(opts, withCustomResolvConf(resolvConfPath), withCustomHosts(etcHostsPath)) + opts = append(opts, WithCustomResolvConf(resolvConfPath), WithCustomHosts(etcHostsPath)) for _, p := range portSlice { pm, err := portutil.ParseFlagP(p) if err != nil { @@ -182,7 +184,7 @@ func generateNetOpts(cmd *cobra.Command, dataStore, stateDir, ns, id string) ([] if macAddress != "" { return nil, nil, "", nil, "", errors.New("conflicting options: mac-address and the network mode") } - if err := verifyContainerNetwork(cmd, netSlice); err != nil { + if err := VerifyContainerNetwork(cmd, netSlice); err != nil { return nil, nil, "", nil, "", err } network := strings.Split(netSlice[0], ":") @@ -190,7 +192,7 @@ func generateNetOpts(cmd *cobra.Command, dataStore, stateDir, ns, id string) ([] return nil, nil, "", nil, "", fmt.Errorf("invalid network: %s, should be \"container:\"", netSlice[0]) } containerName := network[1] - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return nil, nil, "", nil, "", err } @@ -204,7 +206,7 @@ func generateNetOpts(cmd *cobra.Command, dataStore, stateDir, ns, id string) ([] } containerID := found.Container.ID() - conStateDir, err := getContainerStateDirPath(cmd, dataStore, containerID) + conStateDir, err := common.GetContainerStateDirPath(cmd, dataStore, containerID) if err != nil { return err } @@ -217,7 +219,7 @@ func generateNetOpts(cmd *cobra.Command, dataStore, stateDir, ns, id string) ([] hostnamePath := filepath.Join(conStateDir, "hostname") resolvConfPath := filepath.Join(conStateDir, "resolv.conf") etcHostsPath := hostsstore.HostsPath(dataStore, ns, containerID) - netNSPath, err := getContainerNetNSPath(ctx, found.Container) + netNSPath, err := GetContainerNetNSPath(ctx, found.Container) if err != nil { return err } @@ -226,10 +228,10 @@ func generateNetOpts(cmd *cobra.Command, dataStore, stateDir, ns, id string) ([] Type: specs.NetworkNamespace, Path: netNSPath, }), - withCustomResolvConf(resolvConfPath), - withCustomHosts(etcHostsPath), + WithCustomResolvConf(resolvConfPath), + WithCustomHosts(etcHostsPath), oci.WithHostname(hostname), - withCustomEtcHostname(hostnamePath), + WithCustomEtcHostname(hostnamePath), ) // stored in labels with key "nerdctl/networks" netSlice = []string{fmt.Sprintf("container:%s", containerID)} @@ -249,7 +251,7 @@ func generateNetOpts(cmd *cobra.Command, dataStore, stateDir, ns, id string) ([] return opts, netSlice, ipAddress, ports, macAddress, nil } -func getContainerNetNSPath(ctx context.Context, c containerd.Container) (string, error) { +func GetContainerNetNSPath(ctx context.Context, c containerd.Container) (string, error) { task, err := c.Task(ctx, nil) if err != nil { return "", err @@ -264,7 +266,7 @@ func getContainerNetNSPath(ctx context.Context, c containerd.Container) (string, return fmt.Sprintf("/proc/%d/ns/net", task.Pid()), nil } -func verifyCNINetwork(cmd *cobra.Command, netSlice []string, macAddress string) error { +func VerifyCNINetwork(cmd *cobra.Command, netSlice []string, macAddress string) error { cniPath, err := cmd.Flags().GetString("cni-path") if err != nil { return err @@ -297,7 +299,7 @@ func verifyCNINetwork(cmd *cobra.Command, netSlice []string, macAddress string) return nil } -func verifyContainerNetwork(cmd *cobra.Command, netSlice []string) error { +func VerifyContainerNetwork(cmd *cobra.Command, netSlice []string) error { if cmd.Flags().Changed("publish") { return fmt.Errorf("conflicting options: port publishing and the container type network mode") } @@ -319,7 +321,7 @@ func verifyContainerNetwork(cmd *cobra.Command, netSlice []string) error { return nil } -func buildResolvConf(cmd *cobra.Command, resolvConfPath string) error { +func BuildResolvConf(cmd *cobra.Command, resolvConfPath string) error { dnsValue, err := cmd.Flags().GetStringSlice("dns") if err != nil { return err @@ -385,7 +387,7 @@ func buildResolvConf(cmd *cobra.Command, resolvConfPath string) error { return nil } -func getMACAddress(cmd *cobra.Command, netSlice []string) (string, error) { +func GetMACAddress(cmd *cobra.Command, netSlice []string) (string, error) { macAddress, err := cmd.Flags().GetString("mac-address") if err != nil { return "", err diff --git a/cmd/nerdctl/run_restart.go b/cmd/nerdctl/utils/run/run_restart.go similarity index 93% rename from cmd/nerdctl/run_restart.go rename to cmd/nerdctl/utils/run/run_restart.go index 7c60b2c9bd4..7a5e4331946 100644 --- a/cmd/nerdctl/run_restart.go +++ b/cmd/nerdctl/utils/run/run_restart.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package run import ( "context" @@ -27,7 +27,7 @@ import ( "github.com/containerd/nerdctl/pkg/strutil" ) -func generateRestartOpts(ctx context.Context, client *containerd.Client, restartFlag, logURI string) ([]containerd.NewContainerOpts, error) { +func GenerateRestartOpts(ctx context.Context, client *containerd.Client, restartFlag, logURI string) ([]containerd.NewContainerOpts, error) { policySlice := strings.Split(restartFlag, ":") switch policySlice[0] { case "", "no": @@ -59,7 +59,7 @@ func generateRestartOpts(ctx context.Context, client *containerd.Client, restart return opts, nil } -func updateContainerStoppedLabel(ctx context.Context, container containerd.Container, stopped bool) error { +func UpdateContainerStoppedLabel(ctx context.Context, container containerd.Container, stopped bool) error { opt := containerd.WithAdditionalContainerLabels(map[string]string{ restart.ExplicitlyStoppedLabel: strconv.FormatBool(stopped), }) diff --git a/cmd/nerdctl/run_runtime.go b/cmd/nerdctl/utils/run/run_runtime.go similarity index 86% rename from cmd/nerdctl/run_runtime.go rename to cmd/nerdctl/utils/run/run_runtime.go index c10f01b5bc8..1532b2194c0 100644 --- a/cmd/nerdctl/run_runtime.go +++ b/cmd/nerdctl/utils/run/run_runtime.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package run import ( "context" @@ -24,16 +24,16 @@ import ( "github.com/containerd/containerd/containers" "github.com/containerd/containerd/oci" "github.com/containerd/containerd/plugin" - runcoptions "github.com/containerd/containerd/runtime/v2/runc/options" - runtimespec "github.com/opencontainers/runtime-spec/specs-go" + options2 "github.com/containerd/containerd/runtime/v2/runc/options" + "github.com/opencontainers/runtime-spec/specs-go" "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) -func generateRuntimeCOpts(cmd *cobra.Command) ([]containerd.NewContainerOpts, error) { +func GenerateRuntimeCOpts(cmd *cobra.Command) ([]containerd.NewContainerOpts, error) { runtime := plugin.RuntimeRuncV2 var ( - runcOpts runcoptions.Options + runcOpts options2.Options runtimeOpts interface{} = &runcOpts ) cgm, err := cmd.Flags().GetString("cgroup-manager") @@ -67,9 +67,9 @@ func generateRuntimeCOpts(cmd *cobra.Command) ([]containerd.NewContainerOpts, er // WithSysctls sets the provided sysctls onto the spec func WithSysctls(sysctls map[string]string) oci.SpecOpts { - return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) error { + return func(ctx context.Context, client oci.Client, c *containers.Container, s *specs.Spec) error { if s.Linux == nil { - s.Linux = &runtimespec.Linux{} + s.Linux = &specs.Linux{} } if s.Linux.Sysctl == nil { s.Linux.Sysctl = make(map[string]string) diff --git a/cmd/nerdctl/run_security_linux.go b/cmd/nerdctl/utils/run/run_security_linux.go similarity index 99% rename from cmd/nerdctl/run_security_linux.go rename to cmd/nerdctl/utils/run/run_security_linux.go index 7d89f682193..f160c14b883 100644 --- a/cmd/nerdctl/run_security_linux.go +++ b/cmd/nerdctl/utils/run/run_security_linux.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package run import ( "errors" diff --git a/cmd/nerdctl/utils/run/run_stargz_linux.go b/cmd/nerdctl/utils/run/run_stargz_linux.go new file mode 100644 index 00000000000..1ac5a92f8cb --- /dev/null +++ b/cmd/nerdctl/utils/run/run_stargz_linux.go @@ -0,0 +1,29 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package run + +import "github.com/containerd/nerdctl/pkg/testutil" + +func RequiresStargz(base *testutil.Base) { + info := base.Info() + for _, p := range info.Plugins.Storage { + if p == "stargz" { + return + } + } + base.T.Skip("test requires stargz") +} diff --git a/cmd/nerdctl/run_ulimit.go b/cmd/nerdctl/utils/run/run_ulimit.go similarity index 99% rename from cmd/nerdctl/run_ulimit.go rename to cmd/nerdctl/utils/run/run_ulimit.go index 41d86db82c0..cb0d0da0e44 100644 --- a/cmd/nerdctl/run_ulimit.go +++ b/cmd/nerdctl/utils/run/run_ulimit.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package run import ( "context" diff --git a/cmd/nerdctl/run_user.go b/cmd/nerdctl/utils/run/run_user.go similarity index 85% rename from cmd/nerdctl/run_user.go rename to cmd/nerdctl/utils/run/run_user.go index 5ecffc67a22..0fc977de8da 100644 --- a/cmd/nerdctl/run_user.go +++ b/cmd/nerdctl/utils/run/run_user.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package run import ( "context" @@ -26,35 +26,26 @@ import ( "github.com/spf13/cobra" ) -func generateUserOpts(cmd *cobra.Command) ([]oci.SpecOpts, error) { +func GenerateUserOpts(cmd *cobra.Command) ([]oci.SpecOpts, error) { var opts []oci.SpecOpts user, err := cmd.Flags().GetString("user") if err != nil { return nil, err } if user != "" { - opts = append(opts, oci.WithUser(user), withResetAdditionalGIDs(), oci.WithAdditionalGIDs(user)) + opts = append(opts, oci.WithUser(user), WithResetAdditionalGIDs(), oci.WithAdditionalGIDs(user)) } return opts, nil } -func generateUmaskOpts(cmd *cobra.Command) ([]oci.SpecOpts, error) { - var opts []oci.SpecOpts - umask, err := cmd.Flags().GetString("umask") - if err != nil { - return nil, err - } - if cmd.Flags().Changed("umask") && umask != "" { - decVal, err := strconv.ParseUint(umask, 8, 32) - if err != nil { - return nil, fmt.Errorf("invalid Umask Value:%s", umask) - } - opts = append(opts, withAdditionalUmask(uint32(decVal))) +func WithResetAdditionalGIDs() oci.SpecOpts { + return func(_ context.Context, _ oci.Client, _ *containers.Container, s *oci.Spec) error { + s.Process.User.AdditionalGids = nil + return nil } - return opts, nil } -func generateGroupsOpts(cmd *cobra.Command) ([]oci.SpecOpts, error) { +func GenerateGroupsOpts(cmd *cobra.Command) ([]oci.SpecOpts, error) { var opts []oci.SpecOpts groups, err := cmd.Flags().GetStringSlice("group-add") if err != nil { @@ -66,11 +57,20 @@ func generateGroupsOpts(cmd *cobra.Command) ([]oci.SpecOpts, error) { return opts, nil } -func withResetAdditionalGIDs() oci.SpecOpts { - return func(_ context.Context, _ oci.Client, _ *containers.Container, s *oci.Spec) error { - s.Process.User.AdditionalGids = nil - return nil +func GenerateUmaskOpts(cmd *cobra.Command) ([]oci.SpecOpts, error) { + var opts []oci.SpecOpts + umask, err := cmd.Flags().GetString("umask") + if err != nil { + return nil, err } + if cmd.Flags().Changed("umask") && umask != "" { + decVal, err := strconv.ParseUint(umask, 8, 32) + if err != nil { + return nil, fmt.Errorf("invalid Umask Value:%s", umask) + } + opts = append(opts, withAdditionalUmask(uint32(decVal))) + } + return opts, nil } func withAdditionalUmask(umask uint32) oci.SpecOpts { diff --git a/cmd/nerdctl/run_windows.go b/cmd/nerdctl/utils/run/run_windows.go similarity index 77% rename from cmd/nerdctl/run_windows.go rename to cmd/nerdctl/utils/run/run_windows.go index 813570b37d8..05de52b1859 100644 --- a/cmd/nerdctl/run_windows.go +++ b/cmd/nerdctl/utils/run/run_windows.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package run import ( "context" @@ -23,25 +23,12 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/containers" "github.com/containerd/containerd/oci" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" "github.com/docker/go-units" "github.com/spf13/cobra" ) -func WithoutRunMount() func(ctx context.Context, client oci.Client, c *containers.Container, s *oci.Spec) error { - // not valid on windows - return func(_ context.Context, _ oci.Client, _ *containers.Container, s *oci.Spec) error { return nil } -} - -func capShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - candidates := []string{} - return candidates, cobra.ShellCompDirectiveNoFileComp -} - -func runShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return nil, cobra.ShellCompDirectiveNoFileComp -} - -func setPlatformOptions(ctx context.Context, opts []oci.SpecOpts, cmd *cobra.Command, client *containerd.Client, id string, internalLabels internalLabels) ([]oci.SpecOpts, internalLabels, error) { +func SetPlatformOptions(ctx context.Context, opts []oci.SpecOpts, cmd *cobra.Command, client *containerd.Client, id string, internalLabels common.InternalLabels) ([]oci.SpecOpts, common.InternalLabels, error) { cpus, err := cmd.Flags().GetFloat64("cpus") if err != nil { return nil, internalLabels, err @@ -68,3 +55,8 @@ func setPlatformOptions(ctx context.Context, opts []oci.SpecOpts, cmd *cobra.Com return opts, internalLabels, nil } + +func WithoutRunMount() func(ctx context.Context, client oci.Client, c *containers.Container, s *oci.Spec) error { + // not valid on windows + return func(_ context.Context, _ oci.Client, _ *containers.Container, s *oci.Spec) error { return nil } +} diff --git a/cmd/nerdctl/save_linux_test.go b/cmd/nerdctl/utils/save_linux.go similarity index 62% rename from cmd/nerdctl/save_linux_test.go rename to cmd/nerdctl/utils/save_linux.go index c2970a9f04c..ba6cfb4db44 100644 --- a/cmd/nerdctl/save_linux_test.go +++ b/cmd/nerdctl/utils/save_linux.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package utils import ( "encoding/json" @@ -23,32 +23,11 @@ import ( "os" "os/exec" "path/filepath" - "strings" - "testing" - "github.com/containerd/nerdctl/pkg/testutil" - - "gotest.tools/v3/assert" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" ) -func TestSave(t *testing.T) { - base := testutil.NewBase(t) - base.Cmd("pull", testutil.AlpineImage).AssertOK() - archiveTarPath := filepath.Join(t.TempDir(), "a.tar") - base.Cmd("save", "-o", archiveTarPath, testutil.AlpineImage).AssertOK() - rootfsPath := filepath.Join(t.TempDir(), "rootfs") - err := extractDockerArchive(archiveTarPath, rootfsPath) - assert.NilError(t, err) - etcOSReleasePath := filepath.Join(rootfsPath, "/etc/os-release") - etcOSReleaseBytes, err := os.ReadFile(etcOSReleasePath) - assert.NilError(t, err) - etcOSRelease := string(etcOSReleaseBytes) - t.Logf("read %q, extracted from %q", etcOSReleasePath, testutil.AlpineImage) - t.Log(etcOSRelease) - assert.Assert(t, strings.Contains(etcOSRelease, "Alpine")) -} - -func extractDockerArchive(archiveTarPath, rootfsPath string) error { +func ExtractDockerArchive(archiveTarPath, rootfsPath string) error { if err := os.MkdirAll(rootfsPath, 0755); err != nil { return err } @@ -65,7 +44,7 @@ func extractDockerArchive(archiveTarPath, rootfsPath string) error { if err != nil { return err } - var mani DockerArchiveManifestJSON + var mani common.DockerArchiveManifestJSON if err := json.Unmarshal(manifestJSONBytes, &mani); err != nil { return err } @@ -85,14 +64,6 @@ func extractDockerArchive(archiveTarPath, rootfsPath string) error { return nil } -type DockerArchiveManifestJSON []DockerArchiveManifestJSONEntry - -type DockerArchiveManifestJSONEntry struct { - Config string - RepoTags []string - Layers []string -} - func extractTarFile(dirPath, tarFilePath string) error { cmd := exec.Command("tar", "Cxf", dirPath, tarFilePath) if out, err := cmd.CombinedOutput(); err != nil { diff --git a/cmd/nerdctl/top.go b/cmd/nerdctl/utils/top.go similarity index 71% rename from cmd/nerdctl/top.go rename to cmd/nerdctl/utils/top.go index 4f9bf852b9d..2a633c56aea 100644 --- a/cmd/nerdctl/top.go +++ b/cmd/nerdctl/utils/top.go @@ -14,16 +14,7 @@ limitations under the License. */ -/* - Portions from: - - https://github.com/moby/moby/blob/v20.10.6/api/types/container/container_top.go - - https://github.com/moby/moby/blob/v20.10.6/daemon/top_unix.go - Copyright (C) The Moby authors. - Licensed under the Apache License, Version 2.0 - NOTICE: https://github.com/moby/moby/blob/v20.10.6/NOTICE -*/ - -package main +package utils import ( "bytes" @@ -37,10 +28,6 @@ import ( "text/tabwriter" "github.com/containerd/containerd" - "github.com/containerd/nerdctl/pkg/idutil/containerwalker" - "github.com/containerd/nerdctl/pkg/infoutil" - "github.com/containerd/nerdctl/pkg/rootlessutil" - "github.com/spf13/cobra" ) @@ -60,63 +47,6 @@ type ContainerTopOKBody struct { Titles []string `json:"Titles"` } -func newTopCommand() *cobra.Command { - var topCommand = &cobra.Command{ - Use: "top CONTAINER [ps OPTIONS]", - Args: cobra.MinimumNArgs(1), - Short: "Display the running processes of a container", - RunE: topAction, - ValidArgsFunction: topShellComplete, - SilenceUsage: true, - SilenceErrors: true, - } - topCommand.Flags().SetInterspersed(false) - return topCommand -} - -func topAction(cmd *cobra.Command, args []string) error { - // NOTE: rootless container does not rely on cgroupv1. - // more details about possible ways to resolve this concern: #223 - if rootlessutil.IsRootless() && infoutil.CgroupsVersion() == "1" { - return fmt.Errorf("top requires cgroup v2 for rootless containers, see https://rootlesscontaine.rs/getting-started/common/cgroup2/") - } - - cgroupManager, err := cmd.Flags().GetString("cgroup-manager") - if err != nil { - return err - } - if cgroupManager == "none" { - return errors.New("cgroup manager must not be \"none\"") - } - - client, ctx, cancel, err := newClient(cmd) - if err != nil { - return err - } - defer cancel() - - walker := &containerwalker.ContainerWalker{ - Client: client, - OnFound: func(ctx context.Context, found containerwalker.Found) error { - if found.MatchCount > 1 { - return fmt.Errorf("multiple IDs found with provided prefix: %s", found.Req) - } - if err := containerTop(ctx, cmd, client, found.Container.ID(), strings.Join(args[1:], " ")); err != nil { - return err - } - return nil - }, - } - - n, err := walker.Walk(ctx, args[0]) - if err != nil { - return err - } else if n == 0 { - return fmt.Errorf("no such container %s", args[0]) - } - return nil -} - // appendProcess2ProcList is from https://github.com/moby/moby/blob/v20.10.6/daemon/top_unix.go#L49-L55 func appendProcess2ProcList(procList *ContainerTopOKBody, fields []string) { // Make sure number of fields equals number of header titles @@ -239,14 +169,14 @@ func parsePSOutput(output []byte, procs []uint32) (*ContainerTopOKBody, error) { return procList, nil } -// containerTop was inspired from https://github.com/moby/moby/blob/v20.10.6/daemon/top_unix.go#L133-L189 +// ContainerTop was inspired from https://github.com/moby/moby/blob/v20.10.6/daemon/top_unix.go#L133-L189 // // ContainerTop lists the processes running inside of the given // container by calling ps with the given args, or with the flags // "-ef" if no args are given. An error is returned if the container // is not found, or is not running, or if there are any problems // running ps, or parsing the output. -func containerTop(ctx context.Context, cmd *cobra.Command, client *containerd.Client, id string, psArgs string) error { +func ContainerTop(ctx context.Context, cmd *cobra.Command, client *containerd.Client, id string, psArgs string) error { if psArgs == "" { psArgs = "-ef" } @@ -318,11 +248,3 @@ func containerTop(ctx context.Context, cmd *cobra.Command, client *containerd.Cl return w.Flush() } - -func topShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - // show running container names - statusFilterFn := func(st containerd.ProcessStatus) bool { - return st == containerd.Running - } - return shellCompleteContainerNames(cmd, statusFilterFn) -} diff --git a/cmd/nerdctl/utils/unpause.go b/cmd/nerdctl/utils/unpause.go new file mode 100644 index 00000000000..55ee687e785 --- /dev/null +++ b/cmd/nerdctl/utils/unpause.go @@ -0,0 +1,49 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package utils + +import ( + "context" + "fmt" + + "github.com/containerd/containerd" + "github.com/containerd/containerd/cio" +) + +func UnpauseContainer(ctx context.Context, client *containerd.Client, id string) error { + container, err := client.LoadContainer(ctx, id) + if err != nil { + return err + } + + task, err := container.Task(ctx, cio.Load) + if err != nil { + return err + } + + status, err := task.Status(ctx) + if err != nil { + return err + } + + switch status.Status { + case containerd.Paused: + return task.Resume(ctx) + default: + return fmt.Errorf("container %s is not paused", id) + } +} diff --git a/cmd/nerdctl/utils/volume/volume.go b/cmd/nerdctl/utils/volume/volume.go new file mode 100644 index 00000000000..ac88a167013 --- /dev/null +++ b/cmd/nerdctl/utils/volume/volume.go @@ -0,0 +1,95 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package volume + +import ( + "encoding/json" + + "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/pkg/inspecttypes/native" + "github.com/containerd/nerdctl/pkg/labels" + "github.com/containerd/nerdctl/pkg/mountutil/volumestore" + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" +) + +type ContainerVolume struct { + Type string + Name string + Source string + Destination string + Mode string + RW bool + Propagation string +} + +// GetVolumeStore returns a volume store +// that corresponds to a directory like `/var/lib/nerdctl/1935db59/volume/default` +func GetVolumeStore(cmd *cobra.Command) (volumestore.VolumeStore, error) { + ns, err := cmd.Flags().GetString("namespace") + if err != nil { + return nil, err + } + dataStore, err := client.GetDataStore(cmd) + if err != nil { + return nil, err + } + return volumestore.New(dataStore, ns) +} + +func GetVolumes(cmd *cobra.Command) (map[string]native.Volume, error) { + volStore, err := GetVolumeStore(cmd) + if err != nil { + return nil, err + } + volumeSize, err := cmd.Flags().GetBool("size") + if err != nil { + return nil, err + } + return volStore.List(volumeSize) +} + +func GetContainerVolumes(containerLabels map[string]string) []*ContainerVolume { + var vols []*ContainerVolume + volLabels := []string{labels.AnonymousVolumes, labels.Mounts} + for _, volLabel := range volLabels { + names, ok := containerLabels[volLabel] + if !ok { + continue + } + var ( + volumes []*ContainerVolume + err error + ) + if volLabel == labels.Mounts { + err = json.Unmarshal([]byte(names), &volumes) + } + if volLabel == labels.AnonymousVolumes { + var anonymous []string + err = json.Unmarshal([]byte(names), &anonymous) + for _, anony := range anonymous { + volumes = append(volumes, &ContainerVolume{Name: anony}) + } + + } + if err != nil { + logrus.Warn(err) + } + vols = append(vols, volumes...) + } + return vols +} diff --git a/cmd/nerdctl/version.go b/cmd/nerdctl/version/version.go similarity index 91% rename from cmd/nerdctl/version.go rename to cmd/nerdctl/version/version.go index 15915173439..c7104e7e0ca 100644 --- a/cmd/nerdctl/version.go +++ b/cmd/nerdctl/version/version.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package version import ( "bytes" @@ -23,12 +23,14 @@ import ( "os" "text/template" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/fmtutil" "github.com/containerd/nerdctl/pkg/infoutil" "github.com/containerd/nerdctl/pkg/inspecttypes/dockercompat" "github.com/spf13/cobra" ) -func newVersionCommand() *cobra.Command { +func NewVersionCommand() *cobra.Command { var versionCommand = &cobra.Command{ Use: "version", Args: cobra.NoArgs, @@ -54,7 +56,7 @@ func versionAction(cmd *cobra.Command, args []string) error { } if format != "" { var err error - tmpl, err = parseTemplate(format) + tmpl, err = fmtutil.ParseTemplate(format) if err != nil { return err } @@ -101,7 +103,7 @@ func versionInfo(cmd *cobra.Command) (dockercompat.VersionInfo, error) { v := dockercompat.VersionInfo{ Client: infoutil.ClientVersion(), } - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return v, err } diff --git a/cmd/nerdctl/volume.go b/cmd/nerdctl/volume.go deleted file mode 100644 index 912f50a2e2b..00000000000 --- a/cmd/nerdctl/volume.go +++ /dev/null @@ -1,55 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package main - -import ( - "github.com/containerd/nerdctl/pkg/mountutil/volumestore" - "github.com/spf13/cobra" -) - -func newVolumeCommand() *cobra.Command { - volumeCommand := &cobra.Command{ - Annotations: map[string]string{Category: Management}, - Use: "volume", - Short: "Manage volumes", - RunE: unknownSubcommandAction, - SilenceUsage: true, - SilenceErrors: true, - } - volumeCommand.AddCommand( - newVolumeLsCommand(), - newVolumeInspectCommand(), - newVolumeCreateCommand(), - newVolumeRmCommand(), - newVolumePruneCommand(), - ) - return volumeCommand -} - -// getVolumeStore returns a volume store -// that corresponds to a directory like `/var/lib/nerdctl/1935db59/volumes/default` -func getVolumeStore(cmd *cobra.Command) (volumestore.VolumeStore, error) { - ns, err := cmd.Flags().GetString("namespace") - if err != nil { - return nil, err - } - dataStore, err := getDataStore(cmd) - if err != nil { - return nil, err - } - return volumestore.New(dataStore, ns) -} diff --git a/cmd/nerdctl/volume/volume.go b/cmd/nerdctl/volume/volume.go new file mode 100644 index 00000000000..5cdaf376b63 --- /dev/null +++ b/cmd/nerdctl/volume/volume.go @@ -0,0 +1,42 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package volume + +import ( + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" + "github.com/spf13/cobra" +) + +func NewVolumeCommand() *cobra.Command { + volumeCommand := &cobra.Command{ + Annotations: map[string]string{common.Category: common.Management}, + Use: "volume", + Short: "Manage volume", + RunE: completion.UnknownSubcommandAction, + SilenceUsage: true, + SilenceErrors: true, + } + volumeCommand.AddCommand( + NewVolumeLsCommand(), + NewVolumeInspectCommand(), + NewVolumeCreateCommand(), + NewVolumeRmCommand(), + NewVolumePruneCommand(), + ) + return volumeCommand +} diff --git a/cmd/nerdctl/volume_create.go b/cmd/nerdctl/volume/volume_create.go similarity index 85% rename from cmd/nerdctl/volume_create.go rename to cmd/nerdctl/volume/volume_create.go index db832c15df6..a7b84dea08a 100644 --- a/cmd/nerdctl/volume_create.go +++ b/cmd/nerdctl/volume/volume_create.go @@ -14,22 +14,24 @@ limitations under the License. */ -package main +package volume import ( "fmt" "github.com/containerd/containerd/identifiers" + "github.com/containerd/nerdctl/cmd/nerdctl/utils" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/volume" "github.com/containerd/nerdctl/pkg/strutil" "github.com/spf13/cobra" ) -func newVolumeCreateCommand() *cobra.Command { +func NewVolumeCreateCommand() *cobra.Command { volumeCreateCommand := &cobra.Command{ Use: "create [flags] VOLUME", Short: "Create a volume", - Args: IsExactArgs(1), + Args: utils.IsExactArgs(1), RunE: volumeCreateAction, SilenceUsage: true, SilenceErrors: true, @@ -44,7 +46,7 @@ func volumeCreateAction(cmd *cobra.Command, args []string) error { return fmt.Errorf("malformed name %s: %w", name, err) } - volStore, err := getVolumeStore(cmd) + volStore, err := volume.GetVolumeStore(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/volume_inspect.go b/cmd/nerdctl/volume/volume_inspect.go similarity index 84% rename from cmd/nerdctl/volume_inspect.go rename to cmd/nerdctl/volume/volume_inspect.go index 8fc19b458b4..cb82567b6b0 100644 --- a/cmd/nerdctl/volume_inspect.go +++ b/cmd/nerdctl/volume/volume_inspect.go @@ -14,13 +14,16 @@ limitations under the License. */ -package main +package volume import ( + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/fmtutil" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/volume" "github.com/spf13/cobra" ) -func newVolumeInspectCommand() *cobra.Command { +func NewVolumeInspectCommand() *cobra.Command { volumeInspectCommand := &cobra.Command{ Use: "inspect [flags] VOLUME [VOLUME...]", Short: "Display detailed information on one or more volumes", @@ -44,7 +47,7 @@ func volumeInspectAction(cmd *cobra.Command, args []string) error { return err } - volStore, err := getVolumeStore(cmd) + volStore, err := volume.GetVolumeStore(cmd) if err != nil { return err } @@ -58,10 +61,10 @@ func volumeInspectAction(cmd *cobra.Command, args []string) error { result[i] = vol } - return formatSlice(cmd, result) + return fmtutil.FormatSlice(cmd, result) } func volumeInspectShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show volume names - return shellCompleteVolumeNames(cmd) + return completion.ShellCompleteVolumeNames(cmd) } diff --git a/cmd/nerdctl/volume_ls.go b/cmd/nerdctl/volume/volume_ls.go similarity index 93% rename from cmd/nerdctl/volume_ls.go rename to cmd/nerdctl/volume/volume_ls.go index 3f38c921447..924646063cd 100644 --- a/cmd/nerdctl/volume_ls.go +++ b/cmd/nerdctl/volume/volume_ls.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package volume import ( "bytes" @@ -26,13 +26,15 @@ import ( "text/template" "github.com/containerd/containerd/pkg/progress" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/fmtutil" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/volume" "github.com/containerd/nerdctl/pkg/inspecttypes/native" "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) -func newVolumeLsCommand() *cobra.Command { +func NewVolumeLsCommand() *cobra.Command { volumeLsCommand := &cobra.Command{ Use: "ls", Aliases: []string{"list"}, @@ -116,13 +118,13 @@ func volumeLsAction(cmd *cobra.Command, args []string) error { return errors.New("format and quiet must not be specified together") } var err error - tmpl, err = parseTemplate(format) + tmpl, err = fmtutil.ParseTemplate(format) if err != nil { return err } } - vols, err := getVolumes(cmd) + vols, err := volume.GetVolumes(cmd) if err != nil { return err } @@ -139,7 +141,7 @@ func volumeLsAction(cmd *cobra.Command, args []string) error { Scope: "local", } if v.Labels != nil { - p.Labels = formatLabels(*v.Labels) + p.Labels = fmtutil.FormatLabels(*v.Labels) } if volumeSize { p.Size = progress.Bytes(v.Size).String() @@ -160,24 +162,12 @@ func volumeLsAction(cmd *cobra.Command, args []string) error { fmt.Fprintf(w, "%s\t%s\n", p.Name, p.Mountpoint) } } - if f, ok := w.(Flusher); ok { + if f, ok := w.(fmtutil.Flusher); ok { return f.Flush() } return nil } -func getVolumes(cmd *cobra.Command) (map[string]native.Volume, error) { - volStore, err := getVolumeStore(cmd) - if err != nil { - return nil, err - } - volumeSize, err := cmd.Flags().GetBool("size") - if err != nil { - return nil, err - } - return volStore.List(volumeSize) -} - func getVolumeFilterFuncs(filters []string) ([]func(*map[string]string) bool, []func(string) bool, []func(int64) bool, bool, error) { isFilter := len(filters) > 0 labelFilterFuncs := make([]func(*map[string]string) bool, 0) diff --git a/cmd/nerdctl/volume_prune.go b/cmd/nerdctl/volume/volume_prune.go similarity index 82% rename from cmd/nerdctl/volume_prune.go rename to cmd/nerdctl/volume/volume_prune.go index e6da1ceb345..825a46a7865 100644 --- a/cmd/nerdctl/volume_prune.go +++ b/cmd/nerdctl/volume/volume_prune.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package volume import ( "context" @@ -22,10 +22,12 @@ import ( "strings" "github.com/containerd/containerd" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/volume" "github.com/spf13/cobra" ) -func newVolumePruneCommand() *cobra.Command { +func NewVolumePruneCommand() *cobra.Command { volumePruneCommand := &cobra.Command{ Use: "prune [flags]", Short: "Remove all unused local volumes", @@ -46,7 +48,7 @@ func volumePruneAction(cmd *cobra.Command, _ []string) error { if !force { var confirm string - msg := "This will remove all local volumes not used by at least one container." + msg := "This will remove all local volume not used by at least one container." msg += "\nAre you sure you want to continue? [y/N] " fmt.Fprintf(cmd.OutOrStdout(), "WARNING! %s", msg) fmt.Fscanf(cmd.InOrStdin(), "%s", &confirm) @@ -56,17 +58,17 @@ func volumePruneAction(cmd *cobra.Command, _ []string) error { } } - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } defer cancel() - return volumePrune(ctx, cmd, client) + return Prune(ctx, cmd, client) } -func volumePrune(ctx context.Context, cmd *cobra.Command, client *containerd.Client) error { - volStore, err := getVolumeStore(cmd) +func Prune(ctx context.Context, cmd *cobra.Command, client *containerd.Client) error { + volStore, err := volume.GetVolumeStore(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/volume_rm.go b/cmd/nerdctl/volume/volume_rm.go similarity index 88% rename from cmd/nerdctl/volume_rm.go rename to cmd/nerdctl/volume/volume_rm.go index b1215c9f949..7d3ff1944ad 100644 --- a/cmd/nerdctl/volume_rm.go +++ b/cmd/nerdctl/volume/volume_rm.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package volume import ( "context" @@ -22,13 +22,16 @@ import ( "fmt" "github.com/containerd/containerd" + nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/volume" "github.com/containerd/nerdctl/pkg/inspecttypes/dockercompat" "github.com/containerd/nerdctl/pkg/labels" "github.com/containerd/nerdctl/pkg/mountutil" "github.com/spf13/cobra" ) -func newVolumeRmCommand() *cobra.Command { +func NewVolumeRmCommand() *cobra.Command { volumeRmCommand := &cobra.Command{ Use: "rm [flags] VOLUME [VOLUME...]", Aliases: []string{"remove"}, @@ -45,7 +48,7 @@ func newVolumeRmCommand() *cobra.Command { } func volumeRmAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := newClient(cmd) + client, ctx, cancel, err := nerdClient.NewClient(cmd) if err != nil { return err } @@ -54,7 +57,7 @@ func volumeRmAction(cmd *cobra.Command, args []string) error { if err != nil { return err } - volStore, err := getVolumeStore(cmd) + volStore, err := volume.GetVolumeStore(cmd) if err != nil { return err } @@ -87,7 +90,7 @@ func volumeRmAction(cmd *cobra.Command, args []string) error { func volumeRmShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show volume names - return shellCompleteVolumeNames(cmd) + return completion.ShellCompleteVolumeNames(cmd) } func usedVolumes(ctx context.Context, containers []containerd.Container) (map[string]struct{}, error) { diff --git a/cmd/nerdctl/build_test.go b/integration/build_test.go similarity index 93% rename from cmd/nerdctl/build_test.go rename to integration/build_test.go index df0f600104f..ce0b08e57e4 100644 --- a/cmd/nerdctl/build_test.go +++ b/integration/build_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "fmt" @@ -23,6 +23,7 @@ import ( "strings" "testing" + "github.com/containerd/nerdctl/cmd/nerdctl/build" "github.com/containerd/nerdctl/pkg/testutil" "gotest.tools/v3/assert" ) @@ -38,7 +39,7 @@ func TestBuild(t *testing.T) { CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) - buildCtx, err := createBuildContext(dockerfile) + buildCtx, err := build.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) @@ -68,7 +69,7 @@ RUN echo hello > /hello CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) - buildCtx, err := createBuildContext(dockerfile) + buildCtx, err := build.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) @@ -80,7 +81,7 @@ RUN echo hello2 > /hello2 CMD ["cat", "/hello2"] `, imageName) - buildCtx2, err := createBuildContext(dockerfile2) + buildCtx2, err := build.CreateBuildContext(dockerfile2) assert.NilError(t, err) defer os.RemoveAll(buildCtx2) @@ -115,7 +116,7 @@ RUN echo hello2 > /hello2 CMD ["cat", "/hello2"] `, imageName) - buildCtx2, err := createBuildContext(dockerfile2) + buildCtx2, err := build.CreateBuildContext(dockerfile2) assert.NilError(t, err) defer os.RemoveAll(buildCtx2) @@ -188,7 +189,7 @@ func TestBuildLocal(t *testing.T) { COPY %s /`, testFileName) - buildCtx, err := createBuildContext(dockerfile) + buildCtx, err := build.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) @@ -216,17 +217,6 @@ COPY %s /`, assert.Equal(t, string(data), testContent) } -func createBuildContext(dockerfile string) (string, error) { - tmpDir, err := os.MkdirTemp("", "nerdctl-build-test") - if err != nil { - return "", err - } - if err = os.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644); err != nil { - return "", err - } - return tmpDir, nil -} - func TestBuildWithBuildArg(t *testing.T) { testutil.RequiresBuild(t) base := testutil.NewBase(t) @@ -240,7 +230,7 @@ ENV TEST_STRING=$TEST_STRING CMD echo $TEST_STRING `, testutil.CommonImage) - buildCtx, err := createBuildContext(dockerfile) + buildCtx, err := build.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) @@ -291,7 +281,7 @@ func TestBuildWithIIDFile(t *testing.T) { CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) - buildCtx, err := createBuildContext(dockerfile) + buildCtx, err := build.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) fileName := filepath.Join(t.TempDir(), "id.txt") @@ -317,7 +307,7 @@ func TestBuildWithLabels(t *testing.T) { LABEL name=nerdctl-build-test-label `, testutil.CommonImage) - buildCtx, err := createBuildContext(dockerfile) + buildCtx, err := build.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) @@ -341,7 +331,7 @@ func TestBuildMultipleTags(t *testing.T) { CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) - buildCtx, err := createBuildContext(dockerfile) + buildCtx, err := build.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) @@ -395,7 +385,7 @@ CMD ["echo", "dockerfile"] err = os.WriteFile(filepath.Join(tmpDir, "Containerfile"), []byte(containerfile), 0644) assert.NilError(t, err) - buildCtx, err := createBuildContext(dockerfile) + buildCtx, err := build.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) @@ -412,7 +402,7 @@ func TestBuildNoTag(t *testing.T) { dockerfile := fmt.Sprintf(`FROM %s CMD ["echo", "nerdctl-build-notag-string"] `, testutil.CommonImage) - buildCtx, err := createBuildContext(dockerfile) + buildCtx, err := build.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) diff --git a/cmd/nerdctl/builder_linux_test.go b/integration/builder_linux_test.go similarity index 89% rename from cmd/nerdctl/builder_linux_test.go rename to integration/builder_linux_test.go index 5376698242d..5ac13ae2a9c 100644 --- a/cmd/nerdctl/builder_linux_test.go +++ b/integration/builder_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "bytes" @@ -22,6 +22,7 @@ import ( "os" "testing" + "github.com/containerd/nerdctl/cmd/nerdctl/build" "github.com/containerd/nerdctl/pkg/testutil" "gotest.tools/v3/assert" ) @@ -34,7 +35,7 @@ func TestBuilderDebug(t *testing.T) { CMD ["echo", "nerdctl-builder-debug-test-string"] `, testutil.CommonImage) - buildCtx, err := createBuildContext(dockerfile) + buildCtx, err := build.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) diff --git a/cmd/nerdctl/commit_test.go b/integration/commit_test.go similarity index 98% rename from cmd/nerdctl/commit_test.go rename to integration/commit_test.go index c48209f1d24..428494680fc 100644 --- a/cmd/nerdctl/commit_test.go +++ b/integration/commit_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "fmt" diff --git a/cmd/nerdctl/completion_linux_test.go b/integration/completion_linux_test.go similarity index 99% rename from cmd/nerdctl/completion_linux_test.go rename to integration/completion_linux_test.go index ccff901371e..e09dde25e85 100644 --- a/cmd/nerdctl/completion_linux_test.go +++ b/integration/completion_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "testing" diff --git a/cmd/nerdctl/compose_build_linux_test.go b/integration/compose_build_linux_test.go similarity index 99% rename from cmd/nerdctl/compose_build_linux_test.go rename to integration/compose_build_linux_test.go index ec6be8cb5b1..0ebf1f5af18 100644 --- a/cmd/nerdctl/compose_build_linux_test.go +++ b/integration/compose_build_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "fmt" diff --git a/cmd/nerdctl/compose_config_test.go b/integration/compose_config_test.go similarity index 99% rename from cmd/nerdctl/compose_config_test.go rename to integration/compose_config_test.go index e6b76f3eea8..7a832ed0097 100644 --- a/cmd/nerdctl/compose_config_test.go +++ b/integration/compose_config_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "fmt" diff --git a/cmd/nerdctl/compose_exec_linux_test.go b/integration/compose_exec_linux_test.go similarity index 99% rename from cmd/nerdctl/compose_exec_linux_test.go rename to integration/compose_exec_linux_test.go index 28d92d76efa..7d0d2e2172a 100644 --- a/cmd/nerdctl/compose_exec_linux_test.go +++ b/integration/compose_exec_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "errors" diff --git a/cmd/nerdctl/compose_images_linux_test.go b/integration/compose_images_linux_test.go similarity index 99% rename from cmd/nerdctl/compose_images_linux_test.go rename to integration/compose_images_linux_test.go index 0fd76840442..97f697dc8a3 100644 --- a/cmd/nerdctl/compose_images_linux_test.go +++ b/integration/compose_images_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "fmt" diff --git a/cmd/nerdctl/compose_kill_linux_test.go b/integration/compose_kill_linux_test.go similarity index 99% rename from cmd/nerdctl/compose_kill_linux_test.go rename to integration/compose_kill_linux_test.go index 420d57de0fe..5f273bc94bc 100644 --- a/cmd/nerdctl/compose_kill_linux_test.go +++ b/integration/compose_kill_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "fmt" diff --git a/cmd/nerdctl/compose_pause_linux_test.go b/integration/compose_pause_linux_test.go similarity index 99% rename from cmd/nerdctl/compose_pause_linux_test.go rename to integration/compose_pause_linux_test.go index b31dfd1bbfb..d085795b608 100644 --- a/cmd/nerdctl/compose_pause_linux_test.go +++ b/integration/compose_pause_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "fmt" diff --git a/cmd/nerdctl/compose_port_linux_test.go b/integration/compose_port_linux_test.go similarity index 99% rename from cmd/nerdctl/compose_port_linux_test.go rename to integration/compose_port_linux_test.go index f5240edc55b..1915483eb5f 100644 --- a/cmd/nerdctl/compose_port_linux_test.go +++ b/integration/compose_port_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "fmt" diff --git a/cmd/nerdctl/compose_ps_linux_test.go b/integration/compose_ps_linux_test.go similarity index 96% rename from cmd/nerdctl/compose_ps_linux_test.go rename to integration/compose_ps_linux_test.go index cbd4c8ccd44..cd054c05e21 100644 --- a/cmd/nerdctl/compose_ps_linux_test.go +++ b/integration/compose_ps_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "encoding/json" @@ -22,6 +22,7 @@ import ( "strings" "testing" + "github.com/containerd/nerdctl/cmd/nerdctl/compose" "github.com/containerd/nerdctl/pkg/testutil" ) @@ -72,7 +73,7 @@ volumes: assertHandler := func(svc string, count int, fields ...string) func(stdout string) error { return func(stdout string) error { // 1. check json output can be unmarshalled back to printables. - var printables []composeContainerPrintable + var printables []compose.ContainerPrintable if err := json.Unmarshal([]byte(stdout), &printables); err != nil { return fmt.Errorf("[service: %s]failed to unmarshal json output from `compose ps`: %s", svc, stdout) } diff --git a/cmd/nerdctl/compose_pull_linux_test.go b/integration/compose_pull_linux_test.go similarity index 98% rename from cmd/nerdctl/compose_pull_linux_test.go rename to integration/compose_pull_linux_test.go index d350892f1b3..7e5faf8f044 100644 --- a/cmd/nerdctl/compose_pull_linux_test.go +++ b/integration/compose_pull_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "fmt" diff --git a/cmd/nerdctl/compose_restart_linux_test.go b/integration/compose_restart_linux_test.go similarity index 99% rename from cmd/nerdctl/compose_restart_linux_test.go rename to integration/compose_restart_linux_test.go index dbf23f05fd4..0e4eb8ee8c8 100644 --- a/cmd/nerdctl/compose_restart_linux_test.go +++ b/integration/compose_restart_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "fmt" diff --git a/cmd/nerdctl/compose_rm_linux_test.go b/integration/compose_rm_linux_test.go similarity index 99% rename from cmd/nerdctl/compose_rm_linux_test.go rename to integration/compose_rm_linux_test.go index 0a1dc5d7b3f..56ad3c5d38b 100644 --- a/cmd/nerdctl/compose_rm_linux_test.go +++ b/integration/compose_rm_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "fmt" diff --git a/cmd/nerdctl/compose_run_linux_test.go b/integration/compose_run_linux_test.go similarity index 98% rename from cmd/nerdctl/compose_run_linux_test.go rename to integration/compose_run_linux_test.go index 8a4daba41e2..9e9c8c64a19 100644 --- a/cmd/nerdctl/compose_run_linux_test.go +++ b/integration/compose_run_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "fmt" @@ -24,6 +24,7 @@ import ( "testing" "time" + "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/pkg/testutil" "github.com/containerd/nerdctl/pkg/testutil/nettestutil" "github.com/containerd/nerdctl/pkg/testutil/testregistry" @@ -422,8 +423,8 @@ func TestComposePushAndPullWithCosignVerify(t *testing.T) { // set up cosign and local registry t.Setenv("COSIGN_PASSWORD", "1") - keyPair := newCosignKeyPair(t, "cosign-key-pair") - defer keyPair.cleanup() + keyPair := utils.NewCosignKeyPair(t, "cosign-key-pair") + defer keyPair.Cleanup() reg := testregistry.NewPlainHTTP(base, 5000) defer reg.Cleanup() @@ -466,8 +467,8 @@ services: x-nerdctl-sign: none entrypoint: - stty -`, imageSvc0, keyPair.publicKey, keyPair.privateKey, - imageSvc1, keyPair.privateKey, imageSvc2) +`, imageSvc0, keyPair.PublicKey, keyPair.PrivateKey, + imageSvc1, keyPair.PrivateKey, imageSvc2) dockerfile := fmt.Sprintf(`FROM %s`, testutil.AlpineImage) diff --git a/cmd/nerdctl/compose_stop_linux_test.go b/integration/compose_stop_linux_test.go similarity index 99% rename from cmd/nerdctl/compose_stop_linux_test.go rename to integration/compose_stop_linux_test.go index 949f046d524..eb7115bc847 100644 --- a/cmd/nerdctl/compose_stop_linux_test.go +++ b/integration/compose_stop_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "fmt" diff --git a/cmd/nerdctl/compose_top_linux_test.go b/integration/compose_top_linux_test.go similarity index 98% rename from cmd/nerdctl/compose_top_linux_test.go rename to integration/compose_top_linux_test.go index 38a94fa84e9..1f6a64e8747 100644 --- a/cmd/nerdctl/compose_top_linux_test.go +++ b/integration/compose_top_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "fmt" diff --git a/cmd/nerdctl/compose_up_linux_test.go b/integration/compose_up_linux_test.go similarity index 98% rename from cmd/nerdctl/compose_up_linux_test.go rename to integration/compose_up_linux_test.go index 9ba2cee293c..4e5316018de 100644 --- a/cmd/nerdctl/compose_up_linux_test.go +++ b/integration/compose_up_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "fmt" @@ -34,44 +34,7 @@ import ( "gotest.tools/v3/assert" ) -func TestComposeUp(t *testing.T) { - base := testutil.NewBase(t) - testComposeUp(t, base, fmt.Sprintf(` -version: '3.1' - -services: - - wordpress: - image: %s - restart: always - ports: - - 8080:80 - environment: - WORDPRESS_DB_HOST: db - WORDPRESS_DB_USER: exampleuser - WORDPRESS_DB_PASSWORD: examplepass - WORDPRESS_DB_NAME: exampledb - volumes: - - wordpress:/var/www/html - - db: - image: %s - restart: always - environment: - MYSQL_DATABASE: exampledb - MYSQL_USER: exampleuser - MYSQL_PASSWORD: examplepass - MYSQL_RANDOM_ROOT_PASSWORD: '1' - volumes: - - db:/var/lib/mysql - -volumes: - wordpress: - db: -`, testutil.WordpressImage, testutil.MariaDBImage)) -} - -func testComposeUp(t *testing.T, base *testutil.Base, dockerComposeYAML string) { +func ComposeUpInTest(t *testing.T, base *testutil.Base, dockerComposeYAML string) { comp := testutil.NewComposeDir(t, dockerComposeYAML) defer comp.CleanUp() @@ -122,6 +85,43 @@ func testComposeUp(t *testing.T, base *testutil.Base, dockerComposeYAML string) base.Cmd("network", "inspect", fmt.Sprintf("%s_default", projectName)).AssertFail() } +func TestComposeUp(t *testing.T) { + base := testutil.NewBase(t) + ComposeUpInTest(t, base, fmt.Sprintf(` +version: '3.1' + +services: + + wordpress: + image: %s + restart: always + ports: + - 8080:80 + environment: + WORDPRESS_DB_HOST: db + WORDPRESS_DB_USER: exampleuser + WORDPRESS_DB_PASSWORD: examplepass + WORDPRESS_DB_NAME: exampledb + volumes: + - wordpress:/var/www/html + + db: + image: %s + restart: always + environment: + MYSQL_DATABASE: exampledb + MYSQL_USER: exampleuser + MYSQL_PASSWORD: examplepass + MYSQL_RANDOM_ROOT_PASSWORD: '1' + volumes: + - db:/var/lib/mysql + +volumes: + wordpress: + db: +`, testutil.WordpressImage, testutil.MariaDBImage)) +} + func TestComposeUpBuild(t *testing.T) { testutil.RequiresBuild(t) base := testutil.NewBase(t) @@ -504,7 +504,7 @@ func TestComposeUpWithBypass4netns(t *testing.T) { testutil.RequireKernelVersion(t, ">= 5.9.0-0") testutil.RequireSystemService(t, "bypass4netnsd") base := testutil.NewBase(t) - testComposeUp(t, base, fmt.Sprintf(` + ComposeUpInTest(t, base, fmt.Sprintf(` version: '3.1' services: diff --git a/cmd/nerdctl/compose_version_test.go b/integration/compose_version_test.go similarity index 98% rename from cmd/nerdctl/compose_version_test.go rename to integration/compose_version_test.go index e9786c932c3..4869b94db46 100644 --- a/cmd/nerdctl/compose_version_test.go +++ b/integration/compose_version_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "testing" diff --git a/cmd/nerdctl/container_inspect_linux_test.go b/integration/container_inspect_linux_test.go similarity index 99% rename from cmd/nerdctl/container_inspect_linux_test.go rename to integration/container_inspect_linux_test.go index fd2d3ec1211..b4cc9ce72a7 100644 --- a/cmd/nerdctl/container_inspect_linux_test.go +++ b/integration/container_inspect_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "fmt" diff --git a/cmd/nerdctl/container_prune_linux_test.go b/integration/container_prune_linux_test.go similarity index 98% rename from cmd/nerdctl/container_prune_linux_test.go rename to integration/container_prune_linux_test.go index bfcda034719..6e0fba49fa6 100644 --- a/cmd/nerdctl/container_prune_linux_test.go +++ b/integration/container_prune_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "testing" diff --git a/cmd/nerdctl/cp_linux_test.go b/integration/cp_linux_test.go similarity index 99% rename from cmd/nerdctl/cp_linux_test.go rename to integration/cp_linux_test.go index 5442ed53b30..f1b2b193703 100644 --- a/cmd/nerdctl/cp_linux_test.go +++ b/integration/cp_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "fmt" diff --git a/cmd/nerdctl/create_linux_test.go b/integration/create_linux_test.go similarity index 99% rename from cmd/nerdctl/create_linux_test.go rename to integration/create_linux_test.go index 693788729da..877d1c12541 100644 --- a/cmd/nerdctl/create_linux_test.go +++ b/integration/create_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "fmt" diff --git a/cmd/nerdctl/exec_linux_test.go b/integration/exec_linux_test.go similarity index 99% rename from cmd/nerdctl/exec_linux_test.go rename to integration/exec_linux_test.go index 37ffcb69d06..429202f6c0a 100644 --- a/cmd/nerdctl/exec_linux_test.go +++ b/integration/exec_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "testing" diff --git a/cmd/nerdctl/exec_test.go b/integration/exec_test.go similarity index 99% rename from cmd/nerdctl/exec_test.go rename to integration/exec_test.go index b96cc74756a..0862a6cd507 100644 --- a/cmd/nerdctl/exec_test.go +++ b/integration/exec_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "errors" diff --git a/cmd/nerdctl/image_convert_linux_test.go b/integration/image_convert_linux_test.go similarity index 99% rename from cmd/nerdctl/image_convert_linux_test.go rename to integration/image_convert_linux_test.go index 10e4611e92d..5b833812a4d 100644 --- a/cmd/nerdctl/image_convert_linux_test.go +++ b/integration/image_convert_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "fmt" diff --git a/cmd/nerdctl/image_convert_test.go b/integration/image_convert_test.go similarity index 98% rename from cmd/nerdctl/image_convert_test.go rename to integration/image_convert_test.go index 4853c1070ce..54c0c978bec 100644 --- a/cmd/nerdctl/image_convert_test.go +++ b/integration/image_convert_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "runtime" diff --git a/cmd/nerdctl/image_encrypt_linux_test.go b/integration/image_encrypt_linux_test.go similarity index 51% rename from cmd/nerdctl/image_encrypt_linux_test.go rename to integration/image_encrypt_linux_test.go index a1ed55a3c49..21dd6b5ae47 100644 --- a/cmd/nerdctl/image_encrypt_linux_test.go +++ b/integration/image_encrypt_linux_test.go @@ -14,68 +14,21 @@ limitations under the License. */ -package main +package integration import ( "fmt" - "os" - "os/exec" - "path/filepath" "testing" - "github.com/containerd/nerdctl/pkg/buildkitutil" + "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/pkg/testutil" "github.com/containerd/nerdctl/pkg/testutil/testregistry" - "gotest.tools/v3/assert" ) -type jweKeyPair struct { - prv string - pub string - cleanup func() -} - -func newJWEKeyPair(t testing.TB) *jweKeyPair { - if _, err := exec.LookPath("openssl"); err != nil { - t.Skip(err) - } - td, err := os.MkdirTemp(t.TempDir(), "jwe-key-pair") - assert.NilError(t, err) - prv := filepath.Join(td, "mykey.pem") - pub := filepath.Join(td, "mypubkey.pem") - cmds := [][]string{ - // Exec openssl commands to ensure that nerdctl is compatible with the output of openssl commands. - // Do NOT refactor this function to use "crypto/rsa" stdlib. - {"openssl", "genrsa", "-out", prv}, - {"openssl", "rsa", "-in", prv, "-pubout", "-out", pub}, - } - for _, f := range cmds { - cmd := exec.Command(f[0], f[1:]...) - if out, err := cmd.CombinedOutput(); err != nil { - t.Fatalf("failed to run %v: %v (%q)", cmd.Args, err, string(out)) - } - } - return &jweKeyPair{ - prv: prv, - pub: pub, - cleanup: func() { - _ = os.RemoveAll(td) - }, - } -} - -func rmiAll(base *testutil.Base) { - imageIDs := base.Cmd("images", "--no-trunc", "-a", "-q").OutLines() - base.Cmd(append([]string{"rmi", "-f"}, imageIDs...)...).AssertOK() - if _, err := buildkitutil.GetBuildkitHost(testutil.Namespace); err == nil { - base.Cmd("builder", "prune").AssertOK() - } -} - func TestImageEncryptJWE(t *testing.T) { testutil.DockerIncompatible(t) - keyPair := newJWEKeyPair(t) - defer keyPair.cleanup() + keyPair := utils.NewJWEKeyPair(t) + defer keyPair.Cleanup() base := testutil.NewBase(t) tID := testutil.Identifier(t) reg := testregistry.NewPlainHTTP(base, 5000) @@ -83,16 +36,16 @@ func TestImageEncryptJWE(t *testing.T) { base.Cmd("pull", testutil.CommonImage).AssertOK() encryptImageRef := fmt.Sprintf("127.0.0.1:%d/%s:encrypted", reg.ListenPort, tID) defer base.Cmd("rmi", encryptImageRef).Run() - base.Cmd("image", "encrypt", "--recipient=jwe:"+keyPair.pub, testutil.CommonImage, encryptImageRef).AssertOK() + base.Cmd("image", "encrypt", "--recipient=jwe:"+keyPair.Pub, testutil.CommonImage, encryptImageRef).AssertOK() base.Cmd("image", "inspect", "--mode=native", "--format={{len .Index.Manifests}}", encryptImageRef).AssertOutExactly("1\n") base.Cmd("image", "inspect", "--mode=native", "--format={{json .Manifest.Layers}}", encryptImageRef).AssertOutContains("org.opencontainers.image.enc.keys.jwe") base.Cmd("push", encryptImageRef).AssertOK() // remove all local images (in the nerdctl-test namespace), to ensure that we do not have blobs of the original image. - rmiAll(base) - base.Cmd("pull", encryptImageRef).AssertFail() // defaults to --unpack=true, and fails due to missing prv key + utils.RmiAll(base) + base.Cmd("pull", encryptImageRef).AssertFail() // defaults to --unpack=true, and fails due to missing Prv key base.Cmd("pull", "--unpack=false", encryptImageRef).AssertOK() decryptImageRef := tID + ":decrypted" defer base.Cmd("rmi", decryptImageRef).Run() - base.Cmd("image", "decrypt", "--key="+keyPair.pub, encryptImageRef, decryptImageRef).AssertFail() // decryption needs prv key, not pub key - base.Cmd("image", "decrypt", "--key="+keyPair.prv, encryptImageRef, decryptImageRef).AssertOK() + base.Cmd("image", "decrypt", "--key="+keyPair.Pub, encryptImageRef, decryptImageRef).AssertFail() // decryption needs Prv key, not Pub key + base.Cmd("image", "decrypt", "--key="+keyPair.Prv, encryptImageRef, decryptImageRef).AssertOK() } diff --git a/cmd/nerdctl/image_inspect_test.go b/integration/image_inspect_test.go similarity index 98% rename from cmd/nerdctl/image_inspect_test.go rename to integration/image_inspect_test.go index 1daae324564..c9d2a7dd503 100644 --- a/cmd/nerdctl/image_inspect_test.go +++ b/integration/image_inspect_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "testing" diff --git a/cmd/nerdctl/image_prune_test.go b/integration/image_prune_test.go similarity index 92% rename from cmd/nerdctl/image_prune_test.go rename to integration/image_prune_test.go index 1683da76cb0..3e23c043864 100644 --- a/cmd/nerdctl/image_prune_test.go +++ b/integration/image_prune_test.go @@ -14,13 +14,14 @@ limitations under the License. */ -package main +package integration import ( "fmt" "os" "testing" + "github.com/containerd/nerdctl/cmd/nerdctl/build" "github.com/containerd/nerdctl/pkg/testutil" "gotest.tools/v3/assert" ) @@ -36,7 +37,7 @@ func TestImagePrune(t *testing.T) { dockerfile := fmt.Sprintf(`FROM %s CMD ["echo", "nerdctl-test-image-prune"]`, testutil.CommonImage) - buildCtx, err := createBuildContext(dockerfile) + buildCtx, err := build.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) diff --git a/cmd/nerdctl/images_test.go b/integration/images_test.go similarity index 97% rename from cmd/nerdctl/images_test.go rename to integration/images_test.go index dbe7ba413c3..adfa914c16a 100644 --- a/cmd/nerdctl/images_test.go +++ b/integration/images_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "fmt" @@ -22,6 +22,7 @@ import ( "strings" "testing" + "github.com/containerd/nerdctl/cmd/nerdctl/build" "github.com/containerd/nerdctl/pkg/tabutil" "github.com/containerd/nerdctl/pkg/testutil" "gotest.tools/v3/assert" @@ -88,7 +89,7 @@ CMD ["echo", "nerdctl-build-test-string"] \n LABEL foo=bar LABEL version=0.1`, testutil.CommonImage) - buildCtx, err := createBuildContext(dockerfile) + buildCtx, err := build.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) base.Cmd("build", "-t", tempName, "-f", buildCtx+"/Dockerfile", buildCtx).AssertOK() diff --git a/cmd/nerdctl/info_test.go b/integration/info_test.go similarity index 98% rename from cmd/nerdctl/info_test.go rename to integration/info_test.go index 7606b0ed601..cfc7d7d5180 100644 --- a/cmd/nerdctl/info_test.go +++ b/integration/info_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "encoding/json" diff --git a/cmd/nerdctl/ipfs_build_linux_test.go b/integration/ipfs_build_linux_test.go similarity index 92% rename from cmd/nerdctl/ipfs_build_linux_test.go rename to integration/ipfs_build_linux_test.go index 4d953b44caf..fd70dd79502 100644 --- a/cmd/nerdctl/ipfs_build_linux_test.go +++ b/integration/ipfs_build_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "fmt" @@ -22,6 +22,7 @@ import ( "strings" "testing" + "github.com/containerd/nerdctl/cmd/nerdctl/build" "github.com/containerd/nerdctl/pkg/testutil" "gotest.tools/v3/assert" @@ -43,7 +44,7 @@ func TestIPFSBuild(t *testing.T) { CMD ["echo", "nerdctl-build-test-string"] `, ipfsCIDBase) - buildCtx, err := createBuildContext(dockerfile) + buildCtx, err := build.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) diff --git a/cmd/nerdctl/ipfs_compose_linux_test.go b/integration/ipfs_compose_linux_test.go similarity index 96% rename from cmd/nerdctl/ipfs_compose_linux_test.go rename to integration/ipfs_compose_linux_test.go index 0114323690c..d29dea96890 100644 --- a/cmd/nerdctl/ipfs_compose_linux_test.go +++ b/integration/ipfs_compose_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "fmt" @@ -23,6 +23,7 @@ import ( "strings" "testing" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/run" "github.com/containerd/nerdctl/pkg/testutil" "github.com/containerd/nerdctl/pkg/testutil/nettestutil" "gotest.tools/v3/assert" @@ -52,14 +53,14 @@ func TestIPFSComposeUp(t *testing.T) { t.Run(tt.name, func(t *testing.T) { base := testutil.NewBase(t) if tt.requiresStargz { - requiresStargz(base) + run.RequiresStargz(base) } ipfsImgs := make([]string, 2) for i, img := range []string{testutil.WordpressImage, testutil.MariaDBImage} { ipfsImgs[i] = pushImageToIPFS(t, base, img, tt.pushOptions...) } base.Env = append(os.Environ(), "CONTAINERD_SNAPSHOTTER="+tt.snapshotter) - testComposeUp(t, base, fmt.Sprintf(` + ComposeUpInTest(t, base, fmt.Sprintf(` version: '3.1' services: diff --git a/cmd/nerdctl/ipfs_linux_test.go b/integration/ipfs_linux_test.go similarity index 91% rename from cmd/nerdctl/ipfs_linux_test.go rename to integration/ipfs_linux_test.go index 026768478ff..6b66a499720 100644 --- a/cmd/nerdctl/ipfs_linux_test.go +++ b/integration/ipfs_linux_test.go @@ -14,13 +14,15 @@ limitations under the License. */ -package main +package integration import ( "fmt" "os" "testing" + "github.com/containerd/nerdctl/cmd/nerdctl/utils" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/run" "github.com/containerd/nerdctl/pkg/infoutil" "github.com/containerd/nerdctl/pkg/rootlessutil" "github.com/containerd/nerdctl/pkg/testutil" @@ -40,23 +42,23 @@ func TestIPFS(t *testing.T) { base.Cmd("run", "--rm", ipfsCID, "echo", "hello").AssertOK() // encryption - keyPair := newJWEKeyPair(t) - defer keyPair.cleanup() + keyPair := utils.NewJWEKeyPair(t) + defer keyPair.Cleanup() tID := testutil.Identifier(t) encryptImageRef := tID + ":enc" layersNum := 1 - base.Cmd("image", "encrypt", "--recipient=jwe:"+keyPair.pub, ipfsCID, encryptImageRef).AssertOK() + base.Cmd("image", "encrypt", "--recipient=jwe:"+keyPair.Pub, ipfsCID, encryptImageRef).AssertOK() base.Cmd("image", "inspect", "--mode=native", "--format={{len .Manifest.Layers}}", encryptImageRef).AssertOutExactly(fmt.Sprintf("%d\n", layersNum)) for i := 0; i < layersNum; i++ { base.Cmd("image", "inspect", "--mode=native", fmt.Sprintf("--format={{json (index .Manifest.Layers %d) }}", i), encryptImageRef).AssertOutContains("org.opencontainers.image.enc.keys.jwe") } ipfsCIDEnc := cidOf(t, base.Cmd("push", "ipfs://"+encryptImageRef).OutLines()) - rmiAll(base) + utils.RmiAll(base) decryptImageRef := tID + ":dec" base.Cmd("pull", "--unpack=false", ipfsCIDEnc).AssertOK() - base.Cmd("image", "decrypt", "--key="+keyPair.pub, ipfsCIDEnc, decryptImageRef).AssertFail() // decryption needs prv key, not pub key - base.Cmd("image", "decrypt", "--key="+keyPair.prv, ipfsCIDEnc, decryptImageRef).AssertOK() + base.Cmd("image", "decrypt", "--key="+keyPair.Pub, ipfsCIDEnc, decryptImageRef).AssertFail() // decryption needs prv key, not pub key + base.Cmd("image", "decrypt", "--key="+keyPair.Prv, ipfsCIDEnc, decryptImageRef).AssertOK() base.Cmd("run", "--rm", decryptImageRef, "/bin/sh", "-c", "echo hello").AssertOK() } @@ -80,7 +82,7 @@ func TestIPFSCommit(t *testing.T) { base.Cmd("kill", newContainer).AssertOK() base.Cmd("rm", newContainer).AssertOK() ipfsCID2 := cidOf(t, base.Cmd("push", "ipfs://"+newImg).OutLines()) - rmiAll(base) + utils.RmiAll(base) base.Cmd("pull", ipfsCID2).AssertOK() base.Cmd("run", "--rm", ipfsCID2, "/bin/sh", "-c", "cat /hello").AssertOK() } @@ -89,7 +91,7 @@ func TestIPFSWithLazyPulling(t *testing.T) { requiresIPFS(t) testutil.DockerIncompatible(t) base := testutil.NewBase(t) - requiresStargz(base) + run.RequiresStargz(base) ipfsCID := pushImageToIPFS(t, base, testutil.AlpineImage, "--estargz") base.Env = append(os.Environ(), "CONTAINERD_SNAPSHOTTER=stargz") @@ -105,7 +107,7 @@ func TestIPFSWithLazyPullingCommit(t *testing.T) { } testutil.DockerIncompatible(t) base := testutil.NewBase(t) - requiresStargz(base) + run.RequiresStargz(base) ipfsCID := pushImageToIPFS(t, base, testutil.AlpineImage, "--estargz") base.Env = append(os.Environ(), "CONTAINERD_SNAPSHOTTER=stargz") @@ -118,7 +120,7 @@ func TestIPFSWithLazyPullingCommit(t *testing.T) { base.Cmd("kill", newContainer).AssertOK() base.Cmd("rm", newContainer).AssertOK() ipfsCID2 := cidOf(t, base.Cmd("push", "--estargz", "ipfs://"+newImg).OutLines()) - rmiAll(base) + utils.RmiAll(base) base.Cmd("pull", ipfsCID2).AssertOK() base.Cmd("run", "--rm", ipfsCID2, "/bin/sh", "-c", "ls /.stargz-snapshotter && cat /hello").AssertOK() diff --git a/cmd/nerdctl/ipfs_registry_linux_test.go b/integration/ipfs_registry_linux_test.go similarity index 95% rename from cmd/nerdctl/ipfs_registry_linux_test.go rename to integration/ipfs_registry_linux_test.go index dd4066322e6..0047e6de842 100644 --- a/cmd/nerdctl/ipfs_registry_linux_test.go +++ b/integration/ipfs_registry_linux_test.go @@ -14,13 +14,14 @@ limitations under the License. */ -package main +package integration import ( "os" "strings" "testing" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/run" "github.com/containerd/nerdctl/pkg/testutil" ) @@ -45,7 +46,7 @@ func TestIPFSRegistryWithLazyPulling(t *testing.T) { testutil.DockerIncompatible(t) base := testutil.NewBase(t) - requiresStargz(base) + run.RequiresStargz(base) base.Env = append(os.Environ(), "CONTAINERD_SNAPSHOTTER=stargz") ipfsCID := pushImageToIPFS(t, base, testutil.AlpineImage, "--estargz") ipfsRegistryAddr := "localhost:5555" diff --git a/cmd/nerdctl/load_linux_test.go b/integration/load_linux_test.go similarity index 98% rename from cmd/nerdctl/load_linux_test.go rename to integration/load_linux_test.go index 9681d1917bd..2deeee70494 100644 --- a/cmd/nerdctl/load_linux_test.go +++ b/integration/load_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "fmt" diff --git a/cmd/nerdctl/login_linux_test.go b/integration/login_linux_test.go similarity index 99% rename from cmd/nerdctl/login_linux_test.go rename to integration/login_linux_test.go index 12fbc8d4377..5b6cf663080 100644 --- a/cmd/nerdctl/login_linux_test.go +++ b/integration/login_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "fmt" diff --git a/cmd/nerdctl/logs_test.go b/integration/logs_test.go similarity index 99% rename from cmd/nerdctl/logs_test.go rename to integration/logs_test.go index 1643c13c817..2a389c38a67 100644 --- a/cmd/nerdctl/logs_test.go +++ b/integration/logs_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "fmt" diff --git a/cmd/nerdctl/main_linux_test.go b/integration/main_linux_test.go similarity index 98% rename from cmd/nerdctl/main_linux_test.go rename to integration/main_linux_test.go index a61fa50ee2b..e0d9272fd2e 100644 --- a/cmd/nerdctl/main_linux_test.go +++ b/integration/main_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "testing" diff --git a/cmd/nerdctl/main_test.go b/integration/main_test.go similarity index 99% rename from cmd/nerdctl/main_test.go rename to integration/main_test.go index 03a09360147..7016444795d 100644 --- a/cmd/nerdctl/main_test.go +++ b/integration/main_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "os" diff --git a/cmd/nerdctl/multi_platform_linux_test.go b/integration/multi_platform_linux_test.go similarity index 96% rename from cmd/nerdctl/multi_platform_linux_test.go rename to integration/multi_platform_linux_test.go index 017d2827c8b..3238bd10684 100644 --- a/cmd/nerdctl/multi_platform_linux_test.go +++ b/integration/multi_platform_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "fmt" @@ -23,6 +23,7 @@ import ( "strings" "testing" + "github.com/containerd/nerdctl/cmd/nerdctl/build" "github.com/containerd/nerdctl/pkg/testutil" "github.com/containerd/nerdctl/pkg/testutil/nettestutil" "github.com/containerd/nerdctl/pkg/testutil/testregistry" @@ -68,7 +69,7 @@ func TestMultiPlatformBuildPush(t *testing.T) { RUN echo dummy `, testutil.AlpineImage) - buildCtx, err := createBuildContext(dockerfile) + buildCtx, err := build.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) @@ -97,7 +98,7 @@ func TestMultiPlatformBuildPushNoRun(t *testing.T) { CMD echo dummy `, testutil.AlpineImage) - buildCtx, err := createBuildContext(dockerfile) + buildCtx, err := build.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) diff --git a/cmd/nerdctl/network_create_linux_test.go b/integration/network_create_linux_test.go similarity index 98% rename from cmd/nerdctl/network_create_linux_test.go rename to integration/network_create_linux_test.go index d055c10bb28..2fc136f1084 100644 --- a/cmd/nerdctl/network_create_linux_test.go +++ b/integration/network_create_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "testing" diff --git a/cmd/nerdctl/network_inspect_test.go b/integration/network_inspect_test.go similarity index 98% rename from cmd/nerdctl/network_inspect_test.go rename to integration/network_inspect_test.go index 76b93ec7097..f2dd6b2e343 100644 --- a/cmd/nerdctl/network_inspect_test.go +++ b/integration/network_inspect_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "runtime" diff --git a/cmd/nerdctl/network_prune_linux_test.go b/integration/network_prune_linux_test.go similarity index 98% rename from cmd/nerdctl/network_prune_linux_test.go rename to integration/network_prune_linux_test.go index d872d540b26..ab974634f35 100644 --- a/cmd/nerdctl/network_prune_linux_test.go +++ b/integration/network_prune_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "testing" diff --git a/cmd/nerdctl/network_rm_linux_test.go b/integration/network_rm_linux_test.go similarity index 99% rename from cmd/nerdctl/network_rm_linux_test.go rename to integration/network_rm_linux_test.go index 9003f2a4bcf..03f913c0613 100644 --- a/cmd/nerdctl/network_rm_linux_test.go +++ b/integration/network_rm_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "testing" diff --git a/cmd/nerdctl/ps_linux_test.go b/integration/ps_linux_test.go similarity index 99% rename from cmd/nerdctl/ps_linux_test.go rename to integration/ps_linux_test.go index d7b04a3f005..ebb326059a5 100644 --- a/cmd/nerdctl/ps_linux_test.go +++ b/integration/ps_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "errors" diff --git a/cmd/nerdctl/pull_linux_test.go b/integration/pull_linux_test.go similarity index 74% rename from cmd/nerdctl/pull_linux_test.go rename to integration/pull_linux_test.go index 0051890899b..face084e905 100644 --- a/cmd/nerdctl/pull_linux_test.go +++ b/integration/pull_linux_test.go @@ -14,49 +14,22 @@ limitations under the License. */ -package main +package integration import ( "fmt" "os" "os/exec" - "path/filepath" "strings" "testing" + "github.com/containerd/nerdctl/cmd/nerdctl/build" + "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/pkg/testutil" "github.com/containerd/nerdctl/pkg/testutil/testregistry" "gotest.tools/v3/assert" ) -type cosignKeyPair struct { - publicKey string - privateKey string - cleanup func() -} - -func newCosignKeyPair(t testing.TB, path string) *cosignKeyPair { - td, err := os.MkdirTemp(t.TempDir(), path) - assert.NilError(t, err) - - cmd := exec.Command("cosign", "generate-key-pair") - cmd.Dir = td - if out, err := cmd.CombinedOutput(); err != nil { - t.Fatalf("failed to run %v: %v (%q)", cmd.Args, err, string(out)) - } - - publicKey := filepath.Join(td, "cosign.pub") - privateKey := filepath.Join(td, "cosign.key") - - return &cosignKeyPair{ - publicKey: publicKey, - privateKey: privateKey, - cleanup: func() { - _ = os.RemoveAll(td) - }, - } -} - func TestImageVerifyWithCosign(t *testing.T) { if _, err := exec.LookPath("cosign"); err != nil { t.Skip() @@ -64,8 +37,8 @@ func TestImageVerifyWithCosign(t *testing.T) { testutil.DockerIncompatible(t) testutil.RequiresBuild(t) t.Setenv("COSIGN_PASSWORD", "1") - keyPair := newCosignKeyPair(t, "cosign-key-pair") - defer keyPair.cleanup() + keyPair := utils.NewCosignKeyPair(t, "cosign-key-pair") + defer keyPair.Cleanup() base := testutil.NewBase(t) defer base.Cmd("builder", "prune").Run() tID := testutil.Identifier(t) @@ -81,13 +54,13 @@ func TestImageVerifyWithCosign(t *testing.T) { CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) - buildCtx, err := createBuildContext(dockerfile) + buildCtx, err := build.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) base.Cmd("build", "-t", testImageRef, buildCtx).AssertOK() - base.Cmd("push", testImageRef, "--sign=cosign", "--cosign-key="+keyPair.privateKey).AssertOK() - base.Cmd("pull", testImageRef, "--verify=cosign", "--cosign-key="+keyPair.publicKey).AssertOK() + base.Cmd("push", testImageRef, "--sign=cosign", "--cosign-key="+keyPair.PrivateKey).AssertOK() + base.Cmd("pull", testImageRef, "--verify=cosign", "--cosign-key="+keyPair.PublicKey).AssertOK() } func TestImagePullPlainHttpWithDefaultPort(t *testing.T) { @@ -105,7 +78,7 @@ func TestImagePullPlainHttpWithDefaultPort(t *testing.T) { CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) - buildCtx, err := createBuildContext(dockerfile) + buildCtx, err := build.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) base.Cmd("build", "-t", testImageRef, buildCtx).AssertOK() @@ -120,8 +93,8 @@ func TestImageVerifyWithCosignShouldFailWhenKeyIsNotCorrect(t *testing.T) { testutil.DockerIncompatible(t) testutil.RequiresBuild(t) t.Setenv("COSIGN_PASSWORD", "1") - keyPair := newCosignKeyPair(t, "cosign-key-pair") - defer keyPair.cleanup() + keyPair := utils.NewCosignKeyPair(t, "cosign-key-pair") + defer keyPair.Cleanup() base := testutil.NewBase(t) defer base.Cmd("builder", "prune").Run() tID := testutil.Identifier(t) @@ -137,15 +110,15 @@ func TestImageVerifyWithCosignShouldFailWhenKeyIsNotCorrect(t *testing.T) { CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) - buildCtx, err := createBuildContext(dockerfile) + buildCtx, err := build.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) base.Cmd("build", "-t", testImageRef, buildCtx).AssertOK() - base.Cmd("push", testImageRef, "--sign=cosign", "--cosign-key="+keyPair.privateKey).AssertOK() - base.Cmd("pull", testImageRef, "--verify=cosign", "--cosign-key="+keyPair.publicKey).AssertOK() + base.Cmd("push", testImageRef, "--sign=cosign", "--cosign-key="+keyPair.PrivateKey).AssertOK() + base.Cmd("pull", testImageRef, "--verify=cosign", "--cosign-key="+keyPair.PublicKey).AssertOK() t.Setenv("COSIGN_PASSWORD", "2") - newKeyPair := newCosignKeyPair(t, "cosign-key-pair-test") - base.Cmd("pull", testImageRef, "--verify=cosign", "--cosign-key="+newKeyPair.publicKey).AssertFail() + newKeyPair := utils.NewCosignKeyPair(t, "cosign-key-pair-test") + base.Cmd("pull", testImageRef, "--verify=cosign", "--cosign-key="+newKeyPair.PublicKey).AssertFail() } diff --git a/cmd/nerdctl/push_linux_test.go b/integration/push_linux_test.go similarity index 99% rename from cmd/nerdctl/push_linux_test.go rename to integration/push_linux_test.go index bfe8cb02bcf..0b4b0fb27c4 100644 --- a/cmd/nerdctl/push_linux_test.go +++ b/integration/push_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "fmt" diff --git a/cmd/nerdctl/rename_linux_test.go b/integration/rename_linux_test.go similarity index 99% rename from cmd/nerdctl/rename_linux_test.go rename to integration/rename_linux_test.go index b082514fe1c..9794ae6df41 100644 --- a/cmd/nerdctl/rename_linux_test.go +++ b/integration/rename_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "testing" diff --git a/cmd/nerdctl/restart_linux_test.go b/integration/restart_linux_test.go similarity index 99% rename from cmd/nerdctl/restart_linux_test.go rename to integration/restart_linux_test.go index b04e0346fc7..f8e272876bc 100644 --- a/cmd/nerdctl/restart_linux_test.go +++ b/integration/restart_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "fmt" diff --git a/cmd/nerdctl/rm_linux_test.go b/integration/rm_linux_test.go similarity index 98% rename from cmd/nerdctl/rm_linux_test.go rename to integration/rm_linux_test.go index 3020dfc42f4..6ea06395d60 100644 --- a/cmd/nerdctl/rm_linux_test.go +++ b/integration/rm_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "testing" diff --git a/cmd/nerdctl/rmi_linux_test.go b/integration/rmi_linux_test.go similarity index 98% rename from cmd/nerdctl/rmi_linux_test.go rename to integration/rmi_linux_test.go index ecc55b435f9..b8c1706f478 100644 --- a/cmd/nerdctl/rmi_linux_test.go +++ b/integration/rmi_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "testing" diff --git a/cmd/nerdctl/run_cgroup_linux_test.go b/integration/run_cgroup_linux_test.go similarity index 98% rename from cmd/nerdctl/run_cgroup_linux_test.go rename to integration/run_cgroup_linux_test.go index c05fea26c20..aeed6120a7e 100644 --- a/cmd/nerdctl/run_cgroup_linux_test.go +++ b/integration/run_cgroup_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "bytes" @@ -25,6 +25,7 @@ import ( "github.com/containerd/cgroups" "github.com/containerd/containerd/pkg/userns" "github.com/containerd/continuity/testutil/loopback" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/run" "github.com/containerd/nerdctl/pkg/testutil" "gotest.tools/v3/assert" ) @@ -252,7 +253,7 @@ func TestParseDevice(t *testing.T) { for _, tc := range testCases { t.Log(tc.s) - devPath, mode, err := parseDevice(tc.s) + devPath, mode, err := run.ParseDevice(tc.s) if tc.err == "" { assert.NilError(t, err) assert.Equal(t, tc.expectedDevPath, devPath) diff --git a/cmd/nerdctl/run_gpus_test.go b/integration/run_gpus_test.go similarity index 75% rename from cmd/nerdctl/run_gpus_test.go rename to integration/run_gpus_test.go index 537a3761e53..3bbed6101db 100644 --- a/cmd/nerdctl/run_gpus_test.go +++ b/integration/run_gpus_test.go @@ -14,11 +14,12 @@ limitations under the License. */ -package main +package integration import ( "testing" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/run" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" ) @@ -31,11 +32,11 @@ func TestParseGpusOptAll(t *testing.T) { "count=all", "count=-1", } { - req, err := parseGPUOptCSV(testcase) + req, err := run.ParseGPUOptCSV(testcase) assert.NilError(t, err) - assert.Equal(t, req.count, -1) - assert.Equal(t, len(req.deviceIDs), 0) - assert.Equal(t, len(req.capabilities), 0) + assert.Equal(t, req.Count, -1) + assert.Equal(t, len(req.DeviceIDs), 0) + assert.Equal(t, len(req.Capabilities), 0) } } @@ -48,10 +49,10 @@ func TestParseGpusOpts(t *testing.T) { "driver=nvidia,\"capabilities=compute,utility\",count=1", "\"capabilities=compute,utility\",count=1", } { - req, err := parseGPUOptCSV(testcase) + req, err := run.ParseGPUOptCSV(testcase) assert.NilError(t, err) - assert.Equal(t, req.count, 1) - assert.Equal(t, len(req.deviceIDs), 0) - assert.Check(t, is.DeepEqual(req.capabilities, []string{"compute", "utility"})) + assert.Equal(t, req.Count, 1) + assert.Equal(t, len(req.DeviceIDs), 0) + assert.Check(t, is.DeepEqual(req.Capabilities, []string{"compute", "utility"})) } } diff --git a/cmd/nerdctl/run_linux_test.go b/integration/run_linux_test.go similarity index 98% rename from cmd/nerdctl/run_linux_test.go rename to integration/run_linux_test.go index 63c082790ce..cca7f8bdf50 100644 --- a/cmd/nerdctl/run_linux_test.go +++ b/integration/run_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "bufio" @@ -29,6 +29,7 @@ import ( "testing" "time" + "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/pkg/rootlessutil" "github.com/containerd/nerdctl/pkg/strutil" "github.com/containerd/nerdctl/pkg/testutil" @@ -54,7 +55,7 @@ func prepareCustomRootfs(base *testutil.Base, imageName string) string { base.Cmd("save", "-o", archiveTarPath, imageName).AssertOK() rootfs, err := os.MkdirTemp(base.T.TempDir(), "rootfs") assert.NilError(base.T, err) - err = extractDockerArchive(archiveTarPath, rootfs) + err = utils.ExtractDockerArchive(archiveTarPath, rootfs) assert.NilError(base.T, err) return rootfs } diff --git a/cmd/nerdctl/run_log_driver_syslog_test.go b/integration/run_log_driver_syslog_test.go similarity index 99% rename from cmd/nerdctl/run_log_driver_syslog_test.go rename to integration/run_log_driver_syslog_test.go index e85a8c1a2a5..fee3005f590 100644 --- a/cmd/nerdctl/run_log_driver_syslog_test.go +++ b/integration/run_log_driver_syslog_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "fmt" diff --git a/cmd/nerdctl/run_mount_linux_test.go b/integration/run_mount_linux_test.go similarity index 98% rename from cmd/nerdctl/run_mount_linux_test.go rename to integration/run_mount_linux_test.go index 37a9d4670f0..c56e37b65e6 100644 --- a/cmd/nerdctl/run_mount_linux_test.go +++ b/integration/run_mount_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "fmt" @@ -24,6 +24,7 @@ import ( "testing" "github.com/containerd/containerd/mount" + "github.com/containerd/nerdctl/cmd/nerdctl/build" "github.com/containerd/nerdctl/pkg/rootlessutil" "github.com/containerd/nerdctl/pkg/testutil" mobymount "github.com/moby/sys/mount" @@ -101,7 +102,7 @@ func TestRunAnonymousVolumeWithBuild(t *testing.T) { VOLUME /foo `, testutil.AlpineImage) - buildCtx, err := createBuildContext(dockerfile) + buildCtx, err := build.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) @@ -125,7 +126,7 @@ RUN mkdir -p /mnt && echo hi > /mnt/initial_file CMD ["cat", "/mnt/initial_file"] `, testutil.AlpineImage) - buildCtx, err := createBuildContext(dockerfile) + buildCtx, err := build.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) @@ -155,7 +156,7 @@ VOLUME /mnt CMD ["cat", "/mnt/initial_file"] `, testutil.AlpineImage) - buildCtx, err := createBuildContext(dockerfile) + buildCtx, err := build.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) @@ -190,7 +191,7 @@ CMD ["readlink", "/mnt/passwd"] `, testutil.AlpineImage) const expected = "../../../../../../../../../../../../../../../../../../etc/passwd\n" - buildCtx, err := createBuildContext(dockerfile) + buildCtx, err := build.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) @@ -219,7 +220,7 @@ func TestRunCopyingUpInitialContentsShouldNotResetTheCopiedContents(t *testing.T RUN echo -n "rev0" > /mnt/file `, testutil.AlpineImage) - buildCtx, err := createBuildContext(dockerfile) + buildCtx, err := build.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) diff --git a/cmd/nerdctl/run_network_linux_test.go b/integration/run_network_linux_test.go similarity index 99% rename from cmd/nerdctl/run_network_linux_test.go rename to integration/run_network_linux_test.go index 0bf6bfcdb6d..097f6cc8b58 100644 --- a/cmd/nerdctl/run_network_linux_test.go +++ b/integration/run_network_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "fmt" diff --git a/cmd/nerdctl/run_restart_linux_test.go b/integration/run_restart_linux_test.go similarity index 99% rename from cmd/nerdctl/run_restart_linux_test.go rename to integration/run_restart_linux_test.go index b57d53a81d3..c9eadfb5c2f 100644 --- a/cmd/nerdctl/run_restart_linux_test.go +++ b/integration/run_restart_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "fmt" diff --git a/cmd/nerdctl/run_runtime_linux_test.go b/integration/run_runtime_linux_test.go similarity index 97% rename from cmd/nerdctl/run_runtime_linux_test.go rename to integration/run_runtime_linux_test.go index fc33c21004a..f36b3699040 100644 --- a/cmd/nerdctl/run_runtime_linux_test.go +++ b/integration/run_runtime_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "testing" diff --git a/cmd/nerdctl/run_security_linux_test.go b/integration/run_security_linux_test.go similarity index 99% rename from cmd/nerdctl/run_security_linux_test.go rename to integration/run_security_linux_test.go index 49db43cbfe2..9b6f0fb22d5 100644 --- a/cmd/nerdctl/run_security_linux_test.go +++ b/integration/run_security_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "fmt" diff --git a/cmd/nerdctl/run_stargz_linux_test.go b/integration/run_stargz_linux_test.go similarity index 81% rename from cmd/nerdctl/run_stargz_linux_test.go rename to integration/run_stargz_linux_test.go index 0e1c8266b3d..7c5f5808d23 100644 --- a/cmd/nerdctl/run_stargz_linux_test.go +++ b/integration/run_stargz_linux_test.go @@ -14,28 +14,19 @@ limitations under the License. */ -package main +package integration import ( "testing" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/run" "github.com/containerd/nerdctl/pkg/testutil" ) func TestRunStargz(t *testing.T) { testutil.DockerIncompatible(t) base := testutil.NewBase(t) - requiresStargz(base) + run.RequiresStargz(base) // if stargz snapshotter is functional, "/.stargz-snapshotter" appears base.Cmd("--snapshotter=stargz", "run", "--rm", testutil.FedoraESGZImage, "ls", "/.stargz-snapshotter").AssertOK() } - -func requiresStargz(base *testutil.Base) { - info := base.Info() - for _, p := range info.Plugins.Storage { - if p == "stargz" { - return - } - } - base.T.Skip("test requires stargz") -} diff --git a/cmd/nerdctl/run_test.go b/integration/run_test.go similarity index 98% rename from cmd/nerdctl/run_test.go rename to integration/run_test.go index 58ce840be10..e8465db4e4a 100644 --- a/cmd/nerdctl/run_test.go +++ b/integration/run_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "errors" @@ -27,6 +27,7 @@ import ( "testing" "time" + "github.com/containerd/nerdctl/cmd/nerdctl/build" "github.com/containerd/nerdctl/pkg/testutil" "gotest.tools/v3/assert" "gotest.tools/v3/icmd" @@ -46,7 +47,7 @@ ENTRYPOINT ["echo", "foo"] CMD ["echo", "bar"] `, testutil.CommonImage) - buildCtx, err := createBuildContext(dockerfile) + buildCtx, err := build.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) @@ -430,7 +431,7 @@ FROM scratch COPY --from=builder /go/src/logger/logger / ` - buildCtx, err := createBuildContext(dockerfile) + buildCtx, err := build.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) tmpDir := t.TempDir() diff --git a/cmd/nerdctl/run_user_linux_test.go b/integration/run_user_linux_test.go similarity index 99% rename from cmd/nerdctl/run_user_linux_test.go rename to integration/run_user_linux_test.go index 262fc7ebc45..5618a2ba351 100644 --- a/cmd/nerdctl/run_user_linux_test.go +++ b/integration/run_user_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "testing" diff --git a/cmd/nerdctl/run_user_windows_test.go b/integration/run_user_windows_test.go similarity index 98% rename from cmd/nerdctl/run_user_windows_test.go rename to integration/run_user_windows_test.go index 27cfd0697af..e4522bb3695 100644 --- a/cmd/nerdctl/run_user_windows_test.go +++ b/integration/run_user_windows_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "testing" diff --git a/cmd/nerdctl/run_verify_linux_test.go b/integration/run_verify_linux_test.go similarity index 84% rename from cmd/nerdctl/run_verify_linux_test.go rename to integration/run_verify_linux_test.go index 32098b9fa5d..4bfa1f7fe74 100644 --- a/cmd/nerdctl/run_verify_linux_test.go +++ b/integration/run_verify_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "fmt" @@ -22,6 +22,8 @@ import ( "os/exec" "testing" + "github.com/containerd/nerdctl/cmd/nerdctl/build" + "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/pkg/testutil" "github.com/containerd/nerdctl/pkg/testutil/testregistry" "gotest.tools/v3/assert" @@ -34,8 +36,8 @@ func TestRunVerifyCosign(t *testing.T) { testutil.DockerIncompatible(t) testutil.RequiresBuild(t) t.Setenv("COSIGN_PASSWORD", "1") - keyPair := newCosignKeyPair(t, "cosign-key-pair") - defer keyPair.cleanup() + keyPair := utils.NewCosignKeyPair(t, "cosign-key-pair") + defer keyPair.Cleanup() base := testutil.NewBase(t) defer base.Cmd("builder", "prune").Run() tID := testutil.Identifier(t) @@ -51,12 +53,12 @@ func TestRunVerifyCosign(t *testing.T) { CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) - buildCtx, err := createBuildContext(dockerfile) + buildCtx, err := build.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) base.Cmd("build", "-t", testImageRef, buildCtx).AssertOK() - base.Cmd("push", testImageRef, "--sign=cosign", "--cosign-key="+keyPair.privateKey).AssertOK() - base.Cmd("run", "--rm", "--verify=cosign", "--cosign-key="+keyPair.publicKey, testImageRef).AssertOK() + base.Cmd("push", testImageRef, "--sign=cosign", "--cosign-key="+keyPair.PrivateKey).AssertOK() + base.Cmd("run", "--rm", "--verify=cosign", "--cosign-key="+keyPair.PublicKey, testImageRef).AssertOK() base.Cmd("run", "--rm", "--verify=cosign", "--cosign-key=dummy", testImageRef).AssertFail() } diff --git a/integration/save_linux_test.go b/integration/save_linux_test.go new file mode 100644 index 00000000000..d6848bfd650 --- /dev/null +++ b/integration/save_linux_test.go @@ -0,0 +1,46 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package integration + +import ( + "os" + "path/filepath" + "strings" + "testing" + + "github.com/containerd/nerdctl/cmd/nerdctl/utils" + "github.com/containerd/nerdctl/pkg/testutil" + + "gotest.tools/v3/assert" +) + +func TestSave(t *testing.T) { + base := testutil.NewBase(t) + base.Cmd("pull", testutil.AlpineImage).AssertOK() + archiveTarPath := filepath.Join(t.TempDir(), "a.tar") + base.Cmd("save", "-o", archiveTarPath, testutil.AlpineImage).AssertOK() + rootfsPath := filepath.Join(t.TempDir(), "rootfs") + err := utils.ExtractDockerArchive(archiveTarPath, rootfsPath) + assert.NilError(t, err) + etcOSReleasePath := filepath.Join(rootfsPath, "/etc/os-release") + etcOSReleaseBytes, err := os.ReadFile(etcOSReleasePath) + assert.NilError(t, err) + etcOSRelease := string(etcOSReleaseBytes) + t.Logf("read %q, extracted from %q", etcOSReleasePath, testutil.AlpineImage) + t.Log(etcOSRelease) + assert.Assert(t, strings.Contains(etcOSRelease, "Alpine")) +} diff --git a/cmd/nerdctl/start_test.go b/integration/start_test.go similarity index 98% rename from cmd/nerdctl/start_test.go rename to integration/start_test.go index 1744cf52e99..7e4f8a0e98e 100644 --- a/cmd/nerdctl/start_test.go +++ b/integration/start_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "errors" diff --git a/cmd/nerdctl/stats_linux_test.go b/integration/stats_linux_test.go similarity index 98% rename from cmd/nerdctl/stats_linux_test.go rename to integration/stats_linux_test.go index 738bb855551..1e1ec8e9933 100644 --- a/cmd/nerdctl/stats_linux_test.go +++ b/integration/stats_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "fmt" diff --git a/cmd/nerdctl/stop_linux_test.go b/integration/stop_linux_test.go similarity index 99% rename from cmd/nerdctl/stop_linux_test.go rename to integration/stop_linux_test.go index a3940188ca7..60bbf0fbad6 100644 --- a/cmd/nerdctl/stop_linux_test.go +++ b/integration/stop_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "fmt" diff --git a/cmd/nerdctl/system_prune_linux_test.go b/integration/system_prune_linux_test.go similarity index 98% rename from cmd/nerdctl/system_prune_linux_test.go rename to integration/system_prune_linux_test.go index 114faeaf288..5ba3f6fe11e 100644 --- a/cmd/nerdctl/system_prune_linux_test.go +++ b/integration/system_prune_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "fmt" diff --git a/cmd/nerdctl/top_linux_test.go b/integration/top_linux_test.go similarity index 98% rename from cmd/nerdctl/top_linux_test.go rename to integration/top_linux_test.go index 52f5bb8c965..844503f9741 100644 --- a/cmd/nerdctl/top_linux_test.go +++ b/integration/top_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "testing" diff --git a/cmd/nerdctl/volume_inspect_test.go b/integration/volume_inspect_test.go similarity index 98% rename from cmd/nerdctl/volume_inspect_test.go rename to integration/volume_inspect_test.go index 6dc948b31cd..b9196e99238 100644 --- a/cmd/nerdctl/volume_inspect_test.go +++ b/integration/volume_inspect_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "crypto/rand" diff --git a/cmd/nerdctl/volume_ls_test.go b/integration/volume_ls_test.go similarity index 99% rename from cmd/nerdctl/volume_ls_test.go rename to integration/volume_ls_test.go index 9a62dd102d4..8f58e83ecee 100644 --- a/cmd/nerdctl/volume_ls_test.go +++ b/integration/volume_ls_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "errors" diff --git a/cmd/nerdctl/volume_prune_linux_test.go b/integration/volume_prune_linux_test.go similarity index 98% rename from cmd/nerdctl/volume_prune_linux_test.go rename to integration/volume_prune_linux_test.go index e9a53b064f0..69c3d7735c9 100644 --- a/cmd/nerdctl/volume_prune_linux_test.go +++ b/integration/volume_prune_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "fmt" diff --git a/cmd/nerdctl/volume_rm_linux_test.go b/integration/volume_rm_linux_test.go similarity index 98% rename from cmd/nerdctl/volume_rm_linux_test.go rename to integration/volume_rm_linux_test.go index b244a5101e2..328fb936e75 100644 --- a/cmd/nerdctl/volume_rm_linux_test.go +++ b/integration/volume_rm_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "fmt" diff --git a/cmd/nerdctl/wait_test.go b/integration/wait_test.go similarity index 98% rename from cmd/nerdctl/wait_test.go rename to integration/wait_test.go index 6a580cf143b..9bbb24ac36f 100644 --- a/cmd/nerdctl/wait_test.go +++ b/integration/wait_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package integration import ( "testing" From e9f141780fa04334db79a4d9fae0c16bf8558e95 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Fri, 16 Dec 2022 00:48:27 +0900 Subject: [PATCH 02/14] [Carry 1639] revert unexpected changes Revert unexpected changes in 5588f706440589d484e3f777890608c3751c1839 Signed-off-by: Akihiro Suda --- cmd/nerdctl/build/build.go | 4 ++-- cmd/nerdctl/client/client.go | 4 ++-- cmd/nerdctl/compose/compose_down.go | 2 +- cmd/nerdctl/container/container.go | 2 +- cmd/nerdctl/container/kill.go | 2 +- cmd/nerdctl/container/pause.go | 2 +- cmd/nerdctl/main.go | 2 +- cmd/nerdctl/ps/ps.go | 2 +- cmd/nerdctl/stats/stats.go | 2 +- cmd/nerdctl/utils/fmtutil/fmtutil.go | 4 ++-- cmd/nerdctl/utils/run/run_network.go | 10 +++++----- cmd/nerdctl/utils/run/run_runtime.go | 10 +++++----- cmd/nerdctl/volume/volume.go | 2 +- cmd/nerdctl/volume/volume_prune.go | 2 +- integration/compose_up_linux_test.go | 6 +++--- integration/ipfs_compose_linux_test.go | 2 +- 16 files changed, 29 insertions(+), 29 deletions(-) diff --git a/cmd/nerdctl/build/build.go b/cmd/nerdctl/build/build.go index db05b70880b..3b4c591a56c 100644 --- a/cmd/nerdctl/build/build.go +++ b/cmd/nerdctl/build/build.go @@ -48,7 +48,7 @@ func NewBuildCommand() *cobra.Command { Short: "Build an image from a Dockerfile. Needs buildkitd to be running.", Long: `Build an image from a Dockerfile. Needs buildkitd to be running. If Dockerfile is not present and -f is not specified, it will look for Containerfile and build with it. `, - RunE: RunBuildAction, + RunE: buildAction, SilenceUsage: true, SilenceErrors: true, } @@ -128,7 +128,7 @@ func isImageSharable(buildkitHost string, namespace, uuid, snapshotter string, p return executor == "containerd" && containerdUUID == uuid && containerdNamespace == namespace && workerSnapshotter == snapshotter && len(platform) == 0, nil } -func RunBuildAction(cmd *cobra.Command, args []string) error { +func buildAction(cmd *cobra.Command, args []string) error { platform, err := cmd.Flags().GetStringSlice("platform") if err != nil { return err diff --git a/cmd/nerdctl/client/client.go b/cmd/nerdctl/client/client.go index 2c36607b29b..fc2b12f514c 100644 --- a/cmd/nerdctl/client/client.go +++ b/cmd/nerdctl/client/client.go @@ -101,7 +101,7 @@ func GetDataStore(cmd *cobra.Command) (string, error) { if err != nil { return "", err } - addrHash, err := GetAddrHash(address) + addrHash, err := getAddrHash(address) if err != nil { return "", err } @@ -112,7 +112,7 @@ func GetDataStore(cmd *cobra.Command) (string, error) { return dataStore, nil } -func GetAddrHash(addr string) (string, error) { +func getAddrHash(addr string) (string, error) { const addrHashLen = 8 if runtime.GOOS != "windows" { diff --git a/cmd/nerdctl/compose/compose_down.go b/cmd/nerdctl/compose/compose_down.go index 7e5d6e3ad55..06136924ef5 100644 --- a/cmd/nerdctl/compose/compose_down.go +++ b/cmd/nerdctl/compose/compose_down.go @@ -31,7 +31,7 @@ func newComposeDownCommand() *cobra.Command { SilenceUsage: true, SilenceErrors: true, } - composeDownCommand.Flags().BoolP("volumes", "v", false, "Remove named volume declared in the `volume` section of the Compose file and anonymous volume attached to containers.") + composeDownCommand.Flags().BoolP("volumes", "v", false, "Remove named volumes declared in the `volumes` section of the Compose file and anonymous volumes attached to containers.") return composeDownCommand } diff --git a/cmd/nerdctl/container/container.go b/cmd/nerdctl/container/container.go index 1db5c57f2f5..e06cf709b58 100644 --- a/cmd/nerdctl/container/container.go +++ b/cmd/nerdctl/container/container.go @@ -29,7 +29,7 @@ func NewContainerCommand() *cobra.Command { containerCommand := &cobra.Command{ Annotations: map[string]string{common.Category: common.Management}, Use: "container", - Short: "Manage Containers", + Short: "Manage containers", RunE: completion.UnknownSubcommandAction, SilenceUsage: true, SilenceErrors: true, diff --git a/cmd/nerdctl/container/kill.go b/cmd/nerdctl/container/kill.go index a239b6659b6..4383506aa2b 100644 --- a/cmd/nerdctl/container/kill.go +++ b/cmd/nerdctl/container/kill.go @@ -38,7 +38,7 @@ import ( func NewKillCommand() *cobra.Command { var killCommand = &cobra.Command{ Use: "kill [flags] CONTAINER [CONTAINER, ...]", - Short: "Kill one or more running Containers", + Short: "Kill one or more running containers", Args: cobra.MinimumNArgs(1), RunE: killAction, ValidArgsFunction: killShellComplete, diff --git a/cmd/nerdctl/container/pause.go b/cmd/nerdctl/container/pause.go index 09147f3622b..22698c7f45f 100644 --- a/cmd/nerdctl/container/pause.go +++ b/cmd/nerdctl/container/pause.go @@ -32,7 +32,7 @@ func NewPauseCommand() *cobra.Command { var pauseCommand = &cobra.Command{ Use: "pause [flags] CONTAINER [CONTAINER, ...]", Args: cobra.MinimumNArgs(1), - Short: "Pause all processes within one or more Containers", + Short: "Pause all processes within one or more containers", RunE: pauseAction, ValidArgsFunction: completion.PauseShellComplete, SilenceUsage: true, diff --git a/cmd/nerdctl/main.go b/cmd/nerdctl/main.go index 48414984afd..f346eefe1b6 100644 --- a/cmd/nerdctl/main.go +++ b/cmd/nerdctl/main.go @@ -370,7 +370,7 @@ Config file ($NERDCTL_TOML): %s apparmor.AddApparmorCommand(rootCmd) cp.AddCpCommand(rootCmd) - // Add aliasToBeInherited to subCommand(s) InheritedFlags + // add aliasToBeInherited to subCommand(s) InheritedFlags for _, subCmd := range rootCmd.Commands() { subCmd.InheritedFlags().AddFlagSet(aliasToBeInherited) } diff --git a/cmd/nerdctl/ps/ps.go b/cmd/nerdctl/ps/ps.go index 2e643b2ac82..59a116dfeee 100644 --- a/cmd/nerdctl/ps/ps.go +++ b/cmd/nerdctl/ps/ps.go @@ -46,7 +46,7 @@ func NewPsCommand() *cobra.Command { var psCommand = &cobra.Command{ Use: "ps", Args: cobra.NoArgs, - Short: "List Containers", + Short: "List containers", RunE: psAction, SilenceUsage: true, SilenceErrors: true, diff --git a/cmd/nerdctl/stats/stats.go b/cmd/nerdctl/stats/stats.go index c831dcac175..21a5249e8c1 100644 --- a/cmd/nerdctl/stats/stats.go +++ b/cmd/nerdctl/stats/stats.go @@ -255,7 +255,7 @@ func statsAction(cmd *cobra.Command, args []string) error { defer close(eventChan) <-started - // Start a goroutine to retrieve the initial list of Containers stats. + // Start a goroutine to retrieve the initial list of containers stats. getContainerList() // make sure each container get at least one valid stat data diff --git a/cmd/nerdctl/utils/fmtutil/fmtutil.go b/cmd/nerdctl/utils/fmtutil/fmtutil.go index 5bbd1d8b135..626111ea485 100644 --- a/cmd/nerdctl/utils/fmtutil/fmtutil.go +++ b/cmd/nerdctl/utils/fmtutil/fmtutil.go @@ -77,7 +77,7 @@ func FormatSlice(cmd *cobra.Command, x []interface{}) error { if err := tmpl.Execute(&b, f); err != nil { if _, ok := err.(template.ExecError); ok { // FallBack to Raw Format - if err = TryRawFormat(&b, f, tmpl); err != nil { + if err = tryRawFormat(&b, f, tmpl); err != nil { return err } } @@ -90,7 +90,7 @@ func FormatSlice(cmd *cobra.Command, x []interface{}) error { return nil } -func TryRawFormat(b *bytes.Buffer, f interface{}, tmpl *template.Template) error { +func tryRawFormat(b *bytes.Buffer, f interface{}, tmpl *template.Template) error { m, err := json.MarshalIndent(f, "", " ") if err != nil { return err diff --git a/cmd/nerdctl/utils/run/run_network.go b/cmd/nerdctl/utils/run/run_network.go index 2c1024d75cf..7ec833ab50a 100644 --- a/cmd/nerdctl/utils/run/run_network.go +++ b/cmd/nerdctl/utils/run/run_network.go @@ -29,7 +29,7 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/containers" "github.com/containerd/containerd/oci" - "github.com/containerd/go-cni" + gocni "github.com/containerd/go-cni" nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" "github.com/containerd/nerdctl/pkg/dnsutil" @@ -59,7 +59,7 @@ func WithCustomEtcHostname(src string) func(context.Context, oci.Client, *contai } } -func GetNetworkSlice(cmd *cobra.Command) ([]string, error) { +func getNetworkSlice(cmd *cobra.Command) ([]string, error) { var netSlice = []string{} var networkSet = false if cmd.Flags().Lookup("network").Changed { @@ -113,7 +113,7 @@ func WithCustomHosts(src string) func(context.Context, oci.Client, *containers.C } } -func GenerateNetOpts(cmd *cobra.Command, dataStore, stateDir, ns, id string) ([]oci.SpecOpts, []string, string, []cni.PortMapping, string, error) { +func GenerateNetOpts(cmd *cobra.Command, dataStore, stateDir, ns, id string) ([]oci.SpecOpts, []string, string, []gocni.PortMapping, string, error) { opts := []oci.SpecOpts{} portSlice, err := cmd.Flags().GetStringSlice("publish") if err != nil { @@ -123,7 +123,7 @@ func GenerateNetOpts(cmd *cobra.Command, dataStore, stateDir, ns, id string) ([] if err != nil { return nil, nil, "", nil, "", err } - netSlice, err := GetNetworkSlice(cmd) + netSlice, err := getNetworkSlice(cmd) if err != nil { return nil, nil, "", nil, "", err } @@ -137,7 +137,7 @@ func GenerateNetOpts(cmd *cobra.Command, dataStore, stateDir, ns, id string) ([] return nil, nil, "", nil, "", err } - ports := make([]cni.PortMapping, 0) + ports := make([]gocni.PortMapping, 0) netType, err := nettype.Detect(netSlice) if err != nil { return nil, nil, "", nil, "", err diff --git a/cmd/nerdctl/utils/run/run_runtime.go b/cmd/nerdctl/utils/run/run_runtime.go index 1532b2194c0..0c92bdd983f 100644 --- a/cmd/nerdctl/utils/run/run_runtime.go +++ b/cmd/nerdctl/utils/run/run_runtime.go @@ -24,8 +24,8 @@ import ( "github.com/containerd/containerd/containers" "github.com/containerd/containerd/oci" "github.com/containerd/containerd/plugin" - options2 "github.com/containerd/containerd/runtime/v2/runc/options" - "github.com/opencontainers/runtime-spec/specs-go" + runcoptions "github.com/containerd/containerd/runtime/v2/runc/options" + runtimespec "github.com/opencontainers/runtime-spec/specs-go" "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -33,7 +33,7 @@ import ( func GenerateRuntimeCOpts(cmd *cobra.Command) ([]containerd.NewContainerOpts, error) { runtime := plugin.RuntimeRuncV2 var ( - runcOpts options2.Options + runcOpts runcoptions.Options runtimeOpts interface{} = &runcOpts ) cgm, err := cmd.Flags().GetString("cgroup-manager") @@ -67,9 +67,9 @@ func GenerateRuntimeCOpts(cmd *cobra.Command) ([]containerd.NewContainerOpts, er // WithSysctls sets the provided sysctls onto the spec func WithSysctls(sysctls map[string]string) oci.SpecOpts { - return func(ctx context.Context, client oci.Client, c *containers.Container, s *specs.Spec) error { + return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) error { if s.Linux == nil { - s.Linux = &specs.Linux{} + s.Linux = &runtimespec.Linux{} } if s.Linux.Sysctl == nil { s.Linux.Sysctl = make(map[string]string) diff --git a/cmd/nerdctl/volume/volume.go b/cmd/nerdctl/volume/volume.go index 5cdaf376b63..faae4beb90a 100644 --- a/cmd/nerdctl/volume/volume.go +++ b/cmd/nerdctl/volume/volume.go @@ -26,7 +26,7 @@ func NewVolumeCommand() *cobra.Command { volumeCommand := &cobra.Command{ Annotations: map[string]string{common.Category: common.Management}, Use: "volume", - Short: "Manage volume", + Short: "Manage volumes", RunE: completion.UnknownSubcommandAction, SilenceUsage: true, SilenceErrors: true, diff --git a/cmd/nerdctl/volume/volume_prune.go b/cmd/nerdctl/volume/volume_prune.go index 825a46a7865..d23c3ed4675 100644 --- a/cmd/nerdctl/volume/volume_prune.go +++ b/cmd/nerdctl/volume/volume_prune.go @@ -48,7 +48,7 @@ func volumePruneAction(cmd *cobra.Command, _ []string) error { if !force { var confirm string - msg := "This will remove all local volume not used by at least one container." + msg := "This will remove all local volumes not used by at least one container." msg += "\nAre you sure you want to continue? [y/N] " fmt.Fprintf(cmd.OutOrStdout(), "WARNING! %s", msg) fmt.Fscanf(cmd.InOrStdin(), "%s", &confirm) diff --git a/integration/compose_up_linux_test.go b/integration/compose_up_linux_test.go index 4e5316018de..6c978154564 100644 --- a/integration/compose_up_linux_test.go +++ b/integration/compose_up_linux_test.go @@ -34,7 +34,7 @@ import ( "gotest.tools/v3/assert" ) -func ComposeUpInTest(t *testing.T, base *testutil.Base, dockerComposeYAML string) { +func testComposeUp(t *testing.T, base *testutil.Base, dockerComposeYAML string) { comp := testutil.NewComposeDir(t, dockerComposeYAML) defer comp.CleanUp() @@ -87,7 +87,7 @@ func ComposeUpInTest(t *testing.T, base *testutil.Base, dockerComposeYAML string func TestComposeUp(t *testing.T) { base := testutil.NewBase(t) - ComposeUpInTest(t, base, fmt.Sprintf(` + testComposeUp(t, base, fmt.Sprintf(` version: '3.1' services: @@ -504,7 +504,7 @@ func TestComposeUpWithBypass4netns(t *testing.T) { testutil.RequireKernelVersion(t, ">= 5.9.0-0") testutil.RequireSystemService(t, "bypass4netnsd") base := testutil.NewBase(t) - ComposeUpInTest(t, base, fmt.Sprintf(` + testComposeUp(t, base, fmt.Sprintf(` version: '3.1' services: diff --git a/integration/ipfs_compose_linux_test.go b/integration/ipfs_compose_linux_test.go index d29dea96890..ab84dd39a3a 100644 --- a/integration/ipfs_compose_linux_test.go +++ b/integration/ipfs_compose_linux_test.go @@ -60,7 +60,7 @@ func TestIPFSComposeUp(t *testing.T) { ipfsImgs[i] = pushImageToIPFS(t, base, img, tt.pushOptions...) } base.Env = append(os.Environ(), "CONTAINERD_SNAPSHOTTER="+tt.snapshotter) - ComposeUpInTest(t, base, fmt.Sprintf(` + testComposeUp(t, base, fmt.Sprintf(` version: '3.1' services: From 206e0c84ba46c99d8c3c1762436b8f56787b390c Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Fri, 16 Dec 2022 01:29:23 +0900 Subject: [PATCH 03/14] [Carry 1639] cmd/nerdctl: reorganize the package structure Signed-off-by: Akihiro Suda --- cmd/nerdctl/{build => builder}/build.go | 2 +- cmd/nerdctl/builder/builder.go | 12 ++--- cmd/nerdctl/container/container.go | 19 ++++---- cmd/nerdctl/container/container_inspect.go | 2 +- cmd/nerdctl/container/container_prune.go | 2 +- cmd/nerdctl/container/{cp => }/cp.go | 2 +- cmd/nerdctl/container/{cp => }/cp_freebsd.go | 2 +- cmd/nerdctl/container/{cp => }/cp_linux.go | 2 +- cmd/nerdctl/container/{cp => }/cp_windows.go | 2 +- cmd/nerdctl/container/{exec => }/exec.go | 2 +- .../container/{exec => }/exec_freebsd.go | 2 +- .../container/{exec => }/exec_linux.go | 2 +- .../container/{exec => }/exec_windows.go | 2 +- cmd/nerdctl/{ps => container}/ps.go | 5 ++- cmd/nerdctl/{stats => container}/stats.go | 2 +- .../{stats => container}/stats_freebsd.go | 2 +- .../{stats => container}/stats_linux.go | 2 +- .../{stats => container}/stats_windows.go | 2 +- cmd/nerdctl/{top => container}/top.go | 2 +- cmd/nerdctl/{history => image}/history.go | 2 +- cmd/nerdctl/image/image.go | 45 ++++++++----------- cmd/nerdctl/image/image_convert.go | 2 +- cmd/nerdctl/image/image_decrypt.go | 2 +- cmd/nerdctl/image/image_encrypt.go | 2 +- cmd/nerdctl/image/image_inspect.go | 2 +- cmd/nerdctl/image/image_prune.go | 2 +- cmd/nerdctl/image/images.go | 3 +- cmd/nerdctl/{load => image}/load.go | 2 +- cmd/nerdctl/{pull => image}/pull.go | 2 +- cmd/nerdctl/{push => image}/push.go | 2 +- cmd/nerdctl/{rmi => image}/rmi.go | 5 ++- cmd/nerdctl/{save => image}/save.go | 2 +- cmd/nerdctl/{tag => image}/tag.go | 2 +- cmd/nerdctl/internal/internal.go | 2 +- cmd/nerdctl/internal/internal_oci_hook.go | 2 +- cmd/nerdctl/ipfs/ipfs.go | 3 +- .../ipfs/{ => registry}/ipfs_registry.go | 10 ++--- .../ipfs/{ => registry}/ipfs_registry_down.go | 4 +- .../{ => registry}/ipfs_registry_serve.go | 4 +- .../ipfs/{ => registry}/ipfs_registry_up.go | 4 +- cmd/nerdctl/main.go | 44 +++++++----------- cmd/nerdctl/namespace/namespace.go | 12 ++--- cmd/nerdctl/namespace/namespace_create.go | 2 +- cmd/nerdctl/namespace/namespace_inspect.go | 2 +- cmd/nerdctl/namespace/namespace_rm.go | 2 +- cmd/nerdctl/namespace/namespace_update.go | 2 +- cmd/nerdctl/network/network.go | 10 ++--- cmd/nerdctl/network/network_create.go | 2 +- cmd/nerdctl/network/network_inspect.go | 2 +- cmd/nerdctl/network/network_ls.go | 2 +- cmd/nerdctl/network/network_prune.go | 2 +- cmd/nerdctl/network/network_rm.go | 2 +- cmd/nerdctl/{event => system}/events.go | 2 +- cmd/nerdctl/system/system.go | 5 +-- cmd/nerdctl/system/system_prune.go | 2 +- cmd/nerdctl/volume/volume.go | 10 ++--- cmd/nerdctl/volume/volume_create.go | 2 +- cmd/nerdctl/volume/volume_inspect.go | 2 +- cmd/nerdctl/volume/volume_ls.go | 2 +- cmd/nerdctl/volume/volume_prune.go | 2 +- cmd/nerdctl/volume/volume_rm.go | 2 +- integration/build_test.go | 24 +++++----- integration/builder_linux_test.go | 4 +- integration/image_prune_test.go | 4 +- integration/images_test.go | 4 +- integration/ipfs_build_linux_test.go | 4 +- integration/multi_platform_linux_test.go | 6 +-- integration/pull_linux_test.go | 8 ++-- integration/run_mount_linux_test.go | 12 ++--- integration/run_test.go | 6 +-- integration/run_verify_linux_test.go | 4 +- 71 files changed, 171 insertions(+), 190 deletions(-) rename cmd/nerdctl/{build => builder}/build.go (99%) rename cmd/nerdctl/container/{cp => }/cp.go (98%) rename cmd/nerdctl/container/{cp => }/cp_freebsd.go (97%) rename cmd/nerdctl/container/{cp => }/cp_linux.go (99%) rename cmd/nerdctl/container/{cp => }/cp_windows.go (97%) rename cmd/nerdctl/container/{exec => }/exec.go (99%) rename cmd/nerdctl/container/{exec => }/exec_freebsd.go (97%) rename cmd/nerdctl/container/{exec => }/exec_linux.go (98%) rename cmd/nerdctl/container/{exec => }/exec_windows.go (97%) rename cmd/nerdctl/{ps => container}/ps.go (98%) rename cmd/nerdctl/{stats => container}/stats.go (99%) rename cmd/nerdctl/{stats => container}/stats_freebsd.go (98%) rename cmd/nerdctl/{stats => container}/stats_linux.go (99%) rename cmd/nerdctl/{stats => container}/stats_windows.go (98%) rename cmd/nerdctl/{top => container}/top.go (99%) rename cmd/nerdctl/{history => image}/history.go (99%) rename cmd/nerdctl/{load => image}/load.go (99%) rename cmd/nerdctl/{pull => image}/pull.go (99%) rename cmd/nerdctl/{push => image}/push.go (99%) rename cmd/nerdctl/{rmi => image}/rmi.go (97%) rename cmd/nerdctl/{save => image}/save.go (99%) rename cmd/nerdctl/{tag => image}/tag.go (99%) rename cmd/nerdctl/ipfs/{ => registry}/ipfs_registry.go (88%) rename cmd/nerdctl/ipfs/{ => registry}/ipfs_registry_down.go (97%) rename cmd/nerdctl/ipfs/{ => registry}/ipfs_registry_serve.go (97%) rename cmd/nerdctl/ipfs/{ => registry}/ipfs_registry_up.go (98%) rename cmd/nerdctl/{event => system}/events.go (99%) diff --git a/cmd/nerdctl/build/build.go b/cmd/nerdctl/builder/build.go similarity index 99% rename from cmd/nerdctl/build/build.go rename to cmd/nerdctl/builder/build.go index 3b4c591a56c..208840855ea 100644 --- a/cmd/nerdctl/build/build.go +++ b/cmd/nerdctl/builder/build.go @@ -14,7 +14,7 @@ limitations under the License. */ -package build +package builder import ( "encoding/json" diff --git a/cmd/nerdctl/builder/builder.go b/cmd/nerdctl/builder/builder.go index a0a3f1c7266..36ae0b80b06 100644 --- a/cmd/nerdctl/builder/builder.go +++ b/cmd/nerdctl/builder/builder.go @@ -22,7 +22,6 @@ import ( "os/exec" "strings" - "github.com/containerd/nerdctl/cmd/nerdctl/build" "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" @@ -42,13 +41,14 @@ func NewBuilderCommand() *cobra.Command { SilenceErrors: true, } builderCommand.AddCommand( - newBuilderPruneCommand(), - newBuilderDebugCommand(), + NewBuildCommand(), + NewPruneCommand(), + NewDebugCommand(), ) return builderCommand } -func newBuilderPruneCommand() *cobra.Command { +func NewPruneCommand() *cobra.Command { shortHelp := `Clean up BuildKit build cache` var buildPruneCommand = &cobra.Command{ Use: "prune", @@ -64,7 +64,7 @@ func newBuilderPruneCommand() *cobra.Command { } func builderPruneAction(cmd *cobra.Command, _ []string) error { - buildkitHost, err := build.GetBuildkitHost(cmd) + buildkitHost, err := GetBuildkitHost(cmd) if err != nil { return err } @@ -81,7 +81,7 @@ func builderPruneAction(cmd *cobra.Command, _ []string) error { return buildctlCmd.Run() } -func newBuilderDebugCommand() *cobra.Command { +func NewDebugCommand() *cobra.Command { shortHelp := `Debug Dockerfile` var buildDebugCommand = &cobra.Command{ Use: "debug", diff --git a/cmd/nerdctl/container/container.go b/cmd/nerdctl/container/container.go index e06cf709b58..88aecdde027 100644 --- a/cmd/nerdctl/container/container.go +++ b/cmd/nerdctl/container/container.go @@ -18,9 +18,6 @@ package container import ( "github.com/containerd/nerdctl/cmd/nerdctl/completion" - "github.com/containerd/nerdctl/cmd/nerdctl/container/cp" - "github.com/containerd/nerdctl/cmd/nerdctl/container/exec" - "github.com/containerd/nerdctl/cmd/nerdctl/ps" "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" "github.com/spf13/cobra" ) @@ -38,9 +35,9 @@ func NewContainerCommand() *cobra.Command { NewCreateCommand(), NewRunCommand(), NewUpdateCommand(), - exec.NewExecCommand(), - LsCommand(), - NewContainerInspectCommand(), + NewExecCommand(), + NewLsCommand(), + NewInspectCommand(), NewLogsCommand(), NewPortCommand(), NewRmCommand(), @@ -53,14 +50,16 @@ func NewContainerCommand() *cobra.Command { NewUnpauseCommand(), NewCommitCommand(), NewRenameCommand(), - NewContainerPruneCommand(), + NewPruneCommand(), + NewTopCommand(), + NewStatsCommand(), ) - cp.AddCpCommand(containerCommand) + AddCpCommand(containerCommand) return containerCommand } -func LsCommand() *cobra.Command { - x := ps.NewPsCommand() +func NewLsCommand() *cobra.Command { + x := NewPsCommandForMain() x.Use = "ls" x.Aliases = []string{"list"} return x diff --git a/cmd/nerdctl/container/container_inspect.go b/cmd/nerdctl/container/container_inspect.go index 38d79882bbd..546fe9e8eb5 100644 --- a/cmd/nerdctl/container/container_inspect.go +++ b/cmd/nerdctl/container/container_inspect.go @@ -31,7 +31,7 @@ import ( "github.com/spf13/cobra" ) -func NewContainerInspectCommand() *cobra.Command { +func NewInspectCommand() *cobra.Command { var containerInspectCommand = &cobra.Command{ Use: "inspect [flags] CONTAINER [CONTAINER, ...]", Short: "Display detailed information on one or more containers.", diff --git a/cmd/nerdctl/container/container_prune.go b/cmd/nerdctl/container/container_prune.go index 3dd534f2f5e..d37d4aacfe4 100644 --- a/cmd/nerdctl/container/container_prune.go +++ b/cmd/nerdctl/container/container_prune.go @@ -31,7 +31,7 @@ import ( "github.com/spf13/cobra" ) -func NewContainerPruneCommand() *cobra.Command { +func NewPruneCommand() *cobra.Command { containerPruneCommand := &cobra.Command{ Use: "prune [flags]", Short: "Remove all stopped containers", diff --git a/cmd/nerdctl/container/cp/cp.go b/cmd/nerdctl/container/cp.go similarity index 98% rename from cmd/nerdctl/container/cp/cp.go rename to cmd/nerdctl/container/cp.go index 28623470331..716fc8fc5c9 100644 --- a/cmd/nerdctl/container/cp/cp.go +++ b/cmd/nerdctl/container/cp.go @@ -14,7 +14,7 @@ limitations under the License. */ -package cp +package container import ( "errors" diff --git a/cmd/nerdctl/container/cp/cp_freebsd.go b/cmd/nerdctl/container/cp_freebsd.go similarity index 97% rename from cmd/nerdctl/container/cp/cp_freebsd.go rename to cmd/nerdctl/container/cp_freebsd.go index 8b82c5f5a1d..4e7d2cfd518 100644 --- a/cmd/nerdctl/container/cp/cp_freebsd.go +++ b/cmd/nerdctl/container/cp_freebsd.go @@ -14,7 +14,7 @@ limitations under the License. */ -package cp +package container import "github.com/spf13/cobra" diff --git a/cmd/nerdctl/container/cp/cp_linux.go b/cmd/nerdctl/container/cp_linux.go similarity index 99% rename from cmd/nerdctl/container/cp/cp_linux.go rename to cmd/nerdctl/container/cp_linux.go index 6248fb2989b..54718ef5fef 100644 --- a/cmd/nerdctl/container/cp/cp_linux.go +++ b/cmd/nerdctl/container/cp_linux.go @@ -14,7 +14,7 @@ limitations under the License. */ -package cp +package container import ( "context" diff --git a/cmd/nerdctl/container/cp/cp_windows.go b/cmd/nerdctl/container/cp_windows.go similarity index 97% rename from cmd/nerdctl/container/cp/cp_windows.go rename to cmd/nerdctl/container/cp_windows.go index 8b82c5f5a1d..4e7d2cfd518 100644 --- a/cmd/nerdctl/container/cp/cp_windows.go +++ b/cmd/nerdctl/container/cp_windows.go @@ -14,7 +14,7 @@ limitations under the License. */ -package cp +package container import "github.com/spf13/cobra" diff --git a/cmd/nerdctl/container/exec/exec.go b/cmd/nerdctl/container/exec.go similarity index 99% rename from cmd/nerdctl/container/exec/exec.go rename to cmd/nerdctl/container/exec.go index 96d23d476bb..80be262d1c0 100644 --- a/cmd/nerdctl/container/exec/exec.go +++ b/cmd/nerdctl/container/exec.go @@ -14,7 +14,7 @@ limitations under the License. */ -package exec +package container import ( "context" diff --git a/cmd/nerdctl/container/exec/exec_freebsd.go b/cmd/nerdctl/container/exec_freebsd.go similarity index 97% rename from cmd/nerdctl/container/exec/exec_freebsd.go rename to cmd/nerdctl/container/exec_freebsd.go index b64da690cc8..57ebca59e4a 100644 --- a/cmd/nerdctl/container/exec/exec_freebsd.go +++ b/cmd/nerdctl/container/exec_freebsd.go @@ -14,7 +14,7 @@ limitations under the License. */ -package exec +package container import ( "github.com/opencontainers/runtime-spec/specs-go" diff --git a/cmd/nerdctl/container/exec/exec_linux.go b/cmd/nerdctl/container/exec_linux.go similarity index 98% rename from cmd/nerdctl/container/exec/exec_linux.go rename to cmd/nerdctl/container/exec_linux.go index ecc08bcfb95..28fb7c09028 100644 --- a/cmd/nerdctl/container/exec/exec_linux.go +++ b/cmd/nerdctl/container/exec_linux.go @@ -14,7 +14,7 @@ limitations under the License. */ -package exec +package container import ( "github.com/containerd/containerd/pkg/cap" diff --git a/cmd/nerdctl/container/exec/exec_windows.go b/cmd/nerdctl/container/exec_windows.go similarity index 97% rename from cmd/nerdctl/container/exec/exec_windows.go rename to cmd/nerdctl/container/exec_windows.go index ffd51e4c6cc..0e8eb6bc563 100644 --- a/cmd/nerdctl/container/exec/exec_windows.go +++ b/cmd/nerdctl/container/exec_windows.go @@ -14,7 +14,7 @@ limitations under the License. */ -package exec +package container import ( "github.com/opencontainers/runtime-spec/specs-go" diff --git a/cmd/nerdctl/ps/ps.go b/cmd/nerdctl/container/ps.go similarity index 98% rename from cmd/nerdctl/ps/ps.go rename to cmd/nerdctl/container/ps.go index 59a116dfeee..0182dc30201 100644 --- a/cmd/nerdctl/ps/ps.go +++ b/cmd/nerdctl/container/ps.go @@ -14,7 +14,7 @@ limitations under the License. */ -package ps +package container import ( "bytes" @@ -42,7 +42,8 @@ import ( "github.com/spf13/cobra" ) -func NewPsCommand() *cobra.Command { +// NewPsCommandForMain is a top-level subcommand. +func NewPsCommandForMain() *cobra.Command { var psCommand = &cobra.Command{ Use: "ps", Args: cobra.NoArgs, diff --git a/cmd/nerdctl/stats/stats.go b/cmd/nerdctl/container/stats.go similarity index 99% rename from cmd/nerdctl/stats/stats.go rename to cmd/nerdctl/container/stats.go index 21a5249e8c1..d45481e5918 100644 --- a/cmd/nerdctl/stats/stats.go +++ b/cmd/nerdctl/container/stats.go @@ -14,7 +14,7 @@ limitations under the License. */ -package stats +package container import ( "bytes" diff --git a/cmd/nerdctl/stats/stats_freebsd.go b/cmd/nerdctl/container/stats_freebsd.go similarity index 98% rename from cmd/nerdctl/stats/stats_freebsd.go rename to cmd/nerdctl/container/stats_freebsd.go index 44f233c2a75..e2dbea58ea6 100644 --- a/cmd/nerdctl/stats/stats_freebsd.go +++ b/cmd/nerdctl/container/stats_freebsd.go @@ -14,7 +14,7 @@ limitations under the License. */ -package stats +package container import ( "github.com/containerd/nerdctl/pkg/inspecttypes/native" diff --git a/cmd/nerdctl/stats/stats_linux.go b/cmd/nerdctl/container/stats_linux.go similarity index 99% rename from cmd/nerdctl/stats/stats_linux.go rename to cmd/nerdctl/container/stats_linux.go index 0b6b4ba39f5..e695b515a56 100644 --- a/cmd/nerdctl/stats/stats_linux.go +++ b/cmd/nerdctl/container/stats_linux.go @@ -14,7 +14,7 @@ limitations under the License. */ -package stats +package container import ( "errors" diff --git a/cmd/nerdctl/stats/stats_windows.go b/cmd/nerdctl/container/stats_windows.go similarity index 98% rename from cmd/nerdctl/stats/stats_windows.go rename to cmd/nerdctl/container/stats_windows.go index 44f233c2a75..e2dbea58ea6 100644 --- a/cmd/nerdctl/stats/stats_windows.go +++ b/cmd/nerdctl/container/stats_windows.go @@ -14,7 +14,7 @@ limitations under the License. */ -package stats +package container import ( "github.com/containerd/nerdctl/pkg/inspecttypes/native" diff --git a/cmd/nerdctl/top/top.go b/cmd/nerdctl/container/top.go similarity index 99% rename from cmd/nerdctl/top/top.go rename to cmd/nerdctl/container/top.go index dfb16ea7007..5632b4bb836 100644 --- a/cmd/nerdctl/top/top.go +++ b/cmd/nerdctl/container/top.go @@ -23,7 +23,7 @@ NOTICE: https://github.com/moby/moby/blob/v20.10.6/NOTICE */ -package top +package container import ( "context" diff --git a/cmd/nerdctl/history/history.go b/cmd/nerdctl/image/history.go similarity index 99% rename from cmd/nerdctl/history/history.go rename to cmd/nerdctl/image/history.go index 61f74aeaa79..b0195995743 100644 --- a/cmd/nerdctl/history/history.go +++ b/cmd/nerdctl/image/history.go @@ -14,7 +14,7 @@ limitations under the License. */ -package history +package image import ( "bytes" diff --git a/cmd/nerdctl/image/image.go b/cmd/nerdctl/image/image.go index 489771764bf..2d076a9ca43 100644 --- a/cmd/nerdctl/image/image.go +++ b/cmd/nerdctl/image/image.go @@ -17,15 +17,8 @@ package image import ( - "github.com/containerd/nerdctl/cmd/nerdctl/build" + "github.com/containerd/nerdctl/cmd/nerdctl/builder" "github.com/containerd/nerdctl/cmd/nerdctl/completion" - "github.com/containerd/nerdctl/cmd/nerdctl/history" - "github.com/containerd/nerdctl/cmd/nerdctl/load" - "github.com/containerd/nerdctl/cmd/nerdctl/pull" - "github.com/containerd/nerdctl/cmd/nerdctl/push" - "github.com/containerd/nerdctl/cmd/nerdctl/rmi" - "github.com/containerd/nerdctl/cmd/nerdctl/save" - "github.com/containerd/nerdctl/cmd/nerdctl/tag" "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" "github.com/spf13/cobra" ) @@ -40,34 +33,34 @@ func NewImageCommand() *cobra.Command { SilenceErrors: true, } cmd.AddCommand( - build.NewBuildCommand(), + builder.NewBuildCommand(), // commitCommand is in "container", not in "image" - LsCommand(), - history.NewHistoryCommand(), - pull.NewPullCommand(), - push.NewPushCommand(), - load.NewLoadCommand(), - save.NewSaveCommand(), - tag.NewTagCommand(), - RmCommand(), - NewImageConvertCommand(), - NewImageInspectCommand(), - NewImageEncryptCommand(), - NewImageDecryptCommand(), - NewImagePruneCommand(), + NewLsCommand(), + NewHistoryCommand(), + NewPullCommand(), + NewPushCommand(), + NewLoadCommand(), + NewSaveCommand(), + NewTagCommand(), + NewRmCommand(), + NewConvertCommand(), + NewInspectCommand(), + NewEncryptCommand(), + NewDecryptCommand(), + NewPruneCommand(), ) return cmd } -func LsCommand() *cobra.Command { - x := NewImagesCommand() +func NewLsCommand() *cobra.Command { + x := NewImagesCommandForMain() x.Use = "ls" x.Aliases = []string{"list"} return x } -func RmCommand() *cobra.Command { - x := rmi.NewRmiCommand() +func NewRmCommand() *cobra.Command { + x := NewRmiCommandForMain() x.Use = "rm" x.Aliases = []string{"remove"} return x diff --git a/cmd/nerdctl/image/image_convert.go b/cmd/nerdctl/image/image_convert.go index 513a5275291..06288f69f17 100644 --- a/cmd/nerdctl/image/image_convert.go +++ b/cmd/nerdctl/image/image_convert.go @@ -59,7 +59,7 @@ For encryption and decryption, use 'nerdctl image (encrypt|decrypt)' command. ` // imageConvertCommand is from https://github.com/containerd/stargz-snapshotter/blob/d58f43a8235e46da73fb94a1a35280cb4d607b2c/cmd/ctr-remote/commands/convert.go -func NewImageConvertCommand() *cobra.Command { +func NewConvertCommand() *cobra.Command { imageConvertCommand := &cobra.Command{ Use: "convert [flags] ...", Short: "convert an image", diff --git a/cmd/nerdctl/image/image_decrypt.go b/cmd/nerdctl/image/image_decrypt.go index 9dedc9a3d93..beeeed6645f 100644 --- a/cmd/nerdctl/image/image_decrypt.go +++ b/cmd/nerdctl/image/image_decrypt.go @@ -45,7 +45,7 @@ Example (decrypt): nerdctl image decrypt --key=mykey.pem example.com/foo:encrypted foo:decrypted ` -func NewImageDecryptCommand() *cobra.Command { +func NewDecryptCommand() *cobra.Command { cmd := &cobra.Command{ Use: "decrypt [flags] ...", Short: "decrypt an image", diff --git a/cmd/nerdctl/image/image_encrypt.go b/cmd/nerdctl/image/image_encrypt.go index 92e9c6ea91a..9760c46edb2 100644 --- a/cmd/nerdctl/image/image_encrypt.go +++ b/cmd/nerdctl/image/image_encrypt.go @@ -45,7 +45,7 @@ CAUTION: This command only encrypts image layers, but does NOT encrypt container To see non-encrypted information, run 'nerdctl image inspect --mode=native --platform=PLATFORM example.com/foo:encrypted' . ` -func NewImageEncryptCommand() *cobra.Command { +func NewEncryptCommand() *cobra.Command { cmd := &cobra.Command{ Use: "encrypt [flags] ...", Short: "encrypt image layers", diff --git a/cmd/nerdctl/image/image_inspect.go b/cmd/nerdctl/image/image_inspect.go index ba8f4d25f83..41f7f39b44a 100644 --- a/cmd/nerdctl/image/image_inspect.go +++ b/cmd/nerdctl/image/image_inspect.go @@ -33,7 +33,7 @@ import ( "github.com/spf13/cobra" ) -func NewImageInspectCommand() *cobra.Command { +func NewInspectCommand() *cobra.Command { var imageInspectCommand = &cobra.Command{ Use: "inspect [flags] IMAGE [IMAGE...]", Args: cobra.MinimumNArgs(1), diff --git a/cmd/nerdctl/image/image_prune.go b/cmd/nerdctl/image/image_prune.go index f127e50032b..3e0ed423e37 100644 --- a/cmd/nerdctl/image/image_prune.go +++ b/cmd/nerdctl/image/image_prune.go @@ -30,7 +30,7 @@ import ( "github.com/spf13/cobra" ) -func NewImagePruneCommand() *cobra.Command { +func NewPruneCommand() *cobra.Command { imagePruneCommand := &cobra.Command{ Use: "prune [flags]", Short: "Remove unused images", diff --git a/cmd/nerdctl/image/images.go b/cmd/nerdctl/image/images.go index 2b136732ecb..d84fe280c1d 100644 --- a/cmd/nerdctl/image/images.go +++ b/cmd/nerdctl/image/images.go @@ -48,7 +48,8 @@ import ( "github.com/spf13/cobra" ) -func NewImagesCommand() *cobra.Command { +// NewImagesCommandForMain is a top-level subcommand. +func NewImagesCommandForMain() *cobra.Command { shortHelp := "List images" longHelp := shortHelp + ` diff --git a/cmd/nerdctl/load/load.go b/cmd/nerdctl/image/load.go similarity index 99% rename from cmd/nerdctl/load/load.go rename to cmd/nerdctl/image/load.go index 6e2ce07ae0f..482025ecaed 100644 --- a/cmd/nerdctl/load/load.go +++ b/cmd/nerdctl/image/load.go @@ -14,7 +14,7 @@ limitations under the License. */ -package load +package image import ( "errors" diff --git a/cmd/nerdctl/pull/pull.go b/cmd/nerdctl/image/pull.go similarity index 99% rename from cmd/nerdctl/pull/pull.go rename to cmd/nerdctl/image/pull.go index 67071eb2f22..ff3bc0e6ba1 100644 --- a/cmd/nerdctl/pull/pull.go +++ b/cmd/nerdctl/image/pull.go @@ -14,7 +14,7 @@ limitations under the License. */ -package pull +package image import ( nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" diff --git a/cmd/nerdctl/push/push.go b/cmd/nerdctl/image/push.go similarity index 99% rename from cmd/nerdctl/push/push.go rename to cmd/nerdctl/image/push.go index 2e246186dce..d33fd9b09b5 100644 --- a/cmd/nerdctl/push/push.go +++ b/cmd/nerdctl/image/push.go @@ -14,7 +14,7 @@ limitations under the License. */ -package push +package image import ( "context" diff --git a/cmd/nerdctl/rmi/rmi.go b/cmd/nerdctl/image/rmi.go similarity index 97% rename from cmd/nerdctl/rmi/rmi.go rename to cmd/nerdctl/image/rmi.go index d3e5118734a..efb02ed3886 100644 --- a/cmd/nerdctl/rmi/rmi.go +++ b/cmd/nerdctl/image/rmi.go @@ -14,7 +14,7 @@ limitations under the License. */ -package rmi +package image import ( "context" @@ -31,7 +31,8 @@ import ( "github.com/spf13/cobra" ) -func NewRmiCommand() *cobra.Command { +// NewRmiCommandForMain is a top-level subcommand. +func NewRmiCommandForMain() *cobra.Command { var rmiCommand = &cobra.Command{ Use: "rmi [flags] IMAGE [IMAGE, ...]", Short: "Remove one or more images", diff --git a/cmd/nerdctl/save/save.go b/cmd/nerdctl/image/save.go similarity index 99% rename from cmd/nerdctl/save/save.go rename to cmd/nerdctl/image/save.go index 1739693373f..830307fd977 100644 --- a/cmd/nerdctl/save/save.go +++ b/cmd/nerdctl/image/save.go @@ -14,7 +14,7 @@ limitations under the License. */ -package save +package image import ( "fmt" diff --git a/cmd/nerdctl/tag/tag.go b/cmd/nerdctl/image/tag.go similarity index 99% rename from cmd/nerdctl/tag/tag.go rename to cmd/nerdctl/image/tag.go index d2304684eef..4fda2d19171 100644 --- a/cmd/nerdctl/tag/tag.go +++ b/cmd/nerdctl/image/tag.go @@ -14,7 +14,7 @@ limitations under the License. */ -package tag +package image import ( "context" diff --git a/cmd/nerdctl/internal/internal.go b/cmd/nerdctl/internal/internal.go index 644be4c6db2..cf8f70bf9f4 100644 --- a/cmd/nerdctl/internal/internal.go +++ b/cmd/nerdctl/internal/internal.go @@ -30,7 +30,7 @@ func NewInternalCommand() *cobra.Command { } internalCommand.AddCommand( - NewInternalOCIHookCommandCommand(), + newOCIHookCommand(), ) return internalCommand diff --git a/cmd/nerdctl/internal/internal_oci_hook.go b/cmd/nerdctl/internal/internal_oci_hook.go index a81b3150614..6b0191d5d43 100644 --- a/cmd/nerdctl/internal/internal_oci_hook.go +++ b/cmd/nerdctl/internal/internal_oci_hook.go @@ -26,7 +26,7 @@ import ( "github.com/spf13/cobra" ) -func NewInternalOCIHookCommandCommand() *cobra.Command { +func newOCIHookCommand() *cobra.Command { var internalOCIHookCommand = &cobra.Command{ Use: "oci-hook", Short: "OCI hook", diff --git a/cmd/nerdctl/ipfs/ipfs.go b/cmd/nerdctl/ipfs/ipfs.go index 3c6f20ada1e..2aaf5f750ff 100644 --- a/cmd/nerdctl/ipfs/ipfs.go +++ b/cmd/nerdctl/ipfs/ipfs.go @@ -18,6 +18,7 @@ package ipfs import ( "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/ipfs/registry" "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" "github.com/spf13/cobra" ) @@ -32,7 +33,7 @@ func NewIPFSCommand() *cobra.Command { SilenceErrors: true, } cmd.AddCommand( - NewIPFSRegistryCommand(), + registry.NewRegistryCommand(), ) return cmd } diff --git a/cmd/nerdctl/ipfs/ipfs_registry.go b/cmd/nerdctl/ipfs/registry/ipfs_registry.go similarity index 88% rename from cmd/nerdctl/ipfs/ipfs_registry.go rename to cmd/nerdctl/ipfs/registry/ipfs_registry.go index d5829315afd..e83364dce2d 100644 --- a/cmd/nerdctl/ipfs/ipfs_registry.go +++ b/cmd/nerdctl/ipfs/registry/ipfs_registry.go @@ -14,7 +14,7 @@ limitations under the License. */ -package ipfs +package registry import ( "github.com/containerd/nerdctl/cmd/nerdctl/completion" @@ -23,7 +23,7 @@ import ( "github.com/spf13/cobra" ) -func NewIPFSRegistryCommand() *cobra.Command { +func NewRegistryCommand() *cobra.Command { cmd := &cobra.Command{ Annotations: map[string]string{common.Category: common.Management}, Use: "registry", @@ -34,9 +34,9 @@ func NewIPFSRegistryCommand() *cobra.Command { SilenceErrors: true, } cmd.AddCommand( - NewIPFSRegistryServeCommand(), - NewIPFSRegistryUpCommand(), - NewIPFSRegistryDownCommand(), + NewServeCommand(), + NewUpCommand(), + NewDownCommand(), ) return cmd } diff --git a/cmd/nerdctl/ipfs/ipfs_registry_down.go b/cmd/nerdctl/ipfs/registry/ipfs_registry_down.go similarity index 97% rename from cmd/nerdctl/ipfs/ipfs_registry_down.go rename to cmd/nerdctl/ipfs/registry/ipfs_registry_down.go index 48f25c64bd2..6cc5bc567fb 100644 --- a/cmd/nerdctl/ipfs/ipfs_registry_down.go +++ b/cmd/nerdctl/ipfs/registry/ipfs_registry_down.go @@ -14,7 +14,7 @@ limitations under the License. */ -package ipfs +package registry import ( "context" @@ -27,7 +27,7 @@ import ( "github.com/spf13/cobra" ) -func NewIPFSRegistryDownCommand() *cobra.Command { +func NewDownCommand() *cobra.Command { var ipfsRegistryDownCommand = &cobra.Command{ Use: "down", Short: "stop registry as a background container \"ipfs-registry\".", diff --git a/cmd/nerdctl/ipfs/ipfs_registry_serve.go b/cmd/nerdctl/ipfs/registry/ipfs_registry_serve.go similarity index 97% rename from cmd/nerdctl/ipfs/ipfs_registry_serve.go rename to cmd/nerdctl/ipfs/registry/ipfs_registry_serve.go index fa191b91bf1..6deaa2a263a 100644 --- a/cmd/nerdctl/ipfs/ipfs_registry_serve.go +++ b/cmd/nerdctl/ipfs/registry/ipfs_registry_serve.go @@ -14,7 +14,7 @@ limitations under the License. */ -package ipfs +package registry import ( "fmt" @@ -33,7 +33,7 @@ const ( defaultIPFSReadTimeoutDuration = 0 ) -func NewIPFSRegistryServeCommand() *cobra.Command { +func NewServeCommand() *cobra.Command { var ipfsRegistryServeCommand = &cobra.Command{ Use: "serve", Short: "serve read-only registry backed by IPFS on localhost. Use \"nerdctl ipfs registry up\".", diff --git a/cmd/nerdctl/ipfs/ipfs_registry_up.go b/cmd/nerdctl/ipfs/registry/ipfs_registry_up.go similarity index 98% rename from cmd/nerdctl/ipfs/ipfs_registry_up.go rename to cmd/nerdctl/ipfs/registry/ipfs_registry_up.go index 4aa73a2bd64..6fc35f9ec33 100644 --- a/cmd/nerdctl/ipfs/ipfs_registry_up.go +++ b/cmd/nerdctl/ipfs/registry/ipfs_registry_up.go @@ -14,7 +14,7 @@ limitations under the License. */ -package ipfs +package registry import ( "context" @@ -36,7 +36,7 @@ import ( const ipfsRegistryContainerName = "ipfs-registry" -func NewIPFSRegistryUpCommand() *cobra.Command { +func NewUpCommand() *cobra.Command { var ipfsRegistryUpCommand = &cobra.Command{ Use: "up", Short: "Start registry as a background container \"ipfs-registry\", backed by the current user's IPFS API", diff --git a/cmd/nerdctl/main.go b/cmd/nerdctl/main.go index f346eefe1b6..76dcc9547db 100644 --- a/cmd/nerdctl/main.go +++ b/cmd/nerdctl/main.go @@ -27,33 +27,19 @@ import ( "github.com/containerd/containerd/defaults" "github.com/containerd/containerd/namespaces" "github.com/containerd/nerdctl/cmd/nerdctl/apparmor" - "github.com/containerd/nerdctl/cmd/nerdctl/build" "github.com/containerd/nerdctl/cmd/nerdctl/builder" "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/cmd/nerdctl/compose" "github.com/containerd/nerdctl/cmd/nerdctl/container" - "github.com/containerd/nerdctl/cmd/nerdctl/container/cp" - "github.com/containerd/nerdctl/cmd/nerdctl/container/exec" - "github.com/containerd/nerdctl/cmd/nerdctl/event" - "github.com/containerd/nerdctl/cmd/nerdctl/history" "github.com/containerd/nerdctl/cmd/nerdctl/image" "github.com/containerd/nerdctl/cmd/nerdctl/inspect" "github.com/containerd/nerdctl/cmd/nerdctl/internal" "github.com/containerd/nerdctl/cmd/nerdctl/ipfs" - "github.com/containerd/nerdctl/cmd/nerdctl/load" "github.com/containerd/nerdctl/cmd/nerdctl/login" "github.com/containerd/nerdctl/cmd/nerdctl/logout" "github.com/containerd/nerdctl/cmd/nerdctl/namespace" "github.com/containerd/nerdctl/cmd/nerdctl/network" - "github.com/containerd/nerdctl/cmd/nerdctl/ps" - "github.com/containerd/nerdctl/cmd/nerdctl/pull" - "github.com/containerd/nerdctl/cmd/nerdctl/push" - "github.com/containerd/nerdctl/cmd/nerdctl/rmi" - "github.com/containerd/nerdctl/cmd/nerdctl/save" - "github.com/containerd/nerdctl/cmd/nerdctl/stats" "github.com/containerd/nerdctl/cmd/nerdctl/system" - "github.com/containerd/nerdctl/cmd/nerdctl/tag" - "github.com/containerd/nerdctl/cmd/nerdctl/top" "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" version2 "github.com/containerd/nerdctl/cmd/nerdctl/version" @@ -296,11 +282,11 @@ Config file ($NERDCTL_TOML): %s // #region Run & Exec container.NewRunCommand(), container.NewUpdateCommand(), - exec.NewExecCommand(), + container.NewExecCommand(), // #endregion // #region Container management - ps.NewPsCommand(), + container.NewPsCommandForMain(), container.NewLogsCommand(), container.NewPortCommand(), container.NewStopCommand(), @@ -316,21 +302,21 @@ Config file ($NERDCTL_TOML): %s // #endregion // Build - build.NewBuildCommand(), + builder.NewBuildCommand(), // #region Image management - image.NewImagesCommand(), - pull.NewPullCommand(), - push.NewPushCommand(), - load.NewLoadCommand(), - save.NewSaveCommand(), - tag.NewTagCommand(), - rmi.NewRmiCommand(), - history.NewHistoryCommand(), + image.NewImagesCommandForMain(), + image.NewPullCommand(), + image.NewPushCommand(), + image.NewLoadCommand(), + image.NewSaveCommand(), + image.NewTagCommand(), + image.NewRmiCommandForMain(), + image.NewHistoryCommand(), // #endregion // #region System - event.NewEventsCommand(), + system.NewEventsCommand(), system.NewInfoCommand(), version2.NewVersionCommand(), // #endregion @@ -339,8 +325,8 @@ Config file ($NERDCTL_TOML): %s inspect.NewInspectCommand(), // stats - top.NewTopCommand(), - stats.NewStatsCommand(), + container.NewTopCommand(), + container.NewStatsCommand(), // #region Management container.NewContainerCommand(), @@ -368,7 +354,7 @@ Config file ($NERDCTL_TOML): %s ipfs.NewIPFSCommand(), ) apparmor.AddApparmorCommand(rootCmd) - cp.AddCpCommand(rootCmd) + container.AddCpCommand(rootCmd) // add aliasToBeInherited to subCommand(s) InheritedFlags for _, subCmd := range rootCmd.Commands() { diff --git a/cmd/nerdctl/namespace/namespace.go b/cmd/nerdctl/namespace/namespace.go index 762b7ba68a2..f76978aa1ed 100644 --- a/cmd/nerdctl/namespace/namespace.go +++ b/cmd/nerdctl/namespace/namespace.go @@ -43,15 +43,15 @@ func NewNamespaceCommand() *cobra.Command { SilenceUsage: true, SilenceErrors: true, } - namespaceCommand.AddCommand(NewNamespaceLsCommand()) - namespaceCommand.AddCommand(NewNamespaceRmCommand()) - namespaceCommand.AddCommand(NewNamespaceCreateCommand()) - namespaceCommand.AddCommand(NewNamespacelabelUpdateCommand()) - namespaceCommand.AddCommand(NewNamespaceInspectCommand()) + namespaceCommand.AddCommand(NewLsCommand()) + namespaceCommand.AddCommand(NewRmCommand()) + namespaceCommand.AddCommand(NewCreateCommand()) + namespaceCommand.AddCommand(NewUpdateCommand()) + namespaceCommand.AddCommand(NewInspectCommand()) return namespaceCommand } -func NewNamespaceLsCommand() *cobra.Command { +func NewLsCommand() *cobra.Command { namespaceLsCommand := &cobra.Command{ Use: "ls", Aliases: []string{"list"}, diff --git a/cmd/nerdctl/namespace/namespace_create.go b/cmd/nerdctl/namespace/namespace_create.go index 9aca9ee77bc..20e1b617712 100644 --- a/cmd/nerdctl/namespace/namespace_create.go +++ b/cmd/nerdctl/namespace/namespace_create.go @@ -22,7 +22,7 @@ import ( "github.com/spf13/cobra" ) -func NewNamespaceCreateCommand() *cobra.Command { +func NewCreateCommand() *cobra.Command { namespaceCreateCommand := &cobra.Command{ Use: "create NAMESPACE", Short: "Create a new namespace", diff --git a/cmd/nerdctl/namespace/namespace_inspect.go b/cmd/nerdctl/namespace/namespace_inspect.go index a7fd10fb3f7..d51549ec9dd 100644 --- a/cmd/nerdctl/namespace/namespace_inspect.go +++ b/cmd/nerdctl/namespace/namespace_inspect.go @@ -24,7 +24,7 @@ import ( "github.com/spf13/cobra" ) -func NewNamespaceInspectCommand() *cobra.Command { +func NewInspectCommand() *cobra.Command { namespaceInspectCommand := &cobra.Command{ Use: "inspect NAMESPACE", Short: "Display detailed information on one or more namespaces.", diff --git a/cmd/nerdctl/namespace/namespace_rm.go b/cmd/nerdctl/namespace/namespace_rm.go index 9ab2ba30c4a..0aafa40ca2f 100644 --- a/cmd/nerdctl/namespace/namespace_rm.go +++ b/cmd/nerdctl/namespace/namespace_rm.go @@ -25,7 +25,7 @@ import ( "github.com/spf13/cobra" ) -func NewNamespaceRmCommand() *cobra.Command { +func NewRmCommand() *cobra.Command { namespaceRmCommand := &cobra.Command{ Use: "remove [flags] NAMESPACE [NAMESPACE...]", Aliases: []string{"rm"}, diff --git a/cmd/nerdctl/namespace/namespace_update.go b/cmd/nerdctl/namespace/namespace_update.go index f6eb166ad19..6012d5f2dac 100644 --- a/cmd/nerdctl/namespace/namespace_update.go +++ b/cmd/nerdctl/namespace/namespace_update.go @@ -21,7 +21,7 @@ import ( "github.com/spf13/cobra" ) -func NewNamespacelabelUpdateCommand() *cobra.Command { +func NewUpdateCommand() *cobra.Command { namespaceLableCommand := &cobra.Command{ Use: "update [flags] NAMESPACE", Short: "Update labels for a namespace", diff --git a/cmd/nerdctl/network/network.go b/cmd/nerdctl/network/network.go index 903e63becf9..e1b24286200 100644 --- a/cmd/nerdctl/network/network.go +++ b/cmd/nerdctl/network/network.go @@ -32,11 +32,11 @@ func NewNetworkCommand() *cobra.Command { SilenceErrors: true, } networkCommand.AddCommand( - NewNetworkLsCommand(), - NewNetworkInspectCommand(), - NewNetworkCreateCommand(), - NewNetworkRmCommand(), - NewNetworkPruneCommand(), + NewLsCommand(), + NewInspectCommand(), + NewCreateCommand(), + NewRmCommand(), + NewPruneCommand(), ) return networkCommand } diff --git a/cmd/nerdctl/network/network_create.go b/cmd/nerdctl/network/network_create.go index c9127e07f89..dcda2859440 100644 --- a/cmd/nerdctl/network/network_create.go +++ b/cmd/nerdctl/network/network_create.go @@ -28,7 +28,7 @@ import ( "github.com/spf13/cobra" ) -func NewNetworkCreateCommand() *cobra.Command { +func NewCreateCommand() *cobra.Command { var networkCreateCommand = &cobra.Command{ Use: "create [flags] NETWORK", Short: "Create a network", diff --git a/cmd/nerdctl/network/network_inspect.go b/cmd/nerdctl/network/network_inspect.go index 30cda74f999..4df86c2fb59 100644 --- a/cmd/nerdctl/network/network_inspect.go +++ b/cmd/nerdctl/network/network_inspect.go @@ -29,7 +29,7 @@ import ( "github.com/spf13/cobra" ) -func NewNetworkInspectCommand() *cobra.Command { +func NewInspectCommand() *cobra.Command { networkInspectCommand := &cobra.Command{ Use: "inspect [flags] NETWORK [NETWORK, ...]", Short: "Display detailed information on one or more networks", diff --git a/cmd/nerdctl/network/network_ls.go b/cmd/nerdctl/network/network_ls.go index b1b7a70998a..388f3f3fdc1 100644 --- a/cmd/nerdctl/network/network_ls.go +++ b/cmd/nerdctl/network/network_ls.go @@ -29,7 +29,7 @@ import ( "github.com/spf13/cobra" ) -func NewNetworkLsCommand() *cobra.Command { +func NewLsCommand() *cobra.Command { cmd := &cobra.Command{ Use: "ls", Aliases: []string{"list"}, diff --git a/cmd/nerdctl/network/network_prune.go b/cmd/nerdctl/network/network_prune.go index abea9fb3fc7..66f9d1ca97d 100644 --- a/cmd/nerdctl/network/network_prune.go +++ b/cmd/nerdctl/network/network_prune.go @@ -31,7 +31,7 @@ import ( var networkDriversToKeep = []string{"host", "none", DefaultNetworkDriver} -func NewNetworkPruneCommand() *cobra.Command { +func NewPruneCommand() *cobra.Command { networkPruneCommand := &cobra.Command{ Use: "prune [flags]", Short: "Remove all unused networks", diff --git a/cmd/nerdctl/network/network_rm.go b/cmd/nerdctl/network/network_rm.go index d1cf988c9b7..39b12551e71 100644 --- a/cmd/nerdctl/network/network_rm.go +++ b/cmd/nerdctl/network/network_rm.go @@ -30,7 +30,7 @@ import ( "github.com/spf13/cobra" ) -func NewNetworkRmCommand() *cobra.Command { +func NewRmCommand() *cobra.Command { networkRmCommand := &cobra.Command{ Use: "rm [flags] NETWORK [NETWORK, ...]", Aliases: []string{"remove"}, diff --git a/cmd/nerdctl/event/events.go b/cmd/nerdctl/system/events.go similarity index 99% rename from cmd/nerdctl/event/events.go rename to cmd/nerdctl/system/events.go index cb842d859e3..a4794632d20 100644 --- a/cmd/nerdctl/event/events.go +++ b/cmd/nerdctl/system/events.go @@ -14,7 +14,7 @@ limitations under the License. */ -package event +package system import ( "bytes" diff --git a/cmd/nerdctl/system/system.go b/cmd/nerdctl/system/system.go index 5142dfb86cf..9565d4df47d 100644 --- a/cmd/nerdctl/system/system.go +++ b/cmd/nerdctl/system/system.go @@ -18,7 +18,6 @@ package system import ( "github.com/containerd/nerdctl/cmd/nerdctl/completion" - "github.com/containerd/nerdctl/cmd/nerdctl/event" "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" "github.com/spf13/cobra" ) @@ -34,9 +33,9 @@ func NewSystemCommand() *cobra.Command { } // versionCommand is not here systemCommand.AddCommand( - event.NewEventsCommand(), + NewEventsCommand(), NewInfoCommand(), - NewSystemPruneCommand(), + NewPruneCommand(), ) return systemCommand } diff --git a/cmd/nerdctl/system/system_prune.go b/cmd/nerdctl/system/system_prune.go index 4388c561dab..98ef07924b7 100644 --- a/cmd/nerdctl/system/system_prune.go +++ b/cmd/nerdctl/system/system_prune.go @@ -29,7 +29,7 @@ import ( "github.com/spf13/cobra" ) -func NewSystemPruneCommand() *cobra.Command { +func NewPruneCommand() *cobra.Command { systemPruneCommand := &cobra.Command{ Use: "prune [flags]", Short: "Remove unused data", diff --git a/cmd/nerdctl/volume/volume.go b/cmd/nerdctl/volume/volume.go index faae4beb90a..6119be176d9 100644 --- a/cmd/nerdctl/volume/volume.go +++ b/cmd/nerdctl/volume/volume.go @@ -32,11 +32,11 @@ func NewVolumeCommand() *cobra.Command { SilenceErrors: true, } volumeCommand.AddCommand( - NewVolumeLsCommand(), - NewVolumeInspectCommand(), - NewVolumeCreateCommand(), - NewVolumeRmCommand(), - NewVolumePruneCommand(), + NewLsCommand(), + NewInspectCommand(), + NewCreateCommand(), + NewRmCommand(), + NewPruneCommand(), ) return volumeCommand } diff --git a/cmd/nerdctl/volume/volume_create.go b/cmd/nerdctl/volume/volume_create.go index a7b84dea08a..d3914e51f7c 100644 --- a/cmd/nerdctl/volume/volume_create.go +++ b/cmd/nerdctl/volume/volume_create.go @@ -27,7 +27,7 @@ import ( "github.com/spf13/cobra" ) -func NewVolumeCreateCommand() *cobra.Command { +func NewCreateCommand() *cobra.Command { volumeCreateCommand := &cobra.Command{ Use: "create [flags] VOLUME", Short: "Create a volume", diff --git a/cmd/nerdctl/volume/volume_inspect.go b/cmd/nerdctl/volume/volume_inspect.go index cb82567b6b0..6ac6e29c6f9 100644 --- a/cmd/nerdctl/volume/volume_inspect.go +++ b/cmd/nerdctl/volume/volume_inspect.go @@ -23,7 +23,7 @@ import ( "github.com/spf13/cobra" ) -func NewVolumeInspectCommand() *cobra.Command { +func NewInspectCommand() *cobra.Command { volumeInspectCommand := &cobra.Command{ Use: "inspect [flags] VOLUME [VOLUME...]", Short: "Display detailed information on one or more volumes", diff --git a/cmd/nerdctl/volume/volume_ls.go b/cmd/nerdctl/volume/volume_ls.go index 924646063cd..4343cdcca9d 100644 --- a/cmd/nerdctl/volume/volume_ls.go +++ b/cmd/nerdctl/volume/volume_ls.go @@ -34,7 +34,7 @@ import ( "github.com/spf13/cobra" ) -func NewVolumeLsCommand() *cobra.Command { +func NewLsCommand() *cobra.Command { volumeLsCommand := &cobra.Command{ Use: "ls", Aliases: []string{"list"}, diff --git a/cmd/nerdctl/volume/volume_prune.go b/cmd/nerdctl/volume/volume_prune.go index d23c3ed4675..11a4c746b68 100644 --- a/cmd/nerdctl/volume/volume_prune.go +++ b/cmd/nerdctl/volume/volume_prune.go @@ -27,7 +27,7 @@ import ( "github.com/spf13/cobra" ) -func NewVolumePruneCommand() *cobra.Command { +func NewPruneCommand() *cobra.Command { volumePruneCommand := &cobra.Command{ Use: "prune [flags]", Short: "Remove all unused local volumes", diff --git a/cmd/nerdctl/volume/volume_rm.go b/cmd/nerdctl/volume/volume_rm.go index 7d3ff1944ad..7ae5385c776 100644 --- a/cmd/nerdctl/volume/volume_rm.go +++ b/cmd/nerdctl/volume/volume_rm.go @@ -31,7 +31,7 @@ import ( "github.com/spf13/cobra" ) -func NewVolumeRmCommand() *cobra.Command { +func NewRmCommand() *cobra.Command { volumeRmCommand := &cobra.Command{ Use: "rm [flags] VOLUME [VOLUME...]", Aliases: []string{"remove"}, diff --git a/integration/build_test.go b/integration/build_test.go index ce0b08e57e4..db5873a80d6 100644 --- a/integration/build_test.go +++ b/integration/build_test.go @@ -23,7 +23,7 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/cmd/nerdctl/build" + "github.com/containerd/nerdctl/cmd/nerdctl/builder" "github.com/containerd/nerdctl/pkg/testutil" "gotest.tools/v3/assert" ) @@ -39,7 +39,7 @@ func TestBuild(t *testing.T) { CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) - buildCtx, err := build.CreateBuildContext(dockerfile) + buildCtx, err := builder.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) @@ -69,7 +69,7 @@ RUN echo hello > /hello CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) - buildCtx, err := build.CreateBuildContext(dockerfile) + buildCtx, err := builder.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) @@ -81,7 +81,7 @@ RUN echo hello2 > /hello2 CMD ["cat", "/hello2"] `, imageName) - buildCtx2, err := build.CreateBuildContext(dockerfile2) + buildCtx2, err := builder.CreateBuildContext(dockerfile2) assert.NilError(t, err) defer os.RemoveAll(buildCtx2) @@ -116,7 +116,7 @@ RUN echo hello2 > /hello2 CMD ["cat", "/hello2"] `, imageName) - buildCtx2, err := build.CreateBuildContext(dockerfile2) + buildCtx2, err := builder.CreateBuildContext(dockerfile2) assert.NilError(t, err) defer os.RemoveAll(buildCtx2) @@ -189,7 +189,7 @@ func TestBuildLocal(t *testing.T) { COPY %s /`, testFileName) - buildCtx, err := build.CreateBuildContext(dockerfile) + buildCtx, err := builder.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) @@ -230,7 +230,7 @@ ENV TEST_STRING=$TEST_STRING CMD echo $TEST_STRING `, testutil.CommonImage) - buildCtx, err := build.CreateBuildContext(dockerfile) + buildCtx, err := builder.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) @@ -281,7 +281,7 @@ func TestBuildWithIIDFile(t *testing.T) { CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) - buildCtx, err := build.CreateBuildContext(dockerfile) + buildCtx, err := builder.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) fileName := filepath.Join(t.TempDir(), "id.txt") @@ -307,7 +307,7 @@ func TestBuildWithLabels(t *testing.T) { LABEL name=nerdctl-build-test-label `, testutil.CommonImage) - buildCtx, err := build.CreateBuildContext(dockerfile) + buildCtx, err := builder.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) @@ -331,7 +331,7 @@ func TestBuildMultipleTags(t *testing.T) { CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) - buildCtx, err := build.CreateBuildContext(dockerfile) + buildCtx, err := builder.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) @@ -385,7 +385,7 @@ CMD ["echo", "dockerfile"] err = os.WriteFile(filepath.Join(tmpDir, "Containerfile"), []byte(containerfile), 0644) assert.NilError(t, err) - buildCtx, err := build.CreateBuildContext(dockerfile) + buildCtx, err := builder.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) @@ -402,7 +402,7 @@ func TestBuildNoTag(t *testing.T) { dockerfile := fmt.Sprintf(`FROM %s CMD ["echo", "nerdctl-build-notag-string"] `, testutil.CommonImage) - buildCtx, err := build.CreateBuildContext(dockerfile) + buildCtx, err := builder.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) diff --git a/integration/builder_linux_test.go b/integration/builder_linux_test.go index 5ac13ae2a9c..5b62adef9a9 100644 --- a/integration/builder_linux_test.go +++ b/integration/builder_linux_test.go @@ -22,7 +22,7 @@ import ( "os" "testing" - "github.com/containerd/nerdctl/cmd/nerdctl/build" + "github.com/containerd/nerdctl/cmd/nerdctl/builder" "github.com/containerd/nerdctl/pkg/testutil" "gotest.tools/v3/assert" ) @@ -35,7 +35,7 @@ func TestBuilderDebug(t *testing.T) { CMD ["echo", "nerdctl-builder-debug-test-string"] `, testutil.CommonImage) - buildCtx, err := build.CreateBuildContext(dockerfile) + buildCtx, err := builder.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) diff --git a/integration/image_prune_test.go b/integration/image_prune_test.go index 3e23c043864..09a17e04c93 100644 --- a/integration/image_prune_test.go +++ b/integration/image_prune_test.go @@ -21,7 +21,7 @@ import ( "os" "testing" - "github.com/containerd/nerdctl/cmd/nerdctl/build" + "github.com/containerd/nerdctl/cmd/nerdctl/builder" "github.com/containerd/nerdctl/pkg/testutil" "gotest.tools/v3/assert" ) @@ -37,7 +37,7 @@ func TestImagePrune(t *testing.T) { dockerfile := fmt.Sprintf(`FROM %s CMD ["echo", "nerdctl-test-image-prune"]`, testutil.CommonImage) - buildCtx, err := build.CreateBuildContext(dockerfile) + buildCtx, err := builder.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) diff --git a/integration/images_test.go b/integration/images_test.go index adfa914c16a..4f5ef6184c8 100644 --- a/integration/images_test.go +++ b/integration/images_test.go @@ -22,7 +22,7 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/cmd/nerdctl/build" + "github.com/containerd/nerdctl/cmd/nerdctl/builder" "github.com/containerd/nerdctl/pkg/tabutil" "github.com/containerd/nerdctl/pkg/testutil" "gotest.tools/v3/assert" @@ -89,7 +89,7 @@ CMD ["echo", "nerdctl-build-test-string"] \n LABEL foo=bar LABEL version=0.1`, testutil.CommonImage) - buildCtx, err := build.CreateBuildContext(dockerfile) + buildCtx, err := builder.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) base.Cmd("build", "-t", tempName, "-f", buildCtx+"/Dockerfile", buildCtx).AssertOK() diff --git a/integration/ipfs_build_linux_test.go b/integration/ipfs_build_linux_test.go index fd70dd79502..bbdf718bff1 100644 --- a/integration/ipfs_build_linux_test.go +++ b/integration/ipfs_build_linux_test.go @@ -22,7 +22,7 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/cmd/nerdctl/build" + "github.com/containerd/nerdctl/cmd/nerdctl/builder" "github.com/containerd/nerdctl/pkg/testutil" "gotest.tools/v3/assert" @@ -44,7 +44,7 @@ func TestIPFSBuild(t *testing.T) { CMD ["echo", "nerdctl-build-test-string"] `, ipfsCIDBase) - buildCtx, err := build.CreateBuildContext(dockerfile) + buildCtx, err := builder.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) diff --git a/integration/multi_platform_linux_test.go b/integration/multi_platform_linux_test.go index 3238bd10684..f2854ef4a45 100644 --- a/integration/multi_platform_linux_test.go +++ b/integration/multi_platform_linux_test.go @@ -23,7 +23,7 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/cmd/nerdctl/build" + "github.com/containerd/nerdctl/cmd/nerdctl/builder" "github.com/containerd/nerdctl/pkg/testutil" "github.com/containerd/nerdctl/pkg/testutil/nettestutil" "github.com/containerd/nerdctl/pkg/testutil/testregistry" @@ -69,7 +69,7 @@ func TestMultiPlatformBuildPush(t *testing.T) { RUN echo dummy `, testutil.AlpineImage) - buildCtx, err := build.CreateBuildContext(dockerfile) + buildCtx, err := builder.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) @@ -98,7 +98,7 @@ func TestMultiPlatformBuildPushNoRun(t *testing.T) { CMD echo dummy `, testutil.AlpineImage) - buildCtx, err := build.CreateBuildContext(dockerfile) + buildCtx, err := builder.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) diff --git a/integration/pull_linux_test.go b/integration/pull_linux_test.go index face084e905..f3fb24b1be5 100644 --- a/integration/pull_linux_test.go +++ b/integration/pull_linux_test.go @@ -23,7 +23,7 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/cmd/nerdctl/build" + "github.com/containerd/nerdctl/cmd/nerdctl/builder" "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/pkg/testutil" "github.com/containerd/nerdctl/pkg/testutil/testregistry" @@ -54,7 +54,7 @@ func TestImageVerifyWithCosign(t *testing.T) { CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) - buildCtx, err := build.CreateBuildContext(dockerfile) + buildCtx, err := builder.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) @@ -78,7 +78,7 @@ func TestImagePullPlainHttpWithDefaultPort(t *testing.T) { CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) - buildCtx, err := build.CreateBuildContext(dockerfile) + buildCtx, err := builder.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) base.Cmd("build", "-t", testImageRef, buildCtx).AssertOK() @@ -110,7 +110,7 @@ func TestImageVerifyWithCosignShouldFailWhenKeyIsNotCorrect(t *testing.T) { CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) - buildCtx, err := build.CreateBuildContext(dockerfile) + buildCtx, err := builder.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) diff --git a/integration/run_mount_linux_test.go b/integration/run_mount_linux_test.go index c56e37b65e6..5c603cdd754 100644 --- a/integration/run_mount_linux_test.go +++ b/integration/run_mount_linux_test.go @@ -24,7 +24,7 @@ import ( "testing" "github.com/containerd/containerd/mount" - "github.com/containerd/nerdctl/cmd/nerdctl/build" + "github.com/containerd/nerdctl/cmd/nerdctl/builder" "github.com/containerd/nerdctl/pkg/rootlessutil" "github.com/containerd/nerdctl/pkg/testutil" mobymount "github.com/moby/sys/mount" @@ -102,7 +102,7 @@ func TestRunAnonymousVolumeWithBuild(t *testing.T) { VOLUME /foo `, testutil.AlpineImage) - buildCtx, err := build.CreateBuildContext(dockerfile) + buildCtx, err := builder.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) @@ -126,7 +126,7 @@ RUN mkdir -p /mnt && echo hi > /mnt/initial_file CMD ["cat", "/mnt/initial_file"] `, testutil.AlpineImage) - buildCtx, err := build.CreateBuildContext(dockerfile) + buildCtx, err := builder.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) @@ -156,7 +156,7 @@ VOLUME /mnt CMD ["cat", "/mnt/initial_file"] `, testutil.AlpineImage) - buildCtx, err := build.CreateBuildContext(dockerfile) + buildCtx, err := builder.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) @@ -191,7 +191,7 @@ CMD ["readlink", "/mnt/passwd"] `, testutil.AlpineImage) const expected = "../../../../../../../../../../../../../../../../../../etc/passwd\n" - buildCtx, err := build.CreateBuildContext(dockerfile) + buildCtx, err := builder.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) @@ -220,7 +220,7 @@ func TestRunCopyingUpInitialContentsShouldNotResetTheCopiedContents(t *testing.T RUN echo -n "rev0" > /mnt/file `, testutil.AlpineImage) - buildCtx, err := build.CreateBuildContext(dockerfile) + buildCtx, err := builder.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) diff --git a/integration/run_test.go b/integration/run_test.go index e8465db4e4a..ea2b9f2d7a4 100644 --- a/integration/run_test.go +++ b/integration/run_test.go @@ -27,7 +27,7 @@ import ( "testing" "time" - "github.com/containerd/nerdctl/cmd/nerdctl/build" + "github.com/containerd/nerdctl/cmd/nerdctl/builder" "github.com/containerd/nerdctl/pkg/testutil" "gotest.tools/v3/assert" "gotest.tools/v3/icmd" @@ -47,7 +47,7 @@ ENTRYPOINT ["echo", "foo"] CMD ["echo", "bar"] `, testutil.CommonImage) - buildCtx, err := build.CreateBuildContext(dockerfile) + buildCtx, err := builder.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) @@ -431,7 +431,7 @@ FROM scratch COPY --from=builder /go/src/logger/logger / ` - buildCtx, err := build.CreateBuildContext(dockerfile) + buildCtx, err := builder.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) tmpDir := t.TempDir() diff --git a/integration/run_verify_linux_test.go b/integration/run_verify_linux_test.go index 4bfa1f7fe74..38845cb9f79 100644 --- a/integration/run_verify_linux_test.go +++ b/integration/run_verify_linux_test.go @@ -22,7 +22,7 @@ import ( "os/exec" "testing" - "github.com/containerd/nerdctl/cmd/nerdctl/build" + "github.com/containerd/nerdctl/cmd/nerdctl/builder" "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/pkg/testutil" "github.com/containerd/nerdctl/pkg/testutil/testregistry" @@ -53,7 +53,7 @@ func TestRunVerifyCosign(t *testing.T) { CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) - buildCtx, err := build.CreateBuildContext(dockerfile) + buildCtx, err := builder.CreateBuildContext(dockerfile) assert.NilError(t, err) defer os.RemoveAll(buildCtx) From 111661277c9eb31dc1c4a65723f73f7fac58d573 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Fri, 16 Dec 2022 09:21:57 +0900 Subject: [PATCH 04/14] [Carry 1639] nerdClient -> ncclient (avoid upper chars) Signed-off-by: Akihiro Suda --- cmd/nerdctl/builder/build.go | 6 +++--- cmd/nerdctl/completion/completion_unix.go | 6 +++--- cmd/nerdctl/compose/compose_build.go | 4 ++-- cmd/nerdctl/compose/compose_config.go | 4 ++-- cmd/nerdctl/compose/compose_down.go | 4 ++-- cmd/nerdctl/compose/compose_exec.go | 4 ++-- cmd/nerdctl/compose/compose_images.go | 4 ++-- cmd/nerdctl/compose/compose_kill.go | 4 ++-- cmd/nerdctl/compose/compose_logs.go | 4 ++-- cmd/nerdctl/compose/compose_pause.go | 6 +++--- cmd/nerdctl/compose/compose_port.go | 4 ++-- cmd/nerdctl/compose/compose_ps.go | 4 ++-- cmd/nerdctl/compose/compose_pull.go | 4 ++-- cmd/nerdctl/compose/compose_push.go | 4 ++-- cmd/nerdctl/compose/compose_restart.go | 4 ++-- cmd/nerdctl/compose/compose_rm.go | 4 ++-- cmd/nerdctl/compose/compose_run.go | 4 ++-- cmd/nerdctl/compose/compose_stop.go | 4 ++-- cmd/nerdctl/compose/compose_top.go | 4 ++-- cmd/nerdctl/compose/compose_up.go | 4 ++-- cmd/nerdctl/container/commit.go | 4 ++-- cmd/nerdctl/container/container_inspect.go | 4 ++-- cmd/nerdctl/container/container_prune.go | 4 ++-- cmd/nerdctl/container/create.go | 4 ++-- cmd/nerdctl/container/exec.go | 4 ++-- cmd/nerdctl/container/kill.go | 4 ++-- cmd/nerdctl/container/logs.go | 6 +++--- cmd/nerdctl/container/pause.go | 4 ++-- cmd/nerdctl/container/port.go | 4 ++-- cmd/nerdctl/container/ps.go | 4 ++-- cmd/nerdctl/container/rename.go | 6 +++--- cmd/nerdctl/container/restart.go | 4 ++-- cmd/nerdctl/container/rm.go | 4 ++-- cmd/nerdctl/container/run.go | 4 ++-- cmd/nerdctl/container/start.go | 4 ++-- cmd/nerdctl/container/stats.go | 6 +++--- cmd/nerdctl/container/stop.go | 4 ++-- cmd/nerdctl/container/top.go | 4 ++-- cmd/nerdctl/container/unpause.go | 4 ++-- cmd/nerdctl/container/update.go | 4 ++-- cmd/nerdctl/container/wait.go | 4 ++-- cmd/nerdctl/image/history.go | 4 ++-- cmd/nerdctl/image/image_convert.go | 6 +++--- cmd/nerdctl/image/image_cryptutil.go | 4 ++-- cmd/nerdctl/image/image_inspect.go | 4 ++-- cmd/nerdctl/image/image_prune.go | 4 ++-- cmd/nerdctl/image/images.go | 4 ++-- cmd/nerdctl/image/pull.go | 4 ++-- cmd/nerdctl/image/push.go | 4 ++-- cmd/nerdctl/image/rmi.go | 4 ++-- cmd/nerdctl/image/save.go | 4 ++-- cmd/nerdctl/image/tag.go | 4 ++-- cmd/nerdctl/inspect/inspect.go | 4 ++-- cmd/nerdctl/ipfs/registry/ipfs_registry_down.go | 4 ++-- cmd/nerdctl/ipfs/registry/ipfs_registry_up.go | 6 +++--- cmd/nerdctl/namespace/namespace.go | 6 +++--- cmd/nerdctl/namespace/namespace_create.go | 4 ++-- cmd/nerdctl/namespace/namespace_inspect.go | 4 ++-- cmd/nerdctl/namespace/namespace_rm.go | 4 ++-- cmd/nerdctl/namespace/namespace_update.go | 4 ++-- cmd/nerdctl/network/network_prune.go | 4 ++-- cmd/nerdctl/network/network_rm.go | 4 ++-- cmd/nerdctl/system/events.go | 4 ++-- cmd/nerdctl/system/info.go | 4 ++-- cmd/nerdctl/system/system_prune.go | 4 ++-- cmd/nerdctl/utils/container/container_create.go | 4 ++-- cmd/nerdctl/utils/image.go | 4 ++-- cmd/nerdctl/utils/run/run_network.go | 4 ++-- cmd/nerdctl/version/version.go | 4 ++-- cmd/nerdctl/volume/volume_prune.go | 4 ++-- cmd/nerdctl/volume/volume_rm.go | 4 ++-- 71 files changed, 151 insertions(+), 151 deletions(-) diff --git a/cmd/nerdctl/builder/build.go b/cmd/nerdctl/builder/build.go index 208840855ea..d4585e57887 100644 --- a/cmd/nerdctl/builder/build.go +++ b/cmd/nerdctl/builder/build.go @@ -30,7 +30,7 @@ import ( "github.com/containerd/containerd/errdefs" dockerreference "github.com/containerd/containerd/reference/docker" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/pkg/buildkitutil" @@ -215,7 +215,7 @@ func buildAction(cmd *cobra.Command, args []string) error { if len(tags) > 1 { logrus.Debug("Found more than 1 tag") - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return fmt.Errorf("unable to tag images: %s", err) } @@ -260,7 +260,7 @@ func generateBuildctlArgs(cmd *cobra.Command, buildkitHost string, platform, arg return "", nil, false, "", nil, nil, err } if output == "" { - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return "", nil, false, "", nil, nil, err } diff --git a/cmd/nerdctl/completion/completion_unix.go b/cmd/nerdctl/completion/completion_unix.go index d6f725eaf42..2baa67407c5 100644 --- a/cmd/nerdctl/completion/completion_unix.go +++ b/cmd/nerdctl/completion/completion_unix.go @@ -19,7 +19,7 @@ package completion import ( - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/pkg/infoutil" "github.com/containerd/nerdctl/pkg/rootlessutil" "github.com/sirupsen/logrus" @@ -32,7 +32,7 @@ func ShellCompleteNamespaceNames(cmd *cobra.Command, args []string, toComplete s return nil, cobra.ShellCompDirectiveNoFileComp } - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return nil, cobra.ShellCompDirectiveError } @@ -53,7 +53,7 @@ func ShellCompleteSnapshotterNames(cmd *cobra.Command, args []string, toComplete _ = rootlessutil.ParentMain() return nil, cobra.ShellCompDirectiveNoFileComp } - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return nil, cobra.ShellCompDirectiveError } diff --git a/cmd/nerdctl/compose/compose_build.go b/cmd/nerdctl/compose/compose_build.go index 03763388e18..949cd2cf3e0 100644 --- a/cmd/nerdctl/compose/compose_build.go +++ b/cmd/nerdctl/compose/compose_build.go @@ -17,7 +17,7 @@ package compose import ( - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/pkg/composer" "github.com/spf13/cobra" ) @@ -57,7 +57,7 @@ func composeBuildAction(cmd *cobra.Command, args []string) error { return err } - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose/compose_config.go b/cmd/nerdctl/compose/compose_config.go index f64dfd09dcf..fafaf6c1e04 100644 --- a/cmd/nerdctl/compose/compose_config.go +++ b/cmd/nerdctl/compose/compose_config.go @@ -19,7 +19,7 @@ package compose import ( "fmt" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/pkg/composer" "github.com/spf13/cobra" ) @@ -64,7 +64,7 @@ func composeConfigAction(cmd *cobra.Command, args []string) error { return err } - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose/compose_down.go b/cmd/nerdctl/compose/compose_down.go index 06136924ef5..7601e5f8039 100644 --- a/cmd/nerdctl/compose/compose_down.go +++ b/cmd/nerdctl/compose/compose_down.go @@ -17,7 +17,7 @@ package compose import ( - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/pkg/composer" "github.com/spf13/cobra" ) @@ -40,7 +40,7 @@ func composeDownAction(cmd *cobra.Command, args []string) error { if err != nil { return err } - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose/compose_exec.go b/cmd/nerdctl/compose/compose_exec.go index 1a8ef882311..a3805c48c41 100644 --- a/cmd/nerdctl/compose/compose_exec.go +++ b/cmd/nerdctl/compose/compose_exec.go @@ -19,7 +19,7 @@ package compose import ( "errors" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/pkg/composer" "github.com/spf13/cobra" ) @@ -95,7 +95,7 @@ func composeExecAction(cmd *cobra.Command, args []string) error { return errors.New("currently flag -t and -d cannot be specified together (FIXME)") } - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose/compose_images.go b/cmd/nerdctl/compose/compose_images.go index 3724f1146dc..8a212f91a8a 100644 --- a/cmd/nerdctl/compose/compose_images.go +++ b/cmd/nerdctl/compose/compose_images.go @@ -25,7 +25,7 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/pkg/progress" "github.com/containerd/containerd/snapshots" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/pkg/imgutil" "github.com/containerd/nerdctl/pkg/labels" @@ -53,7 +53,7 @@ func composeImagesAction(cmd *cobra.Command, args []string) error { return err } - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose/compose_kill.go b/cmd/nerdctl/compose/compose_kill.go index 14920d18d0c..e7ef0fb5c85 100644 --- a/cmd/nerdctl/compose/compose_kill.go +++ b/cmd/nerdctl/compose/compose_kill.go @@ -17,7 +17,7 @@ package compose import ( - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/pkg/composer" "github.com/spf13/cobra" ) @@ -39,7 +39,7 @@ func composeKillAction(cmd *cobra.Command, args []string) error { if err != nil { return err } - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose/compose_logs.go b/cmd/nerdctl/compose/compose_logs.go index 2f148c46099..c5e456358c1 100644 --- a/cmd/nerdctl/compose/compose_logs.go +++ b/cmd/nerdctl/compose/compose_logs.go @@ -17,7 +17,7 @@ package compose import ( - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/pkg/composer" "github.com/spf13/cobra" ) @@ -60,7 +60,7 @@ func composeLogsAction(cmd *cobra.Command, args []string) error { return err } - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose/compose_pause.go b/cmd/nerdctl/compose/compose_pause.go index d37b3a1db02..2da68c950a3 100644 --- a/cmd/nerdctl/compose/compose_pause.go +++ b/cmd/nerdctl/compose/compose_pause.go @@ -21,7 +21,7 @@ import ( "sync" "github.com/containerd/containerd" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/pkg/labels" "github.com/spf13/cobra" @@ -41,7 +41,7 @@ func newComposePauseCommand() *cobra.Command { } func composePauseAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } @@ -99,7 +99,7 @@ func newComposeUnpauseCommand() *cobra.Command { } func composeUnpauseAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose/compose_port.go b/cmd/nerdctl/compose/compose_port.go index e30b761be22..e3333bf9c0d 100644 --- a/cmd/nerdctl/compose/compose_port.go +++ b/cmd/nerdctl/compose/compose_port.go @@ -20,7 +20,7 @@ import ( "fmt" "strconv" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/pkg/composer" "github.com/spf13/cobra" ) @@ -67,7 +67,7 @@ func composePortAction(cmd *cobra.Command, args []string) error { return fmt.Errorf("unexpected port: %d", port) } - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose/compose_ps.go b/cmd/nerdctl/compose/compose_ps.go index ead686a9d83..b8a750779ae 100644 --- a/cmd/nerdctl/compose/compose_ps.go +++ b/cmd/nerdctl/compose/compose_ps.go @@ -24,7 +24,7 @@ import ( "github.com/containerd/containerd" gocni "github.com/containerd/go-cni" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/pkg/formatter" "github.com/containerd/nerdctl/pkg/labels" "github.com/containerd/nerdctl/pkg/portutil" @@ -69,7 +69,7 @@ func composePsAction(cmd *cobra.Command, args []string) error { return fmt.Errorf("unsupported format %s, supported formats are: [json]", format) } - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose/compose_pull.go b/cmd/nerdctl/compose/compose_pull.go index cda660c0003..4fd7a947c9d 100644 --- a/cmd/nerdctl/compose/compose_pull.go +++ b/cmd/nerdctl/compose/compose_pull.go @@ -17,7 +17,7 @@ package compose import ( - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/pkg/composer" "github.com/spf13/cobra" ) @@ -35,7 +35,7 @@ func newComposePullCommand() *cobra.Command { } func composePullAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose/compose_push.go b/cmd/nerdctl/compose/compose_push.go index 9fe991e973b..a02190e37ba 100644 --- a/cmd/nerdctl/compose/compose_push.go +++ b/cmd/nerdctl/compose/compose_push.go @@ -17,7 +17,7 @@ package compose import ( - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/pkg/composer" "github.com/spf13/cobra" ) @@ -34,7 +34,7 @@ func newComposePushCommand() *cobra.Command { } func composePushAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose/compose_restart.go b/cmd/nerdctl/compose/compose_restart.go index f6880fdca0d..3474cd51c97 100644 --- a/cmd/nerdctl/compose/compose_restart.go +++ b/cmd/nerdctl/compose/compose_restart.go @@ -17,7 +17,7 @@ package compose import ( - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/pkg/composer" "github.com/spf13/cobra" ) @@ -45,7 +45,7 @@ func composeRestartAction(cmd *cobra.Command, args []string) error { opt.Timeout = &timeValue } - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose/compose_rm.go b/cmd/nerdctl/compose/compose_rm.go index 6fe62b6b968..617106ddfd7 100644 --- a/cmd/nerdctl/compose/compose_rm.go +++ b/cmd/nerdctl/compose/compose_rm.go @@ -20,7 +20,7 @@ import ( "fmt" "strings" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/pkg/composer" "github.com/spf13/cobra" ) @@ -69,7 +69,7 @@ func composeRemoveAction(cmd *cobra.Command, args []string) error { return err } - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose/compose_run.go b/cmd/nerdctl/compose/compose_run.go index 55f193d1167..7772c5a4760 100644 --- a/cmd/nerdctl/compose/compose_run.go +++ b/cmd/nerdctl/compose/compose_run.go @@ -20,7 +20,7 @@ import ( "errors" "fmt" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/pkg/composer" "github.com/spf13/cobra" ) @@ -168,7 +168,7 @@ func composeRunAction(cmd *cobra.Command, args []string) error { return errors.New("currently flag -t and -d cannot be specified together (FIXME)") } - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose/compose_stop.go b/cmd/nerdctl/compose/compose_stop.go index 5526baffbc8..a0e9bb7318c 100644 --- a/cmd/nerdctl/compose/compose_stop.go +++ b/cmd/nerdctl/compose/compose_stop.go @@ -17,7 +17,7 @@ package compose import ( - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/pkg/composer" "github.com/spf13/cobra" ) @@ -45,7 +45,7 @@ func composeStopAction(cmd *cobra.Command, args []string) error { opt.Timeout = &timeValue } - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose/compose_top.go b/cmd/nerdctl/compose/compose_top.go index 4e0ef0e86c2..79193c06dfe 100644 --- a/cmd/nerdctl/compose/compose_top.go +++ b/cmd/nerdctl/compose/compose_top.go @@ -20,7 +20,7 @@ import ( "fmt" "github.com/containerd/containerd" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/pkg/labels" "github.com/spf13/cobra" @@ -39,7 +39,7 @@ func newComposeTopCommand() *cobra.Command { } func composeTopAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose/compose_up.go b/cmd/nerdctl/compose/compose_up.go index a367c2aed7b..781f74c13e0 100644 --- a/cmd/nerdctl/compose/compose_up.go +++ b/cmd/nerdctl/compose/compose_up.go @@ -22,7 +22,7 @@ import ( "strconv" "strings" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/pkg/composer" "github.com/spf13/cobra" ) @@ -100,7 +100,7 @@ func composeUpAction(cmd *cobra.Command, services []string) error { scale[parts[0]] = uint64(replicas) } - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container/commit.go b/cmd/nerdctl/container/commit.go index e3d9a330e74..387ec78e66a 100644 --- a/cmd/nerdctl/container/commit.go +++ b/cmd/nerdctl/container/commit.go @@ -22,7 +22,7 @@ import ( "fmt" "strings" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" @@ -55,7 +55,7 @@ func commitAction(cmd *cobra.Command, args []string) error { return err } - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container/container_inspect.go b/cmd/nerdctl/container/container_inspect.go index 546fe9e8eb5..4c9f0348c93 100644 --- a/cmd/nerdctl/container/container_inspect.go +++ b/cmd/nerdctl/container/container_inspect.go @@ -21,7 +21,7 @@ import ( "fmt" "time" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/cmd/nerdctl/utils/fmtutil" "github.com/containerd/nerdctl/pkg/containerinspector" @@ -54,7 +54,7 @@ func NewInspectCommand() *cobra.Command { } func InspectAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container/container_prune.go b/cmd/nerdctl/container/container_prune.go index d37d4aacfe4..7649c5a7763 100644 --- a/cmd/nerdctl/container/container_prune.go +++ b/cmd/nerdctl/container/container_prune.go @@ -23,7 +23,7 @@ import ( "strings" "github.com/containerd/containerd" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" containerUtils "github.com/containerd/nerdctl/cmd/nerdctl/utils/container" @@ -62,7 +62,7 @@ func containerPruneAction(cmd *cobra.Command, _ []string) error { } } - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container/create.go b/cmd/nerdctl/container/create.go index 15ba655cfb5..11416d9413f 100644 --- a/cmd/nerdctl/container/create.go +++ b/cmd/nerdctl/container/create.go @@ -20,7 +20,7 @@ import ( "fmt" "runtime" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/cmd/nerdctl/utils/container" "github.com/containerd/nerdctl/cmd/nerdctl/utils/run" @@ -68,7 +68,7 @@ func createAction(cmd *cobra.Command, args []string) error { return fmt.Errorf("%s requires experimental mode to be enabled", platform) } - client, ctx, cancel, err := nerdClient.NewClientWithPlatform(cmd, platform) + client, ctx, cancel, err := ncclient.NewClientWithPlatform(cmd, platform) if err != nil { return err } diff --git a/cmd/nerdctl/container/exec.go b/cmd/nerdctl/container/exec.go index 80be262d1c0..ad6934d62cc 100644 --- a/cmd/nerdctl/container/exec.go +++ b/cmd/nerdctl/container/exec.go @@ -28,7 +28,7 @@ import ( "github.com/containerd/containerd/cio" "github.com/containerd/containerd/cmd/ctr/commands" "github.com/containerd/containerd/cmd/ctr/commands/tasks" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" containerUtils "github.com/containerd/nerdctl/cmd/nerdctl/utils/container" "github.com/containerd/nerdctl/cmd/nerdctl/utils/run" @@ -76,7 +76,7 @@ func execAction(cmd *cobra.Command, args []string) error { args = newArg } - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container/kill.go b/cmd/nerdctl/container/kill.go index 4383506aa2b..ff9d18dec5b 100644 --- a/cmd/nerdctl/container/kill.go +++ b/cmd/nerdctl/container/kill.go @@ -26,7 +26,7 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/cio" "github.com/containerd/containerd/errdefs" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" @@ -63,7 +63,7 @@ func killAction(cmd *cobra.Command, args []string) error { return err } - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container/logs.go b/cmd/nerdctl/container/logs.go index 86d30fad10d..fa29db14c45 100644 --- a/cmd/nerdctl/container/logs.go +++ b/cmd/nerdctl/container/logs.go @@ -25,7 +25,7 @@ import ( "syscall" "github.com/containerd/containerd" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" @@ -54,7 +54,7 @@ func NewLogsCommand() *cobra.Command { } func logsAction(cmd *cobra.Command, args []string) error { - dataStore, err := nerdClient.GetDataStore(cmd) + dataStore, err := ncclient.GetDataStore(cmd) if err != nil { return err } @@ -68,7 +68,7 @@ func logsAction(cmd *cobra.Command, args []string) error { logrus.Warn("Currently, `nerdctl logs` only supports containers created with `nerdctl run -d`") } - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container/pause.go b/cmd/nerdctl/container/pause.go index 22698c7f45f..8964f25756a 100644 --- a/cmd/nerdctl/container/pause.go +++ b/cmd/nerdctl/container/pause.go @@ -20,7 +20,7 @@ import ( "context" "fmt" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" @@ -42,7 +42,7 @@ func NewPauseCommand() *cobra.Command { } func pauseAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container/port.go b/cmd/nerdctl/container/port.go index 2b989836c96..54af8abdf6c 100644 --- a/cmd/nerdctl/container/port.go +++ b/cmd/nerdctl/container/port.go @@ -22,7 +22,7 @@ import ( "strconv" "strings" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/pkg/containerutil" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" @@ -72,7 +72,7 @@ func portAction(cmd *cobra.Command, args []string) error { } } - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container/ps.go b/cmd/nerdctl/container/ps.go index 0182dc30201..3ce3e5ca4be 100644 --- a/cmd/nerdctl/container/ps.go +++ b/cmd/nerdctl/container/ps.go @@ -31,7 +31,7 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/errdefs" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/cmd/nerdctl/utils/container" "github.com/containerd/nerdctl/cmd/nerdctl/utils/fmtutil" @@ -69,7 +69,7 @@ func NewPsCommandForMain() *cobra.Command { } func psAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container/rename.go b/cmd/nerdctl/container/rename.go index 0d682b82115..82e456c0c12 100644 --- a/cmd/nerdctl/container/rename.go +++ b/cmd/nerdctl/container/rename.go @@ -21,7 +21,7 @@ import ( "fmt" "github.com/containerd/containerd" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/pkg/dnsutil/hostsstore" @@ -45,7 +45,7 @@ func NewRenameCommand() *cobra.Command { } func renameAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } @@ -55,7 +55,7 @@ func renameAction(cmd *cobra.Command, args []string) error { return err } - dataStore, err := nerdClient.GetDataStore(cmd) + dataStore, err := ncclient.GetDataStore(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container/restart.go b/cmd/nerdctl/container/restart.go index 4622a50a892..4be2e0792dd 100644 --- a/cmd/nerdctl/container/restart.go +++ b/cmd/nerdctl/container/restart.go @@ -21,7 +21,7 @@ import ( "fmt" "time" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/cmd/nerdctl/utils/action" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" @@ -54,7 +54,7 @@ func restartAction(cmd *cobra.Command, args []string) error { timeout = &t } - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container/rm.go b/cmd/nerdctl/container/rm.go index 41dfb66af2d..a2f467f1be0 100644 --- a/cmd/nerdctl/container/rm.go +++ b/cmd/nerdctl/container/rm.go @@ -20,7 +20,7 @@ import ( "context" "fmt" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/cmd/nerdctl/utils/container" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" @@ -53,7 +53,7 @@ func rmAction(cmd *cobra.Command, args []string) error { return err } - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container/run.go b/cmd/nerdctl/container/run.go index 452b620c7fd..320d337dbe5 100644 --- a/cmd/nerdctl/container/run.go +++ b/cmd/nerdctl/container/run.go @@ -25,7 +25,7 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/cmd/ctr/commands" "github.com/containerd/containerd/cmd/ctr/commands/tasks" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" containerUtils "github.com/containerd/nerdctl/cmd/nerdctl/utils/container" @@ -73,7 +73,7 @@ func runAction(cmd *cobra.Command, args []string) error { if err != nil { return err } - client, ctx, cancel, err := nerdClient.NewClientWithPlatform(cmd, platform) + client, ctx, cancel, err := ncclient.NewClientWithPlatform(cmd, platform) if err != nil { return err } diff --git a/cmd/nerdctl/container/start.go b/cmd/nerdctl/container/start.go index 08e0834e333..e80054e65db 100644 --- a/cmd/nerdctl/container/start.go +++ b/cmd/nerdctl/container/start.go @@ -20,7 +20,7 @@ import ( "context" "fmt" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/cmd/nerdctl/utils/action" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" @@ -45,7 +45,7 @@ func NewStartCommand() *cobra.Command { } func startAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container/stats.go b/cmd/nerdctl/container/stats.go index d45481e5918..6da995cb35a 100644 --- a/cmd/nerdctl/container/stats.go +++ b/cmd/nerdctl/container/stats.go @@ -30,7 +30,7 @@ import ( eventstypes "github.com/containerd/containerd/api/events" "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/events" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/cmd/nerdctl/utils/fmtutil" "github.com/containerd/nerdctl/pkg/containerinspector" @@ -151,7 +151,7 @@ func statsAction(cmd *cobra.Command, args []string) error { waitFirst := &sync.WaitGroup{} cStats := stats{} - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } @@ -392,7 +392,7 @@ func collect(cmd *cobra.Command, s *statsutil.Stats, waitFirst *sync.WaitGroup, } }() - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { s.SetError(err) return diff --git a/cmd/nerdctl/container/stop.go b/cmd/nerdctl/container/stop.go index 34a6262ebc5..2d82038130f 100644 --- a/cmd/nerdctl/container/stop.go +++ b/cmd/nerdctl/container/stop.go @@ -21,7 +21,7 @@ import ( "fmt" "time" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/cmd/nerdctl/utils/action" "github.com/spf13/cobra" @@ -56,7 +56,7 @@ func stopAction(cmd *cobra.Command, args []string) error { timeout = &t } - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container/top.go b/cmd/nerdctl/container/top.go index 5632b4bb836..eb9f98a46b9 100644 --- a/cmd/nerdctl/container/top.go +++ b/cmd/nerdctl/container/top.go @@ -31,7 +31,7 @@ import ( "fmt" "strings" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" @@ -70,7 +70,7 @@ func topAction(cmd *cobra.Command, args []string) error { return errors.New("cgroup manager must not be \"none\"") } - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container/unpause.go b/cmd/nerdctl/container/unpause.go index 6bebe6dd743..5dbffa117ad 100644 --- a/cmd/nerdctl/container/unpause.go +++ b/cmd/nerdctl/container/unpause.go @@ -20,7 +20,7 @@ import ( "context" "fmt" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" @@ -42,7 +42,7 @@ func NewUnpauseCommand() *cobra.Command { } func unpauseAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container/update.go b/cmd/nerdctl/container/update.go index 84a407034b1..a6aa3250b4d 100644 --- a/cmd/nerdctl/container/update.go +++ b/cmd/nerdctl/container/update.go @@ -27,7 +27,7 @@ import ( "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/log" "github.com/containerd/containerd/pkg/cri/util" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/pkg/formatter" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" @@ -83,7 +83,7 @@ func setUpdateFlags(cmd *cobra.Command) { } func updateAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container/wait.go b/cmd/nerdctl/container/wait.go index c4bfbc41856..8e0fa4a23d3 100644 --- a/cmd/nerdctl/container/wait.go +++ b/cmd/nerdctl/container/wait.go @@ -22,7 +22,7 @@ import ( "io" "github.com/containerd/containerd" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" "github.com/hashicorp/go-multierror" @@ -43,7 +43,7 @@ func NewWaitCommand() *cobra.Command { } func containerWaitAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/image/history.go b/cmd/nerdctl/image/history.go index b0195995743..6566da7a8c5 100644 --- a/cmd/nerdctl/image/history.go +++ b/cmd/nerdctl/image/history.go @@ -29,7 +29,7 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/pkg/progress" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/cmd/nerdctl/utils/fmtutil" @@ -73,7 +73,7 @@ type historyPrintable struct { } func historyAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/image/image_convert.go b/cmd/nerdctl/image/image_convert.go index 06288f69f17..0bae92cf14e 100644 --- a/cmd/nerdctl/image/image_convert.go +++ b/cmd/nerdctl/image/image_convert.go @@ -30,7 +30,7 @@ import ( "github.com/containerd/containerd/images" "github.com/containerd/containerd/images/converter" "github.com/containerd/containerd/images/converter/uncompress" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" converterutil "github.com/containerd/nerdctl/pkg/imgutil/converter" "github.com/containerd/nerdctl/pkg/platformutil" @@ -180,7 +180,7 @@ func imageConvertAction(cmd *cobra.Command, args []string) error { return err } - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } @@ -460,7 +460,7 @@ func getNydusConvertOpts(cmd *cobra.Command) (*nydusconvert.PackOption, error) { return nil, err } if workDir == "" { - workDir, err = nerdClient.GetDataStore(cmd) + workDir, err = ncclient.GetDataStore(cmd) if err != nil { return nil, err } diff --git a/cmd/nerdctl/image/image_cryptutil.go b/cmd/nerdctl/image/image_cryptutil.go index 1a6bfac5c25..57323d0a0c2 100644 --- a/cmd/nerdctl/image/image_cryptutil.go +++ b/cmd/nerdctl/image/image_cryptutil.go @@ -25,7 +25,7 @@ import ( "github.com/containerd/containerd/images/converter" "github.com/containerd/imgcrypt/images/encryption" "github.com/containerd/imgcrypt/images/encryption/parsehelpers" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/pkg/platformutil" "github.com/containerd/nerdctl/pkg/referenceutil" @@ -138,7 +138,7 @@ func getImgcryptAction(encrypt bool) func(cmd *cobra.Command, args []string) err return err } - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/image/image_inspect.go b/cmd/nerdctl/image/image_inspect.go index 41f7f39b44a..88cc9540d52 100644 --- a/cmd/nerdctl/image/image_inspect.go +++ b/cmd/nerdctl/image/image_inspect.go @@ -23,7 +23,7 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/platforms" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/cmd/nerdctl/utils/fmtutil" "github.com/containerd/nerdctl/pkg/idutil/imagewalker" @@ -79,7 +79,7 @@ func InspectActionWithPlatform(cmd *cobra.Command, args []string, platform strin platformM := platforms.Only(platformParsed) clientOpts = append(clientOpts, containerd.WithDefaultPlatform(platformM)) } - client, ctx, cancel, err := nerdClient.NewClient(cmd, clientOpts...) + client, ctx, cancel, err := ncclient.NewClient(cmd, clientOpts...) if err != nil { return err } diff --git a/cmd/nerdctl/image/image_prune.go b/cmd/nerdctl/image/image_prune.go index 3e0ed423e37..4b32136d0e2 100644 --- a/cmd/nerdctl/image/image_prune.go +++ b/cmd/nerdctl/image/image_prune.go @@ -24,7 +24,7 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/images" "github.com/containerd/containerd/platforms" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/opencontainers/go-digest" "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -75,7 +75,7 @@ func imagePruneAction(cmd *cobra.Command, _ []string) error { } } - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/image/images.go b/cmd/nerdctl/image/images.go index d84fe280c1d..9578ffef409 100644 --- a/cmd/nerdctl/image/images.go +++ b/cmd/nerdctl/image/images.go @@ -36,7 +36,7 @@ import ( "github.com/containerd/containerd/platforms" dockerreference "github.com/containerd/containerd/reference/docker" "github.com/containerd/containerd/snapshots" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/cmd/nerdctl/utils/fmtutil" @@ -101,7 +101,7 @@ func imagesAction(cmd *cobra.Command, args []string) error { filters = append(filters, fmt.Sprintf("name==%s", canonicalRef.String())) filters = append(filters, fmt.Sprintf("name==%s", args[0])) } - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/image/pull.go b/cmd/nerdctl/image/pull.go index ff3bc0e6ba1..ace3c08bbb8 100644 --- a/cmd/nerdctl/image/pull.go +++ b/cmd/nerdctl/image/pull.go @@ -17,7 +17,7 @@ package image import ( - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/pkg/platformutil" @@ -61,7 +61,7 @@ func NewPullCommand() *cobra.Command { func pullAction(cmd *cobra.Command, args []string) error { rawRef := args[0] - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/image/push.go b/cmd/nerdctl/image/push.go index d33fd9b09b5..b8b6958fc38 100644 --- a/cmd/nerdctl/image/push.go +++ b/cmd/nerdctl/image/push.go @@ -26,7 +26,7 @@ import ( "github.com/containerd/containerd/images/converter" refdocker "github.com/containerd/containerd/reference/docker" "github.com/containerd/containerd/remotes" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/pkg/cosignutil" @@ -88,7 +88,7 @@ func NewPushCommand() *cobra.Command { func pushAction(cmd *cobra.Command, args []string) error { rawRef := args[0] - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/image/rmi.go b/cmd/nerdctl/image/rmi.go index efb02ed3886..42d8cb80f51 100644 --- a/cmd/nerdctl/image/rmi.go +++ b/cmd/nerdctl/image/rmi.go @@ -23,7 +23,7 @@ import ( "github.com/containerd/containerd/images" "github.com/containerd/containerd/platforms" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/pkg/formatter" "github.com/containerd/nerdctl/pkg/idutil/imagewalker" @@ -61,7 +61,7 @@ func rmiAction(cmd *cobra.Command, args []string) error { delOpts = append(delOpts, images.SynchronousDelete()) } - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/image/save.go b/cmd/nerdctl/image/save.go index 830307fd977..7db9ae296bd 100644 --- a/cmd/nerdctl/image/save.go +++ b/cmd/nerdctl/image/save.go @@ -22,7 +22,7 @@ import ( "os" "github.com/containerd/containerd/images/archive" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/pkg/platformutil" "github.com/containerd/nerdctl/pkg/referenceutil" @@ -85,7 +85,7 @@ func saveAction(cmd *cobra.Command, args []string) error { } func saveImage(images []string, out io.Writer, saveOpts []archive.ExportOpt, cmd *cobra.Command) error { - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/image/tag.go b/cmd/nerdctl/image/tag.go index 4fda2d19171..de462960a5c 100644 --- a/cmd/nerdctl/image/tag.go +++ b/cmd/nerdctl/image/tag.go @@ -21,7 +21,7 @@ import ( "fmt" "github.com/containerd/containerd/errdefs" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/pkg/idutil/imagewalker" @@ -44,7 +44,7 @@ func NewTagCommand() *cobra.Command { } func tagAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/inspect/inspect.go b/cmd/nerdctl/inspect/inspect.go index a4d8b763241..d4c47571171 100644 --- a/cmd/nerdctl/inspect/inspect.go +++ b/cmd/nerdctl/inspect/inspect.go @@ -20,7 +20,7 @@ import ( "context" "fmt" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/cmd/nerdctl/container" "github.com/containerd/nerdctl/cmd/nerdctl/image" @@ -76,7 +76,7 @@ func inspectAction(cmd *cobra.Command, args []string) error { return fmt.Errorf("%q is not a valid value for --type", inspectType) } - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/ipfs/registry/ipfs_registry_down.go b/cmd/nerdctl/ipfs/registry/ipfs_registry_down.go index 6cc5bc567fb..3ace21106ed 100644 --- a/cmd/nerdctl/ipfs/registry/ipfs_registry_down.go +++ b/cmd/nerdctl/ipfs/registry/ipfs_registry_down.go @@ -21,7 +21,7 @@ import ( "fmt" "os/exec" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" "github.com/spf13/cobra" @@ -40,7 +40,7 @@ func NewDownCommand() *cobra.Command { } func ipfsRegistryDownAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/ipfs/registry/ipfs_registry_up.go b/cmd/nerdctl/ipfs/registry/ipfs_registry_up.go index 6fc35f9ec33..18277cb0e07 100644 --- a/cmd/nerdctl/ipfs/registry/ipfs_registry_up.go +++ b/cmd/nerdctl/ipfs/registry/ipfs_registry_up.go @@ -25,7 +25,7 @@ import ( "path/filepath" "time" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" "github.com/hashicorp/go-multierror" @@ -53,7 +53,7 @@ func NewUpCommand() *cobra.Command { } func ipfsRegistryUpAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } @@ -94,7 +94,7 @@ func runRegistryAsContainer(cmd *cobra.Command) error { if err != nil { return err } - dataStore, err := nerdClient.GetDataStore(cmd) + dataStore, err := ncclient.GetDataStore(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/namespace/namespace.go b/cmd/nerdctl/namespace/namespace.go index f76978aa1ed..5ca87bad8f8 100644 --- a/cmd/nerdctl/namespace/namespace.go +++ b/cmd/nerdctl/namespace/namespace.go @@ -24,7 +24,7 @@ import ( "text/tabwriter" "github.com/containerd/containerd/namespaces" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" "github.com/containerd/nerdctl/pkg/mountutil/volumestore" @@ -65,7 +65,7 @@ func NewLsCommand() *cobra.Command { } func namespaceLsAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } @@ -87,7 +87,7 @@ func namespaceLsAction(cmd *cobra.Command, args []string) error { return nil } - dataStore, err := nerdClient.GetDataStore(cmd) + dataStore, err := ncclient.GetDataStore(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/namespace/namespace_create.go b/cmd/nerdctl/namespace/namespace_create.go index 20e1b617712..55d7a8c6f91 100644 --- a/cmd/nerdctl/namespace/namespace_create.go +++ b/cmd/nerdctl/namespace/namespace_create.go @@ -18,7 +18,7 @@ package namespace import ( "github.com/containerd/containerd/cmd/ctr/commands" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/spf13/cobra" ) @@ -42,7 +42,7 @@ func namespaceCreateAction(cmd *cobra.Command, args []string) error { return err } - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/namespace/namespace_inspect.go b/cmd/nerdctl/namespace/namespace_inspect.go index d51549ec9dd..dad74e4fa2a 100644 --- a/cmd/nerdctl/namespace/namespace_inspect.go +++ b/cmd/nerdctl/namespace/namespace_inspect.go @@ -18,7 +18,7 @@ package namespace import ( "github.com/containerd/containerd/namespaces" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/utils/fmtutil" "github.com/containerd/nerdctl/pkg/inspecttypes/native" "github.com/spf13/cobra" @@ -41,7 +41,7 @@ func NewInspectCommand() *cobra.Command { } func labelInspectAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/namespace/namespace_rm.go b/cmd/nerdctl/namespace/namespace_rm.go index 0aafa40ca2f..41b1dcf1ce7 100644 --- a/cmd/nerdctl/namespace/namespace_rm.go +++ b/cmd/nerdctl/namespace/namespace_rm.go @@ -21,7 +21,7 @@ import ( "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/log" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/spf13/cobra" ) @@ -41,7 +41,7 @@ func NewRmCommand() *cobra.Command { func namespaceRmAction(cmd *cobra.Command, args []string) error { var exitErr error - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/namespace/namespace_update.go b/cmd/nerdctl/namespace/namespace_update.go index 6012d5f2dac..f71ea04413a 100644 --- a/cmd/nerdctl/namespace/namespace_update.go +++ b/cmd/nerdctl/namespace/namespace_update.go @@ -17,7 +17,7 @@ package namespace import ( - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/spf13/cobra" ) @@ -40,7 +40,7 @@ func labelUpdateAction(cmd *cobra.Command, args []string) error { return err } - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/network/network_prune.go b/cmd/nerdctl/network/network_prune.go index 66f9d1ca97d..e440a254709 100644 --- a/cmd/nerdctl/network/network_prune.go +++ b/cmd/nerdctl/network/network_prune.go @@ -22,7 +22,7 @@ import ( "strings" "github.com/containerd/containerd" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/pkg/netutil" "github.com/containerd/nerdctl/pkg/strutil" "github.com/sirupsen/logrus" @@ -63,7 +63,7 @@ func networkPruneAction(cmd *cobra.Command, _ []string) error { } } - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/network/network_rm.go b/cmd/nerdctl/network/network_rm.go index 39b12551e71..2bdeca27a9a 100644 --- a/cmd/nerdctl/network/network_rm.go +++ b/cmd/nerdctl/network/network_rm.go @@ -20,7 +20,7 @@ import ( "context" "fmt" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" "github.com/containerd/nerdctl/pkg/idutil/netwalker" @@ -46,7 +46,7 @@ func NewRmCommand() *cobra.Command { } func networkRmAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/system/events.go b/cmd/nerdctl/system/events.go index a4794632d20..7a5a8977cc6 100644 --- a/cmd/nerdctl/system/events.go +++ b/cmd/nerdctl/system/events.go @@ -26,7 +26,7 @@ import ( "github.com/containerd/containerd/events" "github.com/containerd/containerd/log" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/utils/fmtutil" "github.com/containerd/typeurl" @@ -64,7 +64,7 @@ type Out struct { // eventsActions is from https://github.com/containerd/containerd/blob/v1.4.3/cmd/ctr/commands/events/events.go func eventsAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/system/info.go b/cmd/nerdctl/system/info.go index 7574c3eada4..cbc90f7d296 100644 --- a/cmd/nerdctl/system/info.go +++ b/cmd/nerdctl/system/info.go @@ -23,7 +23,7 @@ import ( "strings" "text/template" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/utils/fmtutil" "golang.org/x/text/cases" "golang.org/x/text/language" @@ -75,7 +75,7 @@ func infoAction(cmd *cobra.Command, args []string) error { } } - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/system/system_prune.go b/cmd/nerdctl/system/system_prune.go index 98ef07924b7..218afb4ef70 100644 --- a/cmd/nerdctl/system/system_prune.go +++ b/cmd/nerdctl/system/system_prune.go @@ -20,7 +20,7 @@ import ( "fmt" "strings" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/container" "github.com/containerd/nerdctl/cmd/nerdctl/image" "github.com/containerd/nerdctl/cmd/nerdctl/network" @@ -87,7 +87,7 @@ func systemPruneAction(cmd *cobra.Command, args []string) error { } } - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/utils/container/container_create.go b/cmd/nerdctl/utils/container/container_create.go index 2d95d5be030..90e44eb98a0 100644 --- a/cmd/nerdctl/utils/container/container_create.go +++ b/cmd/nerdctl/utils/container/container_create.go @@ -34,7 +34,7 @@ import ( "github.com/containerd/containerd/cio" "github.com/containerd/containerd/containers" "github.com/containerd/containerd/oci" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" "github.com/containerd/nerdctl/cmd/nerdctl/utils/run" @@ -86,7 +86,7 @@ func CreateContainer(ctx context.Context, cmd *cobra.Command, client *containerd } } - dataStore, err := nerdClient.GetDataStore(cmd) + dataStore, err := ncclient.GetDataStore(cmd) if err != nil { return nil, nil, err } diff --git a/cmd/nerdctl/utils/image.go b/cmd/nerdctl/utils/image.go index 8b2edb70700..59285bff743 100644 --- a/cmd/nerdctl/utils/image.go +++ b/cmd/nerdctl/utils/image.go @@ -28,7 +28,7 @@ import ( "github.com/containerd/containerd/images/archive" "github.com/containerd/containerd/platforms" "github.com/containerd/containerd/snapshots" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" "github.com/opencontainers/image-spec/identity" "github.com/sirupsen/logrus" @@ -38,7 +38,7 @@ import ( func LoadImage(in io.Reader, cmd *cobra.Command, platMC platforms.MatchComparer, quiet bool) error { // In addition to passing WithImagePlatform() to client.Import(), we also need to pass WithDefaultPlatform() to NewClient(). // Otherwise unpacking may fail. - client, ctx, cancel, err := nerdClient.NewClient(cmd, containerd.WithDefaultPlatform(platMC)) + client, ctx, cancel, err := ncclient.NewClient(cmd, containerd.WithDefaultPlatform(platMC)) if err != nil { return err } diff --git a/cmd/nerdctl/utils/run/run_network.go b/cmd/nerdctl/utils/run/run_network.go index 7ec833ab50a..c6eb93c3f8f 100644 --- a/cmd/nerdctl/utils/run/run_network.go +++ b/cmd/nerdctl/utils/run/run_network.go @@ -30,7 +30,7 @@ import ( "github.com/containerd/containerd/containers" "github.com/containerd/containerd/oci" gocni "github.com/containerd/go-cni" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" "github.com/containerd/nerdctl/pkg/dnsutil" "github.com/containerd/nerdctl/pkg/dnsutil/hostsstore" @@ -192,7 +192,7 @@ func GenerateNetOpts(cmd *cobra.Command, dataStore, stateDir, ns, id string) ([] return nil, nil, "", nil, "", fmt.Errorf("invalid network: %s, should be \"container:\"", netSlice[0]) } containerName := network[1] - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return nil, nil, "", nil, "", err } diff --git a/cmd/nerdctl/version/version.go b/cmd/nerdctl/version/version.go index c7104e7e0ca..33659fd8370 100644 --- a/cmd/nerdctl/version/version.go +++ b/cmd/nerdctl/version/version.go @@ -23,7 +23,7 @@ import ( "os" "text/template" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/utils/fmtutil" "github.com/containerd/nerdctl/pkg/infoutil" "github.com/containerd/nerdctl/pkg/inspecttypes/dockercompat" @@ -103,7 +103,7 @@ func versionInfo(cmd *cobra.Command) (dockercompat.VersionInfo, error) { v := dockercompat.VersionInfo{ Client: infoutil.ClientVersion(), } - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return v, err } diff --git a/cmd/nerdctl/volume/volume_prune.go b/cmd/nerdctl/volume/volume_prune.go index 11a4c746b68..2e117559d05 100644 --- a/cmd/nerdctl/volume/volume_prune.go +++ b/cmd/nerdctl/volume/volume_prune.go @@ -22,7 +22,7 @@ import ( "strings" "github.com/containerd/containerd" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/utils/volume" "github.com/spf13/cobra" ) @@ -58,7 +58,7 @@ func volumePruneAction(cmd *cobra.Command, _ []string) error { } } - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/volume/volume_rm.go b/cmd/nerdctl/volume/volume_rm.go index 7ae5385c776..1960e7636a0 100644 --- a/cmd/nerdctl/volume/volume_rm.go +++ b/cmd/nerdctl/volume/volume_rm.go @@ -22,7 +22,7 @@ import ( "fmt" "github.com/containerd/containerd" - nerdClient "github.com/containerd/nerdctl/cmd/nerdctl/client" + ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/cmd/nerdctl/utils/volume" "github.com/containerd/nerdctl/pkg/inspecttypes/dockercompat" @@ -48,7 +48,7 @@ func NewRmCommand() *cobra.Command { } func volumeRmAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := nerdClient.NewClient(cmd) + client, ctx, cancel, err := ncclient.NewClient(cmd) if err != nil { return err } From 09cdb02fb3f516219f555dae3cf2bd663cb3c53e Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Fri, 16 Dec 2022 09:24:31 +0900 Subject: [PATCH 05/14] [Carry 1639] client.NewClient -> client.New Signed-off-by: Akihiro Suda --- cmd/nerdctl/builder/build.go | 4 ++-- cmd/nerdctl/client/client.go | 6 +++--- cmd/nerdctl/completion/completion.go | 4 ++-- cmd/nerdctl/completion/completion_unix.go | 4 ++-- cmd/nerdctl/compose/compose_build.go | 2 +- cmd/nerdctl/compose/compose_config.go | 2 +- cmd/nerdctl/compose/compose_down.go | 2 +- cmd/nerdctl/compose/compose_exec.go | 2 +- cmd/nerdctl/compose/compose_images.go | 2 +- cmd/nerdctl/compose/compose_kill.go | 2 +- cmd/nerdctl/compose/compose_logs.go | 2 +- cmd/nerdctl/compose/compose_pause.go | 4 ++-- cmd/nerdctl/compose/compose_port.go | 2 +- cmd/nerdctl/compose/compose_ps.go | 2 +- cmd/nerdctl/compose/compose_pull.go | 2 +- cmd/nerdctl/compose/compose_push.go | 2 +- cmd/nerdctl/compose/compose_restart.go | 2 +- cmd/nerdctl/compose/compose_rm.go | 2 +- cmd/nerdctl/compose/compose_run.go | 2 +- cmd/nerdctl/compose/compose_stop.go | 2 +- cmd/nerdctl/compose/compose_top.go | 2 +- cmd/nerdctl/compose/compose_up.go | 2 +- cmd/nerdctl/container/commit.go | 2 +- cmd/nerdctl/container/container_inspect.go | 2 +- cmd/nerdctl/container/container_prune.go | 2 +- cmd/nerdctl/container/create.go | 2 +- cmd/nerdctl/container/exec.go | 2 +- cmd/nerdctl/container/kill.go | 2 +- cmd/nerdctl/container/logs.go | 2 +- cmd/nerdctl/container/pause.go | 2 +- cmd/nerdctl/container/port.go | 2 +- cmd/nerdctl/container/ps.go | 2 +- cmd/nerdctl/container/rename.go | 2 +- cmd/nerdctl/container/restart.go | 2 +- cmd/nerdctl/container/rm.go | 2 +- cmd/nerdctl/container/run.go | 2 +- cmd/nerdctl/container/start.go | 2 +- cmd/nerdctl/container/stats.go | 4 ++-- cmd/nerdctl/container/stop.go | 2 +- cmd/nerdctl/container/top.go | 2 +- cmd/nerdctl/container/unpause.go | 2 +- cmd/nerdctl/container/update.go | 2 +- cmd/nerdctl/container/wait.go | 2 +- cmd/nerdctl/image/history.go | 2 +- cmd/nerdctl/image/image_convert.go | 2 +- cmd/nerdctl/image/image_cryptutil.go | 2 +- cmd/nerdctl/image/image_inspect.go | 2 +- cmd/nerdctl/image/image_prune.go | 2 +- cmd/nerdctl/image/images.go | 2 +- cmd/nerdctl/image/pull.go | 2 +- cmd/nerdctl/image/push.go | 2 +- cmd/nerdctl/image/rmi.go | 2 +- cmd/nerdctl/image/save.go | 2 +- cmd/nerdctl/image/tag.go | 2 +- cmd/nerdctl/inspect/inspect.go | 2 +- cmd/nerdctl/ipfs/registry/ipfs_registry_down.go | 2 +- cmd/nerdctl/ipfs/registry/ipfs_registry_up.go | 2 +- cmd/nerdctl/namespace/namespace.go | 2 +- cmd/nerdctl/namespace/namespace_create.go | 2 +- cmd/nerdctl/namespace/namespace_inspect.go | 2 +- cmd/nerdctl/namespace/namespace_rm.go | 2 +- cmd/nerdctl/namespace/namespace_update.go | 2 +- cmd/nerdctl/network/network_prune.go | 2 +- cmd/nerdctl/network/network_rm.go | 2 +- cmd/nerdctl/system/events.go | 2 +- cmd/nerdctl/system/info.go | 2 +- cmd/nerdctl/system/system_prune.go | 2 +- cmd/nerdctl/utils/image.go | 2 +- cmd/nerdctl/utils/run/run_network.go | 2 +- cmd/nerdctl/version/version.go | 2 +- cmd/nerdctl/volume/volume_prune.go | 2 +- cmd/nerdctl/volume/volume_rm.go | 2 +- 72 files changed, 79 insertions(+), 79 deletions(-) diff --git a/cmd/nerdctl/builder/build.go b/cmd/nerdctl/builder/build.go index d4585e57887..a1d473aaed0 100644 --- a/cmd/nerdctl/builder/build.go +++ b/cmd/nerdctl/builder/build.go @@ -215,7 +215,7 @@ func buildAction(cmd *cobra.Command, args []string) error { if len(tags) > 1 { logrus.Debug("Found more than 1 tag") - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return fmt.Errorf("unable to tag images: %s", err) } @@ -260,7 +260,7 @@ func generateBuildctlArgs(cmd *cobra.Command, buildkitHost string, platform, arg return "", nil, false, "", nil, nil, err } if output == "" { - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return "", nil, false, "", nil, nil, err } diff --git a/cmd/nerdctl/client/client.go b/cmd/nerdctl/client/client.go index fc2b12f514c..d693149e26a 100644 --- a/cmd/nerdctl/client/client.go +++ b/cmd/nerdctl/client/client.go @@ -35,7 +35,7 @@ import ( "github.com/opencontainers/go-digest" ) -func NewClient(cmd *cobra.Command, opts ...containerd.ClientOpt) (*containerd.Client, context.Context, context.CancelFunc, error) { +func New(cmd *cobra.Command, opts ...containerd.ClientOpt) (*containerd.Client, context.Context, context.CancelFunc, error) { ctx := cmd.Context() namespace, err := cmd.Flags().GetString("namespace") if err != nil { @@ -65,7 +65,7 @@ func NewClient(cmd *cobra.Command, opts ...containerd.ClientOpt) (*containerd.Cl return client, ctx, cancel, nil } -func NewClientWithPlatform(cmd *cobra.Command, platform string, clientOpts ...containerd.ClientOpt) (*containerd.Client, context.Context, context.CancelFunc, error) { +func NewWithPlatform(cmd *cobra.Command, platform string, clientOpts ...containerd.ClientOpt) (*containerd.Client, context.Context, context.CancelFunc, error) { if platform != "" { if canExec, canExecErr := platformutil.CanExecProbably(platform); !canExec { warn := fmt.Sprintf("Platform %q seems incompatible with the host platform %q. If you see \"exec format error\", see https://github.com/containerd/nerdctl/blob/main/docs/multi-platform.md", @@ -83,7 +83,7 @@ func NewClientWithPlatform(cmd *cobra.Command, platform string, clientOpts ...co platformM := platforms.Only(platformParsed) clientOpts = append(clientOpts, containerd.WithDefaultPlatform(platformM)) } - return NewClient(cmd, clientOpts...) + return New(cmd, clientOpts...) } // GetDataStore returns a string like "/var/lib/nerdctl/1935db59". diff --git a/cmd/nerdctl/completion/completion.go b/cmd/nerdctl/completion/completion.go index b5afa243b33..8ef321d8027 100644 --- a/cmd/nerdctl/completion/completion.go +++ b/cmd/nerdctl/completion/completion.go @@ -31,7 +31,7 @@ import ( ) func ShellCompleteImageNames(cmd *cobra.Command) ([]string, cobra.ShellCompDirective) { - client, ctx, cancel, err := client.NewClient(cmd) + client, ctx, cancel, err := client.New(cmd) if err != nil { return nil, cobra.ShellCompDirectiveError } @@ -50,7 +50,7 @@ func ShellCompleteImageNames(cmd *cobra.Command) ([]string, cobra.ShellCompDirec } func ShellCompleteContainerNames(cmd *cobra.Command, filterFunc func(containerd.ProcessStatus) bool) ([]string, cobra.ShellCompDirective) { - client, ctx, cancel, err := client.NewClient(cmd) + client, ctx, cancel, err := client.New(cmd) if err != nil { return nil, cobra.ShellCompDirectiveError } diff --git a/cmd/nerdctl/completion/completion_unix.go b/cmd/nerdctl/completion/completion_unix.go index 2baa67407c5..120ea83616d 100644 --- a/cmd/nerdctl/completion/completion_unix.go +++ b/cmd/nerdctl/completion/completion_unix.go @@ -32,7 +32,7 @@ func ShellCompleteNamespaceNames(cmd *cobra.Command, args []string, toComplete s return nil, cobra.ShellCompDirectiveNoFileComp } - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return nil, cobra.ShellCompDirectiveError } @@ -53,7 +53,7 @@ func ShellCompleteSnapshotterNames(cmd *cobra.Command, args []string, toComplete _ = rootlessutil.ParentMain() return nil, cobra.ShellCompDirectiveNoFileComp } - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return nil, cobra.ShellCompDirectiveError } diff --git a/cmd/nerdctl/compose/compose_build.go b/cmd/nerdctl/compose/compose_build.go index 949cd2cf3e0..660cee1440a 100644 --- a/cmd/nerdctl/compose/compose_build.go +++ b/cmd/nerdctl/compose/compose_build.go @@ -57,7 +57,7 @@ func composeBuildAction(cmd *cobra.Command, args []string) error { return err } - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose/compose_config.go b/cmd/nerdctl/compose/compose_config.go index fafaf6c1e04..54587d7466d 100644 --- a/cmd/nerdctl/compose/compose_config.go +++ b/cmd/nerdctl/compose/compose_config.go @@ -64,7 +64,7 @@ func composeConfigAction(cmd *cobra.Command, args []string) error { return err } - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose/compose_down.go b/cmd/nerdctl/compose/compose_down.go index 7601e5f8039..8238b742dee 100644 --- a/cmd/nerdctl/compose/compose_down.go +++ b/cmd/nerdctl/compose/compose_down.go @@ -40,7 +40,7 @@ func composeDownAction(cmd *cobra.Command, args []string) error { if err != nil { return err } - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose/compose_exec.go b/cmd/nerdctl/compose/compose_exec.go index a3805c48c41..ff53c4e9b1b 100644 --- a/cmd/nerdctl/compose/compose_exec.go +++ b/cmd/nerdctl/compose/compose_exec.go @@ -95,7 +95,7 @@ func composeExecAction(cmd *cobra.Command, args []string) error { return errors.New("currently flag -t and -d cannot be specified together (FIXME)") } - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose/compose_images.go b/cmd/nerdctl/compose/compose_images.go index 8a212f91a8a..251d7327c0b 100644 --- a/cmd/nerdctl/compose/compose_images.go +++ b/cmd/nerdctl/compose/compose_images.go @@ -53,7 +53,7 @@ func composeImagesAction(cmd *cobra.Command, args []string) error { return err } - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose/compose_kill.go b/cmd/nerdctl/compose/compose_kill.go index e7ef0fb5c85..5f8978bfb87 100644 --- a/cmd/nerdctl/compose/compose_kill.go +++ b/cmd/nerdctl/compose/compose_kill.go @@ -39,7 +39,7 @@ func composeKillAction(cmd *cobra.Command, args []string) error { if err != nil { return err } - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose/compose_logs.go b/cmd/nerdctl/compose/compose_logs.go index c5e456358c1..a1cce7476fe 100644 --- a/cmd/nerdctl/compose/compose_logs.go +++ b/cmd/nerdctl/compose/compose_logs.go @@ -60,7 +60,7 @@ func composeLogsAction(cmd *cobra.Command, args []string) error { return err } - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose/compose_pause.go b/cmd/nerdctl/compose/compose_pause.go index 2da68c950a3..fe7aff3507d 100644 --- a/cmd/nerdctl/compose/compose_pause.go +++ b/cmd/nerdctl/compose/compose_pause.go @@ -41,7 +41,7 @@ func newComposePauseCommand() *cobra.Command { } func composePauseAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } @@ -99,7 +99,7 @@ func newComposeUnpauseCommand() *cobra.Command { } func composeUnpauseAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose/compose_port.go b/cmd/nerdctl/compose/compose_port.go index e3333bf9c0d..3430c4085c3 100644 --- a/cmd/nerdctl/compose/compose_port.go +++ b/cmd/nerdctl/compose/compose_port.go @@ -67,7 +67,7 @@ func composePortAction(cmd *cobra.Command, args []string) error { return fmt.Errorf("unexpected port: %d", port) } - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose/compose_ps.go b/cmd/nerdctl/compose/compose_ps.go index b8a750779ae..17d01dee19c 100644 --- a/cmd/nerdctl/compose/compose_ps.go +++ b/cmd/nerdctl/compose/compose_ps.go @@ -69,7 +69,7 @@ func composePsAction(cmd *cobra.Command, args []string) error { return fmt.Errorf("unsupported format %s, supported formats are: [json]", format) } - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose/compose_pull.go b/cmd/nerdctl/compose/compose_pull.go index 4fd7a947c9d..035a070750e 100644 --- a/cmd/nerdctl/compose/compose_pull.go +++ b/cmd/nerdctl/compose/compose_pull.go @@ -35,7 +35,7 @@ func newComposePullCommand() *cobra.Command { } func composePullAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose/compose_push.go b/cmd/nerdctl/compose/compose_push.go index a02190e37ba..e1da041b164 100644 --- a/cmd/nerdctl/compose/compose_push.go +++ b/cmd/nerdctl/compose/compose_push.go @@ -34,7 +34,7 @@ func newComposePushCommand() *cobra.Command { } func composePushAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose/compose_restart.go b/cmd/nerdctl/compose/compose_restart.go index 3474cd51c97..5974a78da03 100644 --- a/cmd/nerdctl/compose/compose_restart.go +++ b/cmd/nerdctl/compose/compose_restart.go @@ -45,7 +45,7 @@ func composeRestartAction(cmd *cobra.Command, args []string) error { opt.Timeout = &timeValue } - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose/compose_rm.go b/cmd/nerdctl/compose/compose_rm.go index 617106ddfd7..0ecb05277b1 100644 --- a/cmd/nerdctl/compose/compose_rm.go +++ b/cmd/nerdctl/compose/compose_rm.go @@ -69,7 +69,7 @@ func composeRemoveAction(cmd *cobra.Command, args []string) error { return err } - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose/compose_run.go b/cmd/nerdctl/compose/compose_run.go index 7772c5a4760..3548ccd062f 100644 --- a/cmd/nerdctl/compose/compose_run.go +++ b/cmd/nerdctl/compose/compose_run.go @@ -168,7 +168,7 @@ func composeRunAction(cmd *cobra.Command, args []string) error { return errors.New("currently flag -t and -d cannot be specified together (FIXME)") } - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose/compose_stop.go b/cmd/nerdctl/compose/compose_stop.go index a0e9bb7318c..e0e9d784e2d 100644 --- a/cmd/nerdctl/compose/compose_stop.go +++ b/cmd/nerdctl/compose/compose_stop.go @@ -45,7 +45,7 @@ func composeStopAction(cmd *cobra.Command, args []string) error { opt.Timeout = &timeValue } - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose/compose_top.go b/cmd/nerdctl/compose/compose_top.go index 79193c06dfe..5ca35090ce3 100644 --- a/cmd/nerdctl/compose/compose_top.go +++ b/cmd/nerdctl/compose/compose_top.go @@ -39,7 +39,7 @@ func newComposeTopCommand() *cobra.Command { } func composeTopAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose/compose_up.go b/cmd/nerdctl/compose/compose_up.go index 781f74c13e0..53d59401098 100644 --- a/cmd/nerdctl/compose/compose_up.go +++ b/cmd/nerdctl/compose/compose_up.go @@ -100,7 +100,7 @@ func composeUpAction(cmd *cobra.Command, services []string) error { scale[parts[0]] = uint64(replicas) } - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container/commit.go b/cmd/nerdctl/container/commit.go index 387ec78e66a..404fe67d003 100644 --- a/cmd/nerdctl/container/commit.go +++ b/cmd/nerdctl/container/commit.go @@ -55,7 +55,7 @@ func commitAction(cmd *cobra.Command, args []string) error { return err } - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container/container_inspect.go b/cmd/nerdctl/container/container_inspect.go index 4c9f0348c93..3a22e96bd56 100644 --- a/cmd/nerdctl/container/container_inspect.go +++ b/cmd/nerdctl/container/container_inspect.go @@ -54,7 +54,7 @@ func NewInspectCommand() *cobra.Command { } func InspectAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container/container_prune.go b/cmd/nerdctl/container/container_prune.go index 7649c5a7763..6168c0b4163 100644 --- a/cmd/nerdctl/container/container_prune.go +++ b/cmd/nerdctl/container/container_prune.go @@ -62,7 +62,7 @@ func containerPruneAction(cmd *cobra.Command, _ []string) error { } } - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container/create.go b/cmd/nerdctl/container/create.go index 11416d9413f..fbe089d42d1 100644 --- a/cmd/nerdctl/container/create.go +++ b/cmd/nerdctl/container/create.go @@ -68,7 +68,7 @@ func createAction(cmd *cobra.Command, args []string) error { return fmt.Errorf("%s requires experimental mode to be enabled", platform) } - client, ctx, cancel, err := ncclient.NewClientWithPlatform(cmd, platform) + client, ctx, cancel, err := ncclient.NewWithPlatform(cmd, platform) if err != nil { return err } diff --git a/cmd/nerdctl/container/exec.go b/cmd/nerdctl/container/exec.go index ad6934d62cc..f6ced68542b 100644 --- a/cmd/nerdctl/container/exec.go +++ b/cmd/nerdctl/container/exec.go @@ -76,7 +76,7 @@ func execAction(cmd *cobra.Command, args []string) error { args = newArg } - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container/kill.go b/cmd/nerdctl/container/kill.go index ff9d18dec5b..090ff6d4004 100644 --- a/cmd/nerdctl/container/kill.go +++ b/cmd/nerdctl/container/kill.go @@ -63,7 +63,7 @@ func killAction(cmd *cobra.Command, args []string) error { return err } - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container/logs.go b/cmd/nerdctl/container/logs.go index fa29db14c45..609f25e5fb4 100644 --- a/cmd/nerdctl/container/logs.go +++ b/cmd/nerdctl/container/logs.go @@ -68,7 +68,7 @@ func logsAction(cmd *cobra.Command, args []string) error { logrus.Warn("Currently, `nerdctl logs` only supports containers created with `nerdctl run -d`") } - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container/pause.go b/cmd/nerdctl/container/pause.go index 8964f25756a..1f1923d996e 100644 --- a/cmd/nerdctl/container/pause.go +++ b/cmd/nerdctl/container/pause.go @@ -42,7 +42,7 @@ func NewPauseCommand() *cobra.Command { } func pauseAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container/port.go b/cmd/nerdctl/container/port.go index 54af8abdf6c..a7ab4328684 100644 --- a/cmd/nerdctl/container/port.go +++ b/cmd/nerdctl/container/port.go @@ -72,7 +72,7 @@ func portAction(cmd *cobra.Command, args []string) error { } } - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container/ps.go b/cmd/nerdctl/container/ps.go index 3ce3e5ca4be..14cfa488452 100644 --- a/cmd/nerdctl/container/ps.go +++ b/cmd/nerdctl/container/ps.go @@ -69,7 +69,7 @@ func NewPsCommandForMain() *cobra.Command { } func psAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container/rename.go b/cmd/nerdctl/container/rename.go index 82e456c0c12..28225b3dc28 100644 --- a/cmd/nerdctl/container/rename.go +++ b/cmd/nerdctl/container/rename.go @@ -45,7 +45,7 @@ func NewRenameCommand() *cobra.Command { } func renameAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container/restart.go b/cmd/nerdctl/container/restart.go index 4be2e0792dd..c351a06a587 100644 --- a/cmd/nerdctl/container/restart.go +++ b/cmd/nerdctl/container/restart.go @@ -54,7 +54,7 @@ func restartAction(cmd *cobra.Command, args []string) error { timeout = &t } - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container/rm.go b/cmd/nerdctl/container/rm.go index a2f467f1be0..9da3a936eb8 100644 --- a/cmd/nerdctl/container/rm.go +++ b/cmd/nerdctl/container/rm.go @@ -53,7 +53,7 @@ func rmAction(cmd *cobra.Command, args []string) error { return err } - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container/run.go b/cmd/nerdctl/container/run.go index 320d337dbe5..79106474131 100644 --- a/cmd/nerdctl/container/run.go +++ b/cmd/nerdctl/container/run.go @@ -73,7 +73,7 @@ func runAction(cmd *cobra.Command, args []string) error { if err != nil { return err } - client, ctx, cancel, err := ncclient.NewClientWithPlatform(cmd, platform) + client, ctx, cancel, err := ncclient.NewWithPlatform(cmd, platform) if err != nil { return err } diff --git a/cmd/nerdctl/container/start.go b/cmd/nerdctl/container/start.go index e80054e65db..64de04291df 100644 --- a/cmd/nerdctl/container/start.go +++ b/cmd/nerdctl/container/start.go @@ -45,7 +45,7 @@ func NewStartCommand() *cobra.Command { } func startAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container/stats.go b/cmd/nerdctl/container/stats.go index 6da995cb35a..21a549f3434 100644 --- a/cmd/nerdctl/container/stats.go +++ b/cmd/nerdctl/container/stats.go @@ -151,7 +151,7 @@ func statsAction(cmd *cobra.Command, args []string) error { waitFirst := &sync.WaitGroup{} cStats := stats{} - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } @@ -392,7 +392,7 @@ func collect(cmd *cobra.Command, s *statsutil.Stats, waitFirst *sync.WaitGroup, } }() - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { s.SetError(err) return diff --git a/cmd/nerdctl/container/stop.go b/cmd/nerdctl/container/stop.go index 2d82038130f..a0d10ab213b 100644 --- a/cmd/nerdctl/container/stop.go +++ b/cmd/nerdctl/container/stop.go @@ -56,7 +56,7 @@ func stopAction(cmd *cobra.Command, args []string) error { timeout = &t } - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container/top.go b/cmd/nerdctl/container/top.go index eb9f98a46b9..fa3e8a8877e 100644 --- a/cmd/nerdctl/container/top.go +++ b/cmd/nerdctl/container/top.go @@ -70,7 +70,7 @@ func topAction(cmd *cobra.Command, args []string) error { return errors.New("cgroup manager must not be \"none\"") } - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container/unpause.go b/cmd/nerdctl/container/unpause.go index 5dbffa117ad..bf85fb6ab02 100644 --- a/cmd/nerdctl/container/unpause.go +++ b/cmd/nerdctl/container/unpause.go @@ -42,7 +42,7 @@ func NewUnpauseCommand() *cobra.Command { } func unpauseAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container/update.go b/cmd/nerdctl/container/update.go index a6aa3250b4d..e669a7fefeb 100644 --- a/cmd/nerdctl/container/update.go +++ b/cmd/nerdctl/container/update.go @@ -83,7 +83,7 @@ func setUpdateFlags(cmd *cobra.Command) { } func updateAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container/wait.go b/cmd/nerdctl/container/wait.go index 8e0fa4a23d3..7f64df4ddca 100644 --- a/cmd/nerdctl/container/wait.go +++ b/cmd/nerdctl/container/wait.go @@ -43,7 +43,7 @@ func NewWaitCommand() *cobra.Command { } func containerWaitAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/image/history.go b/cmd/nerdctl/image/history.go index 6566da7a8c5..b36b91a0f1b 100644 --- a/cmd/nerdctl/image/history.go +++ b/cmd/nerdctl/image/history.go @@ -73,7 +73,7 @@ type historyPrintable struct { } func historyAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/image/image_convert.go b/cmd/nerdctl/image/image_convert.go index 0bae92cf14e..34589335951 100644 --- a/cmd/nerdctl/image/image_convert.go +++ b/cmd/nerdctl/image/image_convert.go @@ -180,7 +180,7 @@ func imageConvertAction(cmd *cobra.Command, args []string) error { return err } - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/image/image_cryptutil.go b/cmd/nerdctl/image/image_cryptutil.go index 57323d0a0c2..024d9c7aae1 100644 --- a/cmd/nerdctl/image/image_cryptutil.go +++ b/cmd/nerdctl/image/image_cryptutil.go @@ -138,7 +138,7 @@ func getImgcryptAction(encrypt bool) func(cmd *cobra.Command, args []string) err return err } - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/image/image_inspect.go b/cmd/nerdctl/image/image_inspect.go index 88cc9540d52..64858da324b 100644 --- a/cmd/nerdctl/image/image_inspect.go +++ b/cmd/nerdctl/image/image_inspect.go @@ -79,7 +79,7 @@ func InspectActionWithPlatform(cmd *cobra.Command, args []string, platform strin platformM := platforms.Only(platformParsed) clientOpts = append(clientOpts, containerd.WithDefaultPlatform(platformM)) } - client, ctx, cancel, err := ncclient.NewClient(cmd, clientOpts...) + client, ctx, cancel, err := ncclient.New(cmd, clientOpts...) if err != nil { return err } diff --git a/cmd/nerdctl/image/image_prune.go b/cmd/nerdctl/image/image_prune.go index 4b32136d0e2..6ca1734eab6 100644 --- a/cmd/nerdctl/image/image_prune.go +++ b/cmd/nerdctl/image/image_prune.go @@ -75,7 +75,7 @@ func imagePruneAction(cmd *cobra.Command, _ []string) error { } } - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/image/images.go b/cmd/nerdctl/image/images.go index 9578ffef409..eeb299df8d9 100644 --- a/cmd/nerdctl/image/images.go +++ b/cmd/nerdctl/image/images.go @@ -101,7 +101,7 @@ func imagesAction(cmd *cobra.Command, args []string) error { filters = append(filters, fmt.Sprintf("name==%s", canonicalRef.String())) filters = append(filters, fmt.Sprintf("name==%s", args[0])) } - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/image/pull.go b/cmd/nerdctl/image/pull.go index ace3c08bbb8..f8bba256b29 100644 --- a/cmd/nerdctl/image/pull.go +++ b/cmd/nerdctl/image/pull.go @@ -61,7 +61,7 @@ func NewPullCommand() *cobra.Command { func pullAction(cmd *cobra.Command, args []string) error { rawRef := args[0] - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/image/push.go b/cmd/nerdctl/image/push.go index b8b6958fc38..5376668e457 100644 --- a/cmd/nerdctl/image/push.go +++ b/cmd/nerdctl/image/push.go @@ -88,7 +88,7 @@ func NewPushCommand() *cobra.Command { func pushAction(cmd *cobra.Command, args []string) error { rawRef := args[0] - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/image/rmi.go b/cmd/nerdctl/image/rmi.go index 42d8cb80f51..1ef24071128 100644 --- a/cmd/nerdctl/image/rmi.go +++ b/cmd/nerdctl/image/rmi.go @@ -61,7 +61,7 @@ func rmiAction(cmd *cobra.Command, args []string) error { delOpts = append(delOpts, images.SynchronousDelete()) } - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/image/save.go b/cmd/nerdctl/image/save.go index 7db9ae296bd..06bca0a84a4 100644 --- a/cmd/nerdctl/image/save.go +++ b/cmd/nerdctl/image/save.go @@ -85,7 +85,7 @@ func saveAction(cmd *cobra.Command, args []string) error { } func saveImage(images []string, out io.Writer, saveOpts []archive.ExportOpt, cmd *cobra.Command) error { - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/image/tag.go b/cmd/nerdctl/image/tag.go index de462960a5c..4010e79a158 100644 --- a/cmd/nerdctl/image/tag.go +++ b/cmd/nerdctl/image/tag.go @@ -44,7 +44,7 @@ func NewTagCommand() *cobra.Command { } func tagAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/inspect/inspect.go b/cmd/nerdctl/inspect/inspect.go index d4c47571171..2f2f1763c06 100644 --- a/cmd/nerdctl/inspect/inspect.go +++ b/cmd/nerdctl/inspect/inspect.go @@ -76,7 +76,7 @@ func inspectAction(cmd *cobra.Command, args []string) error { return fmt.Errorf("%q is not a valid value for --type", inspectType) } - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/ipfs/registry/ipfs_registry_down.go b/cmd/nerdctl/ipfs/registry/ipfs_registry_down.go index 3ace21106ed..7b95112b3fd 100644 --- a/cmd/nerdctl/ipfs/registry/ipfs_registry_down.go +++ b/cmd/nerdctl/ipfs/registry/ipfs_registry_down.go @@ -40,7 +40,7 @@ func NewDownCommand() *cobra.Command { } func ipfsRegistryDownAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/ipfs/registry/ipfs_registry_up.go b/cmd/nerdctl/ipfs/registry/ipfs_registry_up.go index 18277cb0e07..bf7ab6b826f 100644 --- a/cmd/nerdctl/ipfs/registry/ipfs_registry_up.go +++ b/cmd/nerdctl/ipfs/registry/ipfs_registry_up.go @@ -53,7 +53,7 @@ func NewUpCommand() *cobra.Command { } func ipfsRegistryUpAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/namespace/namespace.go b/cmd/nerdctl/namespace/namespace.go index 5ca87bad8f8..3689c0c7066 100644 --- a/cmd/nerdctl/namespace/namespace.go +++ b/cmd/nerdctl/namespace/namespace.go @@ -65,7 +65,7 @@ func NewLsCommand() *cobra.Command { } func namespaceLsAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/namespace/namespace_create.go b/cmd/nerdctl/namespace/namespace_create.go index 55d7a8c6f91..80ad04bd436 100644 --- a/cmd/nerdctl/namespace/namespace_create.go +++ b/cmd/nerdctl/namespace/namespace_create.go @@ -42,7 +42,7 @@ func namespaceCreateAction(cmd *cobra.Command, args []string) error { return err } - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/namespace/namespace_inspect.go b/cmd/nerdctl/namespace/namespace_inspect.go index dad74e4fa2a..3d16452df8e 100644 --- a/cmd/nerdctl/namespace/namespace_inspect.go +++ b/cmd/nerdctl/namespace/namespace_inspect.go @@ -41,7 +41,7 @@ func NewInspectCommand() *cobra.Command { } func labelInspectAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/namespace/namespace_rm.go b/cmd/nerdctl/namespace/namespace_rm.go index 41b1dcf1ce7..a8e919e6383 100644 --- a/cmd/nerdctl/namespace/namespace_rm.go +++ b/cmd/nerdctl/namespace/namespace_rm.go @@ -41,7 +41,7 @@ func NewRmCommand() *cobra.Command { func namespaceRmAction(cmd *cobra.Command, args []string) error { var exitErr error - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/namespace/namespace_update.go b/cmd/nerdctl/namespace/namespace_update.go index f71ea04413a..fefcc5bf69c 100644 --- a/cmd/nerdctl/namespace/namespace_update.go +++ b/cmd/nerdctl/namespace/namespace_update.go @@ -40,7 +40,7 @@ func labelUpdateAction(cmd *cobra.Command, args []string) error { return err } - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/network/network_prune.go b/cmd/nerdctl/network/network_prune.go index e440a254709..adf21719142 100644 --- a/cmd/nerdctl/network/network_prune.go +++ b/cmd/nerdctl/network/network_prune.go @@ -63,7 +63,7 @@ func networkPruneAction(cmd *cobra.Command, _ []string) error { } } - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/network/network_rm.go b/cmd/nerdctl/network/network_rm.go index 2bdeca27a9a..eab9ac83db5 100644 --- a/cmd/nerdctl/network/network_rm.go +++ b/cmd/nerdctl/network/network_rm.go @@ -46,7 +46,7 @@ func NewRmCommand() *cobra.Command { } func networkRmAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/system/events.go b/cmd/nerdctl/system/events.go index 7a5a8977cc6..6428f5f9441 100644 --- a/cmd/nerdctl/system/events.go +++ b/cmd/nerdctl/system/events.go @@ -64,7 +64,7 @@ type Out struct { // eventsActions is from https://github.com/containerd/containerd/blob/v1.4.3/cmd/ctr/commands/events/events.go func eventsAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/system/info.go b/cmd/nerdctl/system/info.go index cbc90f7d296..5760e13e213 100644 --- a/cmd/nerdctl/system/info.go +++ b/cmd/nerdctl/system/info.go @@ -75,7 +75,7 @@ func infoAction(cmd *cobra.Command, args []string) error { } } - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/system/system_prune.go b/cmd/nerdctl/system/system_prune.go index 218afb4ef70..f493e21ff4f 100644 --- a/cmd/nerdctl/system/system_prune.go +++ b/cmd/nerdctl/system/system_prune.go @@ -87,7 +87,7 @@ func systemPruneAction(cmd *cobra.Command, args []string) error { } } - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/utils/image.go b/cmd/nerdctl/utils/image.go index 59285bff743..787192e25bf 100644 --- a/cmd/nerdctl/utils/image.go +++ b/cmd/nerdctl/utils/image.go @@ -38,7 +38,7 @@ import ( func LoadImage(in io.Reader, cmd *cobra.Command, platMC platforms.MatchComparer, quiet bool) error { // In addition to passing WithImagePlatform() to client.Import(), we also need to pass WithDefaultPlatform() to NewClient(). // Otherwise unpacking may fail. - client, ctx, cancel, err := ncclient.NewClient(cmd, containerd.WithDefaultPlatform(platMC)) + client, ctx, cancel, err := ncclient.New(cmd, containerd.WithDefaultPlatform(platMC)) if err != nil { return err } diff --git a/cmd/nerdctl/utils/run/run_network.go b/cmd/nerdctl/utils/run/run_network.go index c6eb93c3f8f..5dfb2576005 100644 --- a/cmd/nerdctl/utils/run/run_network.go +++ b/cmd/nerdctl/utils/run/run_network.go @@ -192,7 +192,7 @@ func GenerateNetOpts(cmd *cobra.Command, dataStore, stateDir, ns, id string) ([] return nil, nil, "", nil, "", fmt.Errorf("invalid network: %s, should be \"container:\"", netSlice[0]) } containerName := network[1] - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return nil, nil, "", nil, "", err } diff --git a/cmd/nerdctl/version/version.go b/cmd/nerdctl/version/version.go index 33659fd8370..70fccb6220a 100644 --- a/cmd/nerdctl/version/version.go +++ b/cmd/nerdctl/version/version.go @@ -103,7 +103,7 @@ func versionInfo(cmd *cobra.Command) (dockercompat.VersionInfo, error) { v := dockercompat.VersionInfo{ Client: infoutil.ClientVersion(), } - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return v, err } diff --git a/cmd/nerdctl/volume/volume_prune.go b/cmd/nerdctl/volume/volume_prune.go index 2e117559d05..4c9bde74108 100644 --- a/cmd/nerdctl/volume/volume_prune.go +++ b/cmd/nerdctl/volume/volume_prune.go @@ -58,7 +58,7 @@ func volumePruneAction(cmd *cobra.Command, _ []string) error { } } - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/volume/volume_rm.go b/cmd/nerdctl/volume/volume_rm.go index 1960e7636a0..3235fb646e0 100644 --- a/cmd/nerdctl/volume/volume_rm.go +++ b/cmd/nerdctl/volume/volume_rm.go @@ -48,7 +48,7 @@ func NewRmCommand() *cobra.Command { } func volumeRmAction(cmd *cobra.Command, args []string) error { - client, ctx, cancel, err := ncclient.NewClient(cmd) + client, ctx, cancel, err := ncclient.New(cmd) if err != nil { return err } From 4e03e4a6dc61c38e9e6f770d2462baf3e92cfc33 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Fri, 16 Dec 2022 09:35:34 +0900 Subject: [PATCH 06/14] [Carry 1639] remove "Get" verb Signed-off-by: Akihiro Suda --- cmd/nerdctl/builder/build.go | 4 ++-- cmd/nerdctl/builder/builder.go | 2 +- cmd/nerdctl/client/client.go | 4 ++-- cmd/nerdctl/completion/completion.go | 2 +- cmd/nerdctl/compose/compose.go | 2 +- cmd/nerdctl/container/logs.go | 2 +- cmd/nerdctl/container/ps.go | 4 ++-- cmd/nerdctl/container/rename.go | 2 +- cmd/nerdctl/image/image_convert.go | 2 +- cmd/nerdctl/internal/internal_oci_hook.go | 2 +- cmd/nerdctl/ipfs/registry/ipfs_registry_up.go | 2 +- cmd/nerdctl/login/login.go | 8 ++++---- cmd/nerdctl/namespace/namespace.go | 2 +- cmd/nerdctl/utils/action/start.go | 2 +- cmd/nerdctl/utils/common/common.go | 2 +- cmd/nerdctl/utils/container/container.go | 14 +++++++------- cmd/nerdctl/utils/container/container_create.go | 4 ++-- cmd/nerdctl/utils/mount.go | 2 +- cmd/nerdctl/utils/network.go | 2 +- cmd/nerdctl/utils/print.go | 2 +- cmd/nerdctl/utils/run/run_network.go | 10 +++++----- cmd/nerdctl/utils/volume/volume.go | 16 ++++++++++------ cmd/nerdctl/volume/volume_create.go | 2 +- cmd/nerdctl/volume/volume_inspect.go | 2 +- cmd/nerdctl/volume/volume_ls.go | 2 +- cmd/nerdctl/volume/volume_prune.go | 2 +- cmd/nerdctl/volume/volume_rm.go | 2 +- 27 files changed, 53 insertions(+), 49 deletions(-) diff --git a/cmd/nerdctl/builder/build.go b/cmd/nerdctl/builder/build.go index a1d473aaed0..d699e0fd272 100644 --- a/cmd/nerdctl/builder/build.go +++ b/cmd/nerdctl/builder/build.go @@ -80,7 +80,7 @@ If Dockerfile is not present and -f is not specified, it will look for Container return buildCommand } -func GetBuildkitHost(cmd *cobra.Command) (string, error) { +func BuildkitHost(cmd *cobra.Command) (string, error) { if cmd.Flags().Changed("buildkit-host") || os.Getenv("BUILDKIT_HOST") != "" { // If address is explicitly specified, use it. buildkitHost, err := cmd.Flags().GetString("buildkit-host") @@ -135,7 +135,7 @@ func buildAction(cmd *cobra.Command, args []string) error { } platform = strutil.DedupeStrSlice(platform) - buildkitHost, err := GetBuildkitHost(cmd) + buildkitHost, err := BuildkitHost(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/builder/builder.go b/cmd/nerdctl/builder/builder.go index 36ae0b80b06..c3c2d2c6c92 100644 --- a/cmd/nerdctl/builder/builder.go +++ b/cmd/nerdctl/builder/builder.go @@ -64,7 +64,7 @@ func NewPruneCommand() *cobra.Command { } func builderPruneAction(cmd *cobra.Command, _ []string) error { - buildkitHost, err := GetBuildkitHost(cmd) + buildkitHost, err := BuildkitHost(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/client/client.go b/cmd/nerdctl/client/client.go index d693149e26a..50bb3f37baf 100644 --- a/cmd/nerdctl/client/client.go +++ b/cmd/nerdctl/client/client.go @@ -86,10 +86,10 @@ func NewWithPlatform(cmd *cobra.Command, platform string, clientOpts ...containe return New(cmd, clientOpts...) } -// GetDataStore returns a string like "/var/lib/nerdctl/1935db59". +// DataStore returns a string like "/var/lib/nerdctl/1935db59". // "1935db9" is from `$(echo -n "/run/containerd/containerd.sock" | sha256sum | cut -c1-8)` // on Windows it will return "%PROGRAMFILES%/nerdctl/1935db59" -func GetDataStore(cmd *cobra.Command) (string, error) { +func DataStore(cmd *cobra.Command) (string, error) { dataRoot, err := cmd.Flags().GetString("data-root") if err != nil { return "", err diff --git a/cmd/nerdctl/completion/completion.go b/cmd/nerdctl/completion/completion.go index 8ef321d8027..151bb405a22 100644 --- a/cmd/nerdctl/completion/completion.go +++ b/cmd/nerdctl/completion/completion.go @@ -131,7 +131,7 @@ func ShellCompleteNetworkNames(cmd *cobra.Command, exclude []string) ([]string, } func ShellCompleteVolumeNames(cmd *cobra.Command) ([]string, cobra.ShellCompDirective) { - vols, err := volume.GetVolumes(cmd) + vols, err := volume.Volumes(cmd) if err != nil { return nil, cobra.ShellCompDirectiveError } diff --git a/cmd/nerdctl/compose/compose.go b/cmd/nerdctl/compose/compose.go index a51e971cfb9..8ab6fa52f02 100644 --- a/cmd/nerdctl/compose/compose.go +++ b/cmd/nerdctl/compose/compose.go @@ -158,7 +158,7 @@ func getComposer(cmd *cobra.Command, client *containerd.Client) (*composer.Compo return false, nil } - volStore, err := volume.GetVolumeStore(cmd) + volStore, err := volume.Store(cmd) if err != nil { return nil, err } diff --git a/cmd/nerdctl/container/logs.go b/cmd/nerdctl/container/logs.go index 609f25e5fb4..77338045f36 100644 --- a/cmd/nerdctl/container/logs.go +++ b/cmd/nerdctl/container/logs.go @@ -54,7 +54,7 @@ func NewLogsCommand() *cobra.Command { } func logsAction(cmd *cobra.Command, args []string) error { - dataStore, err := ncclient.GetDataStore(cmd) + dataStore, err := ncclient.DataStore(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container/ps.go b/cmd/nerdctl/container/ps.go index 14cfa488452..6a286678150 100644 --- a/cmd/nerdctl/container/ps.go +++ b/cmd/nerdctl/container/ps.go @@ -225,7 +225,7 @@ func printContainers(ctx context.Context, client *containerd.Client, cmd *cobra. ID: id, Image: imageName, Platform: info.Labels[labels.Platform], - Names: utils.GetPrintableContainerName(info.Labels), + Names: utils.PrintableContainerName(info.Labels), Ports: formatter.FormatPorts(info.Labels), Status: cStatus, Runtime: info.Runtime.Name, @@ -233,7 +233,7 @@ func printContainers(ctx context.Context, client *containerd.Client, cmd *cobra. } if size || wide { - containerSize, err := container.GetContainerSize(ctx, client, c, info) + containerSize, err := container.ContainerSize(ctx, client, c, info) if err != nil { return err } diff --git a/cmd/nerdctl/container/rename.go b/cmd/nerdctl/container/rename.go index 28225b3dc28..d90af5fe7cb 100644 --- a/cmd/nerdctl/container/rename.go +++ b/cmd/nerdctl/container/rename.go @@ -55,7 +55,7 @@ func renameAction(cmd *cobra.Command, args []string) error { return err } - dataStore, err := ncclient.GetDataStore(cmd) + dataStore, err := ncclient.DataStore(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/image/image_convert.go b/cmd/nerdctl/image/image_convert.go index 34589335951..21e3080ce45 100644 --- a/cmd/nerdctl/image/image_convert.go +++ b/cmd/nerdctl/image/image_convert.go @@ -460,7 +460,7 @@ func getNydusConvertOpts(cmd *cobra.Command) (*nydusconvert.PackOption, error) { return nil, err } if workDir == "" { - workDir, err = ncclient.GetDataStore(cmd) + workDir, err = ncclient.DataStore(cmd) if err != nil { return nil, err } diff --git a/cmd/nerdctl/internal/internal_oci_hook.go b/cmd/nerdctl/internal/internal_oci_hook.go index 6b0191d5d43..88c2bcc0857 100644 --- a/cmd/nerdctl/internal/internal_oci_hook.go +++ b/cmd/nerdctl/internal/internal_oci_hook.go @@ -45,7 +45,7 @@ func internalOCIHookAction(cmd *cobra.Command, args []string) error { if event == "" { return errors.New("event type needs to be passed") } - dataStore, err := client.GetDataStore(cmd) + dataStore, err := client.DataStore(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/ipfs/registry/ipfs_registry_up.go b/cmd/nerdctl/ipfs/registry/ipfs_registry_up.go index bf7ab6b826f..45ea0466a5f 100644 --- a/cmd/nerdctl/ipfs/registry/ipfs_registry_up.go +++ b/cmd/nerdctl/ipfs/registry/ipfs_registry_up.go @@ -94,7 +94,7 @@ func runRegistryAsContainer(cmd *cobra.Command) error { if err != nil { return err } - dataStore, err := ncclient.GetDataStore(cmd) + dataStore, err := ncclient.DataStore(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/login/login.go b/cmd/nerdctl/login/login.go index 41274d59a4b..c88f16b4350 100644 --- a/cmd/nerdctl/login/login.go +++ b/cmd/nerdctl/login/login.go @@ -96,7 +96,7 @@ func loginAction(cmd *cobra.Command, args []string) error { ctx := cmd.Context() isDefaultRegistry := serverAddress == dockerconfigresolver.IndexServer - authConfig, err := GetDefaultAuthConfig(options.username == "" && options.password == "", serverAddress, isDefaultRegistry) + authConfig, err := DefaultAuthConfig(options.username == "" && options.password == "", serverAddress, isDefaultRegistry) if authConfig == nil { authConfig = &types.AuthConfig{ServerAddress: serverAddress} } @@ -174,10 +174,10 @@ func verifyloginOptions(cmd *cobra.Command, options *loginOptions) error { } -// Code from github.com/docker/cli/cli/command (v20.10.3) -// GetDefaultAuthConfig gets the default auth config given a serverAddress +// DefaultAuthConfig gets the default auth config given a serverAddress // If credentials for given serverAddress exists in the credential store, the configuration will be populated with values in it -func GetDefaultAuthConfig(checkCredStore bool, serverAddress string, isDefaultRegistry bool) (*types.AuthConfig, error) { +// Code from github.com/docker/cli/cli/command (v20.10.3) +func DefaultAuthConfig(checkCredStore bool, serverAddress string, isDefaultRegistry bool) (*types.AuthConfig, error) { if !isDefaultRegistry { var err error serverAddress, err = convertToHostname(serverAddress) diff --git a/cmd/nerdctl/namespace/namespace.go b/cmd/nerdctl/namespace/namespace.go index 3689c0c7066..d43c0e22cae 100644 --- a/cmd/nerdctl/namespace/namespace.go +++ b/cmd/nerdctl/namespace/namespace.go @@ -87,7 +87,7 @@ func namespaceLsAction(cmd *cobra.Command, args []string) error { return nil } - dataStore, err := ncclient.GetDataStore(cmd) + dataStore, err := ncclient.DataStore(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/utils/action/start.go b/cmd/nerdctl/utils/action/start.go index d769ae636d0..b01d712cccf 100644 --- a/cmd/nerdctl/utils/action/start.go +++ b/cmd/nerdctl/utils/action/start.go @@ -142,7 +142,7 @@ func reconfigNetContainer(ctx context.Context, c containerd.Container, client *c if err != nil { return err } - netNSPath, err := run.GetContainerNetNSPath(ctx, targetCon) + netNSPath, err := run.ContainerNetNSPath(ctx, targetCon) if err != nil { return err } diff --git a/cmd/nerdctl/utils/common/common.go b/cmd/nerdctl/utils/common/common.go index 5df318b4ac2..f9e1814e47d 100644 --- a/cmd/nerdctl/utils/common/common.go +++ b/cmd/nerdctl/utils/common/common.go @@ -263,7 +263,7 @@ func ReadKVStringsMapfFromLabel(cmd *cobra.Command) (map[string]string, error) { return strutil.ConvertKVStringsToMap(labels), nil } -func GetContainerStateDirPath(cmd *cobra.Command, dataStore, id string) (string, error) { +func ContainerStateDirPath(cmd *cobra.Command, dataStore, id string) (string, error) { ns, err := cmd.Flags().GetString("namespace") if err != nil { return "", err diff --git a/cmd/nerdctl/utils/container/container.go b/cmd/nerdctl/utils/container/container.go index ea1060f65f4..be0677fa57e 100644 --- a/cmd/nerdctl/utils/container/container.go +++ b/cmd/nerdctl/utils/container/container.go @@ -303,7 +303,7 @@ func (cl *FilterContext) matchesNameFilter(info containers.Container) bool { if len(cl.NameFilterFuncs) == 0 { return true } - cName := utils.GetPrintableContainerName(info.Labels) + cName := utils.PrintableContainerName(info.Labels) for _, nameFilterFunc := range cl.NameFilterFuncs { if !nameFilterFunc(cName) { continue @@ -352,7 +352,7 @@ func (cl *FilterContext) matchesVolumeFilter(info containers.Container) bool { if len(cl.VolumeFilterFuncs) == 0 { return true } - vols := volume.GetContainerVolumes(info.Labels) + vols := volume.ContainerVolumes(info.Labels) for _, volumeFilterFunc := range cl.VolumeFilterFuncs { if !volumeFilterFunc(vols) { continue @@ -366,7 +366,7 @@ func (cl *FilterContext) matchesNetworkFilter(info containers.Container) bool { if len(cl.NetworkFilterFuncs) == 0 { return true } - networks := utils.GetContainerNetworks(info.Labels) + networks := utils.ContainerNetworks(info.Labels) for _, networkFilterFunc := range cl.NetworkFilterFuncs { if !networkFilterFunc(networks) { continue @@ -382,14 +382,14 @@ func IDOrNameFilter(ctx context.Context, containers []containerd.Container, valu if err != nil { return nil, err } - if strings.HasPrefix(info.ID, value) || strings.Contains(utils.GetPrintableContainerName(info.Labels), value) { + if strings.HasPrefix(info.ID, value) || strings.Contains(utils.PrintableContainerName(info.Labels), value) { return &info, nil } } return nil, fmt.Errorf("no such container %s", value) } -func GetContainerSize(ctx context.Context, client *containerd.Client, c containerd.Container, info containers.Container) (string, error) { +func ContainerSize(ctx context.Context, client *containerd.Client, c containerd.Container, info containers.Container) (string, error) { // get container snapshot size snapshotKey := info.SnapshotKey var containerSize int64 @@ -432,7 +432,7 @@ func RemoveContainer(ctx context.Context, cmd *cobra.Command, container containe stateDir := l[labels.StateDir] name := l[labels.Name] - dataStore, err := client.GetDataStore(cmd) + dataStore, err := client.DataStore(cmd) if err != nil { return err } @@ -466,7 +466,7 @@ func RemoveContainer(ctx context.Context, cmd *cobra.Command, container containe if err := json.Unmarshal([]byte(anonVolumesJSON), &anonVolumes); err != nil { return err } - volStore, err := volume.GetVolumeStore(cmd) + volStore, err := volume.Store(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/utils/container/container_create.go b/cmd/nerdctl/utils/container/container_create.go index 90e44eb98a0..21144444488 100644 --- a/cmd/nerdctl/utils/container/container_create.go +++ b/cmd/nerdctl/utils/container/container_create.go @@ -86,12 +86,12 @@ func CreateContainer(ctx context.Context, cmd *cobra.Command, client *containerd } } - dataStore, err := ncclient.GetDataStore(cmd) + dataStore, err := ncclient.DataStore(cmd) if err != nil { return nil, nil, err } - stateDir, err := common.GetContainerStateDirPath(cmd, dataStore, id) + stateDir, err := common.ContainerStateDirPath(cmd, dataStore, id) if err != nil { return nil, nil, err } diff --git a/cmd/nerdctl/utils/mount.go b/cmd/nerdctl/utils/mount.go index f7595b95f24..3df780ca789 100644 --- a/cmd/nerdctl/utils/mount.go +++ b/cmd/nerdctl/utils/mount.go @@ -121,7 +121,7 @@ func parseMountFlags(cmd *cobra.Command, volStore volumestore.VolumeStore) ([]*m // generateMountOpts generates volume-related mount opts. // Other mounts such as procfs mount are not handled here. func GenerateMountOpts(ctx context.Context, cmd *cobra.Command, client *containerd.Client, ensuredImage *imgutil.EnsuredImage) ([]oci.SpecOpts, []string, []*mountutil.Processed, error) { - volStore, err := volume.GetVolumeStore(cmd) + volStore, err := volume.Store(cmd) if err != nil { return nil, nil, nil, err } diff --git a/cmd/nerdctl/utils/network.go b/cmd/nerdctl/utils/network.go index ba359e0495b..6f86bb0b60b 100644 --- a/cmd/nerdctl/utils/network.go +++ b/cmd/nerdctl/utils/network.go @@ -23,7 +23,7 @@ import ( "github.com/sirupsen/logrus" ) -func GetContainerNetworks(containerLables map[string]string) []string { +func ContainerNetworks(containerLables map[string]string) []string { var networks []string if names, ok := containerLables[labels.Networks]; ok { if err := json.Unmarshal([]byte(names), &networks); err != nil { diff --git a/cmd/nerdctl/utils/print.go b/cmd/nerdctl/utils/print.go index bd14d11033b..504bcea9866 100644 --- a/cmd/nerdctl/utils/print.go +++ b/cmd/nerdctl/utils/print.go @@ -23,7 +23,7 @@ import ( "github.com/containerd/nerdctl/pkg/labels/k8slabels" ) -func GetPrintableContainerName(containerLabels map[string]string) string { +func PrintableContainerName(containerLabels map[string]string) string { if name, ok := containerLabels[labels.Name]; ok { return name } diff --git a/cmd/nerdctl/utils/run/run_network.go b/cmd/nerdctl/utils/run/run_network.go index 5dfb2576005..214f7dbf5db 100644 --- a/cmd/nerdctl/utils/run/run_network.go +++ b/cmd/nerdctl/utils/run/run_network.go @@ -132,7 +132,7 @@ func GenerateNetOpts(cmd *cobra.Command, dataStore, stateDir, ns, id string) ([] logrus.Warnf("You have assign an IP address %s but no network, So we will use the default network", ipAddress) } - macAddress, err := GetMACAddress(cmd, netSlice) + macAddress, err := MACAddress(cmd, netSlice) if err != nil { return nil, nil, "", nil, "", err } @@ -206,7 +206,7 @@ func GenerateNetOpts(cmd *cobra.Command, dataStore, stateDir, ns, id string) ([] } containerID := found.Container.ID() - conStateDir, err := common.GetContainerStateDirPath(cmd, dataStore, containerID) + conStateDir, err := common.ContainerStateDirPath(cmd, dataStore, containerID) if err != nil { return err } @@ -219,7 +219,7 @@ func GenerateNetOpts(cmd *cobra.Command, dataStore, stateDir, ns, id string) ([] hostnamePath := filepath.Join(conStateDir, "hostname") resolvConfPath := filepath.Join(conStateDir, "resolv.conf") etcHostsPath := hostsstore.HostsPath(dataStore, ns, containerID) - netNSPath, err := GetContainerNetNSPath(ctx, found.Container) + netNSPath, err := ContainerNetNSPath(ctx, found.Container) if err != nil { return err } @@ -251,7 +251,7 @@ func GenerateNetOpts(cmd *cobra.Command, dataStore, stateDir, ns, id string) ([] return opts, netSlice, ipAddress, ports, macAddress, nil } -func GetContainerNetNSPath(ctx context.Context, c containerd.Container) (string, error) { +func ContainerNetNSPath(ctx context.Context, c containerd.Container) (string, error) { task, err := c.Task(ctx, nil) if err != nil { return "", err @@ -387,7 +387,7 @@ func BuildResolvConf(cmd *cobra.Command, resolvConfPath string) error { return nil } -func GetMACAddress(cmd *cobra.Command, netSlice []string) (string, error) { +func MACAddress(cmd *cobra.Command, netSlice []string) (string, error) { macAddress, err := cmd.Flags().GetString("mac-address") if err != nil { return "", err diff --git a/cmd/nerdctl/utils/volume/volume.go b/cmd/nerdctl/utils/volume/volume.go index ac88a167013..c514f8f68e4 100644 --- a/cmd/nerdctl/utils/volume/volume.go +++ b/cmd/nerdctl/utils/volume/volume.go @@ -27,6 +27,8 @@ import ( "github.com/spf13/cobra" ) +// ContainerVolume is a misnomer. +// TODO: find a better name. type ContainerVolume struct { Type string Name string @@ -37,22 +39,22 @@ type ContainerVolume struct { Propagation string } -// GetVolumeStore returns a volume store +// Store returns a volume store // that corresponds to a directory like `/var/lib/nerdctl/1935db59/volume/default` -func GetVolumeStore(cmd *cobra.Command) (volumestore.VolumeStore, error) { +func Store(cmd *cobra.Command) (volumestore.VolumeStore, error) { ns, err := cmd.Flags().GetString("namespace") if err != nil { return nil, err } - dataStore, err := client.GetDataStore(cmd) + dataStore, err := client.DataStore(cmd) if err != nil { return nil, err } return volumestore.New(dataStore, ns) } -func GetVolumes(cmd *cobra.Command) (map[string]native.Volume, error) { - volStore, err := GetVolumeStore(cmd) +func Volumes(cmd *cobra.Command) (map[string]native.Volume, error) { + volStore, err := Store(cmd) if err != nil { return nil, err } @@ -63,7 +65,9 @@ func GetVolumes(cmd *cobra.Command) (map[string]native.Volume, error) { return volStore.List(volumeSize) } -func GetContainerVolumes(containerLabels map[string]string) []*ContainerVolume { +// ContainerVolumes is a misnomer. +// TODO: find a better name. +func ContainerVolumes(containerLabels map[string]string) []*ContainerVolume { var vols []*ContainerVolume volLabels := []string{labels.AnonymousVolumes, labels.Mounts} for _, volLabel := range volLabels { diff --git a/cmd/nerdctl/volume/volume_create.go b/cmd/nerdctl/volume/volume_create.go index d3914e51f7c..c3b7995c75d 100644 --- a/cmd/nerdctl/volume/volume_create.go +++ b/cmd/nerdctl/volume/volume_create.go @@ -46,7 +46,7 @@ func volumeCreateAction(cmd *cobra.Command, args []string) error { return fmt.Errorf("malformed name %s: %w", name, err) } - volStore, err := volume.GetVolumeStore(cmd) + volStore, err := volume.Store(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/volume/volume_inspect.go b/cmd/nerdctl/volume/volume_inspect.go index 6ac6e29c6f9..b01d74ccd63 100644 --- a/cmd/nerdctl/volume/volume_inspect.go +++ b/cmd/nerdctl/volume/volume_inspect.go @@ -47,7 +47,7 @@ func volumeInspectAction(cmd *cobra.Command, args []string) error { return err } - volStore, err := volume.GetVolumeStore(cmd) + volStore, err := volume.Store(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/volume/volume_ls.go b/cmd/nerdctl/volume/volume_ls.go index 4343cdcca9d..212d135824c 100644 --- a/cmd/nerdctl/volume/volume_ls.go +++ b/cmd/nerdctl/volume/volume_ls.go @@ -124,7 +124,7 @@ func volumeLsAction(cmd *cobra.Command, args []string) error { } } - vols, err := volume.GetVolumes(cmd) + vols, err := volume.Volumes(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/volume/volume_prune.go b/cmd/nerdctl/volume/volume_prune.go index 4c9bde74108..6e3f24c6d3c 100644 --- a/cmd/nerdctl/volume/volume_prune.go +++ b/cmd/nerdctl/volume/volume_prune.go @@ -68,7 +68,7 @@ func volumePruneAction(cmd *cobra.Command, _ []string) error { } func Prune(ctx context.Context, cmd *cobra.Command, client *containerd.Client) error { - volStore, err := volume.GetVolumeStore(cmd) + volStore, err := volume.Store(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/volume/volume_rm.go b/cmd/nerdctl/volume/volume_rm.go index 3235fb646e0..976bfa4c315 100644 --- a/cmd/nerdctl/volume/volume_rm.go +++ b/cmd/nerdctl/volume/volume_rm.go @@ -57,7 +57,7 @@ func volumeRmAction(cmd *cobra.Command, args []string) error { if err != nil { return err } - volStore, err := volume.GetVolumeStore(cmd) + volStore, err := volume.Store(cmd) if err != nil { return err } From c0566a4e2ac82fdeb75bead7c19fa1c52e36182f Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Fri, 16 Dec 2022 11:57:38 +0900 Subject: [PATCH 07/14] [Carry 1639] split cmd/nerdctl/utils/container Signed-off-by: Akihiro Suda --- cmd/nerdctl/container/container_prune.go | 4 +- cmd/nerdctl/container/create.go | 3 +- cmd/nerdctl/container/exec.go | 3 +- cmd/nerdctl/container/ps.go | 37 +++- cmd/nerdctl/container/rm.go | 4 +- cmd/nerdctl/container/run.go | 6 +- cmd/nerdctl/utils/action/remove.go | 156 ++++++++++++++++ .../containerfilter.go} | 168 +----------------- .../container_create.go => run/create.go} | 19 +- 9 files changed, 212 insertions(+), 188 deletions(-) create mode 100644 cmd/nerdctl/utils/action/remove.go rename cmd/nerdctl/utils/{container/container.go => containerfilter/containerfilter.go} (68%) rename cmd/nerdctl/utils/{container/container_create.go => run/create.go} (96%) diff --git a/cmd/nerdctl/container/container_prune.go b/cmd/nerdctl/container/container_prune.go index 6168c0b4163..cd90352d42a 100644 --- a/cmd/nerdctl/container/container_prune.go +++ b/cmd/nerdctl/container/container_prune.go @@ -24,8 +24,8 @@ import ( "github.com/containerd/containerd" ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/action" "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" - containerUtils "github.com/containerd/nerdctl/cmd/nerdctl/utils/container" "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -79,7 +79,7 @@ func Prune(ctx context.Context, cmd *cobra.Command, client *containerd.Client) e var deleted []string for _, container := range containers { - err = containerUtils.RemoveContainer(ctx, cmd, container, false, true) + err = action.RemoveContainer(ctx, cmd, container, false, true) if err == nil { deleted = append(deleted, container.ID()) continue diff --git a/cmd/nerdctl/container/create.go b/cmd/nerdctl/container/create.go index fbe089d42d1..2ee42241008 100644 --- a/cmd/nerdctl/container/create.go +++ b/cmd/nerdctl/container/create.go @@ -22,7 +22,6 @@ import ( ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" - "github.com/containerd/nerdctl/cmd/nerdctl/utils/container" "github.com/containerd/nerdctl/cmd/nerdctl/utils/run" "github.com/spf13/cobra" ) @@ -74,7 +73,7 @@ func createAction(cmd *cobra.Command, args []string) error { } defer cancel() - container, gc, err := container.CreateContainer(ctx, cmd, client, args, platform, false, false, true) + container, gc, err := run.CreateContainer(ctx, cmd, client, args, platform, false, false, true) if err != nil { if gc != nil { gc() diff --git a/cmd/nerdctl/container/exec.go b/cmd/nerdctl/container/exec.go index f6ced68542b..6854fef914b 100644 --- a/cmd/nerdctl/container/exec.go +++ b/cmd/nerdctl/container/exec.go @@ -30,7 +30,6 @@ import ( "github.com/containerd/containerd/cmd/ctr/commands/tasks" ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" - containerUtils "github.com/containerd/nerdctl/cmd/nerdctl/utils/container" "github.com/containerd/nerdctl/cmd/nerdctl/utils/run" "github.com/containerd/nerdctl/pkg/flagutil" "github.com/containerd/nerdctl/pkg/idgen" @@ -251,7 +250,7 @@ func generateExecProcessSpec(ctx context.Context, cmd *cobra.Command, args []str if err != nil { return nil, err } - envs, err := containerUtils.GenerateEnvs(envFile, env) + envs, err := run.GenerateEnvs(envFile, env) if err != nil { return nil, err } diff --git a/cmd/nerdctl/container/ps.go b/cmd/nerdctl/container/ps.go index 6a286678150..29d68519662 100644 --- a/cmd/nerdctl/container/ps.go +++ b/cmd/nerdctl/container/ps.go @@ -30,10 +30,12 @@ import ( "time" "github.com/containerd/containerd" + "github.com/containerd/containerd/containers" "github.com/containerd/containerd/errdefs" + "github.com/containerd/containerd/pkg/progress" ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/utils" - "github.com/containerd/nerdctl/cmd/nerdctl/utils/container" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/containerfilter" "github.com/containerd/nerdctl/cmd/nerdctl/utils/fmtutil" "github.com/containerd/nerdctl/pkg/formatter" "github.com/containerd/nerdctl/pkg/labels" @@ -97,7 +99,7 @@ func psAction(cmd *cobra.Command, args []string) error { if err != nil { return err } - filterCtx, err := container.FoldContainerFilters(ctx, containers, filters) + filterCtx, err := containerfilter.FoldContainerFilters(ctx, containers, filters) if err != nil { return err } @@ -233,7 +235,7 @@ func printContainers(ctx context.Context, client *containerd.Client, cmd *cobra. } if size || wide { - containerSize, err := container.ContainerSize(ctx, client, c, info) + containerSize, err := containerSize(ctx, client, c, info) if err != nil { return err } @@ -283,3 +285,32 @@ func printContainers(ctx context.Context, client *containerd.Client, cmd *cobra. } return nil } + +func containerSize(ctx context.Context, client *containerd.Client, c containerd.Container, info containers.Container) (string, error) { + // get container snapshot size + snapshotKey := info.SnapshotKey + var containerSize int64 + + if snapshotKey != "" { + usage, err := client.SnapshotService(info.Snapshotter).Usage(ctx, snapshotKey) + if err != nil { + return "", err + } + containerSize = usage.Size + } + + // get the image interface + image, err := c.Image(ctx) + if err != nil { + return "", err + } + + sn := client.SnapshotService(info.Snapshotter) + + imageSize, err := utils.UnpackedImageSize(ctx, sn, image) + if err != nil { + return "", err + } + + return fmt.Sprintf("%s (virtual %s)", progress.Bytes(containerSize).String(), progress.Bytes(imageSize).String()), nil +} diff --git a/cmd/nerdctl/container/rm.go b/cmd/nerdctl/container/rm.go index 9da3a936eb8..47ee9974ccc 100644 --- a/cmd/nerdctl/container/rm.go +++ b/cmd/nerdctl/container/rm.go @@ -22,7 +22,7 @@ import ( ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" - "github.com/containerd/nerdctl/cmd/nerdctl/utils/container" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/action" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -65,7 +65,7 @@ func rmAction(cmd *cobra.Command, args []string) error { if found.MatchCount > 1 { return fmt.Errorf("multiple IDs found with provided prefix: %s", found.Req) } - if err := container.RemoveContainer(ctx, cmd, found.Container, force, removeAnonVolumes); err != nil { + if err := action.RemoveContainer(ctx, cmd, found.Container, force, removeAnonVolumes); err != nil { return err } _, err = fmt.Fprintf(cmd.OutOrStdout(), "%s\n", found.Req) diff --git a/cmd/nerdctl/container/run.go b/cmd/nerdctl/container/run.go index 79106474131..73219952c45 100644 --- a/cmd/nerdctl/container/run.go +++ b/cmd/nerdctl/container/run.go @@ -27,8 +27,8 @@ import ( "github.com/containerd/containerd/cmd/ctr/commands/tasks" ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/action" "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" - containerUtils "github.com/containerd/nerdctl/cmd/nerdctl/utils/container" "github.com/containerd/nerdctl/cmd/nerdctl/utils/run" "github.com/containerd/nerdctl/pkg/labels" "github.com/containerd/nerdctl/pkg/taskutil" @@ -91,7 +91,7 @@ func runAction(cmd *cobra.Command, args []string) error { if err != nil { return err } - container, gc, err := containerUtils.CreateContainer(ctx, cmd, client, args, platform, flagI, flagT, flagD) + container, gc, err := run.CreateContainer(ctx, cmd, client, args, platform, flagI, flagT, flagD) if err != nil { if gc != nil { defer gc() @@ -109,7 +109,7 @@ func runAction(cmd *cobra.Command, args []string) error { return errors.New("flag -d and --rm cannot be specified together") } defer func() { - if err := containerUtils.RemoveContainer(ctx, cmd, container, true, true); err != nil { + if err := action.RemoveContainer(ctx, cmd, container, true, true); err != nil { logrus.WithError(err).Warnf("failed to remove container %s", id) } }() diff --git a/cmd/nerdctl/utils/action/remove.go b/cmd/nerdctl/utils/action/remove.go new file mode 100644 index 00000000000..0a6196bf064 --- /dev/null +++ b/cmd/nerdctl/utils/action/remove.go @@ -0,0 +1,156 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package action + +import ( + "context" + "encoding/json" + "fmt" + "os" + "syscall" + + "github.com/containerd/containerd" + "github.com/containerd/containerd/cio" + "github.com/containerd/containerd/errdefs" + "github.com/containerd/containerd/namespaces" + "github.com/containerd/nerdctl/cmd/nerdctl/client" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/volume" + "github.com/containerd/nerdctl/pkg/dnsutil/hostsstore" + "github.com/containerd/nerdctl/pkg/labels" + "github.com/containerd/nerdctl/pkg/namestore" + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" +) + +func RemoveContainer(ctx context.Context, cmd *cobra.Command, container containerd.Container, force bool, removeAnonVolumes bool) (retErr error) { + ns, err := namespaces.NamespaceRequired(ctx) + if err != nil { + return err + } + + id := container.ID() + l, err := container.Labels(ctx) + if err != nil { + return err + } + stateDir := l[labels.StateDir] + name := l[labels.Name] + + dataStore, err := client.DataStore(cmd) + if err != nil { + return err + } + namst, err := namestore.New(dataStore, ns) + if err != nil { + return err + } + + defer func() { + if errdefs.IsNotFound(retErr) { + retErr = nil + } + if retErr != nil { + return + } + + if err := os.RemoveAll(stateDir); err != nil { + logrus.WithError(retErr).Warnf("failed to remove container state dir %s", stateDir) + } + if name != "" { + if err := namst.Release(name, id); err != nil { + logrus.WithError(retErr).Warnf("failed to release container Name %s", name) + } + } + if err := hostsstore.DeallocHostsFile(dataStore, ns, id); err != nil { + logrus.WithError(retErr).Warnf("failed to remove hosts file for container %q", id) + } + }() + if anonVolumesJSON, ok := l[labels.AnonymousVolumes]; ok && removeAnonVolumes { + var anonVolumes []string + if err := json.Unmarshal([]byte(anonVolumesJSON), &anonVolumes); err != nil { + return err + } + volStore, err := volume.Store(cmd) + if err != nil { + return err + } + defer func() { + if _, err := volStore.Remove(anonVolumes); err != nil { + logrus.WithError(err).Warnf("failed to remove anonymous volume %v", anonVolumes) + } + }() + } + + task, err := container.Task(ctx, cio.Load) + if err != nil { + if errdefs.IsNotFound(err) { + if container.Delete(ctx, containerd.WithSnapshotCleanup) != nil { + return container.Delete(ctx) + } + } + return err + } + + status, err := task.Status(ctx) + if err != nil { + if errdefs.IsNotFound(err) { + return nil + } + return err + } + + switch status.Status { + case containerd.Created, containerd.Stopped: + if _, err := task.Delete(ctx); err != nil && !errdefs.IsNotFound(err) { + return fmt.Errorf("failed to delete task %v: %w", id, err) + } + case containerd.Paused: + if !force { + return common.NewStatusError(fmt.Errorf("you cannot remove a %v container %v. Unpause the container before attempting removal or force remove", status.Status, id)) + } + _, err := task.Delete(ctx, containerd.WithProcessKill) + if err != nil && !errdefs.IsNotFound(err) { + return fmt.Errorf("failed to delete task %v: %w", id, err) + } + // default is the case, when status.Status = containerd.Running + default: + if !force { + return common.NewStatusError(fmt.Errorf("you cannot remove a %v container %v. Stop the container before attempting removal or force remove", status.Status, id)) + } + if err := task.Kill(ctx, syscall.SIGKILL); err != nil { + logrus.WithError(err).Warnf("failed to send SIGKILL") + } + es, err := task.Wait(ctx) + if err == nil { + <-es + } + _, err = task.Delete(ctx, containerd.WithProcessKill) + if err != nil && !errdefs.IsNotFound(err) { + logrus.WithError(err).Warnf("failed to delete task %v", id) + } + } + var delOpts []containerd.DeleteOpts + if _, err := container.Image(ctx); err == nil { + delOpts = append(delOpts, containerd.WithSnapshotCleanup) + } + + if err := container.Delete(ctx, delOpts...); err != nil { + return err + } + return err +} diff --git a/cmd/nerdctl/utils/container/container.go b/cmd/nerdctl/utils/containerfilter/containerfilter.go similarity index 68% rename from cmd/nerdctl/utils/container/container.go rename to cmd/nerdctl/utils/containerfilter/containerfilter.go index be0677fa57e..36c7bfd7b05 100644 --- a/cmd/nerdctl/utils/container/container.go +++ b/cmd/nerdctl/utils/containerfilter/containerfilter.go @@ -14,33 +14,20 @@ limitations under the License. */ -package container +package containerfilter import ( "context" - "encoding/json" "fmt" - "os" "strconv" "strings" - "syscall" "time" "github.com/containerd/containerd" - "github.com/containerd/containerd/cio" "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/namespaces" - "github.com/containerd/containerd/pkg/progress" - "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/utils" - "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" "github.com/containerd/nerdctl/cmd/nerdctl/utils/volume" - "github.com/containerd/nerdctl/pkg/dnsutil/hostsstore" - "github.com/containerd/nerdctl/pkg/labels" - "github.com/containerd/nerdctl/pkg/namestore" "github.com/sirupsen/logrus" - "github.com/spf13/cobra" ) func FoldContainerFilters(ctx context.Context, containers []containerd.Container, filters []string) (*FilterContext, error) { @@ -143,7 +130,7 @@ func (cl *FilterContext) foldStatusFilter(_ context.Context, filter, value strin } func (cl *FilterContext) foldBeforeFilter(ctx context.Context, filter, value string) error { - beforeC, err := IDOrNameFilter(ctx, cl.Containers, value) + beforeC, err := idOrNameFilter(ctx, cl.Containers, value) if err == nil { cl.BeforeFilterFuncs = append(cl.BeforeFilterFuncs, func(t time.Time) bool { return t.Before(beforeC.CreatedAt) @@ -153,7 +140,7 @@ func (cl *FilterContext) foldBeforeFilter(ctx context.Context, filter, value str } func (cl *FilterContext) foldSinceFilter(ctx context.Context, filter, value string) error { - sinceC, err := IDOrNameFilter(ctx, cl.Containers, value) + sinceC, err := idOrNameFilter(ctx, cl.Containers, value) if err == nil { cl.SinceFilterFuncs = append(cl.SinceFilterFuncs, func(t time.Time) bool { return t.After(sinceC.CreatedAt) @@ -376,7 +363,7 @@ func (cl *FilterContext) matchesNetworkFilter(info containers.Container) bool { return false } -func IDOrNameFilter(ctx context.Context, containers []containerd.Container, value string) (*containers.Container, error) { +func idOrNameFilter(ctx context.Context, containers []containerd.Container, value string) (*containers.Container, error) { for _, container := range containers { info, err := container.Info(ctx, containerd.WithoutRefreshedMetadata) if err != nil { @@ -388,150 +375,3 @@ func IDOrNameFilter(ctx context.Context, containers []containerd.Container, valu } return nil, fmt.Errorf("no such container %s", value) } - -func ContainerSize(ctx context.Context, client *containerd.Client, c containerd.Container, info containers.Container) (string, error) { - // get container snapshot size - snapshotKey := info.SnapshotKey - var containerSize int64 - - if snapshotKey != "" { - usage, err := client.SnapshotService(info.Snapshotter).Usage(ctx, snapshotKey) - if err != nil { - return "", err - } - containerSize = usage.Size - } - - // get the image interface - image, err := c.Image(ctx) - if err != nil { - return "", err - } - - sn := client.SnapshotService(info.Snapshotter) - - imageSize, err := utils.UnpackedImageSize(ctx, sn, image) - if err != nil { - return "", err - } - - return fmt.Sprintf("%s (virtual %s)", progress.Bytes(containerSize).String(), progress.Bytes(imageSize).String()), nil -} - -func RemoveContainer(ctx context.Context, cmd *cobra.Command, container containerd.Container, force bool, removeAnonVolumes bool) (retErr error) { - ns, err := namespaces.NamespaceRequired(ctx) - if err != nil { - return err - } - - id := container.ID() - l, err := container.Labels(ctx) - if err != nil { - return err - } - stateDir := l[labels.StateDir] - name := l[labels.Name] - - dataStore, err := client.DataStore(cmd) - if err != nil { - return err - } - namst, err := namestore.New(dataStore, ns) - if err != nil { - return err - } - - defer func() { - if errdefs.IsNotFound(retErr) { - retErr = nil - } - if retErr != nil { - return - } - - if err := os.RemoveAll(stateDir); err != nil { - logrus.WithError(retErr).Warnf("failed to remove container state dir %s", stateDir) - } - if name != "" { - if err := namst.Release(name, id); err != nil { - logrus.WithError(retErr).Warnf("failed to release container Name %s", name) - } - } - if err := hostsstore.DeallocHostsFile(dataStore, ns, id); err != nil { - logrus.WithError(retErr).Warnf("failed to remove hosts file for container %q", id) - } - }() - if anonVolumesJSON, ok := l[labels.AnonymousVolumes]; ok && removeAnonVolumes { - var anonVolumes []string - if err := json.Unmarshal([]byte(anonVolumesJSON), &anonVolumes); err != nil { - return err - } - volStore, err := volume.Store(cmd) - if err != nil { - return err - } - defer func() { - if _, err := volStore.Remove(anonVolumes); err != nil { - logrus.WithError(err).Warnf("failed to remove anonymous volume %v", anonVolumes) - } - }() - } - - task, err := container.Task(ctx, cio.Load) - if err != nil { - if errdefs.IsNotFound(err) { - if container.Delete(ctx, containerd.WithSnapshotCleanup) != nil { - return container.Delete(ctx) - } - } - return err - } - - status, err := task.Status(ctx) - if err != nil { - if errdefs.IsNotFound(err) { - return nil - } - return err - } - - switch status.Status { - case containerd.Created, containerd.Stopped: - if _, err := task.Delete(ctx); err != nil && !errdefs.IsNotFound(err) { - return fmt.Errorf("failed to delete task %v: %w", id, err) - } - case containerd.Paused: - if !force { - return common.NewStatusError(fmt.Errorf("you cannot remove a %v container %v. Unpause the container before attempting removal or force remove", status.Status, id)) - } - _, err := task.Delete(ctx, containerd.WithProcessKill) - if err != nil && !errdefs.IsNotFound(err) { - return fmt.Errorf("failed to delete task %v: %w", id, err) - } - // default is the case, when status.Status = containerd.Running - default: - if !force { - return common.NewStatusError(fmt.Errorf("you cannot remove a %v container %v. Stop the container before attempting removal or force remove", status.Status, id)) - } - if err := task.Kill(ctx, syscall.SIGKILL); err != nil { - logrus.WithError(err).Warnf("failed to send SIGKILL") - } - es, err := task.Wait(ctx) - if err == nil { - <-es - } - _, err = task.Delete(ctx, containerd.WithProcessKill) - if err != nil && !errdefs.IsNotFound(err) { - logrus.WithError(err).Warnf("failed to delete task %v", id) - } - } - var delOpts []containerd.DeleteOpts - if _, err := container.Image(ctx); err == nil { - delOpts = append(delOpts, containerd.WithSnapshotCleanup) - } - - if err := container.Delete(ctx, delOpts...); err != nil { - return err - } - return err -} diff --git a/cmd/nerdctl/utils/container/container_create.go b/cmd/nerdctl/utils/run/create.go similarity index 96% rename from cmd/nerdctl/utils/container/container_create.go rename to cmd/nerdctl/utils/run/create.go index 21144444488..210bf949922 100644 --- a/cmd/nerdctl/utils/container/container_create.go +++ b/cmd/nerdctl/utils/run/create.go @@ -14,7 +14,7 @@ limitations under the License. */ -package container +package run import ( "bufio" @@ -37,7 +37,6 @@ import ( ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" - "github.com/containerd/nerdctl/cmd/nerdctl/utils/run" "github.com/containerd/nerdctl/pkg/idgen" "github.com/containerd/nerdctl/pkg/imgutil" "github.com/containerd/nerdctl/pkg/labels" @@ -104,7 +103,7 @@ func CreateContainer(ctx context.Context, cmd *cobra.Command, client *containerd oci.WithDefaultSpec(), ) - opts, internalLabels, err = run.SetPlatformOptions(ctx, opts, cmd, client, id, internalLabels) + opts, internalLabels, err = SetPlatformOptions(ctx, opts, cmd, client, id, internalLabels) if err != nil { return nil, nil, err } @@ -209,7 +208,7 @@ func CreateContainer(ctx context.Context, cmd *cobra.Command, client *containerd if err != nil { return nil, nil, err } - restartOpts, err := run.GenerateRestartOpts(ctx, client, restartValue, logURI) + restartOpts, err := GenerateRestartOpts(ctx, client, restartValue, logURI) if err != nil { return nil, nil, err } @@ -241,10 +240,10 @@ func CreateContainer(ctx context.Context, cmd *cobra.Command, client *containerd if err := os.WriteFile(hostnamePath, []byte(hostname+"\n"), 0644); err != nil { return nil, nil, err } - opts = append(opts, run.WithCustomEtcHostname(hostnamePath)) + opts = append(opts, WithCustomEtcHostname(hostnamePath)) } - netOpts, netSlice, ipAddress, ports, macAddress, err := run.GenerateNetOpts(cmd, dataStore, stateDir, ns, id) + netOpts, netSlice, ipAddress, ports, macAddress, err := GenerateNetOpts(cmd, dataStore, stateDir, ns, id) if err != nil { return nil, nil, err } @@ -260,25 +259,25 @@ func CreateContainer(ctx context.Context, cmd *cobra.Command, client *containerd } opts = append(opts, hookOpt) - uOpts, err := run.GenerateUserOpts(cmd) + uOpts, err := GenerateUserOpts(cmd) if err != nil { return nil, nil, err } opts = append(opts, uOpts...) - gOpts, err := run.GenerateGroupsOpts(cmd) + gOpts, err := GenerateGroupsOpts(cmd) if err != nil { return nil, nil, err } opts = append(opts, gOpts...) - umaskOpts, err := run.GenerateUmaskOpts(cmd) + umaskOpts, err := GenerateUmaskOpts(cmd) if err != nil { return nil, nil, err } opts = append(opts, umaskOpts...) - rtCOpts, err := run.GenerateRuntimeCOpts(cmd) + rtCOpts, err := GenerateRuntimeCOpts(cmd) if err != nil { return nil, nil, err } From 478ad5640b12cfb878038b68ac7e9061761e2281 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Fri, 16 Dec 2022 15:02:40 +0900 Subject: [PATCH 08/14] [Carry 1639] move cmd/nerdctl/utils/{pause,unpause}.go Signed-off-by: Akihiro Suda --- cmd/nerdctl/compose/compose_pause.go | 6 +++--- cmd/nerdctl/container/pause.go | 4 ++-- cmd/nerdctl/container/unpause.go | 4 ++-- cmd/nerdctl/utils/{ => action}/pause.go | 2 +- cmd/nerdctl/utils/{ => action}/unpause.go | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) rename cmd/nerdctl/utils/{ => action}/pause.go (98%) rename cmd/nerdctl/utils/{ => action}/unpause.go (98%) diff --git a/cmd/nerdctl/compose/compose_pause.go b/cmd/nerdctl/compose/compose_pause.go index fe7aff3507d..c536be7190c 100644 --- a/cmd/nerdctl/compose/compose_pause.go +++ b/cmd/nerdctl/compose/compose_pause.go @@ -22,7 +22,7 @@ import ( "github.com/containerd/containerd" ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" - "github.com/containerd/nerdctl/cmd/nerdctl/utils" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/action" "github.com/containerd/nerdctl/pkg/labels" "github.com/spf13/cobra" "golang.org/x/sync/errgroup" @@ -67,7 +67,7 @@ func composePauseAction(cmd *cobra.Command, args []string) error { for _, c := range containers { c := c eg.Go(func() error { - if err := utils.PauseContainer(ctx, client, c.ID()); err != nil { + if err := action.PauseContainer(ctx, client, c.ID()); err != nil { return err } info, err := c.Info(ctx, containerd.WithoutRefreshedMetadata) @@ -125,7 +125,7 @@ func composeUnpauseAction(cmd *cobra.Command, args []string) error { for _, c := range containers { c := c eg.Go(func() error { - if err := utils.UnpauseContainer(ctx, client, c.ID()); err != nil { + if err := action.UnpauseContainer(ctx, client, c.ID()); err != nil { return err } info, err := c.Info(ctx, containerd.WithoutRefreshedMetadata) diff --git a/cmd/nerdctl/container/pause.go b/cmd/nerdctl/container/pause.go index 1f1923d996e..e89c37d45e4 100644 --- a/cmd/nerdctl/container/pause.go +++ b/cmd/nerdctl/container/pause.go @@ -22,7 +22,7 @@ import ( ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" - "github.com/containerd/nerdctl/cmd/nerdctl/utils" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/action" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" "github.com/spf13/cobra" @@ -54,7 +54,7 @@ func pauseAction(cmd *cobra.Command, args []string) error { if found.MatchCount > 1 { return fmt.Errorf("multiple IDs found with provided prefix: %s", found.Req) } - if err := utils.PauseContainer(ctx, client, found.Container.ID()); err != nil { + if err := action.PauseContainer(ctx, client, found.Container.ID()); err != nil { return err } diff --git a/cmd/nerdctl/container/unpause.go b/cmd/nerdctl/container/unpause.go index bf85fb6ab02..926a06d5458 100644 --- a/cmd/nerdctl/container/unpause.go +++ b/cmd/nerdctl/container/unpause.go @@ -22,7 +22,7 @@ import ( ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" - "github.com/containerd/nerdctl/cmd/nerdctl/utils" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/action" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" "github.com/spf13/cobra" @@ -54,7 +54,7 @@ func unpauseAction(cmd *cobra.Command, args []string) error { if found.MatchCount > 1 { return fmt.Errorf("multiple IDs found with provided prefix: %s", found.Req) } - if err := utils.UnpauseContainer(ctx, client, found.Container.ID()); err != nil { + if err := action.UnpauseContainer(ctx, client, found.Container.ID()); err != nil { return err } diff --git a/cmd/nerdctl/utils/pause.go b/cmd/nerdctl/utils/action/pause.go similarity index 98% rename from cmd/nerdctl/utils/pause.go rename to cmd/nerdctl/utils/action/pause.go index 759191e4e33..c6188a33f1f 100644 --- a/cmd/nerdctl/utils/pause.go +++ b/cmd/nerdctl/utils/action/pause.go @@ -14,7 +14,7 @@ limitations under the License. */ -package utils +package action import ( "context" diff --git a/cmd/nerdctl/utils/unpause.go b/cmd/nerdctl/utils/action/unpause.go similarity index 98% rename from cmd/nerdctl/utils/unpause.go rename to cmd/nerdctl/utils/action/unpause.go index 55ee687e785..bfeaaf8fc47 100644 --- a/cmd/nerdctl/utils/unpause.go +++ b/cmd/nerdctl/utils/action/unpause.go @@ -14,7 +14,7 @@ limitations under the License. */ -package utils +package action import ( "context" From 9bfbfa2dea8b3c1e331a03dfc1df0aa5ce211e03 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Fri, 16 Dec 2022 15:05:58 +0900 Subject: [PATCH 09/14] [Carry 1639] move cmd/nerdctl/utils/mount.go Signed-off-by: Akihiro Suda --- cmd/nerdctl/utils/run/create.go | 2 +- cmd/nerdctl/utils/{ => run}/mount.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename cmd/nerdctl/utils/{ => run}/mount.go (99%) diff --git a/cmd/nerdctl/utils/run/create.go b/cmd/nerdctl/utils/run/create.go index 210bf949922..d59b1b7cd81 100644 --- a/cmd/nerdctl/utils/run/create.go +++ b/cmd/nerdctl/utils/run/create.go @@ -150,7 +150,7 @@ func CreateContainer(ctx context.Context, cmd *cobra.Command, client *containerd opts = append(opts, oci.WithTTY) } - mountOpts, anonVolumes, mountPoints, err := utils.GenerateMountOpts(ctx, cmd, client, ensuredImage) + mountOpts, anonVolumes, mountPoints, err := GenerateMountOpts(ctx, cmd, client, ensuredImage) if err != nil { return nil, nil, err } diff --git a/cmd/nerdctl/utils/mount.go b/cmd/nerdctl/utils/run/mount.go similarity index 99% rename from cmd/nerdctl/utils/mount.go rename to cmd/nerdctl/utils/run/mount.go index 3df780ca789..843bb1d146f 100644 --- a/cmd/nerdctl/utils/mount.go +++ b/cmd/nerdctl/utils/run/mount.go @@ -14,7 +14,7 @@ limitations under the License. */ -package utils +package run import ( "context" From a1d9fa8a0426eec2d5cfb21a1225fddd12ddbe2e Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Fri, 16 Dec 2022 15:10:15 +0900 Subject: [PATCH 10/14] [Carry 1639] move cmd/nerdctl/utils/network.go Signed-off-by: Akihiro Suda --- .../utils/containerfilter/containerfilter.go | 14 +++++++- cmd/nerdctl/utils/network.go | 34 ------------------- 2 files changed, 13 insertions(+), 35 deletions(-) delete mode 100644 cmd/nerdctl/utils/network.go diff --git a/cmd/nerdctl/utils/containerfilter/containerfilter.go b/cmd/nerdctl/utils/containerfilter/containerfilter.go index 36c7bfd7b05..1dcff0e4bac 100644 --- a/cmd/nerdctl/utils/containerfilter/containerfilter.go +++ b/cmd/nerdctl/utils/containerfilter/containerfilter.go @@ -18,6 +18,7 @@ package containerfilter import ( "context" + "encoding/json" "fmt" "strconv" "strings" @@ -27,6 +28,7 @@ import ( "github.com/containerd/containerd/containers" "github.com/containerd/nerdctl/cmd/nerdctl/utils" "github.com/containerd/nerdctl/cmd/nerdctl/utils/volume" + "github.com/containerd/nerdctl/pkg/labels" "github.com/sirupsen/logrus" ) @@ -353,7 +355,7 @@ func (cl *FilterContext) matchesNetworkFilter(info containers.Container) bool { if len(cl.NetworkFilterFuncs) == 0 { return true } - networks := utils.ContainerNetworks(info.Labels) + networks := containerNetworks(info.Labels) for _, networkFilterFunc := range cl.NetworkFilterFuncs { if !networkFilterFunc(networks) { continue @@ -375,3 +377,13 @@ func idOrNameFilter(ctx context.Context, containers []containerd.Container, valu } return nil, fmt.Errorf("no such container %s", value) } + +func containerNetworks(containerLables map[string]string) []string { + var networks []string + if names, ok := containerLables[labels.Networks]; ok { + if err := json.Unmarshal([]byte(names), &networks); err != nil { + logrus.Warn(err) + } + } + return networks +} diff --git a/cmd/nerdctl/utils/network.go b/cmd/nerdctl/utils/network.go deleted file mode 100644 index 6f86bb0b60b..00000000000 --- a/cmd/nerdctl/utils/network.go +++ /dev/null @@ -1,34 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package utils - -import ( - "encoding/json" - - "github.com/containerd/nerdctl/pkg/labels" - "github.com/sirupsen/logrus" -) - -func ContainerNetworks(containerLables map[string]string) []string { - var networks []string - if names, ok := containerLables[labels.Networks]; ok { - if err := json.Unmarshal([]byte(names), &networks); err != nil { - logrus.Warn(err) - } - } - return networks -} From b00b5fe87d78628e279f4d7bae000874078712cb Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Fri, 16 Dec 2022 15:17:12 +0900 Subject: [PATCH 11/14] [Carry 1639] move cmd/nerdctl/utils/top.go Signed-off-by: Akihiro Suda --- cmd/nerdctl/compose/compose_top.go | 4 ++-- cmd/nerdctl/container/top.go | 4 ++-- cmd/nerdctl/utils/{ => action}/top.go | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) rename cmd/nerdctl/utils/{ => action}/top.go (99%) diff --git a/cmd/nerdctl/compose/compose_top.go b/cmd/nerdctl/compose/compose_top.go index 5ca35090ce3..fb418e764f8 100644 --- a/cmd/nerdctl/compose/compose_top.go +++ b/cmd/nerdctl/compose/compose_top.go @@ -21,7 +21,7 @@ import ( "github.com/containerd/containerd" ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" - "github.com/containerd/nerdctl/cmd/nerdctl/utils" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/action" "github.com/containerd/nerdctl/pkg/labels" "github.com/spf13/cobra" ) @@ -74,7 +74,7 @@ func composeTopAction(cmd *cobra.Command, args []string) error { } fmt.Fprintf(stdout, "%s\n", info.Labels[labels.Name]) // `compose ps` uses empty ps args - err = utils.ContainerTop(ctx, cmd, client, c.ID(), "") + err = action.ContainerTop(ctx, cmd, client, c.ID(), "") if err != nil { return err } diff --git a/cmd/nerdctl/container/top.go b/cmd/nerdctl/container/top.go index fa3e8a8877e..4da28e016f4 100644 --- a/cmd/nerdctl/container/top.go +++ b/cmd/nerdctl/container/top.go @@ -33,7 +33,7 @@ import ( ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" - "github.com/containerd/nerdctl/cmd/nerdctl/utils" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/action" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" "github.com/containerd/nerdctl/pkg/infoutil" "github.com/containerd/nerdctl/pkg/rootlessutil" @@ -82,7 +82,7 @@ func topAction(cmd *cobra.Command, args []string) error { if found.MatchCount > 1 { return fmt.Errorf("multiple IDs found with provided prefix: %s", found.Req) } - if err := utils.ContainerTop(ctx, cmd, client, found.Container.ID(), strings.Join(args[1:], " ")); err != nil { + if err := action.ContainerTop(ctx, cmd, client, found.Container.ID(), strings.Join(args[1:], " ")); err != nil { return err } return nil diff --git a/cmd/nerdctl/utils/top.go b/cmd/nerdctl/utils/action/top.go similarity index 99% rename from cmd/nerdctl/utils/top.go rename to cmd/nerdctl/utils/action/top.go index 2a633c56aea..da0d35e8ecd 100644 --- a/cmd/nerdctl/utils/top.go +++ b/cmd/nerdctl/utils/action/top.go @@ -14,7 +14,7 @@ limitations under the License. */ -package utils +package action import ( "bytes" From 3b81f3136c6ef04193ebfc9edd0068b662e8be33 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Fri, 16 Dec 2022 15:18:21 +0900 Subject: [PATCH 12/14] [Carry 1639] fix the header of top.go Signed-off-by: Akihiro Suda --- cmd/nerdctl/container/top.go | 9 --------- cmd/nerdctl/utils/action/top.go | 9 +++++++++ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/cmd/nerdctl/container/top.go b/cmd/nerdctl/container/top.go index 4da28e016f4..bf5642ce837 100644 --- a/cmd/nerdctl/container/top.go +++ b/cmd/nerdctl/container/top.go @@ -14,15 +14,6 @@ limitations under the License. */ -/* - Portions from: - - https://github.com/moby/moby/blob/v20.10.6/api/types/container/container_top.go - - https://github.com/moby/moby/blob/v20.10.6/daemon/top_unix.go - Copyright (C) The Moby authors. - Licensed under the Apache License, Version 2.0 - NOTICE: https://github.com/moby/moby/blob/v20.10.6/NOTICE -*/ - package container import ( diff --git a/cmd/nerdctl/utils/action/top.go b/cmd/nerdctl/utils/action/top.go index da0d35e8ecd..7462c1c1a9a 100644 --- a/cmd/nerdctl/utils/action/top.go +++ b/cmd/nerdctl/utils/action/top.go @@ -14,6 +14,15 @@ limitations under the License. */ +/* + Portions from: + - https://github.com/moby/moby/blob/v20.10.6/api/types/container/container_top.go + - https://github.com/moby/moby/blob/v20.10.6/daemon/top_unix.go + Copyright (C) The Moby authors. + Licensed under the Apache License, Version 2.0 + NOTICE: https://github.com/moby/moby/blob/v20.10.6/NOTICE +*/ + package action import ( From 4284097c15db4d30dc692e06ce6f6858a03f109b Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Fri, 16 Dec 2022 15:26:33 +0900 Subject: [PATCH 13/14] [Carry 1639] move cmd/nerdctl/utils/run Signed-off-by: Akihiro Suda --- cmd/nerdctl/container/create.go | 2 +- cmd/nerdctl/container/exec.go | 2 +- cmd/nerdctl/container/run.go | 2 +- cmd/nerdctl/utils/{ => action}/run/create.go | 0 cmd/nerdctl/utils/{ => action}/run/mount.go | 0 cmd/nerdctl/utils/{ => action}/run/run.go | 0 cmd/nerdctl/utils/{ => action}/run/run_cgroup_freebsd.go | 0 cmd/nerdctl/utils/{ => action}/run/run_cgroup_linux.go | 0 cmd/nerdctl/utils/{ => action}/run/run_cgroup_windows.go | 0 cmd/nerdctl/utils/{ => action}/run/run_freebsd.go | 0 cmd/nerdctl/utils/{ => action}/run/run_gpus.go | 0 cmd/nerdctl/utils/{ => action}/run/run_linux.go | 0 cmd/nerdctl/utils/{ => action}/run/run_network.go | 0 cmd/nerdctl/utils/{ => action}/run/run_restart.go | 0 cmd/nerdctl/utils/{ => action}/run/run_runtime.go | 0 cmd/nerdctl/utils/{ => action}/run/run_security_linux.go | 0 cmd/nerdctl/utils/{ => action}/run/run_stargz_linux.go | 0 cmd/nerdctl/utils/{ => action}/run/run_ulimit.go | 0 cmd/nerdctl/utils/{ => action}/run/run_user.go | 0 cmd/nerdctl/utils/{ => action}/run/run_windows.go | 0 cmd/nerdctl/utils/action/start.go | 2 +- cmd/nerdctl/utils/action/stop.go | 2 +- integration/ipfs_compose_linux_test.go | 2 +- integration/ipfs_linux_test.go | 2 +- integration/ipfs_registry_linux_test.go | 2 +- integration/run_cgroup_linux_test.go | 2 +- integration/run_gpus_test.go | 2 +- integration/run_stargz_linux_test.go | 2 +- 28 files changed, 11 insertions(+), 11 deletions(-) rename cmd/nerdctl/utils/{ => action}/run/create.go (100%) rename cmd/nerdctl/utils/{ => action}/run/mount.go (100%) rename cmd/nerdctl/utils/{ => action}/run/run.go (100%) rename cmd/nerdctl/utils/{ => action}/run/run_cgroup_freebsd.go (100%) rename cmd/nerdctl/utils/{ => action}/run/run_cgroup_linux.go (100%) rename cmd/nerdctl/utils/{ => action}/run/run_cgroup_windows.go (100%) rename cmd/nerdctl/utils/{ => action}/run/run_freebsd.go (100%) rename cmd/nerdctl/utils/{ => action}/run/run_gpus.go (100%) rename cmd/nerdctl/utils/{ => action}/run/run_linux.go (100%) rename cmd/nerdctl/utils/{ => action}/run/run_network.go (100%) rename cmd/nerdctl/utils/{ => action}/run/run_restart.go (100%) rename cmd/nerdctl/utils/{ => action}/run/run_runtime.go (100%) rename cmd/nerdctl/utils/{ => action}/run/run_security_linux.go (100%) rename cmd/nerdctl/utils/{ => action}/run/run_stargz_linux.go (100%) rename cmd/nerdctl/utils/{ => action}/run/run_ulimit.go (100%) rename cmd/nerdctl/utils/{ => action}/run/run_user.go (100%) rename cmd/nerdctl/utils/{ => action}/run/run_windows.go (100%) diff --git a/cmd/nerdctl/container/create.go b/cmd/nerdctl/container/create.go index 2ee42241008..3c55f6b086d 100644 --- a/cmd/nerdctl/container/create.go +++ b/cmd/nerdctl/container/create.go @@ -22,7 +22,7 @@ import ( ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" - "github.com/containerd/nerdctl/cmd/nerdctl/utils/run" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/action/run" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/container/exec.go b/cmd/nerdctl/container/exec.go index 6854fef914b..f7d75ee0685 100644 --- a/cmd/nerdctl/container/exec.go +++ b/cmd/nerdctl/container/exec.go @@ -30,7 +30,7 @@ import ( "github.com/containerd/containerd/cmd/ctr/commands/tasks" ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" - "github.com/containerd/nerdctl/cmd/nerdctl/utils/run" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/action/run" "github.com/containerd/nerdctl/pkg/flagutil" "github.com/containerd/nerdctl/pkg/idgen" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" diff --git a/cmd/nerdctl/container/run.go b/cmd/nerdctl/container/run.go index 73219952c45..5ecd646e542 100644 --- a/cmd/nerdctl/container/run.go +++ b/cmd/nerdctl/container/run.go @@ -28,8 +28,8 @@ import ( ncclient "github.com/containerd/nerdctl/cmd/nerdctl/client" "github.com/containerd/nerdctl/cmd/nerdctl/completion" "github.com/containerd/nerdctl/cmd/nerdctl/utils/action" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/action/run" "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" - "github.com/containerd/nerdctl/cmd/nerdctl/utils/run" "github.com/containerd/nerdctl/pkg/labels" "github.com/containerd/nerdctl/pkg/taskutil" "github.com/sirupsen/logrus" diff --git a/cmd/nerdctl/utils/run/create.go b/cmd/nerdctl/utils/action/run/create.go similarity index 100% rename from cmd/nerdctl/utils/run/create.go rename to cmd/nerdctl/utils/action/run/create.go diff --git a/cmd/nerdctl/utils/run/mount.go b/cmd/nerdctl/utils/action/run/mount.go similarity index 100% rename from cmd/nerdctl/utils/run/mount.go rename to cmd/nerdctl/utils/action/run/mount.go diff --git a/cmd/nerdctl/utils/run/run.go b/cmd/nerdctl/utils/action/run/run.go similarity index 100% rename from cmd/nerdctl/utils/run/run.go rename to cmd/nerdctl/utils/action/run/run.go diff --git a/cmd/nerdctl/utils/run/run_cgroup_freebsd.go b/cmd/nerdctl/utils/action/run/run_cgroup_freebsd.go similarity index 100% rename from cmd/nerdctl/utils/run/run_cgroup_freebsd.go rename to cmd/nerdctl/utils/action/run/run_cgroup_freebsd.go diff --git a/cmd/nerdctl/utils/run/run_cgroup_linux.go b/cmd/nerdctl/utils/action/run/run_cgroup_linux.go similarity index 100% rename from cmd/nerdctl/utils/run/run_cgroup_linux.go rename to cmd/nerdctl/utils/action/run/run_cgroup_linux.go diff --git a/cmd/nerdctl/utils/run/run_cgroup_windows.go b/cmd/nerdctl/utils/action/run/run_cgroup_windows.go similarity index 100% rename from cmd/nerdctl/utils/run/run_cgroup_windows.go rename to cmd/nerdctl/utils/action/run/run_cgroup_windows.go diff --git a/cmd/nerdctl/utils/run/run_freebsd.go b/cmd/nerdctl/utils/action/run/run_freebsd.go similarity index 100% rename from cmd/nerdctl/utils/run/run_freebsd.go rename to cmd/nerdctl/utils/action/run/run_freebsd.go diff --git a/cmd/nerdctl/utils/run/run_gpus.go b/cmd/nerdctl/utils/action/run/run_gpus.go similarity index 100% rename from cmd/nerdctl/utils/run/run_gpus.go rename to cmd/nerdctl/utils/action/run/run_gpus.go diff --git a/cmd/nerdctl/utils/run/run_linux.go b/cmd/nerdctl/utils/action/run/run_linux.go similarity index 100% rename from cmd/nerdctl/utils/run/run_linux.go rename to cmd/nerdctl/utils/action/run/run_linux.go diff --git a/cmd/nerdctl/utils/run/run_network.go b/cmd/nerdctl/utils/action/run/run_network.go similarity index 100% rename from cmd/nerdctl/utils/run/run_network.go rename to cmd/nerdctl/utils/action/run/run_network.go diff --git a/cmd/nerdctl/utils/run/run_restart.go b/cmd/nerdctl/utils/action/run/run_restart.go similarity index 100% rename from cmd/nerdctl/utils/run/run_restart.go rename to cmd/nerdctl/utils/action/run/run_restart.go diff --git a/cmd/nerdctl/utils/run/run_runtime.go b/cmd/nerdctl/utils/action/run/run_runtime.go similarity index 100% rename from cmd/nerdctl/utils/run/run_runtime.go rename to cmd/nerdctl/utils/action/run/run_runtime.go diff --git a/cmd/nerdctl/utils/run/run_security_linux.go b/cmd/nerdctl/utils/action/run/run_security_linux.go similarity index 100% rename from cmd/nerdctl/utils/run/run_security_linux.go rename to cmd/nerdctl/utils/action/run/run_security_linux.go diff --git a/cmd/nerdctl/utils/run/run_stargz_linux.go b/cmd/nerdctl/utils/action/run/run_stargz_linux.go similarity index 100% rename from cmd/nerdctl/utils/run/run_stargz_linux.go rename to cmd/nerdctl/utils/action/run/run_stargz_linux.go diff --git a/cmd/nerdctl/utils/run/run_ulimit.go b/cmd/nerdctl/utils/action/run/run_ulimit.go similarity index 100% rename from cmd/nerdctl/utils/run/run_ulimit.go rename to cmd/nerdctl/utils/action/run/run_ulimit.go diff --git a/cmd/nerdctl/utils/run/run_user.go b/cmd/nerdctl/utils/action/run/run_user.go similarity index 100% rename from cmd/nerdctl/utils/run/run_user.go rename to cmd/nerdctl/utils/action/run/run_user.go diff --git a/cmd/nerdctl/utils/run/run_windows.go b/cmd/nerdctl/utils/action/run/run_windows.go similarity index 100% rename from cmd/nerdctl/utils/run/run_windows.go rename to cmd/nerdctl/utils/action/run/run_windows.go diff --git a/cmd/nerdctl/utils/action/start.go b/cmd/nerdctl/utils/action/start.go index b01d712cccf..6b3b980e0d1 100644 --- a/cmd/nerdctl/utils/action/start.go +++ b/cmd/nerdctl/utils/action/start.go @@ -30,8 +30,8 @@ import ( "github.com/containerd/containerd/cio" "github.com/containerd/containerd/cmd/ctr/commands" "github.com/containerd/containerd/oci" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/action/run" "github.com/containerd/nerdctl/cmd/nerdctl/utils/common" - "github.com/containerd/nerdctl/cmd/nerdctl/utils/run" "github.com/containerd/nerdctl/pkg/formatter" "github.com/containerd/nerdctl/pkg/labels" "github.com/containerd/nerdctl/pkg/netutil/nettype" diff --git a/cmd/nerdctl/utils/action/stop.go b/cmd/nerdctl/utils/action/stop.go index 5985f3253a2..157938dd0a9 100644 --- a/cmd/nerdctl/utils/action/stop.go +++ b/cmd/nerdctl/utils/action/stop.go @@ -23,7 +23,7 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/cio" - "github.com/containerd/nerdctl/cmd/nerdctl/utils/run" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/action/run" "github.com/containerd/nerdctl/pkg/labels" "github.com/moby/sys/signal" "github.com/sirupsen/logrus" diff --git a/integration/ipfs_compose_linux_test.go b/integration/ipfs_compose_linux_test.go index ab84dd39a3a..f19be6ee92c 100644 --- a/integration/ipfs_compose_linux_test.go +++ b/integration/ipfs_compose_linux_test.go @@ -23,7 +23,7 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/cmd/nerdctl/utils/run" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/action/run" "github.com/containerd/nerdctl/pkg/testutil" "github.com/containerd/nerdctl/pkg/testutil/nettestutil" "gotest.tools/v3/assert" diff --git a/integration/ipfs_linux_test.go b/integration/ipfs_linux_test.go index 6b66a499720..d973c1019f0 100644 --- a/integration/ipfs_linux_test.go +++ b/integration/ipfs_linux_test.go @@ -22,7 +22,7 @@ import ( "testing" "github.com/containerd/nerdctl/cmd/nerdctl/utils" - "github.com/containerd/nerdctl/cmd/nerdctl/utils/run" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/action/run" "github.com/containerd/nerdctl/pkg/infoutil" "github.com/containerd/nerdctl/pkg/rootlessutil" "github.com/containerd/nerdctl/pkg/testutil" diff --git a/integration/ipfs_registry_linux_test.go b/integration/ipfs_registry_linux_test.go index 0047e6de842..5ab8254d991 100644 --- a/integration/ipfs_registry_linux_test.go +++ b/integration/ipfs_registry_linux_test.go @@ -21,7 +21,7 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/cmd/nerdctl/utils/run" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/action/run" "github.com/containerd/nerdctl/pkg/testutil" ) diff --git a/integration/run_cgroup_linux_test.go b/integration/run_cgroup_linux_test.go index aeed6120a7e..1b3b5d58346 100644 --- a/integration/run_cgroup_linux_test.go +++ b/integration/run_cgroup_linux_test.go @@ -25,7 +25,7 @@ import ( "github.com/containerd/cgroups" "github.com/containerd/containerd/pkg/userns" "github.com/containerd/continuity/testutil/loopback" - "github.com/containerd/nerdctl/cmd/nerdctl/utils/run" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/action/run" "github.com/containerd/nerdctl/pkg/testutil" "gotest.tools/v3/assert" ) diff --git a/integration/run_gpus_test.go b/integration/run_gpus_test.go index 3bbed6101db..54b82320b03 100644 --- a/integration/run_gpus_test.go +++ b/integration/run_gpus_test.go @@ -19,7 +19,7 @@ package integration import ( "testing" - "github.com/containerd/nerdctl/cmd/nerdctl/utils/run" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/action/run" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" ) diff --git a/integration/run_stargz_linux_test.go b/integration/run_stargz_linux_test.go index 7c5f5808d23..81c2c01a281 100644 --- a/integration/run_stargz_linux_test.go +++ b/integration/run_stargz_linux_test.go @@ -19,7 +19,7 @@ package integration import ( "testing" - "github.com/containerd/nerdctl/cmd/nerdctl/utils/run" + "github.com/containerd/nerdctl/cmd/nerdctl/utils/action/run" "github.com/containerd/nerdctl/pkg/testutil" ) From 3d2c7fd434ebadfb37760f9bfc646f6bbb2521d0 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Fri, 16 Dec 2022 15:49:19 +0900 Subject: [PATCH 14/14] [Carry 1639] reorganize tests Signed-off-by: Akihiro Suda --- .../utils/action/run/run_stargz_linux.go | 29 ------------------- integration/ipfs_compose_linux_test.go | 3 +- integration/ipfs_linux_test.go | 5 ++-- integration/ipfs_registry_linux_test.go | 3 +- integration/run_stargz_linux_test.go | 3 +- pkg/testutil/testutil.go | 10 +++++++ 6 files changed, 15 insertions(+), 38 deletions(-) delete mode 100644 cmd/nerdctl/utils/action/run/run_stargz_linux.go diff --git a/cmd/nerdctl/utils/action/run/run_stargz_linux.go b/cmd/nerdctl/utils/action/run/run_stargz_linux.go deleted file mode 100644 index 1ac5a92f8cb..00000000000 --- a/cmd/nerdctl/utils/action/run/run_stargz_linux.go +++ /dev/null @@ -1,29 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package run - -import "github.com/containerd/nerdctl/pkg/testutil" - -func RequiresStargz(base *testutil.Base) { - info := base.Info() - for _, p := range info.Plugins.Storage { - if p == "stargz" { - return - } - } - base.T.Skip("test requires stargz") -} diff --git a/integration/ipfs_compose_linux_test.go b/integration/ipfs_compose_linux_test.go index f19be6ee92c..a0661d3dde9 100644 --- a/integration/ipfs_compose_linux_test.go +++ b/integration/ipfs_compose_linux_test.go @@ -23,7 +23,6 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/cmd/nerdctl/utils/action/run" "github.com/containerd/nerdctl/pkg/testutil" "github.com/containerd/nerdctl/pkg/testutil/nettestutil" "gotest.tools/v3/assert" @@ -53,7 +52,7 @@ func TestIPFSComposeUp(t *testing.T) { t.Run(tt.name, func(t *testing.T) { base := testutil.NewBase(t) if tt.requiresStargz { - run.RequiresStargz(base) + testutil.RequireStargz(base) } ipfsImgs := make([]string, 2) for i, img := range []string{testutil.WordpressImage, testutil.MariaDBImage} { diff --git a/integration/ipfs_linux_test.go b/integration/ipfs_linux_test.go index d973c1019f0..391af52bb86 100644 --- a/integration/ipfs_linux_test.go +++ b/integration/ipfs_linux_test.go @@ -22,7 +22,6 @@ import ( "testing" "github.com/containerd/nerdctl/cmd/nerdctl/utils" - "github.com/containerd/nerdctl/cmd/nerdctl/utils/action/run" "github.com/containerd/nerdctl/pkg/infoutil" "github.com/containerd/nerdctl/pkg/rootlessutil" "github.com/containerd/nerdctl/pkg/testutil" @@ -91,7 +90,7 @@ func TestIPFSWithLazyPulling(t *testing.T) { requiresIPFS(t) testutil.DockerIncompatible(t) base := testutil.NewBase(t) - run.RequiresStargz(base) + testutil.RequireStargz(base) ipfsCID := pushImageToIPFS(t, base, testutil.AlpineImage, "--estargz") base.Env = append(os.Environ(), "CONTAINERD_SNAPSHOTTER=stargz") @@ -107,7 +106,7 @@ func TestIPFSWithLazyPullingCommit(t *testing.T) { } testutil.DockerIncompatible(t) base := testutil.NewBase(t) - run.RequiresStargz(base) + testutil.RequireStargz(base) ipfsCID := pushImageToIPFS(t, base, testutil.AlpineImage, "--estargz") base.Env = append(os.Environ(), "CONTAINERD_SNAPSHOTTER=stargz") diff --git a/integration/ipfs_registry_linux_test.go b/integration/ipfs_registry_linux_test.go index 5ab8254d991..004878ea10b 100644 --- a/integration/ipfs_registry_linux_test.go +++ b/integration/ipfs_registry_linux_test.go @@ -21,7 +21,6 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/cmd/nerdctl/utils/action/run" "github.com/containerd/nerdctl/pkg/testutil" ) @@ -46,7 +45,7 @@ func TestIPFSRegistryWithLazyPulling(t *testing.T) { testutil.DockerIncompatible(t) base := testutil.NewBase(t) - run.RequiresStargz(base) + testutil.RequireStargz(base) base.Env = append(os.Environ(), "CONTAINERD_SNAPSHOTTER=stargz") ipfsCID := pushImageToIPFS(t, base, testutil.AlpineImage, "--estargz") ipfsRegistryAddr := "localhost:5555" diff --git a/integration/run_stargz_linux_test.go b/integration/run_stargz_linux_test.go index 81c2c01a281..73ab068eba2 100644 --- a/integration/run_stargz_linux_test.go +++ b/integration/run_stargz_linux_test.go @@ -19,14 +19,13 @@ package integration import ( "testing" - "github.com/containerd/nerdctl/cmd/nerdctl/utils/action/run" "github.com/containerd/nerdctl/pkg/testutil" ) func TestRunStargz(t *testing.T) { testutil.DockerIncompatible(t) base := testutil.NewBase(t) - run.RequiresStargz(base) + testutil.RequireStargz(base) // if stargz snapshotter is functional, "/.stargz-snapshotter" appears base.Cmd("--snapshotter=stargz", "run", "--rm", testutil.FedoraESGZImage, "ls", "/.stargz-snapshotter").AssertOK() } diff --git a/pkg/testutil/testutil.go b/pkg/testutil/testutil.go index cc46c8a23c5..8cf1e1d9003 100644 --- a/pkg/testutil/testutil.go +++ b/pkg/testutil/testutil.go @@ -570,6 +570,16 @@ func RequireSystemService(t testing.TB, sv string) { } } +func RequireStargz(base *Base) { + info := base.Info() + for _, p := range info.Plugins.Storage { + if p == "stargz" { + return + } + } + base.T.Skip("test requires stargz") +} + const Namespace = "nerdctl-test" func NewBaseWithNamespace(t *testing.T, ns string) *Base {