├── .dockerignore ├── .github └── workflows │ ├── buildandrelease.yaml │ ├── buildandtest.yaml │ ├── buildxkcd2347.yaml │ └── codeql-analysis.yaml ├── .gitignore ├── .vscode ├── launch.json ├── settings.json └── tasks.json ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── README.md ├── api ├── openapi-spec │ ├── README.md │ ├── lxkns.yaml │ ├── package_test.go │ └── validate_spec_test.go └── types │ ├── containermodel.go │ ├── containermodel_test.go │ ├── discovery.go │ ├── discovery_test.go │ ├── doc.go │ ├── mounts.go │ ├── mounts_test.go │ ├── namespaces.go │ ├── namespaces_test.go │ ├── package_test.go │ ├── pidmap.go │ ├── pidmap_test.go │ ├── processes.go │ ├── processes_test.go │ ├── proctable.go │ └── tasktable.go ├── cmd ├── dumpns │ ├── doc.go │ └── main.go ├── internal │ ├── pkg │ │ ├── caps │ │ │ ├── doc.go │ │ │ ├── package_test.go │ │ │ ├── proccaps.go │ │ │ ├── proccaps_test.go │ │ │ └── test │ │ │ │ ├── status-bad │ │ │ │ ├── status-corrupt │ │ │ │ └── status-good │ │ ├── cli │ │ │ ├── cli.go │ │ │ ├── cli_test.go │ │ │ ├── cliplugin │ │ │ │ └── cliplugin.go │ │ │ ├── doc.go │ │ │ └── package_test.go │ │ ├── debug │ │ │ ├── debug.go │ │ │ ├── debug_test.go │ │ │ ├── doc.go │ │ │ └── package_test.go │ │ ├── filter │ │ │ ├── doc.go │ │ │ ├── nsfilter.go │ │ │ ├── nsfilter_test.go │ │ │ └── package_test.go │ │ ├── output │ │ │ ├── doc.go │ │ │ ├── icon.go │ │ │ ├── icon_test.go │ │ │ ├── label.go │ │ │ └── package_test.go │ │ ├── style │ │ │ ├── colormode.go │ │ │ ├── colormode_test.go │ │ │ ├── config.go │ │ │ ├── defaultthemes.go │ │ │ ├── doc.go │ │ │ ├── lxknsstyles.go │ │ │ ├── package_test.go │ │ │ ├── procmode.go │ │ │ ├── style.go │ │ │ ├── styleconfig.go │ │ │ ├── styleconfig_test.go │ │ │ ├── theme.go │ │ │ └── treestyle.go │ │ ├── task │ │ │ ├── doc.go │ │ │ ├── package_test.go │ │ │ ├── task.go │ │ │ └── task_test.go │ │ └── turtles │ │ │ └── turtles.go │ ├── test │ │ └── getstdout │ │ │ ├── doc.go │ │ │ ├── getstdout.go │ │ │ ├── getstdout_test.go │ │ │ └── package_test.go │ └── tool │ │ ├── doc.go │ │ ├── package_test.go │ │ ├── sort.go │ │ ├── sort_test.go │ │ ├── space.go │ │ ├── space_test.go │ │ ├── visitor.go │ │ └── visitor_test.go ├── lspidns │ ├── cmdroot.go │ ├── doc.go │ ├── main.go │ ├── main_test.go │ ├── package_test.go │ └── visitor.go ├── lsuns │ ├── cmdroot.go │ ├── doc.go │ ├── main.go │ ├── main_test.go │ ├── package_test.go │ └── visitor.go ├── lxkns │ ├── cmdroot.go │ ├── doc.go │ ├── endpoints.go │ ├── main.go │ ├── package_test.go │ ├── server.go │ └── service_test.go ├── mntnssandbox │ └── main.go ├── nscaps │ ├── branch.go │ ├── branch_test.go │ ├── cmdroot.go │ ├── doc.go │ ├── main.go │ ├── main_test.go │ ├── package_test.go │ └── visitor.go └── pidtree │ ├── branchvisitor.go │ ├── cmdroot.go │ ├── doc.go │ ├── label.go │ ├── main.go │ ├── main_test.go │ ├── package_test.go │ └── treevisitor.go ├── containerizer ├── containerizer.go ├── doc.go └── whalefriend │ ├── doc.go │ ├── package_test.go │ ├── whalefriend.go │ └── whalefriend_test.go ├── decorator ├── all │ └── alldecorators.go ├── composer │ ├── decorator.go │ ├── decorator_test.go │ ├── doc.go │ └── package_test.go ├── decorator.go ├── doc.go ├── dockerplugin │ ├── decorator.go │ └── doc.go ├── industrialedge │ ├── decorator.go │ ├── decorator_test.go │ ├── doc.go │ └── package_test.go └── kuhbernetes │ ├── cri │ ├── decorator.go │ ├── decorator_test.go │ ├── doc.go │ ├── package_test.go │ └── test │ │ └── _kindisch │ │ ├── Dockerfile │ │ └── files │ │ └── etc │ │ ├── cni │ │ └── net.d │ │ │ └── 10-kindnet.conflist │ │ ├── containerd │ │ └── config.toml │ │ └── systemd │ │ └── system │ │ └── containerd.service │ ├── doc.go │ ├── dockershim │ ├── decorator.go │ ├── decorator_test.go │ ├── doc.go │ └── package_test.go │ └── pod.go ├── defs.go ├── defs_version.go ├── deployments ├── industrialedge │ ├── app.yaml │ ├── docker-compose.yaml │ └── lxkns-logo-150x150.png ├── lxkns │ ├── Dockerfile │ ├── README.md │ ├── docker-compose.yaml │ ├── lxkns-apparmor │ └── lxkns-seccomp.json ├── reverse │ ├── docker-compose.yaml │ └── nginx.conf ├── test │ ├── Dockerfile │ ├── README.md │ └── runtests └── wget │ └── docker-compose.yaml ├── discover ├── discover.go ├── discover_lsns_test.go ├── discover_test.go ├── discovery_affinity_sched.go ├── discovery_bindmount.go ├── discovery_bindmount_test.go ├── discovery_containers.go ├── discovery_containers_cind_test.go ├── discovery_containers_test.go ├── discovery_fd.go ├── discovery_fd_test.go ├── discovery_hierarchy.go ├── discovery_hierarchy_test.go ├── discovery_mount.go ├── discovery_mount_test.go ├── discovery_opt.go ├── discovery_opt_labels_test.go ├── discovery_opt_test.go ├── discovery_owners.go ├── discovery_owners_test.go ├── discovery_proc.go ├── discovery_proc_test.go ├── doc.go ├── package_test.go ├── pidmap.go ├── pidmap_test.go ├── ref.go ├── ref_test.go ├── test │ ├── _kindisch │ │ ├── Dockerfile │ │ └── files │ │ │ └── etc │ │ │ ├── containerd │ │ │ └── config.toml │ │ │ └── systemd │ │ │ └── system │ │ │ └── containerd.service │ └── fdscan │ │ └── proc │ │ ├── 1234 │ │ └── fd │ │ │ └── 0 │ │ └── 5678 │ │ └── fd │ │ ├── 3 │ │ └── junk ├── usernames.go └── usernames_test.go ├── doc.go ├── docs ├── .nojekyll ├── _css │ ├── 300-italic.css │ ├── 300.css │ ├── 500-italic.css │ └── 500.css ├── _fonts │ ├── roboto-latin-300-italic.woff │ ├── roboto-latin-300-italic.woff2 │ ├── roboto-latin-300-normal.woff │ ├── roboto-latin-300-normal.woff2 │ ├── roboto-latin-500-italic.woff │ ├── roboto-latin-500-italic.woff2 │ ├── roboto-latin-500-normal.woff │ ├── roboto-latin-500-normal.woff2 │ ├── roboto-latin-ext-300-italic.woff │ ├── roboto-latin-ext-300-italic.woff2 │ ├── roboto-latin-ext-300-normal.woff │ ├── roboto-latin-ext-300-normal.woff2 │ ├── roboto-latin-ext-500-italic.woff │ ├── roboto-latin-ext-500-italic.woff2 │ ├── roboto-latin-ext-500-normal.woff │ ├── roboto-latin-ext-500-normal.woff2 │ ├── roboto-mono-latin-300-italic.woff │ ├── roboto-mono-latin-300-italic.woff2 │ ├── roboto-mono-latin-300-normal.woff │ ├── roboto-mono-latin-300-normal.woff2 │ ├── roboto-mono-latin-500-italic.woff │ ├── roboto-mono-latin-500-italic.woff2 │ ├── roboto-mono-latin-500-normal.woff │ ├── roboto-mono-latin-500-normal.woff2 │ ├── roboto-mono-latin-ext-300-italic.woff │ ├── roboto-mono-latin-ext-300-italic.woff2 │ ├── roboto-mono-latin-ext-300-normal.woff │ ├── roboto-mono-latin-ext-300-normal.woff2 │ ├── roboto-mono-latin-ext-500-italic.woff │ ├── roboto-mono-latin-ext-500-italic.woff2 │ ├── roboto-mono-latin-ext-500-normal.woff │ └── roboto-mono-latin-ext-500-normal.woff2 ├── _images │ ├── all-namespaces-with-containers-thumbnail.png │ ├── all-namespaces-with-containers.png │ ├── allview.png │ ├── appbar.png │ ├── container-mounts-thumbnail.png │ ├── container-mounts.png │ ├── initial.png │ ├── linux-namespaces.svg │ ├── lxkns-containers.svg │ ├── lxkns-gophers.png │ ├── lxkns-namespaces.svg │ ├── lxkns-podmen.png │ ├── lxkns-processes.svg │ ├── mnthidden.png │ ├── mntinfo.png │ ├── mntview.png │ ├── mountpoint-details.png │ ├── namespaces-discovery.svg │ ├── netview.png │ ├── pid-map.svg │ ├── pidview.png │ ├── podman-containers.png │ ├── refresh.png │ ├── settings.png │ ├── sidebar.png │ ├── teaser-mountpoints.png │ ├── teaser.png │ └── user-podman-rootless-containers.png ├── _media │ ├── favicon.ico │ ├── lxkns192.png │ ├── lxkns512.png │ └── manifest.json ├── _sidebar.md ├── all-namespaces.md ├── cgroup.md ├── changelog.md ├── cli.md ├── containers.md ├── copylicense.md ├── deco.md ├── discovery-examples.md ├── discovery.md ├── docker-managed-plugins.md ├── features.md ├── getting-around.md ├── getting-started.md ├── index.html ├── introduction.md ├── lab-notes.md ├── marshalling-example.md ├── matchers.md ├── mntnssandbox.md ├── model.md ├── mount-namespace.md ├── mountineers.md ├── mountpoint.md ├── refresh.md ├── service-behind-proxy.md ├── service-deployment.md ├── service-extensible.md ├── settings.md ├── sidebar-help.md ├── tinkering.md ├── typed-namespace.md └── typesflavors.md ├── examples ├── barebones │ └── main.go └── lsallns │ └── main.go ├── go.mod ├── go.sum ├── internal ├── gen │ └── version │ │ └── gen_version.go ├── namespaces │ ├── config.go │ ├── hierarchical.go │ ├── namespaces_test.go │ ├── new.go │ ├── package_test.go │ ├── plain.go │ └── user.go └── pidmap │ ├── doc.go │ ├── package_test.go │ ├── pidmap.go │ ├── pidmap_test.go │ └── test │ └── proc │ ├── 1 │ ├── stat │ └── status │ ├── 668 │ ├── stat │ └── status │ ├── 669 │ ├── stat │ └── status │ └── 4200 │ ├── stat │ └── status ├── log ├── doc.go ├── log.go └── logrus │ ├── doc.go │ └── logrus.go ├── lxkns.code-workspace ├── model ├── container.go ├── containerengine.go ├── doc.go ├── group.go ├── namespaces.go ├── namespaces_test.go ├── package_test.go ├── pidmap.go ├── process.go ├── process_cgroups.go ├── process_cgroups_test.go ├── process_iter.go ├── process_iter_test.go ├── process_sort.go ├── process_sort_test.go ├── process_test.go └── test │ ├── cgroupies │ ├── v1 │ │ ├── freezing │ │ │ └── freezer.state │ │ ├── frozen │ │ │ └── freezer.state │ │ ├── somethingelse │ │ │ └── freezer.state │ │ └── thawed │ │ │ └── freezer.state │ └── v2 │ │ ├── frozen │ │ └── cgroup.events │ │ ├── gnawed │ │ └── cgroup.events │ │ └── thawed │ │ └── cgroup.events │ └── proctable │ ├── kaputt │ ├── 1 │ │ └── stat │ ├── 666 │ │ └── stat │ └── 667 │ │ ├── cmdline │ │ └── stat │ └── proc │ ├── 1 │ ├── stat │ └── status │ └── 42 │ ├── cmdline │ ├── stat │ └── status ├── mounts ├── doc.go ├── mount.go ├── mount_test.go └── package_test.go ├── nsioctl ├── doc.go └── nsioctl.go ├── nstest ├── doc.go ├── gmodel │ ├── be_same_namespace.go │ ├── be_same_namespace_test.go │ ├── be_same_process.go │ ├── be_same_process_test.go │ ├── be_same_processtable.go │ ├── be_same_processtable_test.go │ ├── be_similar_task.go │ ├── doc.go │ └── package_test.go └── nsutilcommon.go ├── ops ├── doc.go ├── errors.go ├── examples_test.go ├── fd.go ├── file.go ├── internal │ └── opener │ │ └── opener.go ├── mountineer │ ├── doc.go │ ├── mntnssandbox │ │ ├── doc.go │ │ ├── gomntns.c │ │ └── sandbox.go │ ├── mountineer.go │ ├── mountineer_test.go │ ├── package_test.go │ ├── pause_process.go │ ├── pause_process_test.go │ ├── pause_task.go │ ├── pause_task_test.go │ └── pauser.go ├── owneruid.go ├── package_test.go ├── path.go ├── portable │ ├── doc.go │ ├── integration_test.go │ ├── locate.go │ ├── locate_test.go │ ├── package_test.go │ ├── portable.go │ └── portable_test.go ├── relations │ └── relations.go ├── relations_test.go ├── switchns.go ├── switchns_test.go ├── typedfd.go ├── typedfile.go └── typedpath.go ├── plural ├── doc.go ├── package_test.go ├── plural.go └── plural_test.go ├── puml ├── linux-namespaces.puml ├── lxkns-containers.puml ├── lxkns-namespaces.puml ├── lxkns-processes.puml ├── namespaces-discovery.puml └── pid-map.puml ├── scripts ├── chores.sh ├── cov.sh ├── docker-build.sh ├── docsify.sh ├── goreportcard.sh ├── grype.sh ├── multiarch-builder.sh ├── pkgsite.sh ├── scan.sh ├── testjson.sh └── vuln.sh ├── species ├── doc.go ├── examples_test.go ├── id.go ├── id_test.go ├── package_test.go ├── species.go └── species_test.go ├── test ├── cmd │ └── loosethread │ │ └── loosethread.go ├── containerdtest │ ├── containerdtest.go │ ├── containerdtest_test.go │ ├── doc.go │ └── package_test.go ├── matcher │ ├── be_a_container.go │ ├── be_a_container_example_test.go │ ├── be_a_container_test.go │ ├── be_a_docker_container.go │ ├── be_a_docker_container_example_test.go │ ├── be_a_docker_container_test.go │ ├── be_a_pod.go │ ├── be_a_pod_example_test.go │ ├── be_a_pod_test.go │ ├── be_in_a_group.go │ ├── be_in_a_group_example_test.go │ ├── be_in_a_group_test.go │ ├── be_in_a_pod.go │ ├── be_in_a_pod_example_test.go │ ├── be_in_a_pod_test.go │ ├── be_paused.go │ ├── be_paused_example_test.go │ ├── be_paused_test.go │ ├── doc.go │ ├── have_label.go │ ├── have_label_example_test.go │ ├── have_label_test.go │ ├── package_test.go │ ├── util.go │ ├── with_flavor.go │ ├── with_flavor_example_test.go │ ├── with_flavor_test.go │ ├── with_name.go │ ├── with_name_example_test.go │ ├── with_name_test.go │ ├── with_strict_type.go │ ├── with_strict_type_example_test.go │ ├── with_strict_type_test.go │ ├── with_type.go │ ├── with_type_example_test.go │ └── with_type_test.go └── success │ └── success.go └── web ├── lxkns ├── .dockerignore ├── .env ├── .eslintrc.cjs ├── .gitignore ├── .markdownlint.json ├── .storybook │ ├── main.ts │ └── preview.tsx ├── .vscode │ ├── extensions.json │ └── settings.json ├── .yarnrc.yml ├── README.md ├── eslint.config.js ├── genicons.js ├── icons │ ├── Angryghost.svg │ ├── CPUAffinity.svg │ ├── Children.svg │ ├── Filesystemtype.svg │ ├── Ghost.svg │ ├── Hiddenmount.svg │ ├── Init1.svg │ ├── Namespace.svg │ ├── Owner.svg │ ├── Process.svg │ ├── Readonly.svg │ ├── Root.svg │ ├── Thread.svg │ ├── containers │ │ ├── CRI.svg │ │ ├── ComposerProject.svg │ │ ├── Container.svg │ │ ├── Containerd.svg │ │ ├── Docker.svg │ │ ├── DockerManagedPlugin.svg │ │ ├── IEApp.svg │ │ ├── IERuntime.svg │ │ ├── K8sPod.svg │ │ ├── Kind.svg │ │ ├── Pod.svg │ │ └── Podman.svg │ ├── namespaces │ │ ├── Cgroup.svg │ │ ├── IPC.svg │ │ ├── Mount.svg │ │ ├── Network.svg │ │ ├── PID.svg │ │ └── UTS.svg │ └── propagation │ │ ├── Peer.svg │ │ ├── Slave.svg │ │ └── Unbindable.svg ├── index.html ├── lxkns-logo.svg ├── mdxplugins.cjs ├── mock │ ├── Makefile │ └── getmockdata.ts ├── package.json ├── public │ ├── favicon.ico │ ├── lxkns192.png │ ├── lxkns512.png │ └── manifest.json ├── src │ ├── app │ │ ├── App.tsx │ │ ├── README.md │ │ ├── appstyles.tsx │ │ ├── index.tsx │ │ ├── lxkns.svg │ │ └── treeaction.ts │ ├── components │ │ ├── appbardrawer │ │ │ ├── AppBarDrawer.md │ │ │ ├── AppBarDrawer.stories.tsx │ │ │ ├── AppBarDrawer.tsx │ │ │ ├── DrawerLinkItem.stories.tsx │ │ │ ├── DrawerLinkItem.tsx │ │ │ └── index.ts │ │ ├── cgroupinfo │ │ │ ├── CgroupInfo.stories.tsx │ │ │ ├── CgroupInfo.tsx │ │ │ └── index.ts │ │ ├── chapterskeleton │ │ │ ├── ChapterSkeleton.stories.tsx │ │ │ ├── ChapterSkeleton.tsx │ │ │ └── index.ts │ │ ├── containerinfo │ │ │ ├── ContainerInfo.stories.ts │ │ │ ├── ContainerInfo.tsx │ │ │ └── index.ts │ │ ├── containertree │ │ │ ├── ContainerTree.tsx │ │ │ └── index.tsx │ │ ├── containertypeicon │ │ │ ├── ContainerTypeIcon.stories.ts │ │ │ ├── ContainerTypeIcon.tsx │ │ │ └── index.ts │ │ ├── cpulist │ │ │ ├── CPUList.tsx │ │ │ └── index.ts │ │ ├── discovery │ │ │ ├── Discovery.tsx │ │ │ └── index.ts │ │ ├── engineinfo │ │ │ ├── EngineInfo.tsx │ │ │ └── index.tsx │ │ ├── extlink │ │ │ ├── ExtLink.md │ │ │ ├── ExtLink.stories.tsx │ │ │ ├── ExtLink.tsx │ │ │ └── index.ts │ │ ├── groupedpropagationmembers │ │ │ ├── GroupedPropagationMembers.tsx │ │ │ └── index.ts │ │ ├── helpviewer │ │ │ ├── 01-intro.mdx │ │ │ ├── 02-foobar.mdx │ │ │ ├── 03-newchapter.mdx │ │ │ ├── HelpViewer.stories.tsx │ │ │ ├── HelpViewer.tsx │ │ │ ├── HelpViewer.xx.mdx.xx │ │ │ └── index.ts │ │ ├── mountpointinfo │ │ │ ├── MountpointInfo.md │ │ │ ├── MountpointInfo.stories.ts │ │ │ ├── MountpointInfo.tsx │ │ │ ├── fakedata.ts │ │ │ ├── fslinks.ts │ │ │ └── index.ts │ │ ├── mountpointinfomodal │ │ │ ├── MountpointInfoModal.md │ │ │ ├── MountpointInfoModal.tsx │ │ │ └── index.ts │ │ ├── mountpointpath │ │ │ ├── MountpointPath.md │ │ │ ├── MountpointPath.tsx │ │ │ └── index.ts │ │ ├── mountpointroot │ │ │ ├── MountpointRoot.stories.ts │ │ │ ├── MountpointRoot.tsx │ │ │ └── index.ts │ │ ├── mounttree │ │ │ ├── MountTree.tsx │ │ │ └── index.ts │ │ ├── muimarkdown │ │ │ ├── MuiMarkdown.md │ │ │ ├── MuiMarkdown.tsx │ │ │ ├── example │ │ │ │ ├── example.mdx │ │ │ │ └── minexample.mdx │ │ │ └── index.ts │ │ ├── namespacebadge │ │ │ ├── NamespaceBadge.stories.ts │ │ │ ├── NamespaceBadge.tsx │ │ │ └── index.ts │ │ ├── namespaceicon │ │ │ ├── NamespaceIcon.stories.ts │ │ │ ├── NamespaceIcon.tsx │ │ │ ├── iconmap.ts │ │ │ └── index.ts │ │ ├── namespaceinfo │ │ │ ├── NamespaceInfo.md │ │ │ ├── NamespaceInfo.stories.ts │ │ │ ├── NamespaceInfo.tsx │ │ │ └── index.ts │ │ ├── namespaceprocesstree │ │ │ ├── NamespaceProcessTree.tsx │ │ │ └── index.ts │ │ ├── namespaceref │ │ │ ├── NamespaceRef.md │ │ │ ├── NamespaceRef.stories.ts │ │ │ ├── NamespaceRef.tsx │ │ │ └── index.ts │ │ ├── processinfo │ │ │ ├── ProcessInfo.stories.tsx │ │ │ ├── ProcessInfo.tsx │ │ │ └── index.ts │ │ ├── refresher │ │ │ ├── Refresher.md │ │ │ ├── Refresher.tsx │ │ │ └── index.ts │ │ ├── schedinfo │ │ │ ├── SchedulerInfo.tsx │ │ │ └── index.ts │ │ ├── smarta │ │ │ ├── SmartA.stories.tsx │ │ │ ├── SmartA.tsx │ │ │ └── index.ts │ │ ├── taskinfo │ │ │ ├── TaskInfo.stories.tsx │ │ │ ├── TaskInfo.tsx │ │ │ └── index.ts │ │ ├── usernamespacetree │ │ │ ├── UserNamespaceTree.md │ │ │ ├── UserNamespaceTree.tsx │ │ │ └── index.ts │ │ └── usernamespacetreeitem │ │ │ ├── UserNamespaceTreeItem.md │ │ │ ├── UserNamespaceTreeItem.tsx │ │ │ └── index.ts │ ├── hooks │ │ ├── id │ │ │ ├── id.js │ │ │ └── package.json │ │ └── interval │ │ │ ├── interval.js │ │ │ └── package.json │ ├── icons │ │ ├── Angryghost.tsx │ │ ├── CPUAffinity.tsx │ │ ├── Children.tsx │ │ ├── Filesystemtype.tsx │ │ ├── Ghost.tsx │ │ ├── Hiddenmount.tsx │ │ ├── Init1.tsx │ │ ├── Namespace.tsx │ │ ├── Owner.tsx │ │ ├── Process.tsx │ │ ├── Readonly.tsx │ │ ├── Root.tsx │ │ ├── Thread.tsx │ │ ├── containers │ │ │ ├── CRI.tsx │ │ │ ├── ComposerProject.tsx │ │ │ ├── Container.tsx │ │ │ ├── Containerd.tsx │ │ │ ├── Docker.tsx │ │ │ ├── DockerManagedPlugin.tsx │ │ │ ├── IEApp.tsx │ │ │ ├── IERuntime.tsx │ │ │ ├── K8sPod.tsx │ │ │ ├── Kind.tsx │ │ │ ├── Pod.tsx │ │ │ └── Podman.tsx │ │ ├── namespaces │ │ │ ├── Cgroup.tsx │ │ │ ├── IPC.tsx │ │ │ ├── Mount.tsx │ │ │ ├── Network.tsx │ │ │ ├── PID.tsx │ │ │ └── UTS.tsx │ │ └── propagation │ │ │ ├── Peer.tsx │ │ │ ├── Slave.tsx │ │ │ └── Unbindable.tsx │ ├── index.css │ ├── index.tsx │ ├── mdx.d.ts │ ├── models │ │ └── lxkns │ │ │ ├── container.ts │ │ │ ├── fromjson.ts │ │ │ ├── index.ts │ │ │ ├── mock │ │ │ ├── index.ts │ │ │ ├── mockdata.json │ │ │ └── mockdata.ts │ │ │ ├── model.ts │ │ │ ├── mount.ts │ │ │ └── sortfns.ts │ ├── utils │ │ ├── basename.ts │ │ ├── engine.ts │ │ ├── persistentsettings.ts │ │ └── rgba.ts │ └── views │ │ ├── about │ │ ├── About.mdx │ │ ├── About.tsx │ │ └── index.ts │ │ ├── allnamespaces │ │ ├── AllNamespaces.tsx │ │ └── index.ts │ │ ├── containers │ │ ├── Containers.tsx │ │ └── index.ts │ │ ├── help │ │ ├── Help.tsx │ │ ├── chapters │ │ │ ├── Allview.mdx │ │ │ ├── Appbar.mdx │ │ │ ├── Containers.mdx │ │ │ ├── Lxkns.mdx │ │ │ ├── Mounts.mdx │ │ │ ├── Namespaces.mdx │ │ │ ├── Refresh.mdx │ │ │ ├── Settings.mdx │ │ │ └── Typedviews.mdx │ │ ├── fakediscoverydata.json │ │ ├── fakehelpdata.ts │ │ └── index.ts │ │ ├── settings │ │ ├── Settings.tsx │ │ └── index.ts │ │ └── typednamespaces │ │ ├── TypedNamespaces.tsx │ │ └── index.ts ├── styleguidist │ ├── ComponentCard.md │ ├── ComponentCard.tsx │ ├── MuiThemeWrapper.tsx │ ├── assets │ │ ├── favicon.ico │ │ └── public │ │ │ └── lxkns192.png │ └── styles.js ├── tsconfig.json ├── tsconfig.node.json ├── vite.config.ts └── yarn.lock └── puml └── vscode-plantuml-plugin-is-stupid /.dockerignore: -------------------------------------------------------------------------------- 1 | .git/ 2 | .github/ 3 | .vscode/ 4 | .dockerignore 5 | .gitignore 6 | .markdownlint.yaml 7 | 8 | coverage*.* 9 | 10 | __debug_bin 11 | lsallns 12 | dumpns 13 | lspidns 14 | lsuns 15 | nscaps 16 | pidtree 17 | 18 | README.md 19 | LICENSE 20 | Makefile 21 | 22 | deployments/ 23 | scripts/ 24 | web/ 25 | -------------------------------------------------------------------------------- /.github/workflows/buildxkcd2347.yaml: -------------------------------------------------------------------------------- 1 | name: build xkcd 2347 2 | on: 3 | push: 4 | branches: 5 | - master 6 | pull_request: 7 | branches: 8 | - master 9 | - develop 10 | 11 | permissions: 12 | contents: read 13 | 14 | jobs: 15 | 16 | build: 17 | name: Build web UI 18 | runs-on: ubuntu-latest 19 | steps: 20 | - name: Check out code into the Go module directory 21 | uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # pin@v3 22 | 23 | - name: test build 24 | run: | 25 | rm -f .yarnrc.yml 26 | corepack enable 27 | yarn set version berry 28 | yarn config set nodeLinker node-modules 29 | yarn workspaces focus --production 30 | yarn eslint --init 31 | yarn build 32 | working-directory: web/lxkns 33 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yaml: -------------------------------------------------------------------------------- 1 | name: "CodeQL" 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - master 10 | - develop 11 | schedule: 12 | - cron: '36 13 * * 1' 13 | 14 | jobs: 15 | analyze: 16 | name: Analyze 17 | runs-on: ubuntu-latest 18 | 19 | permissions: 20 | actions: read # for github/codeql-action/init to get workflow details 21 | contents: read # for actions/checkout to fetch code 22 | security-events: write # for github/codeql-action/analyze to upload SARIF results 23 | 24 | strategy: 25 | fail-fast: false 26 | matrix: 27 | language: [ 'go', 'javascript' ] 28 | 29 | steps: 30 | - name: Checkout repository 31 | uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # pin@v3 32 | 33 | - name: Initialize CodeQL 34 | uses: github/codeql-action/init@8b7fcbfac2aae0e6c24d9f9ebd5830b1290b18e4 # pin@v2 35 | with: 36 | languages: ${{ matrix.language }} 37 | 38 | - name: Autobuild 39 | uses: github/codeql-action/autobuild@8b7fcbfac2aae0e6c24d9f9ebd5830b1290b18e4 # pin@v2 40 | 41 | - name: Perform CodeQL Analysis 42 | uses: github/codeql-action/analyze@8b7fcbfac2aae0e6c24d9f9ebd5830b1290b18e4 # pin@v2 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /main 2 | /lsuns 3 | /lspidns 4 | /pidtree 5 | /lxkns 6 | /dumpns 7 | /nscaps 8 | /barebones 9 | /lsallns 10 | /coverage.txt 11 | /coverage.out 12 | /coverage-root.txt 13 | /coverage-root.out 14 | /coverage.html 15 | __debug_bin 16 | /web/node_modules 17 | .eslintcache 18 | node_modules 19 | *.log 20 | .yarn/ 21 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Debug as root", 6 | "type": "go", 7 | "request": "launch", 8 | "mode": "exec", 9 | "asRoot": true, 10 | "program": "${fileDirname}/__debug_bin", 11 | "console": "integratedTerminal", 12 | "preLaunchTask": "go build (debug)", 13 | }, 14 | { 15 | "name": "Debug test as root", 16 | "type": "go", 17 | "request": "launch", 18 | "mode": "exec", 19 | "asRoot": true, 20 | "program": "${fileDirname}/__debug_bin", 21 | "cwd": "${fileDirname}", 22 | "console": "integratedTerminal", 23 | "preLaunchTask": "go test (debug)", 24 | } 25 | ] 26 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "go.diagnostic.vulncheck": "Imports" 3 | } -------------------------------------------------------------------------------- /api/openapi-spec/README.md: -------------------------------------------------------------------------------- 1 | # lxkns OpenAPI 3.0 Specification 2 | 3 | This directory contains the REST API specification of the lxkns service, in 4 | [OpenAPI 3.0 format](https://github.com/OAI/OpenAPI-Specification/). 5 | 6 | ## Brower-Based Editing 7 | 8 | ### Swagger 9 | 10 | For those of us who are not adverse to editing OpenAPI specifications using a 11 | browser-based UI instead of the plain YAML, there are several options. These are 12 | just two of them, the first one being Swagger's own editor: 13 | 14 | ```bash 15 | docker run -d --name swagger-editor -p 8080:8080 swaggerapi/swagger-editor 16 | ``` 17 | 18 | ### Apicurito 19 | 20 | [Apicuri(t)o](https://www.apicur.io/apicurito/) is another editor, featuring 21 | both a visualization as the YAML/JSON definition views. This starts Apicurito 22 | which is the editor component only without any (database) backend. 23 | 24 | ```bash 25 | docker run -d --name apicurito -p 8080:8080 apicurio/apicurito-ui 26 | ``` 27 | -------------------------------------------------------------------------------- /api/openapi-spec/package_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package openapispec 16 | 17 | import ( 18 | "testing" 19 | 20 | . "github.com/onsi/ginkgo/v2" 21 | . "github.com/onsi/gomega" 22 | ) 23 | 24 | func TestOpenApiSpec(t *testing.T) { 25 | RegisterFailHandler(Fail) 26 | RunSpecs(t, "lxkns/api/openapi-spec package") 27 | } 28 | -------------------------------------------------------------------------------- /api/types/package_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package types 16 | 17 | import ( 18 | "testing" 19 | 20 | . "github.com/onsi/ginkgo/v2" 21 | . "github.com/onsi/gomega" 22 | ) 23 | 24 | func TestNamespaceTypes(t *testing.T) { 25 | RegisterFailHandler(Fail) 26 | RunSpecs(t, "lxkns/api/types package") 27 | } 28 | -------------------------------------------------------------------------------- /cmd/dumpns/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | dumpns runs a namespace (and process) discovery and then dumps the results as 3 | JSON. 4 | 5 | # Usage 6 | 7 | To use dumpns: 8 | 9 | dumpns [flag] 10 | 11 | For example, to view the discovery information as colored, pretty-printed JSON: 12 | 13 | dumpns -c | jq -C | less -SR 14 | 15 | # Flags 16 | 17 | The following dumpns flags are available: 18 | 19 | -c, --compact compact instead of pretty-printed output 20 | -h, --help help for dumpns 21 | -i, --indent uint use the given number of spaces (no more than 8) for indentation (default 2) 22 | -t, --tab use tabs for indentation instead of two spaces 23 | -v, --version version for dumpns 24 | --wait duration max duration to wait for container engine workload synchronization (default 3s) 25 | */ 26 | package main 27 | -------------------------------------------------------------------------------- /cmd/internal/pkg/caps/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package caps provides textual information about the effective capabilities of a 3 | process. 4 | */ 5 | package caps 6 | -------------------------------------------------------------------------------- /cmd/internal/pkg/caps/package_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package caps 16 | 17 | import ( 18 | "testing" 19 | 20 | . "github.com/onsi/ginkgo/v2" 21 | . "github.com/onsi/gomega" 22 | ) 23 | 24 | func TestCaps(t *testing.T) { 25 | RegisterFailHandler(Fail) 26 | RunSpecs(t, "lxkns/cmd/internal/pkg/caps package") 27 | } 28 | -------------------------------------------------------------------------------- /cmd/internal/pkg/caps/test/status-bad: -------------------------------------------------------------------------------- 1 | Name: foobar 2 | CapBnd: 0000003fffffffff 3 | Seccomp: 0 4 | -------------------------------------------------------------------------------- /cmd/internal/pkg/caps/test/status-corrupt: -------------------------------------------------------------------------------- 1 | Name: foobar 2 | CapEff: 0000003gffffffff 3 | CapBnd: 0000003fffffffff 4 | Seccomp: 0 5 | -------------------------------------------------------------------------------- /cmd/internal/pkg/caps/test/status-good: -------------------------------------------------------------------------------- 1 | Name: foobar 2 | CapEff: 0000003fffffffff 3 | CapBnd: 0000003fffffffff 4 | Seccomp: 0 5 | -------------------------------------------------------------------------------- /cmd/internal/pkg/cli/cliplugin/cliplugin.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package cliplugin 16 | 17 | import "github.com/spf13/cobra" 18 | 19 | // SetupCLI defines an exposed plugin symbol type for adding things to a cobra 20 | // root command. 21 | type SetupCLI func(*cobra.Command) 22 | 23 | // BeforeCommand defines an exposed plugin symbol type for running checks after 24 | // the command line args have been processed and before running the command. 25 | type BeforeCommand func(*cobra.Command) error 26 | -------------------------------------------------------------------------------- /cmd/internal/pkg/cli/package_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package cli 16 | 17 | import ( 18 | "testing" 19 | 20 | . "github.com/onsi/ginkgo/v2" 21 | . "github.com/onsi/gomega" 22 | ) 23 | 24 | func TestCLI(t *testing.T) { 25 | RegisterFailHandler(Fail) 26 | RunSpecs(t, "cmd/internal/pkg/cli") 27 | } 28 | -------------------------------------------------------------------------------- /cmd/internal/pkg/debug/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package debug supplies the --log and --debug CLI flags. 3 | 4 | - --log enables logging to stderr from info level on and upwards. 5 | - --debug enables logging to stderr from debug level on and upwards, so no tracing. 6 | */ 7 | package debug 8 | -------------------------------------------------------------------------------- /cmd/internal/pkg/debug/package_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package debug 16 | 17 | import ( 18 | "testing" 19 | 20 | . "github.com/onsi/ginkgo/v2" 21 | . "github.com/onsi/gomega" 22 | ) 23 | 24 | func TestDebug(t *testing.T) { 25 | RegisterFailHandler(Fail) 26 | RunSpecs(t, "lxkns/cmd/internal/pkg/debug package") 27 | } 28 | -------------------------------------------------------------------------------- /cmd/internal/pkg/filter/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package filter provides CLI-controlled filtering of namespaces by type. It 3 | provides the CLI commands "--filter" flag. 4 | */ 5 | package filter 6 | -------------------------------------------------------------------------------- /cmd/internal/pkg/filter/package_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package filter 16 | 17 | import ( 18 | "testing" 19 | 20 | . "github.com/onsi/ginkgo/v2" 21 | . "github.com/onsi/gomega" 22 | ) 23 | 24 | func TestCLI(t *testing.T) { 25 | RegisterFailHandler(Fail) 26 | RunSpecs(t, "cmd/internal/pkg/filter") 27 | } 28 | -------------------------------------------------------------------------------- /cmd/internal/pkg/output/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package output provides terminal output convenience helpers for namespace type 3 | icons and cgroup information rendering. 4 | */ 5 | package output 6 | -------------------------------------------------------------------------------- /cmd/internal/pkg/output/package_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package output 16 | 17 | import ( 18 | "testing" 19 | 20 | . "github.com/onsi/ginkgo/v2" 21 | . "github.com/onsi/gomega" 22 | ) 23 | 24 | func TestOutput(t *testing.T) { 25 | RegisterFailHandler(Fail) 26 | RunSpecs(t, "lxkns/cmd/internal/pkg/output package") 27 | } 28 | -------------------------------------------------------------------------------- /cmd/internal/pkg/style/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package style styles text output of the CLI commands with foreground and 3 | background colors, as well as different text styles (bold, italics, ...). 4 | 5 | Text styling is user-configurable and optionally stored in a YAML file in the 6 | users' home directories as ~/.lxknsrc.yaml. 7 | 8 | Additionally, this package provides CLI flags: "--theme" to control the theme 9 | used (dark or light), "--color" for enabling or disabling colorization 10 | (including automatic detection), and "--treestyle" for changing the style of the 11 | ASCII/Unicode tree rendering. 12 | */ 13 | package style 14 | -------------------------------------------------------------------------------- /cmd/internal/pkg/style/package_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package style 16 | 17 | import ( 18 | "testing" 19 | 20 | . "github.com/onsi/ginkgo/v2" 21 | . "github.com/onsi/gomega" 22 | ) 23 | 24 | func TestStyle(t *testing.T) { 25 | RegisterFailHandler(Fail) 26 | RunSpecs(t, "cmd/internal/pkg/style") 27 | } 28 | -------------------------------------------------------------------------------- /cmd/internal/pkg/task/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package task provides the “--task” CLI flag to enable task discovery. 3 | 4 | Use [Enabled] to query whether task discovery has been requested (enabled), or 5 | [FromTasks] that instead returns an appropriate discovery option. 6 | */ 7 | package task 8 | -------------------------------------------------------------------------------- /cmd/internal/pkg/task/package_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package task 16 | 17 | import ( 18 | "testing" 19 | 20 | . "github.com/onsi/ginkgo/v2" 21 | . "github.com/onsi/gomega" 22 | ) 23 | 24 | func TestTask(t *testing.T) { 25 | RegisterFailHandler(Fail) 26 | RunSpecs(t, "lxkns/cmd/internal/pkg/task package") 27 | } 28 | -------------------------------------------------------------------------------- /cmd/internal/test/getstdout/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package getstdout captures [os.Stdout] and [os.Stderr] while executing a 3 | specified function, returning the captured output afterwards. 4 | */ 5 | package getstdout 6 | -------------------------------------------------------------------------------- /cmd/internal/test/getstdout/package_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package getstdout 16 | 17 | import ( 18 | "testing" 19 | 20 | . "github.com/onsi/ginkgo/v2" 21 | . "github.com/onsi/gomega" 22 | ) 23 | 24 | func TestGetStdout(t *testing.T) { 25 | RegisterFailHandler(Fail) 26 | RunSpecs(t, "cmd/internal/test/getstdout") 27 | } 28 | -------------------------------------------------------------------------------- /cmd/internal/tool/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package tool provides convenience helpers useful to the lxkns CLI tools. 3 | */ 4 | package tool 5 | -------------------------------------------------------------------------------- /cmd/internal/tool/package_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package tool 16 | 17 | import ( 18 | "testing" 19 | 20 | . "github.com/onsi/ginkgo/v2" 21 | . "github.com/onsi/gomega" 22 | ) 23 | 24 | func shtrings(x ...string) []string { return x } 25 | 26 | func TestCmdInternalTool(t *testing.T) { 27 | RegisterFailHandler(Fail) 28 | RunSpecs(t, "lxkns/cmd/internal/tool package") 29 | } 30 | -------------------------------------------------------------------------------- /cmd/internal/tool/sort.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package tool 16 | 17 | import "golang.org/x/exp/slices" 18 | 19 | // Sort sorts a copy of the passed slice using the specified less function and 20 | // returns the sorted copy. 21 | func Sort[E any](s []E, less func(e1, e2 E) int) []E { 22 | s = slices.Clone(s) 23 | slices.SortFunc(s, less) 24 | return s 25 | } 26 | -------------------------------------------------------------------------------- /cmd/internal/tool/sort_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package tool 16 | 17 | import ( 18 | "strings" 19 | 20 | "golang.org/x/exp/slices" 21 | 22 | . "github.com/onsi/ginkgo/v2" 23 | . "github.com/onsi/gomega" 24 | ) 25 | 26 | var _ = Describe("sorting", func() { 27 | 28 | DescribeTable("sorting a copy", 29 | func(x []string, expected []string) { 30 | original := slices.Clone(x) 31 | actual := Sort(x, strings.Compare) 32 | Expect(actual).To(ConsistOf(expected), "not correctly sorted") 33 | Expect(x).To(ConsistOf(original), "modified original") 34 | }, 35 | Entry(nil, shtrings("bar", "foo"), shtrings("bar", "foo")), 36 | Entry(nil, shtrings("foo", "bar"), shtrings("bar", "foo")), 37 | ) 38 | 39 | }) 40 | -------------------------------------------------------------------------------- /cmd/internal/tool/space.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package tool 16 | 17 | // Space concatenates the passed strings, ensuring they are properly separated 18 | // by only a single space between each source string, where necessary. Empty 19 | // strings are correctly handled without inserting unnecessary separating 20 | // spaces. 21 | func Space(s string, more ...string) string { 22 | for _, s2 := range more { 23 | if s != "" && s2 != "" { 24 | s += " " 25 | } 26 | s += s2 27 | } 28 | return s 29 | } 30 | -------------------------------------------------------------------------------- /cmd/internal/tool/space_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package tool 16 | 17 | import ( 18 | . "github.com/onsi/ginkgo/v2" 19 | . "github.com/onsi/gomega" 20 | ) 21 | 22 | var _ = Describe("spacing concatenated strings", func() { 23 | 24 | DescribeTable("spacing between string elements", 25 | func(x []string, expected string) { 26 | Expect(Space(x[0], x[1:]...)).To(Equal(expected)) 27 | }, 28 | Entry(nil, shtrings("foo"), "foo"), 29 | Entry(nil, shtrings("foo", "bar", "baz"), "foo bar baz"), 30 | Entry(nil, shtrings("foo", "", "", "bar", ""), "foo bar"), 31 | ) 32 | 33 | }) 34 | -------------------------------------------------------------------------------- /cmd/internal/tool/visitor_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package tool 16 | 17 | import ( 18 | . "github.com/onsi/ginkgo/v2" 19 | . "github.com/onsi/gomega" 20 | ) 21 | 22 | var _ = Describe("visitor tools", func() { 23 | 24 | It("converts slices into reflect.Value slices", func() { 25 | s := shtrings("yes!", "no!", "ohh!") 26 | rs := ReflectValuesSlice(s) 27 | Expect(rs).To(HaveLen(len(s))) 28 | for idx, rv := range rs { 29 | Expect(rv.Interface()).To(Equal(s[idx])) 30 | } 31 | }) 32 | 33 | }) 34 | -------------------------------------------------------------------------------- /cmd/lspidns/main.go: -------------------------------------------------------------------------------- 1 | // The "lspns" CLI tool for listing PID namespaces. 2 | 3 | // Copyright 2020 Harald Albrecht. 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 6 | // use this file except in compliance with the License. You may obtain a copy 7 | // of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | // License for the specific language governing permissions and limitations 15 | // under the License. 16 | 17 | package main 18 | 19 | import ( 20 | "os" 21 | ) 22 | 23 | func main() { 24 | // This is cobra boilerplate documentation, except for the missing call to 25 | // fmt.Println(err) which in the original boilerplate is just plain wrong: 26 | // it renders the error message twice, see also: 27 | // https://github.com/spf13/cobra/issues/304 28 | if err := newRootCmd().Execute(); err != nil { 29 | osExit(1) 30 | } 31 | } 32 | 33 | // For CLI unit tests... 34 | var osExit = os.Exit 35 | -------------------------------------------------------------------------------- /cmd/lspidns/package_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package main 16 | 17 | import ( 18 | "testing" 19 | 20 | . "github.com/onsi/ginkgo/v2" 21 | . "github.com/onsi/gomega" 22 | "github.com/thediveo/lxkns/cmd/internal/pkg/style" 23 | ) 24 | 25 | func TestLsunsCmd(t *testing.T) { 26 | style.PrepareForTest() 27 | RegisterFailHandler(Fail) 28 | RunSpecs(t, "lspidns command") 29 | } 30 | -------------------------------------------------------------------------------- /cmd/lsuns/main.go: -------------------------------------------------------------------------------- 1 | // The "lsuns" CLI tool for listing user namespaces, and optionally the other 2 | // namespaces they "own". 3 | 4 | // Copyright 2020 Harald Albrecht. 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 7 | // use this file except in compliance with the License. You may obtain a copy 8 | // of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 14 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 15 | // License for the specific language governing permissions and limitations 16 | // under the License. 17 | 18 | package main 19 | 20 | import ( 21 | "os" 22 | ) 23 | 24 | func main() { 25 | // This is cobra boilerplate documentation, except for the missing call to 26 | // fmt.Println(err) which in the original boilerplate is just plain wrong: 27 | // it renders the error message twice, see also: 28 | // https://github.com/spf13/cobra/issues/304 29 | if err := newRootCmd().Execute(); err != nil { 30 | osExit(1) 31 | } 32 | } 33 | 34 | // For CLI unit tests... 35 | var osExit = os.Exit 36 | -------------------------------------------------------------------------------- /cmd/lsuns/package_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package main 16 | 17 | import ( 18 | "testing" 19 | 20 | . "github.com/onsi/ginkgo/v2" 21 | . "github.com/onsi/gomega" 22 | "github.com/thediveo/lxkns/cmd/internal/pkg/style" 23 | ) 24 | 25 | func TestLsunsCmd(t *testing.T) { 26 | style.PrepareForTest() 27 | RegisterFailHandler(Fail) 28 | RunSpecs(t, "lsuns command") 29 | } 30 | -------------------------------------------------------------------------------- /cmd/lxkns/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | lxkns is a micro-service for discovering Linux-kernel namespaces and related 4 | information, such as namespace'd processes and the mapping of process 5 | identifiers (PIDs) between hierarchical PID namespaces. 6 | 7 | The lxkns service API definition can be found in api/openapi-spec/lxkns.yaml 8 | inside the top-level project directory. 9 | 10 | Usage 11 | 12 | To use lxkns: 13 | 14 | lxkns [flag] 15 | 16 | Flags 17 | 18 | The following lxkns flags are available: 19 | 20 | --debug enables debugging output 21 | -h, --help help for lxkns 22 | --http string HTTP service address (default "[::]:5010") 23 | --initialcgroup switches into initial cgroup namespace 24 | --shutdown duration graceful shutdown duration limit (default 15s) 25 | --silent silences everything below the error level 26 | -v, --version version for lxkns 27 | --wait duration max duration to wait for container engine workload synchronization (default 3s) 28 | 29 | */ 30 | 31 | package main 32 | -------------------------------------------------------------------------------- /cmd/lxkns/package_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package main 16 | 17 | import ( 18 | "testing" 19 | 20 | . "github.com/onsi/ginkgo/v2" 21 | . "github.com/onsi/gomega" 22 | ) 23 | 24 | func TestNamespaceTypes(t *testing.T) { 25 | RegisterFailHandler(Fail) 26 | RunSpecs(t, "lxkns/cmd/lxkns package") 27 | } 28 | -------------------------------------------------------------------------------- /cmd/mntnssandbox/main.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package main 16 | 17 | import _ "github.com/thediveo/lxkns/ops/mountineer/mntnssandbox" // it's all fine. 18 | 19 | func main() { 20 | panic("missing mount namespace reference") 21 | } 22 | -------------------------------------------------------------------------------- /cmd/nscaps/main.go: -------------------------------------------------------------------------------- 1 | // The "nscaps" CLI tool for calculating the capabilities a process has in a 2 | // particular namespace. 3 | 4 | // Copyright 2020 Harald Albrecht. 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 7 | // use this file except in compliance with the License. You may obtain a copy 8 | // of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 14 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 15 | // License for the specific language governing permissions and limitations 16 | // under the License. 17 | 18 | package main 19 | 20 | import ( 21 | "os" 22 | ) 23 | 24 | func main() { 25 | // This is cobra boilerplate documentation, except for the missing call to 26 | // fmt.Println(err) which in the original boilerplate is just plain wrong: 27 | // it renders the error message twice, see also: 28 | // https://github.com/spf13/cobra/issues/304 29 | if err := newRootCmd().Execute(); err != nil { 30 | osExit(1) 31 | } 32 | } 33 | 34 | // For CLI unit tests... 35 | var osExit = os.Exit 36 | -------------------------------------------------------------------------------- /cmd/pidtree/package_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package main 16 | 17 | import ( 18 | "testing" 19 | 20 | . "github.com/onsi/ginkgo/v2" 21 | . "github.com/onsi/gomega" 22 | "github.com/thediveo/lxkns/cmd/internal/pkg/style" 23 | ) 24 | 25 | func TestPidtreeCmd(t *testing.T) { 26 | style.PrepareForTest() 27 | RegisterFailHandler(Fail) 28 | RunSpecs(t, "pidtree command") 29 | } 30 | -------------------------------------------------------------------------------- /containerizer/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package containerizer provides the implementations to store data about 3 | [Container] and [ContainerEngine] objects. Subpackages provide so-called 4 | “containerizers” (implementing [Containerizer]) that discover Containers from 5 | specific container engines. 6 | 7 | Nota bene: the lxkns model defines only the [model.Container] and 8 | [model.ContainerEngine] interfaces instead of implementations in order to break 9 | import cycles that otherwise would invariably occur. 10 | 11 | Nota bene-bene: sometimes, preemptive interfaces are simply necessary, because 12 | they don't have any idea of Golotry. especially, when the domain-specific 13 | (namespace) language uses type inheritance and embedding doesn't eat the cake. 14 | */ 15 | package containerizer 16 | -------------------------------------------------------------------------------- /containerizer/whalefriend/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package whalefriend implements a [containerizer.Containerizer] that discovers 3 | containers from container engines supported by the [@thediveo/whalewatcher] 4 | module, such as Docker and containerd (moby & friends). 5 | 6 | [@thediveo/whalewatcher]: https://github.com/thediveo/whalewatcher 7 | */ 8 | package whalefriend 9 | -------------------------------------------------------------------------------- /containerizer/whalefriend/package_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package whalefriend 16 | 17 | import ( 18 | "testing" 19 | 20 | . "github.com/onsi/ginkgo/v2" 21 | . "github.com/onsi/gomega" 22 | ) 23 | 24 | func TestContainerizerWhalefriend(t *testing.T) { 25 | RegisterFailHandler(Fail) 26 | RunSpecs(t, "lxkns/containerizer/whalefriend package") 27 | } 28 | -------------------------------------------------------------------------------- /decorator/all/alldecorators.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package all imports and activates all lxkns (container) decorator plugins, 3 | activating them during discoveries. 4 | */ 5 | package all 6 | 7 | import ( 8 | _ "github.com/thediveo/lxkns/decorator/composer" // pull in decorator plugin 9 | _ "github.com/thediveo/lxkns/decorator/dockerplugin" // pull in decorator plugin 10 | _ "github.com/thediveo/lxkns/decorator/industrialedge" // pull in decorator plugin 11 | _ "github.com/thediveo/lxkns/decorator/kuhbernetes/cri" // pull in decorator plugin 12 | _ "github.com/thediveo/lxkns/decorator/kuhbernetes/dockershim" // pull in decorator plugin 13 | ) 14 | -------------------------------------------------------------------------------- /decorator/composer/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package composer decorates lxkns information models with (Docker) Composer 3 | project groups. 4 | 5 | # Group Decoration 6 | 7 | - Composer groups are typed as "com.docker.compose.project". 8 | 9 | # Container Decoration 10 | 11 | - None. 12 | */ 13 | package composer 14 | -------------------------------------------------------------------------------- /decorator/composer/package_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package composer 16 | 17 | import ( 18 | "testing" 19 | 20 | . "github.com/onsi/ginkgo/v2" 21 | . "github.com/onsi/gomega" 22 | ) 23 | 24 | func TestComposerDecorator(t *testing.T) { 25 | RegisterFailHandler(Fail) 26 | RunSpecs(t, "lxkns/decorator/composer package") 27 | } 28 | -------------------------------------------------------------------------------- /decorator/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package decorator defines the [Decorate] plug-in interface, where the so-called 3 | “decorators” adorn the container information model with additional data, such 4 | as container grouping and unified pod-related container labels. 5 | 6 | Sub-packages contain specific decorators for (Docker) composer groups, 7 | Kubernetes pod (groups), et cetera. 8 | */ 9 | package decorator 10 | -------------------------------------------------------------------------------- /decorator/dockerplugin/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package dockerplugin decorates containerd containers that are represent managed 3 | Docker plugins. 4 | */ 5 | package dockerplugin 6 | -------------------------------------------------------------------------------- /decorator/industrialedge/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package industrialedge decorates the composer-project flavor of [Siemens 3 | Industrial Edge] apps (“IE apps”) when an IE App project is detected. 4 | Additionally, this decorator also decorates the “Industrial Edge runtime” 5 | container. 6 | 7 | This Decorator must be run only after the (Docker) composer project decorator 8 | ([github.com/thediveo/lxkns/decorator/composer]), as it relies on the composer 9 | groups having already been detected and their [model.Group] objects created. 10 | 11 | # Group Flavor 12 | 13 | - The flavor of composer project groups for Industrial Edge apps (also) is 14 | "com.siemens.industrialedge.app". Please note that the group type is (still) 15 | "com.docker.composer.project". 16 | 17 | # Container Flavor 18 | 19 | - The flavor of the container housing the Industrial Edge runtime is 20 | "com.siemens.industrialedge.runtime". 21 | - The flavor of containers belonging to Industrial Edge apps is 22 | "com.siemens.industrialedge.app". 23 | 24 | [Siemens Industrial Edge]: https://siemens.com/industrial-edge 25 | */ 26 | package industrialedge 27 | -------------------------------------------------------------------------------- /decorator/industrialedge/package_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package industrialedge 16 | 17 | import ( 18 | "testing" 19 | 20 | . "github.com/onsi/ginkgo/v2" 21 | . "github.com/onsi/gomega" 22 | ) 23 | 24 | func TestIEDecorator(t *testing.T) { 25 | RegisterFailHandler(Fail) 26 | RunSpecs(t, "lxkns/decorator/industrialedge package") 27 | } 28 | -------------------------------------------------------------------------------- /decorator/kuhbernetes/cri/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package cri decorates Kubernetes pod groups discovered from CRI-managed 3 | containers, based on their CRI-related labels. This decorator operates on 4 | containers (including sandboxes) discovered by the generic CRI engine client. 5 | */ 6 | package cri 7 | -------------------------------------------------------------------------------- /decorator/kuhbernetes/cri/package_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package cri 16 | 17 | import ( 18 | "testing" 19 | 20 | . "github.com/onsi/ginkgo/v2" 21 | . "github.com/onsi/gomega" 22 | ) 23 | 24 | func TestK8sContainerdDecorator(t *testing.T) { 25 | RegisterFailHandler(Fail) 26 | RunSpecs(t, "lxkns/decorator/kuhbernetes/cri package") 27 | } 28 | -------------------------------------------------------------------------------- /decorator/kuhbernetes/cri/test/_kindisch/Dockerfile: -------------------------------------------------------------------------------- 1 | # Enforce that the kindest/base tag to build from must always be specified. 2 | ARG KINDEST_BASE_TAG 3 | 4 | FROM kindest/base:${KINDEST_BASE_TAG} 5 | 6 | # Complete and also modify the kindest/base configuration. 7 | COPY files/ / 8 | -------------------------------------------------------------------------------- /decorator/kuhbernetes/cri/test/_kindisch/files/etc/cni/net.d/10-kindnet.conflist: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "cniVersion": "0.3.1", 4 | "name": "kindnet", 5 | "plugins": [ 6 | { 7 | "type": "ptp", 8 | "ipMasq": false, 9 | "ipam": { 10 | "type": "host-local", 11 | "dataDir": "/run/cni-ipam-state", 12 | "routes": [ 13 | 14 | 15 | { "dst": "0.0.0.0/0" } 16 | ], 17 | "ranges": [ 18 | 19 | 20 | [ { "subnet": "10.244.0.0/24" } ] 21 | ] 22 | } 23 | , 24 | "mtu": 1500 25 | 26 | }, 27 | { 28 | "type": "portmap", 29 | "capabilities": { 30 | "portMappings": true 31 | } 32 | } 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /decorator/kuhbernetes/cri/test/_kindisch/files/etc/systemd/system/containerd.service: -------------------------------------------------------------------------------- 1 | # derived containerd systemd service file from the official: 2 | # https://github.com/containerd/containerd/blob/master/containerd.service 3 | [Unit] 4 | Description=containerd container runtime 5 | Documentation=https://containerd.io 6 | After=network.target local-fs.target 7 | # disable rate limiting 8 | StartLimitIntervalSec=0 9 | 10 | [Service] 11 | ExecStartPre=-/sbin/modprobe overlay 12 | ExecStart=/usr/local/bin/containerd -l debug 13 | StandardOutput=journal+console 14 | 15 | Type=notify 16 | Delegate=yes 17 | KillMode=process 18 | Restart=always 19 | RestartSec=1 20 | # Having non-zero Limit*s causes performance problems due to accounting overhead 21 | # in the kernel. We recommend using cgroups to do container-local accounting. 22 | LimitNPROC=infinity 23 | LimitCORE=infinity 24 | LimitNOFILE=infinity 25 | TasksMax=infinity 26 | OOMScoreAdjust=-999 27 | 28 | [Install] 29 | WantedBy=multi-user.target 30 | -------------------------------------------------------------------------------- /decorator/kuhbernetes/dockershim/package_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package dockershim 16 | 17 | import ( 18 | "testing" 19 | "time" 20 | 21 | . "github.com/onsi/ginkgo/v2" 22 | . "github.com/onsi/gomega" 23 | ) 24 | 25 | var slowSpec = NodeTimeout(30 * time.Second) 26 | 27 | func TestK8sDockershimDecorator(t *testing.T) { 28 | RegisterFailHandler(Fail) 29 | RunSpecs(t, "lxkns/decorator/kuhbernetes/dockershim package") 30 | } 31 | -------------------------------------------------------------------------------- /defs.go: -------------------------------------------------------------------------------- 1 | // General package definitions. 2 | 3 | // Copyright 2020 Harald Albrecht. 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 6 | // use this file except in compliance with the License. You may obtain a copy 7 | // of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | // License for the specific language governing permissions and limitations 15 | // under the License. 16 | 17 | package lxkns 18 | 19 | // SemVersion is the semantic version string of the lxkns module. 20 | //go:generate go run ./internal/gen/version 21 | -------------------------------------------------------------------------------- /defs_version.go: -------------------------------------------------------------------------------- 1 | // Let goreportcard check us. 2 | // Code generated by gen_version; DO NOT EDIT. 3 | 4 | package lxkns 5 | 6 | // SemVersion is the semantic version string of the lxkns module. 7 | const SemVersion = "0.38.0" 8 | -------------------------------------------------------------------------------- /deployments/industrialedge/app.yaml: -------------------------------------------------------------------------------- 1 | name: "Linux-kernel Namespaces" 2 | repository: lxkns 3 | website: "https://github.com/thediveo/lxkns" 4 | description: > 5 | Linux-kernel Namespaces (lxkns) is a diagnosis application for deep-diving 6 | into some of the inner mechanics underneath container technology, namely 7 | "namespaces". Discover Linux-kernel namespaces and mount points (including 8 | hierarchy and "overmounts") in Industrial Edge devices. For easy 9 | identification, lxkns relates the namespaces discovered to running containers 10 | and apps, where possible; this is useful as on the kernel level, namespaces do 11 | not (sic!) have names. 12 | category: Other 13 | icon: lxkns-logo-150x150.png 14 | -------------------------------------------------------------------------------- /deployments/industrialedge/lxkns-logo-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/deployments/industrialedge/lxkns-logo-150x150.png -------------------------------------------------------------------------------- /deployments/lxkns/README.md: -------------------------------------------------------------------------------- 1 | # lxkns as a Service 2 | 3 | Deploys an lxkns-powered namespace discovery service as a container. 4 | 5 | - service API is exposed on port `5010` of the host system. 6 | - available service API paths are `/api/{namespaces,processes,pidmap}`. 7 | - read-only container filesystem. 8 | - non-privileged container, running as non-root, yet with some capabilities. 9 | - comes with a dedicated Seccomp profile, derived from Docker's default profile. 10 | - optional AppArmor profile, but as this has to be loaded into the system by a 11 | system admin, the default operation is to switch off AppArmor for the lxkns 12 | container. 13 | 14 | There's an optional AppArmor profile in file `lxkns-apparmor` available; it must 15 | be loaded into the kernel prior to deploying the containerized lxkns service: 16 | 17 | 1. `sudo apparmor_parser lxkns-apparmor` 18 | 2. edit `docker-compose.yaml` and set the `- apparmor:lxkns` element of 19 | `security_opt` to activate the previously loaded profile for the lxkns 20 | container deployment. 21 | -------------------------------------------------------------------------------- /deployments/lxkns/lxkns-apparmor: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | profile lxkns flags=(attach_disconnected,mediate_deleted) { 4 | #include 5 | 6 | network, 7 | capability, 8 | file, 9 | 10 | signal (receive) peer=unconfined, 11 | 12 | signal (send,receive) peer=lxkns, 13 | 14 | deny @{PROC}/* w, # deny write for all files directly in /proc (not in a subdir) 15 | # deny write to files not in /proc//** or /proc/sys/** 16 | deny @{PROC}/{[^1-9],[^1-9][^0-9],[^1-9s][^0-9y][^0-9s],[^1-9][^0-9][^0-9][^0-9]*}/** w, 17 | deny @{PROC}/sys/[^k]** w, # deny /proc/sys except /proc/sys/k* (effectively /proc/sys/kernel) 18 | deny @{PROC}/sys/kernel/{?,??,[^s][^h][^m]**} w, # deny everything except shm* in /proc/sys/kernel/ 19 | deny @{PROC}/sysrq-trigger rwklx, 20 | deny @{PROC}/kcore rwklx, 21 | deny mount, 22 | deny /sys/[^f]*/** wklx, 23 | deny /sys/f[^s]*/** wklx, 24 | deny /sys/fs/[^c]*/** wklx, 25 | deny /sys/fs/c[^g]*/** wklx, 26 | deny /sys/fs/cg[^r]*/** wklx, 27 | deny /sys/firmware/** rwklx, 28 | deny /sys/kernel/security/** rwklx, 29 | 30 | ptrace (read), 31 | 32 | } 33 | -------------------------------------------------------------------------------- /deployments/reverse/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '2.4' 2 | services: 3 | reverse: 4 | image: nginx:1.20 5 | ports: 6 | - "15010:15010" 7 | volumes: 8 | - ./nginx.conf:/etc/nginx/nginx.conf 9 | networks: 10 | # Ensure to use the network for the project "lxkns" as opposed to 11 | # our own project-specific one. This way træfik can successfully 12 | # forward traffic to our lxkns service. 13 | - default 14 | 15 | networks: 16 | default: 17 | # Sticking with defaults, yet forcing the network name, allows us to 18 | # either attach to an already created default network from the "lxkns" 19 | # composer project or create it in case we're started earlier than the 20 | # lxkns project and its default network hasn't ever been created before. 21 | name: lxkns_default -------------------------------------------------------------------------------- /deployments/reverse/nginx.conf: -------------------------------------------------------------------------------- 1 | events {} 2 | http { 3 | server { 4 | listen 15010; 5 | server_name localhost 127.0.0.1 ::1; 6 | proxy_redirect off; 7 | 8 | location /lxkns/ { 9 | proxy_pass http://lxkns.lxkns_default:5010/; 10 | proxy_set_header X-Forwarded-Uri $request_uri; 11 | proxy_set_header Host $host; 12 | proxy_pass_request_headers on; 13 | proxy_buffering off; 14 | proxy_request_buffering off; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /deployments/test/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG GOVERSION=1.16 2 | 3 | FROM golang:${GOVERSION} 4 | RUN apt-get update && \ 5 | apt-get install -y sudo && \ 6 | adduser --disabled-password --gecos "" luser && \ 7 | adduser luser sudo && \ 8 | echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers 9 | WORKDIR /home/luser 10 | # The script to kick off the tests should be fairly stable, more so than 11 | # dependencies, so we cache it as early as we can. 12 | COPY --chown=luser deployments/test/runtests / 13 | # Cache dependencies to some extend, to speed up things... 14 | COPY --chown=luser go.mod go.sum ./ 15 | #RUN su luser -c "go mod graph | awk '{if (\$1 !~ \"@\") print \$2}' | xargs go get" 16 | RUN su luser -c "go mod download -x" 17 | # Copy in the full lxkns module; unfortunately, tests cannot be prebuild and we 18 | # cannot run tests on namespaces in a build container, so that's all we can do 19 | # here. 20 | COPY --chown=luser . . 21 | USER luser 22 | CMD ["/runtests"] 23 | -------------------------------------------------------------------------------- /deployments/test/README.md: -------------------------------------------------------------------------------- 1 | # README 2 | 3 | Runs all tests in a dedicated Docker container; use `make test` in the 4 | project's top-level directory. 5 | 6 | - build variable `GOVERSION` controls the Golang version to use for building a 7 | test image. It defaults to version `1.15` at the time of this writing. 8 | 9 | - all tests are run twice: once without root and once as root. -------------------------------------------------------------------------------- /deployments/test/runtests: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | TIMEOUT=3m 4 | echo "starting tests... 🦗 🦗 🦗" 5 | echo "PHASE I: as root 🤪" 6 | go test -v -p 1 -timeout ${TIMEOUT} -exec sudo ./... 7 | echo "PHASE II: as non-root user 😇" 8 | go test -v -p 1 -timeout ${TIMEOUT} ./... 9 | -------------------------------------------------------------------------------- /discover/package_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package discover 16 | 17 | import ( 18 | "testing" 19 | "time" 20 | 21 | . "github.com/onsi/ginkgo/v2" 22 | . "github.com/onsi/gomega" 23 | ) 24 | 25 | var slowSpec = NodeTimeout(60 * time.Second) 26 | 27 | func TestLinuxKernelNamespaces(t *testing.T) { 28 | RegisterFailHandler(Fail) 29 | RunSpecs(t, "lxkns/discover package") 30 | } 31 | -------------------------------------------------------------------------------- /discover/pidmap.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | //go:build linux 16 | 17 | package discover 18 | 19 | import ( 20 | ipidmap "github.com/thediveo/lxkns/internal/pidmap" 21 | "github.com/thediveo/lxkns/model" 22 | ) 23 | 24 | // NewPIDMap returns a new PID map ([model.PIDMapper]) based on the specified 25 | // discovery results and further information gathered from the /proc filesystem. 26 | func NewPIDMap(result *Result) model.PIDMapper { 27 | return ipidmap.NewPIDMap(result.Processes) 28 | } 29 | -------------------------------------------------------------------------------- /discover/test/_kindisch/Dockerfile: -------------------------------------------------------------------------------- 1 | # Enforce that the kindest/base tag to build from must always be specified. 2 | ARG KINDEST_BASE_TAG 3 | 4 | FROM kindest/base:${KINDEST_BASE_TAG} 5 | 6 | # Complete and also modify the kindest/base configuration. 7 | COPY files/ / 8 | -------------------------------------------------------------------------------- /discover/test/_kindisch/files/etc/systemd/system/containerd.service: -------------------------------------------------------------------------------- 1 | # derived containerd systemd service file from the official: 2 | # https://github.com/containerd/containerd/blob/master/containerd.service 3 | [Unit] 4 | Description=containerd container runtime 5 | Documentation=https://containerd.io 6 | After=network.target local-fs.target 7 | # disable rate limiting 8 | StartLimitIntervalSec=0 9 | 10 | [Service] 11 | ExecStartPre=-/sbin/modprobe overlay 12 | ExecStart=/usr/local/bin/containerd -l debug 13 | StandardOutput=journal+console 14 | 15 | Type=notify 16 | Delegate=yes 17 | KillMode=process 18 | Restart=always 19 | RestartSec=1 20 | # Having non-zero Limit*s causes performance problems due to accounting overhead 21 | # in the kernel. We recommend using cgroups to do container-local accounting. 22 | LimitNPROC=infinity 23 | LimitCORE=infinity 24 | LimitNOFILE=infinity 25 | TasksMax=infinity 26 | OOMScoreAdjust=-999 27 | 28 | [Install] 29 | WantedBy=multi-user.target 30 | -------------------------------------------------------------------------------- /discover/test/fdscan/proc/1234/fd/0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/discover/test/fdscan/proc/1234/fd/0 -------------------------------------------------------------------------------- /discover/test/fdscan/proc/5678/fd/3: -------------------------------------------------------------------------------- 1 | net:[12345678] -------------------------------------------------------------------------------- /discover/test/fdscan/proc/5678/fd/junk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/discover/test/fdscan/proc/5678/fd/junk -------------------------------------------------------------------------------- /doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package lxkns discovers Linux kernel namespaces. Please see 3 | [github.com/thediveo/lxkns/discovery] for the specific API to namespace 4 | discovery. 5 | 6 | For a broader introduction into lxkns, including the service deployment and web 7 | user interface, please refer to the 📖[online manual]. 8 | 9 | Additional TDD support can be found in 10 | [github.com/thediveo/lxkns/test/matchers], implementing domain-specific [Gomega] 11 | matchers about containers, container groups, pods, et cetera. 12 | 13 | [Gomega]: https://onsi.github.io/gomega 14 | [online manual]: https://thediveo.github.io/lxkns/#/ 15 | */ 16 | package lxkns 17 | -------------------------------------------------------------------------------- /docs/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/.nojekyll -------------------------------------------------------------------------------- /docs/_fonts/roboto-latin-300-italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_fonts/roboto-latin-300-italic.woff -------------------------------------------------------------------------------- /docs/_fonts/roboto-latin-300-italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_fonts/roboto-latin-300-italic.woff2 -------------------------------------------------------------------------------- /docs/_fonts/roboto-latin-300-normal.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_fonts/roboto-latin-300-normal.woff -------------------------------------------------------------------------------- /docs/_fonts/roboto-latin-300-normal.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_fonts/roboto-latin-300-normal.woff2 -------------------------------------------------------------------------------- /docs/_fonts/roboto-latin-500-italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_fonts/roboto-latin-500-italic.woff -------------------------------------------------------------------------------- /docs/_fonts/roboto-latin-500-italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_fonts/roboto-latin-500-italic.woff2 -------------------------------------------------------------------------------- /docs/_fonts/roboto-latin-500-normal.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_fonts/roboto-latin-500-normal.woff -------------------------------------------------------------------------------- /docs/_fonts/roboto-latin-500-normal.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_fonts/roboto-latin-500-normal.woff2 -------------------------------------------------------------------------------- /docs/_fonts/roboto-latin-ext-300-italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_fonts/roboto-latin-ext-300-italic.woff -------------------------------------------------------------------------------- /docs/_fonts/roboto-latin-ext-300-italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_fonts/roboto-latin-ext-300-italic.woff2 -------------------------------------------------------------------------------- /docs/_fonts/roboto-latin-ext-300-normal.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_fonts/roboto-latin-ext-300-normal.woff -------------------------------------------------------------------------------- /docs/_fonts/roboto-latin-ext-300-normal.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_fonts/roboto-latin-ext-300-normal.woff2 -------------------------------------------------------------------------------- /docs/_fonts/roboto-latin-ext-500-italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_fonts/roboto-latin-ext-500-italic.woff -------------------------------------------------------------------------------- /docs/_fonts/roboto-latin-ext-500-italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_fonts/roboto-latin-ext-500-italic.woff2 -------------------------------------------------------------------------------- /docs/_fonts/roboto-latin-ext-500-normal.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_fonts/roboto-latin-ext-500-normal.woff -------------------------------------------------------------------------------- /docs/_fonts/roboto-latin-ext-500-normal.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_fonts/roboto-latin-ext-500-normal.woff2 -------------------------------------------------------------------------------- /docs/_fonts/roboto-mono-latin-300-italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_fonts/roboto-mono-latin-300-italic.woff -------------------------------------------------------------------------------- /docs/_fonts/roboto-mono-latin-300-italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_fonts/roboto-mono-latin-300-italic.woff2 -------------------------------------------------------------------------------- /docs/_fonts/roboto-mono-latin-300-normal.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_fonts/roboto-mono-latin-300-normal.woff -------------------------------------------------------------------------------- /docs/_fonts/roboto-mono-latin-300-normal.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_fonts/roboto-mono-latin-300-normal.woff2 -------------------------------------------------------------------------------- /docs/_fonts/roboto-mono-latin-500-italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_fonts/roboto-mono-latin-500-italic.woff -------------------------------------------------------------------------------- /docs/_fonts/roboto-mono-latin-500-italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_fonts/roboto-mono-latin-500-italic.woff2 -------------------------------------------------------------------------------- /docs/_fonts/roboto-mono-latin-500-normal.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_fonts/roboto-mono-latin-500-normal.woff -------------------------------------------------------------------------------- /docs/_fonts/roboto-mono-latin-500-normal.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_fonts/roboto-mono-latin-500-normal.woff2 -------------------------------------------------------------------------------- /docs/_fonts/roboto-mono-latin-ext-300-italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_fonts/roboto-mono-latin-ext-300-italic.woff -------------------------------------------------------------------------------- /docs/_fonts/roboto-mono-latin-ext-300-italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_fonts/roboto-mono-latin-ext-300-italic.woff2 -------------------------------------------------------------------------------- /docs/_fonts/roboto-mono-latin-ext-300-normal.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_fonts/roboto-mono-latin-ext-300-normal.woff -------------------------------------------------------------------------------- /docs/_fonts/roboto-mono-latin-ext-300-normal.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_fonts/roboto-mono-latin-ext-300-normal.woff2 -------------------------------------------------------------------------------- /docs/_fonts/roboto-mono-latin-ext-500-italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_fonts/roboto-mono-latin-ext-500-italic.woff -------------------------------------------------------------------------------- /docs/_fonts/roboto-mono-latin-ext-500-italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_fonts/roboto-mono-latin-ext-500-italic.woff2 -------------------------------------------------------------------------------- /docs/_fonts/roboto-mono-latin-ext-500-normal.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_fonts/roboto-mono-latin-ext-500-normal.woff -------------------------------------------------------------------------------- /docs/_fonts/roboto-mono-latin-ext-500-normal.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_fonts/roboto-mono-latin-ext-500-normal.woff2 -------------------------------------------------------------------------------- /docs/_images/all-namespaces-with-containers-thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_images/all-namespaces-with-containers-thumbnail.png -------------------------------------------------------------------------------- /docs/_images/all-namespaces-with-containers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_images/all-namespaces-with-containers.png -------------------------------------------------------------------------------- /docs/_images/allview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_images/allview.png -------------------------------------------------------------------------------- /docs/_images/appbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_images/appbar.png -------------------------------------------------------------------------------- /docs/_images/container-mounts-thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_images/container-mounts-thumbnail.png -------------------------------------------------------------------------------- /docs/_images/container-mounts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_images/container-mounts.png -------------------------------------------------------------------------------- /docs/_images/initial.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_images/initial.png -------------------------------------------------------------------------------- /docs/_images/lxkns-gophers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_images/lxkns-gophers.png -------------------------------------------------------------------------------- /docs/_images/lxkns-podmen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_images/lxkns-podmen.png -------------------------------------------------------------------------------- /docs/_images/mnthidden.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_images/mnthidden.png -------------------------------------------------------------------------------- /docs/_images/mntinfo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_images/mntinfo.png -------------------------------------------------------------------------------- /docs/_images/mntview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_images/mntview.png -------------------------------------------------------------------------------- /docs/_images/mountpoint-details.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_images/mountpoint-details.png -------------------------------------------------------------------------------- /docs/_images/netview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_images/netview.png -------------------------------------------------------------------------------- /docs/_images/pidview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_images/pidview.png -------------------------------------------------------------------------------- /docs/_images/podman-containers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_images/podman-containers.png -------------------------------------------------------------------------------- /docs/_images/refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_images/refresh.png -------------------------------------------------------------------------------- /docs/_images/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_images/settings.png -------------------------------------------------------------------------------- /docs/_images/sidebar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_images/sidebar.png -------------------------------------------------------------------------------- /docs/_images/teaser-mountpoints.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_images/teaser-mountpoints.png -------------------------------------------------------------------------------- /docs/_images/teaser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_images/teaser.png -------------------------------------------------------------------------------- /docs/_images/user-podman-rootless-containers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_images/user-podman-rootless-containers.png -------------------------------------------------------------------------------- /docs/_media/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_media/favicon.ico -------------------------------------------------------------------------------- /docs/_media/lxkns192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_media/lxkns192.png -------------------------------------------------------------------------------- /docs/_media/lxkns512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/docs/_media/lxkns512.png -------------------------------------------------------------------------------- /docs/_media/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "lxkns manual", 3 | "name": "Linux Namespaces Manual", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "lxkns192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "lxkns512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /docs/_sidebar.md: -------------------------------------------------------------------------------- 1 | 2 | * [Introduction](/) 3 | * [Features](features) 4 | * [Getting Started](getting-started) 5 | * [Getting Around](getting-around) 6 | * [Sidebar/Help](sidebar-help) 7 | * [Discovery Refresh](refresh) 8 | * [All Namespaces View](all-namespaces) 9 | * [Namespace Type Views](typed-namespace) 10 | * [Mount Namespaces View](mount-namespace) 11 | * [Settings](settings) 12 | * Discovery 13 | * [Namespaces](discovery) 14 | * [Containers](containers) 15 | * [Cgroups](cgroup) 16 | * [Mount Points](mountpoint) 17 | * [Docker Managed Plugins](docker-managed-plugins) 18 | * Service 19 | * [Deployment](service-deployment) 20 | * [Behind a Proxy](service-behind-proxy) 21 | * [Extensible](service-extensible) 22 | * API 23 | * [Important Changes](changelog) 24 | * [Discovery Examples](discovery-examples) 25 | * [(Un)marshalling Example](marshalling-example) 26 | * [Information Model](model) 27 | * [Container Types/Flavors](typesflavors) 28 | * [Decorations](deco) 29 | * [Mountineers](mountineers) 30 | * [Gomega Matchers](matchers) 31 | * [Lab Notes](lab-notes) 32 | * [CLI Tools](cli) 33 | * [mntnssandbox](mntnssandbox) 34 | * [Tinkering](tinkering) 35 | * [Copyright+License](copylicense) 36 | -------------------------------------------------------------------------------- /docs/copylicense.md: -------------------------------------------------------------------------------- 1 | # Copyright and License 2 | 3 | `lxkns` is copyright © 2020‒23 Harald Albrecht, and licensed under the [Apache 4 | License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0). 5 | -------------------------------------------------------------------------------- /docs/getting-around.md: -------------------------------------------------------------------------------- 1 | # Getting Around 2 | 3 | After [deploying the lxkns service](getting-started), please navigate your web 4 | browser to [http://localhost:5010](http://localhost:5010), where you should be 5 | greeted by the web user interface of the lxkns service. 6 | 7 | ![lxkns initial UI view](_images/initial.png) 8 | 9 | Initially, the UI will show only a title and a few icon buttons, this is the 10 | so-called "application bar". So let us now look around the UI more closely in 11 | the following sections. 12 | -------------------------------------------------------------------------------- /docs/marshalling-example.md: -------------------------------------------------------------------------------- 1 | # (Un)Marshalling Example 2 | 3 | `lxkns` supports un/marshalling discovery results from/to JSON. Both the 4 | namespaces and process information can be passed via JSON and correctly 5 | regenerated. 6 | 7 | ```go 8 | package main 9 | 10 | import ( 11 | "fmt" 12 | "github.com/thediveo/lxkns/discover" 13 | apitypes "github.com/thediveo/lxkns/api/types" 14 | ) 15 | 16 | func main() { 17 | b, _ := json.Marshal( 18 | apitypes.NewDiscoveryResult( 19 | discover.Namespaces(discover.WithStandardDiscovery()))) 20 | 21 | dr := apitypes.NewDiscoveryResult(nil) 22 | _ = json.Unmarshal(b, &dr) 23 | result := (*discover.Result)(dr) 24 | } 25 | ``` 26 | 27 | > [!NOTE] Discovery results need to be explicitly "wrapped" in JSON-able objects 28 | > for un/marshalling. The discovery result objects returned from 29 | > `discover.Namespaces()` cannot be properly un/marshalled, not least as they 30 | > describe an information model with circular references that is optimized for 31 | > quick navigation, not for un/marshalling. 32 | -------------------------------------------------------------------------------- /docs/matchers.md: -------------------------------------------------------------------------------- 1 | # Gomega Matchers 2 | 3 | Developers using the `lxkns` Go API (as opposed to the service REST API) might 4 | be interested in dedicated [Gomega](https://onsi.github.io/gomega/) support. 5 | 6 | The [`test/matcher/` 7 | package](https://pkg.go.dev/github.com/thediveo/lxkns/test/matcher) (godoc 8 | documentation) provides Gomega matchers for matching container names/IDs (and 9 | optional their types and flavors), container group memberships, and more. 10 | 11 | ```go 12 | var containers []*model.Container 13 | 14 | Expect(containers).To(ContainElement(HaveContainerName("foobar"))) 15 | ``` 16 | -------------------------------------------------------------------------------- /docs/refresh.md: -------------------------------------------------------------------------------- 1 | # Discovery Refresh 2 | 3 | The user interface defaults to manual refresh: clicking or tapping ❶ will start 4 | a new discovery. If the discovery takes more time (such as on a system under 5 | heavy load) or in case of a slow connection a progress indicator automatically 6 | appears after approximately one second. 7 | 8 | > [!NOTE] Discoveries cause some load on the target system, so please opt for 9 | > either on-demand manual refreshes or choose a more relaxed refresh interval. 10 | 11 | ![refresh discovery](_images/refresh.png ':class=framedscreenshot') 12 | 13 | Clicking or tapping ❷ opens a pop-up menu to either disable any automatic 14 | refreshing or to choose from a set of available refresh intervals (500ms, 1s, 15 | 5s, 10s, 30s, 1min, 5min). 16 | -------------------------------------------------------------------------------- /docs/sidebar-help.md: -------------------------------------------------------------------------------- 1 | # Sidebar and Help 2 | 3 | Clicking or tapping the sidebar symbol ❶ in the application bar opens the 4 | sidebar. On touch devices, the sidebar can also be opened by swiping from the 5 | left border to the right. 6 | 7 | ![application bar](_images/appbar.png ':class=framedscreenshot') 8 | 9 | The application bar additionally offers these quick-access actions: 10 | 11 | - ❷ collapses all tree levels, except for the root level as well as its 12 | immediate children. 13 | - ❸ expands all tree levels. 14 | - ❹ manual discovery and automatic refresh control. See also [discovery 15 | refresh](#discovery-refresh). 16 | 17 | The sidebar can be closed either by click or tapping the close symbol ❶ or by 18 | click or tapping outside the sidebar. 19 | 20 | ![sidebar](_images/sidebar.png ':class=framedscreenshot') 21 | 22 | The sidebar also gives quick access to the integrated help ❷: multiple chapters 23 | explain the displayed information in more detail. 24 | -------------------------------------------------------------------------------- /docs/typed-namespace.md: -------------------------------------------------------------------------------- 1 | # Namespace Type Views 2 | 3 | The type-specific namespace views show only namespaces for a single specific 4 | type. Most of these views are flat views, except for PID and user namespace 5 | views. The type of namespaces shown is also indicated by the title in the 6 | application bar. The number badge shows the number of namespaces found of this 7 | specific type. 8 | 9 | ![PID view](_images/pidview.png ':class=framedscreenshot') 10 | 11 | Most types of namespaces are flat without any hierarchy, such as network 12 | namespaces. That is, there aren't network namespaces inside other network 13 | namespaces. 14 | 15 | ![network view](_images/netview.png ':class=framedscreenshot') 16 | -------------------------------------------------------------------------------- /internal/namespaces/package_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package namespaces 16 | 17 | import ( 18 | "testing" 19 | 20 | . "github.com/onsi/ginkgo/v2" 21 | . "github.com/onsi/gomega" 22 | ) 23 | 24 | func TestNamespaceTypes(t *testing.T) { 25 | RegisterFailHandler(Fail) 26 | RunSpecs(t, "lxkns/internal/namespaces package") 27 | } 28 | -------------------------------------------------------------------------------- /internal/pidmap/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package pidmap translates process PIDs (and also task TIDs) between different 3 | PID namespaces. 4 | */ 5 | package pidmap 6 | -------------------------------------------------------------------------------- /internal/pidmap/package_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package pidmap 16 | 17 | import ( 18 | "testing" 19 | 20 | . "github.com/onsi/ginkgo/v2" 21 | . "github.com/onsi/gomega" 22 | ) 23 | 24 | func TestPidmap(t *testing.T) { 25 | RegisterFailHandler(Fail) 26 | RunSpecs(t, "lxkns/internal/pidmap package") 27 | } 28 | -------------------------------------------------------------------------------- /internal/pidmap/test/proc/1/stat: -------------------------------------------------------------------------------- 1 | 1 (init) R 0 1 1 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 0 123 2 | -------------------------------------------------------------------------------- /internal/pidmap/test/proc/1/status: -------------------------------------------------------------------------------- 1 | NSpid: 10 2 | -------------------------------------------------------------------------------- /internal/pidmap/test/proc/4200/stat: -------------------------------------------------------------------------------- 1 | 4200 (foobar) R 0 1 1 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 0 123 2 | -------------------------------------------------------------------------------- /internal/pidmap/test/proc/4200/status: -------------------------------------------------------------------------------- 1 | NSpid: 4200 1 2 | -------------------------------------------------------------------------------- /internal/pidmap/test/proc/668/stat: -------------------------------------------------------------------------------- 1 | 668 (foobar) R 1 42 42 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 0 123 2 | -------------------------------------------------------------------------------- /internal/pidmap/test/proc/668/status: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/internal/pidmap/test/proc/668/status -------------------------------------------------------------------------------- /internal/pidmap/test/proc/669/stat: -------------------------------------------------------------------------------- 1 | 669 (foobar) R 1 42 42 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 0 123 2 | -------------------------------------------------------------------------------- /internal/pidmap/test/proc/669/status: -------------------------------------------------------------------------------- 1 | NSpid: 1 2 2 | -------------------------------------------------------------------------------- /log/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package log allows consumers of the lxkns module to forward logging originating 3 | in the lxkns module to whatever logger module they prefer. 4 | 5 | The accompanying package [github.com/thediveo/lxkns/log/logrus] can be used as a 6 | simple means to forward all lxkns-originating logging messages to the standard 7 | [sirupsen/logrus] logger instance. YMMV, however. 8 | 9 | To forward lxkns-originating log messages to a different logging module only 10 | needs an adaptor implementing the Logger interface: it consists of just two 11 | methods: 12 | 13 | - Log(level Level, msg string) 14 | - SetLevel(level Level) 15 | 16 | A consumer of the lxkns module then sets her specific logging adapter: 17 | 18 | SetLog(myadapter) 19 | 20 | An adapter can either forward the [SetLevel] method, but it is also perfectly 21 | fine to ignore these interface calls: this allows keeping separate logging 22 | levels for lxkns and the consuming application; for instance, disabling or 23 | restricting lxkns logging while still doing verbose application logging. 24 | 25 | [sirupsen/logrus]: https://github.com/sirupsen/logrus 26 | */ 27 | package log 28 | -------------------------------------------------------------------------------- /log/logrus/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package logrus enables logging within the lxkns module and directs all logging 3 | output to the [sirupsen/logrus] logging module. 4 | 5 | This redirection gets automatically switched on by simply importing this package 6 | into an application: 7 | 8 | import _ "github.com/thediveo/lxkns/log/logrus" 9 | 10 | [sirupsen/logrus]: https://github.com/sirupsen/logrus 11 | */ 12 | package logrus 13 | -------------------------------------------------------------------------------- /lxkns.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "." 5 | } 6 | ], 7 | "settings": { 8 | "go.lintTool": "golangci-lint", 9 | "plantuml.diagramsRoot": "puml", 10 | "plantuml.exportFormat": "svg", 11 | "plantuml.exportOutDir": "docs/_images", 12 | "plantuml.exportSubFolder": false, 13 | "go.testFlags": [ 14 | "-v" 15 | ], 16 | "makefile.extensionOutputFolder": "./.vscode", 17 | } 18 | } -------------------------------------------------------------------------------- /model/package_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package model 16 | 17 | import ( 18 | "testing" 19 | 20 | . "github.com/onsi/ginkgo/v2/dsl/core" 21 | . "github.com/onsi/gomega" 22 | ) 23 | 24 | func TestNamespaceTypes(t *testing.T) { 25 | RegisterFailHandler(Fail) 26 | RunSpecs(t, "lxkns/model package") 27 | } 28 | -------------------------------------------------------------------------------- /model/test/cgroupies/v1/freezing/freezer.state: -------------------------------------------------------------------------------- 1 | FREEZING -------------------------------------------------------------------------------- /model/test/cgroupies/v1/frozen/freezer.state: -------------------------------------------------------------------------------- 1 | FROZEN -------------------------------------------------------------------------------- /model/test/cgroupies/v1/somethingelse/freezer.state: -------------------------------------------------------------------------------- 1 | ANDNOWFORSOMETHINGELSE -------------------------------------------------------------------------------- /model/test/cgroupies/v1/thawed/freezer.state: -------------------------------------------------------------------------------- 1 | THAWED -------------------------------------------------------------------------------- /model/test/cgroupies/v2/frozen/cgroup.events: -------------------------------------------------------------------------------- 1 | fubared 1 2 | frozen 1 -------------------------------------------------------------------------------- /model/test/cgroupies/v2/gnawed/cgroup.events: -------------------------------------------------------------------------------- 1 | gnawed 42 2 | -------------------------------------------------------------------------------- /model/test/cgroupies/v2/thawed/cgroup.events: -------------------------------------------------------------------------------- 1 | SNAFU 666 2 | frozen 0 3 | -------------------------------------------------------------------------------- /model/test/proctable/kaputt/1/stat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/model/test/proctable/kaputt/1/stat -------------------------------------------------------------------------------- /model/test/proctable/kaputt/666/stat: -------------------------------------------------------------------------------- 1 | 666 () R 1 42 42 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 0 123 2 | -------------------------------------------------------------------------------- /model/test/proctable/kaputt/667/cmdline: -------------------------------------------------------------------------------- 1 | mumble.exearg1arg2 -------------------------------------------------------------------------------- /model/test/proctable/kaputt/667/stat: -------------------------------------------------------------------------------- 1 | 42 (foobar) R 1 42 42 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 0 123 2 | -------------------------------------------------------------------------------- /model/test/proctable/proc/1/stat: -------------------------------------------------------------------------------- 1 | 1 (init) R 0 1 1 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 0 123 2 | -------------------------------------------------------------------------------- /model/test/proctable/proc/1/status: -------------------------------------------------------------------------------- 1 | Foo: bar 2 | NSpid: 1 3 | Bar: baz 4 | -------------------------------------------------------------------------------- /model/test/proctable/proc/42/cmdline: -------------------------------------------------------------------------------- 1 | /foo/bar/mumble.exearg1arg2 -------------------------------------------------------------------------------- /model/test/proctable/proc/42/stat: -------------------------------------------------------------------------------- 1 | 42 (foobar) R 1 42 42 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 0 123 2 | -------------------------------------------------------------------------------- /model/test/proctable/proc/42/status: -------------------------------------------------------------------------------- 1 | Foo: bar 2 | NSpid: 42 3 | Bar: baz 4 | -------------------------------------------------------------------------------- /mounts/package_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package mounts 16 | 17 | import ( 18 | "testing" 19 | 20 | . "github.com/onsi/ginkgo/v2" 21 | . "github.com/onsi/gomega" 22 | ) 23 | 24 | func TestNamespaceTypes(t *testing.T) { 25 | RegisterFailHandler(Fail) 26 | RunSpecs(t, "lxkns/mounts package") 27 | } 28 | -------------------------------------------------------------------------------- /nsioctl/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package nsioctl defines namespace-related ioctl request values that aren't 3 | defined in the sys/unix standard package. 4 | 5 | # References 6 | 7 | - See also [ioctl_ns(2)] for details about the namespace-related ioctl 8 | operations. 9 | - For background information on getting the network namespace of a TAP/TUN 10 | netdev please refer to [TUNGETDEVNETNS]. 11 | 12 | [ioctl_ns(2)]: https://man7.org/linux/man-pages/man2/ioctl_ns.2.html 13 | [TUNGETDEVNETNS]: https://unix.stackexchange.com/a/743003 14 | */ 15 | package nsioctl 16 | -------------------------------------------------------------------------------- /nstest/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package nstest provides testing support in the context of Linux kernel 3 | namespaces. 4 | */ 5 | package nstest 6 | -------------------------------------------------------------------------------- /nstest/gmodel/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package gmodel provides Gomega matches for lxkns model elements. 3 | */ 4 | package gmodel 5 | -------------------------------------------------------------------------------- /nstest/gmodel/package_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package gmodel 16 | 17 | import ( 18 | "testing" 19 | 20 | . "github.com/onsi/ginkgo/v2" 21 | . "github.com/onsi/gomega" 22 | ) 23 | 24 | func TestModelMatchers(t *testing.T) { 25 | RegisterFailHandler(Fail) 26 | RunSpecs(t, "lxkns/nstest/gnamespaces matchers package") 27 | } 28 | -------------------------------------------------------------------------------- /ops/mountineer/package_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package mountineer 16 | 17 | import ( 18 | "testing" 19 | 20 | . "github.com/onsi/ginkgo/v2" 21 | . "github.com/onsi/gomega" 22 | ) 23 | 24 | func TestNamespaceTypes(t *testing.T) { 25 | RegisterFailHandler(Fail) 26 | RunSpecs(t, "lxkns/ops/mountineer package") 27 | } 28 | -------------------------------------------------------------------------------- /ops/package_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package ops 16 | 17 | import ( 18 | "testing" 19 | 20 | . "github.com/onsi/ginkgo/v2" 21 | . "github.com/onsi/gomega" 22 | ) 23 | 24 | func TestRelations(t *testing.T) { 25 | RegisterFailHandler(Fail) 26 | RunSpecs(t, "lxkns/ops package") 27 | } 28 | -------------------------------------------------------------------------------- /ops/portable/package_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package portable 16 | 17 | import ( 18 | "testing" 19 | 20 | . "github.com/onsi/ginkgo/v2" 21 | . "github.com/onsi/gomega" 22 | "github.com/thediveo/lxkns/ops" 23 | "github.com/thediveo/lxkns/species" 24 | ) 25 | 26 | func TestRelations(t *testing.T) { 27 | RegisterFailHandler(Fail) 28 | RunSpecs(t, "lxkns/ops/portable package") 29 | } 30 | 31 | var mynetnsid species.NamespaceID 32 | 33 | var _ = BeforeSuite(func() { 34 | var err error 35 | mynetnsid, err = ops.NamespacePath("/proc/self/ns/net").ID() 36 | Expect(err).To(Succeed()) 37 | }) 38 | -------------------------------------------------------------------------------- /plural/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package plural supplies lxkns with (only) English-language plurals for common 3 | objects appearing in the lxkns information model. This is not a general I18N 4 | package. 5 | */ 6 | package plural 7 | -------------------------------------------------------------------------------- /plural/package_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package plural 16 | 17 | import ( 18 | "testing" 19 | 20 | . "github.com/onsi/ginkgo/v2" 21 | . "github.com/onsi/gomega" 22 | ) 23 | 24 | func TestPlural(t *testing.T) { 25 | RegisterFailHandler(Fail) 26 | RunSpecs(t, "lxkns/plural package") 27 | } 28 | -------------------------------------------------------------------------------- /puml/linux-namespaces.puml: -------------------------------------------------------------------------------- 1 | @startuml linux-namespaces 2 | hide empty fields 3 | hide empty methods 4 | 5 | class "Flat Linux Kernel Namespace" as ns <<(L,LightBlue)>> 6 | 7 | class cgroup <<(L,LightBlue)>> 8 | note bottom: control group 9 | ns <|--- cgroup 10 | class ipc <<(L,LightBlue)>> 11 | note bottom: SYSV\ninter-process\ncommunication 12 | ns <|--- ipc 13 | class mnt <<(L,LightBlue)>> 14 | note bottom: filesystem\nmounts 15 | ns <|--- mnt 16 | class net <<(L,LightBlue)>> 17 | note bottom: network 18 | ns <|--- net 19 | class uts <<(L,LightBlue)>> 20 | note bottom: hostname and\ndomain name 21 | ns <|--- uts 22 | class time <<(L,LightBlue)>> 23 | note bottom: monotonic +\nboot-time clocks 24 | ns <|--- time 25 | 26 | cgroup -[hidden] ipc 27 | 28 | class "Hierarchical Namespace" as hns <<(L,LightBlue)>> 29 | ns <|-- hns 30 | 31 | class pid <<(L,LightBlue)>> 32 | note bottom: PIDs 33 | hns <|-- pid 34 | hns <--> hns : parent/children 35 | 36 | class user <<(L,LightBlue)>> 37 | note bottom: uids/gids,\ncaps, … 38 | hns <|-- user 39 | ns <-- pid : owns 40 | 41 | user -[hidden] pid 42 | 43 | @enduml 44 | -------------------------------------------------------------------------------- /puml/lxkns-containers.puml: -------------------------------------------------------------------------------- 1 | @startuml lxkns-containers 2 | hide empty fields 3 | hide empty methods 4 | !define L <&link-intact> 5 | 6 | package "lxkns.model" { 7 | 8 | class Process { 9 | L *Container 10 | } 11 | 12 | class Container { 13 | ID string 14 | Name string 15 | PID int 16 | Type string 17 | Flavor string 18 | Paused bool 19 | Labels map[string]string 20 | L Groups []*Group 21 | L Engine *ContainerEngine 22 | L Process *Process 23 | } 24 | 25 | Process <- "0,1" Container : "Container " 26 | Process <- Container : "Process" 27 | 28 | class Group { 29 | Name string 30 | Type string 31 | Flavor string 32 | Labels map[string]string 33 | L Containers []*Container 34 | } 35 | 36 | class ContainerEngine { 37 | ID string 38 | Type string 39 | API string 40 | PID int 41 | L Containers []*Container 42 | } 43 | 44 | ContainerEngine "1" -- "1..*" Container : " " 45 | Container "*" - "*" Group : " " 46 | 47 | } 48 | 49 | @enduml 50 | -------------------------------------------------------------------------------- /puml/lxkns-namespaces.puml: -------------------------------------------------------------------------------- 1 | @startuml lxkns-namespaces 2 | hide empty fields 3 | hide empty methods 4 | !define L <&link-intact> 5 | 6 | package "lxkns.model" { 7 | 8 | interface Hierarchy { 9 | L Parent() Hierarchy 10 | L Children() []Hierarchy 11 | } 12 | 13 | interface Ownership { 14 | UID() int 15 | L Ownings() AllNamespaces 16 | } 17 | 18 | Hierarchy "*" -up-> Hierarchy : Parent 19 | Hierarchy <-down- "*" Hierarchy : Children 20 | 21 | Hierarchy -[hidden] Ownership 22 | 23 | Ownership --> "*" Namespace : "Ownings" 24 | 25 | interface Namespace { 26 | ID() species.NamespaceID 27 | Type() species.NamespaceType 28 | L Owner() Hierarchy 29 | Ref() string 30 | L Leaders() []*Process 31 | LeaderPIDs() []PIDType 32 | L Ealdorman() *Process 33 | L LooseThreads() []*Task 34 | LooseThreadsIDs() []PIDType 35 | String() string 36 | } 37 | 38 | Hierarchy <-- Namespace : "Owner" 39 | 40 | interface NamespaceStringer { 41 | TypeIDString() string 42 | } 43 | Namespace <|- NamespaceStringer 44 | 45 | @enduml 46 | -------------------------------------------------------------------------------- /puml/lxkns-processes.puml: -------------------------------------------------------------------------------- 1 | @startuml lxkns-processes 2 | skinparam nodesep 70 3 | hide empty fields 4 | hide empty methods 5 | !define L <&link-intact> 6 | 7 | package "lxkns.model" { 8 | 9 | interface Namespace { 10 | L Leaders() []*Process 11 | L Ealdorman() *Process 12 | L LooseThreads() []*Task 13 | } 14 | 15 | Namespace ---> "0,1" Process : Ealdorman 16 | Namespace ---> "*" Process : Leaders 17 | Namespace ---> "*" Task: LooseThreads 18 | 19 | class ProcessTable 20 | Process <-- ProcessTable : "[PID]" 21 | 22 | class ProTaskCommon <> { 23 | L Namespaces NamespacesSet 24 | } 25 | 26 | ProTaskCommon --o Task 27 | ProTaskCommon --o Process 28 | ProTaskCommon -> "8" Namespace : Namespaces 29 | 30 | 31 | class Task { 32 | L Process *Process 33 | } 34 | 35 | class Process { 36 | L Parent *Process 37 | L Tasks []*Task 38 | L *Container 39 | } 40 | 41 | Process "*" --> Process : Parent 42 | Task <- Process : "Tasks" "1,*" 43 | 44 | class Container { 45 | PID int 46 | L Process *Process 47 | } 48 | 49 | Process -> "0,1" Container : Container 50 | Process <- Container : "Process" 51 | 52 | } 53 | 54 | @enduml 55 | -------------------------------------------------------------------------------- /puml/namespaces-discovery.puml: -------------------------------------------------------------------------------- 1 | @startuml namespaces-discovery 2 | hide empty fields 3 | hide empty methods 4 | 5 | namespace lxkns { 6 | 7 | class Discover as " " <<(F,LightGray)>> { 8 | Discover(opts DiscoverOpts) *DiscoveryResult 9 | } 10 | 11 | Discover <.. DiscoverOpts : "controls" 12 | Discover ..> DiscoveryResult : "returns" 13 | 14 | class "DiscoverOpts" <<(S,YellowGreen)>> { 15 | NamespaceTypes species.NamespaceType 16 | ScanProcs bool 17 | ScanTasks bool 18 | ScanFds bool 19 | ScanBindmounts bool 20 | DiscoverHierarchy bool 21 | DiscoverOwnership bool 22 | DiscoverFreezerState bool 23 | DiscoverMounts bool 24 | Containerizer containerizer.Containerizer 25 | } 26 | 27 | class "DiscoveryResult" <<(S,YellowGreen)>> { 28 | Options DiscoverOpts 29 | Namespaces model.AllNamespaces 30 | InitialNamespaces model.NamespacesSet 31 | ' TODO: Root(s) 32 | Processes model.ProcessTable 33 | Mounts NamespacedMountPathMap 34 | Containers []*model.Container 35 | } 36 | 37 | } 38 | 39 | @enduml 40 | -------------------------------------------------------------------------------- /scripts/chores.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | echo "checking pkgsite..." 5 | go install golang.org/x/pkgsite/cmd/pkgsite@latest 6 | 7 | echo "checking govulncheck..." 8 | go install golang.org/x/vuln/cmd/govulncheck@latest 9 | 10 | echo "checking gobadge..." 11 | go install github.com/AlexBeauchemin/gobadge@latest 12 | 13 | echo "checking goreportcard and friends..." 14 | GOREPORTCARDTMPDIR="$(mktemp -d)" 15 | trap 'rm -rf -- "$GOREPORTCARDTMPDIR"' EXIT 16 | git clone https://github.com/gojp/goreportcard.git "$GOREPORTCARDTMPDIR" 17 | (cd "$GOREPORTCARDTMPDIR" && make install && go install ./cmd/goreportcard-cli) 18 | go install github.com/gordonklaus/ineffassign@latest 19 | go install github.com/client9/misspell/cmd/misspell@latest 20 | 21 | echo "checking pkgsite NPM helpers..." 22 | (cd $HOME && npm update --silent browser-sync) 23 | (cd $HOME && npm update --silent nodemon) 24 | -------------------------------------------------------------------------------- /scripts/docsify.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # In case the user hasn't set an explicit installation location, avoid polluting 5 | # our own project... 6 | npm list --depth=0 docsify-cli &>/dev/null || \ 7 | (cd $HOME && npm install docsify-cli) 8 | 9 | echo "starting docsify on port 3300 (and 3301)..." 10 | npm exec -- docsify serve -p 3300 -P 3301 "$@" 11 | -------------------------------------------------------------------------------- /scripts/goreportcard.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | if ! command -v goreportcard-cli &>/dev/null; then 5 | export PATH="$(go env GOPATH)/bin:$PATH" 6 | if ! command -v goreportcard-cli &>/dev/null; then 7 | rm -rf /tmp/goreportcard || true 8 | git clone https://github.com/gojp/goreportcard.git /tmp/goreportcard 9 | (cd /tmp/goreportcard && make install && go install ./cmd/goreportcard-cli) 10 | rm -rf /tmp/goreportcard || true 11 | # Install a somewhat recent ineffassign over the totally outdated one 12 | # that goreportcard still insists of infecting the system with. 13 | go install github.com/gordonklaus/ineffassign@latest 14 | # Install the missing misspell, oh well... 15 | go install github.com/client9/misspell/cmd/misspell@latest 16 | fi 17 | fi 18 | 19 | goreportcard-cli -v ./... 20 | -------------------------------------------------------------------------------- /scripts/grype.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | if ! command -v grype &>/dev/null; then 5 | export PATH="$(go env GOPATH)/bin:$PATH" 6 | if ! command -v grype^ &>/dev/null; then 7 | go install github.com/anchore/grype/cmd/grype@latest 8 | fi 9 | fi 10 | 11 | grype dir:. 12 | -------------------------------------------------------------------------------- /scripts/multiarch-builder.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | # Note: requires qemu to be installed. On Debian-based distros, install using 5 | # "sudo apt-get install -y qemu qemu-user-static". Ubuntu starting with 23.04, 6 | # use "sudo apt-get install -y qemu-system qemu-user-static" instead. 7 | 8 | PLATFORMS="linux/amd64,linux/arm64" 9 | 10 | BOBTHEBUILDER="builderbob" 11 | 12 | # Had our builder been created in the past and still exists? 13 | echo "🔎 checking for builder..." 14 | if ! docker buildx inspect "${BOBTHEBUILDER}" 2>/dev/null 1>&2; then 15 | echo "👨‍🏭 creating builder..." 16 | # https://github.com/docker/buildx/issues/835 17 | docker buildx create --name "${BOBTHEBUILDER}" \ 18 | --bootstrap \ 19 | --platform "${PLATFORMS}" \ 20 | --driver-opt network=host --buildkitd-flags "--allow-insecure-entitlement network.host" 21 | fi 22 | 23 | echo "🔎 ensuring local registry is up..." 24 | docker start registry || docker run -d -p 5000:5000 --restart=always --name registry registry:2 25 | 26 | echo "🏗 building..." 27 | rm -rf dist/ 28 | mkdir -p dist/ 29 | ./scripts/docker-build.sh \ 30 | ./deployments/lxkns/Dockerfile \ 31 | -t localhost:5000/lxkns \ 32 | --builder "${BOBTHEBUILDER}" --platform "${PLATFORMS}" \ 33 | --push \ 34 | --network host \ 35 | "$@" 36 | -------------------------------------------------------------------------------- /scripts/pkgsite.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | if ! command -v pkgsite &>/dev/null; then 5 | export PATH="$(go env GOPATH)/bin:$PATH" 6 | if ! command -v pkgsite &>/dev/null; then 7 | go install golang.org/x/pkgsite/cmd/pkgsite@master 8 | fi 9 | fi 10 | 11 | # In case the user hasn't set an explicit installation location, avoid polluting 12 | # our own project... 13 | npm list --depth=0 browser-sync &>/dev/null || \ 14 | (cd $HOME && npm install browser-sync) 15 | 16 | npm list --depth=0 nodemon &>/dev/null || \ 17 | (cd $HOME && npm install nodemon) 18 | 19 | # https://stackoverflow.com/a/2173421 20 | trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT 21 | 22 | # https://mdaverde.com/posts/golang-local-docs 23 | npm exec -- browser-sync start --port 6060 --proxy localhost:6061 --reload-delay 2000 --reload-debounce 5000 --no-ui --no-open & 24 | PKGSITE=$(which pkgsite) 25 | npm exec -- nodemon --signal SIGTERM --watch './**/*' -e go --exec "browser-sync --port 6060 reload && $PKGSITE -http=localhost:6061 ." 26 | -------------------------------------------------------------------------------- /scripts/scan.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | export PATH="$(go env GOPATH)/bin:$PATH" 5 | go install github.com/anchore/syft/cmd/syft@latest 6 | go install github.com/anchore/grype@latest 7 | 8 | BOMFILE=$(mktemp "/tmp/lxkns-scan.XXXXXX.json") 9 | trap 'rm -- "$BOMFILE"' EXIT 10 | syft dir:. -o json > $BOMFILE 11 | grype sbom:$BOMFILE 12 | -------------------------------------------------------------------------------- /scripts/testjson.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Quick and dirty check for lsallns always showing the same information, 4 | # regardless of originating from its own discovery or an imported JSON 5 | # discovery result. 6 | 7 | # Of course, this isn't atomic, so it's still prone to spurious failures on a 8 | # system where namespaces tend to come and go quickly and often. 9 | 10 | TEMPFILE=$(mktemp) 11 | # Dump all namespaces (and processes) as JSON and then generate an lsallns 12 | # list from it. 13 | sudo go run ./cmd/dumpns -c | go run ./examples/lsallns -i - > ${TEMPFILE} 14 | # Now run a direct lsallns and compare the output of it with the one generated 15 | # only indirectly. 16 | sudo go run ./examples/lsallns | diff -s - ${TEMPFILE} 17 | rm ${TEMPFILE} 18 | -------------------------------------------------------------------------------- /scripts/vuln.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | if ! command -v govulncheck &>/dev/null; then 5 | export PATH="$(go env GOPATH)/bin:$PATH" 6 | if ! command -v govulncheck &>/dev/null; then 7 | echo "installing govulncheck..." 8 | go install golang.org/x/vuln/cmd/govulncheck@latest 9 | fi 10 | fi 11 | if [[ $(find "$(go env GOPATH)/bin/govulncheck" -mtime +1 -print) ]]; then 12 | echo "updating govulncheck to @latest..." 13 | go install golang.org/x/vuln/cmd/govulncheck@latest 14 | fi 15 | 16 | govulncheck ./... 17 | -------------------------------------------------------------------------------- /species/package_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package species 16 | 17 | import ( 18 | "testing" 19 | 20 | . "github.com/onsi/ginkgo/v2" 21 | . "github.com/onsi/gomega" 22 | ) 23 | 24 | func TestNamespaceTypes(t *testing.T) { 25 | RegisterFailHandler(Fail) 26 | RunSpecs(t, "lxkns/species package") 27 | } 28 | -------------------------------------------------------------------------------- /test/containerdtest/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package containerdtest is a poor-man's dockertest. 3 | */ 4 | package containerdtest 5 | -------------------------------------------------------------------------------- /test/containerdtest/package_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package containerdtest 16 | 17 | import ( 18 | "testing" 19 | 20 | . "github.com/onsi/ginkgo/v2" 21 | . "github.com/onsi/gomega" 22 | ) 23 | 24 | func TestContainerdtest(t *testing.T) { 25 | RegisterFailHandler(Fail) 26 | RunSpecs(t, "lxkns/test/containerd package") 27 | } 28 | -------------------------------------------------------------------------------- /test/matcher/be_a_container.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package matcher 16 | 17 | import ( 18 | o "github.com/onsi/gomega" 19 | "github.com/onsi/gomega/types" 20 | ) 21 | 22 | // BeAContainer succeeds if actual is a model.Container or *model.Container and 23 | // also satisfies all its option matchers. A typical use is to use BeAContainer 24 | // in combination with the "WithX" matchers, such as WithName and WithType. Of 25 | // course, any other matcher can be specified as an option matcher to 26 | // BeAContainer as needed. 27 | func BeAContainer(options ...types.GomegaMatcher) types.GomegaMatcher { 28 | return withContainer("HaveContainer", o.SatisfyAll(options...)) 29 | } 30 | -------------------------------------------------------------------------------- /test/matcher/be_a_docker_container.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package matcher 16 | 17 | import ( 18 | o "github.com/onsi/gomega" 19 | "github.com/onsi/gomega/types" 20 | "github.com/thediveo/whalewatcher/engineclient/moby" 21 | ) 22 | 23 | // BeADockerContainer succeeds if actual is a Docker container and also satisfy 24 | // all its option matchers. 25 | func BeADockerContainer(options ...types.GomegaMatcher) types.GomegaMatcher { 26 | return withContainer("BeADockerContainer", 27 | o.SatisfyAll(WithType(moby.Type), o.SatisfyAll(options...))) 28 | } 29 | -------------------------------------------------------------------------------- /test/matcher/be_a_docker_container_example_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package matcher 16 | 17 | import ( 18 | . "github.com/onsi/gomega" 19 | "github.com/thediveo/lxkns/model" 20 | "github.com/thediveo/whalewatcher/engineclient/moby" 21 | ) 22 | 23 | func ExampleBeADockerContainer() { 24 | var dockerC = model.Container{ 25 | ID: "1234567890", 26 | Name: "foo_bar", 27 | Type: moby.Type, 28 | Flavor: "fluffy", 29 | } 30 | otherC := dockerC 31 | otherC.Type = "cry-oh.io" 32 | 33 | Expect(dockerC).To(BeADockerContainer()) 34 | Expect(otherC).NotTo(BeADockerContainer()) 35 | //Output: 36 | } 37 | -------------------------------------------------------------------------------- /test/matcher/be_a_pod.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package matcher 16 | 17 | import ( 18 | o "github.com/onsi/gomega" 19 | "github.com/onsi/gomega/types" 20 | "github.com/thediveo/lxkns/decorator/kuhbernetes" 21 | ) 22 | 23 | // BeAPod succeeds if actual is a model.Group or a *model.Group with the 24 | // Kubernetes pod type, and also satisfies all specified option matchers. 25 | func BeAPod(options ...types.GomegaMatcher) types.GomegaMatcher { 26 | return withGroup("BeAPod", o.SatisfyAll( 27 | o.HaveField("Type", kuhbernetes.PodGroupType), 28 | o.SatisfyAll(options...))) 29 | } 30 | -------------------------------------------------------------------------------- /test/matcher/be_a_pod_example_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package matcher 16 | 17 | import ( 18 | . "github.com/onsi/gomega" 19 | "github.com/thediveo/lxkns/decorator/composer" 20 | "github.com/thediveo/lxkns/decorator/kuhbernetes" 21 | "github.com/thediveo/lxkns/model" 22 | ) 23 | 24 | func ExampleBeAPod() { 25 | group := model.Group{ 26 | Name: "test/foopod", 27 | Type: kuhbernetes.PodGroupType, 28 | } 29 | composergroup := model.Group{ 30 | Name: "foobar-project", 31 | Type: composer.ComposerGroupType, 32 | } 33 | Expect(group).To(BeAPod()) 34 | Expect(composergroup).NotTo(BeAPod()) 35 | //Output: 36 | } 37 | -------------------------------------------------------------------------------- /test/matcher/be_in_a_group.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package matcher 16 | 17 | import ( 18 | o "github.com/onsi/gomega" 19 | "github.com/onsi/gomega/types" 20 | ) 21 | 22 | // BeInAGroup succeeds if actual is a model.Container or *model.Container and 23 | // the specified option matchers all succeed on a group the actual container 24 | // belongs to. 25 | // 26 | // Expect(c).To(BeInAGroup(WithName("my_project"))) 27 | func BeInAGroup(opts ...types.GomegaMatcher) types.GomegaMatcher { 28 | return withContainer("BeInAGroup", 29 | o.HaveField("Groups", o.ContainElement(o.SatisfyAll(opts...)))) 30 | } 31 | -------------------------------------------------------------------------------- /test/matcher/be_in_a_group_example_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package matcher 16 | 17 | import ( 18 | . "github.com/onsi/gomega" 19 | "github.com/thediveo/lxkns/decorator/kuhbernetes" 20 | "github.com/thediveo/lxkns/model" 21 | ) 22 | 23 | func ExampleBeInAGroup() { 24 | var container = model.Container{ 25 | ID: "1234567890", 26 | Name: "foo_bar", 27 | Type: "ducker.io", 28 | Flavor: "fluffy", 29 | Groups: []*model.Group{ 30 | {Name: "fluffy", Type: "group.io", Flavor: "fluffy.io"}, 31 | }, 32 | } 33 | 34 | Expect(container).To(BeInAGroup(WithName("fluffy"))) 35 | Expect(container).NotTo(BeInAGroup(WithType(kuhbernetes.PodGroupType))) 36 | //Output: 37 | } 38 | -------------------------------------------------------------------------------- /test/matcher/be_in_a_pod.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package matcher 16 | 17 | import ( 18 | o "github.com/onsi/gomega" 19 | "github.com/onsi/gomega/types" 20 | ) 21 | 22 | // BeInAPod succeeds if actual is a model.Container or *model.Container and the 23 | // container is grouped by a Kubernetes/k8s pod for which all the option 24 | // matchers also succeed. 25 | // 26 | // Expect(c).To(BeInAPod(WithName("default/mypod"))) 27 | func BeInAPod(opts ...types.GomegaMatcher) types.GomegaMatcher { 28 | return withContainer("BeInAPod", 29 | o.HaveField("Groups", 30 | o.ContainElement(BeAPod(opts...)))) 31 | } 32 | -------------------------------------------------------------------------------- /test/matcher/be_paused.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package matcher 16 | 17 | import ( 18 | o "github.com/onsi/gomega" 19 | "github.com/onsi/gomega/types" 20 | ) 21 | 22 | // BePaused succeeds if actual is a model.Container or *model.Container and the 23 | // container is paused. 24 | // 25 | // Expect(c).To(BePaused()) 26 | func BePaused() types.GomegaMatcher { 27 | return withContainer("BePaused", o.HaveField("Paused", o.BeTrue())) 28 | } 29 | -------------------------------------------------------------------------------- /test/matcher/be_paused_example_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package matcher 16 | 17 | import ( 18 | . "github.com/onsi/gomega" 19 | "github.com/thediveo/lxkns/model" 20 | ) 21 | 22 | func ExampleBePaused() { 23 | var container = model.Container{ 24 | ID: "1234567890", 25 | Name: "foo_bar", 26 | Type: "ducker.io", 27 | Flavor: "fluffy", 28 | Groups: []*model.Group{ 29 | {Name: "fluffy", Type: "group.io", Flavor: "fluffy.io"}, 30 | }, 31 | Paused: true, 32 | } 33 | cp := container 34 | cp.Paused = false 35 | 36 | Expect(container).To(BePaused()) 37 | Expect(cp).NotTo(BePaused()) 38 | //Output: 39 | } 40 | -------------------------------------------------------------------------------- /test/matcher/be_paused_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package matcher 16 | 17 | import ( 18 | . "github.com/onsi/ginkgo/v2" 19 | . "github.com/onsi/gomega" 20 | "github.com/thediveo/lxkns/model" 21 | ) 22 | 23 | var _ = Describe("BePaused matcher", func() { 24 | 25 | var container = model.Container{ 26 | ID: "1234567890", 27 | Name: "foo_bar", 28 | Type: "ducker.io", 29 | Flavor: "fluffy", 30 | Groups: []*model.Group{ 31 | {Name: "fluffy", Type: "group.io", Flavor: "fluffy.io"}, 32 | }, 33 | Paused: true, 34 | } 35 | 36 | It("matches a paused container", func() { 37 | Expect(container).To(BePaused()) 38 | 39 | c := container 40 | c.Paused = false 41 | Expect(c).NotTo(BePaused()) 42 | }) 43 | 44 | }) 45 | -------------------------------------------------------------------------------- /test/matcher/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package matcher implements Gomega matchers for lxkns information model 3 | artifacts, such as containers and container groups (pods in particular). These 4 | matchers can be used in unit tests of applications using the lxkns API and 5 | information model. 6 | 7 | While these matchers almost always can be easily written using the existing 8 | Gomega matchers these new matchers offer to spell expectations out in a 9 | domain-specific language. 10 | 11 | For instance, instead of: 12 | 13 | Expect(actual).To(ContainElement(And(HaveField("Name", "foo"), HaveField("Type", "docker.com")))) 14 | 15 | more succinctly: 16 | 17 | Expect(actual).To(ContainElement(BeADockerContainer(WithName("foo")))) 18 | */ 19 | package matcher 20 | -------------------------------------------------------------------------------- /test/matcher/have_label_example_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package matcher 16 | 17 | import ( 18 | . "github.com/onsi/gomega" 19 | "github.com/thediveo/lxkns/model" 20 | ) 21 | 22 | func ExampleHaveLabel() { 23 | var container = model.Container{ 24 | ID: "1234567890", 25 | Name: "foo_bar", 26 | Type: "ducker.io", 27 | Flavor: "fluffy", 28 | Labels: model.Labels{ 29 | "foo": "FOO", 30 | }, 31 | } 32 | 33 | Expect(container).To(HaveLabel("foo")) // any value 34 | Expect(container).To(HaveLabel("foo", "FOO")) // specific value 35 | 36 | Expect(container).NotTo(HaveLabel("bar")) // not at all 37 | Expect(container).NotTo(HaveLabel("foo", "BAR")) // not this value 38 | //Output: 39 | } 40 | -------------------------------------------------------------------------------- /test/matcher/with_flavor.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package matcher 16 | 17 | import ( 18 | o "github.com/onsi/gomega" 19 | "github.com/onsi/gomega/types" 20 | ) 21 | 22 | // WithFlavor succeeds if actual has a Flavor field and the specified flavor 23 | // matches this field. 24 | func WithFlavor(flavor string) types.GomegaMatcher { 25 | return o.SatisfyAny(o.HaveField("Flavor", flavor)) 26 | } 27 | -------------------------------------------------------------------------------- /test/matcher/with_flavor_example_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package matcher 16 | 17 | import ( 18 | . "github.com/onsi/gomega" 19 | "github.com/thediveo/lxkns/model" 20 | "github.com/thediveo/whalewatcher/engineclient/moby" 21 | ) 22 | 23 | func ExampleWithFlavor() { 24 | var container = model.Container{ 25 | Type: moby.Type, 26 | Flavor: "moby", 27 | } 28 | 29 | Expect(container).To(WithFlavor("moby")) 30 | Expect(container).NotTo(WithFlavor(moby.Type)) 31 | //Output: 32 | } 33 | -------------------------------------------------------------------------------- /test/matcher/with_flavor_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package matcher 16 | 17 | import ( 18 | . "github.com/onsi/ginkgo/v2" 19 | . "github.com/onsi/gomega" 20 | "github.com/thediveo/lxkns/model" 21 | "github.com/thediveo/whalewatcher/engineclient/moby" 22 | ) 23 | 24 | var _ = Describe("WithFlavor matcher", func() { 25 | 26 | It("matches container by flavor only", func() { 27 | var container = model.Container{ 28 | Type: moby.Type, 29 | Flavor: "moby", 30 | } 31 | 32 | Expect(container).To(WithFlavor(container.Flavor)) 33 | Expect(container).NotTo(WithFlavor(container.Type)) 34 | }) 35 | 36 | }) 37 | -------------------------------------------------------------------------------- /test/matcher/with_name.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package matcher 16 | 17 | import ( 18 | o "github.com/onsi/gomega" 19 | "github.com/onsi/gomega/types" 20 | ) 21 | 22 | // WithName succeeds if actual has a Name field and optionally an ID field, and 23 | // the specified nameid matches at least one of these fields. 24 | func WithName(nameid string) types.GomegaMatcher { 25 | return o.SatisfyAny( 26 | o.HaveField("Name", nameid), 27 | o.And(o.HaveExistingField("ID"), o.HaveField("ID", nameid))) 28 | } 29 | -------------------------------------------------------------------------------- /test/matcher/with_name_example_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package matcher 16 | 17 | import ( 18 | . "github.com/onsi/gomega" 19 | "github.com/thediveo/lxkns/model" 20 | ) 21 | 22 | func ExampleWithName() { 23 | var container = model.Container{ 24 | ID: "1234abcde", 25 | Name: "morbid_moby", 26 | } 27 | 28 | Expect(container).To(WithName("1234abcde")) 29 | Expect(container).To(WithName("morbid_moby")) 30 | //Output: 31 | } 32 | -------------------------------------------------------------------------------- /test/matcher/with_strict_type.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package matcher 16 | 17 | import ( 18 | o "github.com/onsi/gomega" 19 | "github.com/onsi/gomega/types" 20 | ) 21 | 22 | // WithStrictType succeeds if actual has a Type field and the specified type 23 | // matches it. 24 | func WithStrictType(typ string) types.GomegaMatcher { 25 | return o.HaveField("Type", typ) 26 | } 27 | -------------------------------------------------------------------------------- /test/matcher/with_strict_type_example_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package matcher 16 | 17 | import ( 18 | . "github.com/onsi/gomega" 19 | "github.com/thediveo/lxkns/model" 20 | "github.com/thediveo/whalewatcher/engineclient/moby" 21 | ) 22 | 23 | func ExampleWithStrictType() { 24 | var container = model.Container{ 25 | Type: moby.Type, 26 | Flavor: "moby", 27 | } 28 | 29 | Expect(container).To(WithStrictType(container.Type)) 30 | Expect(container).NotTo(WithStrictType(container.Flavor)) 31 | //Output: 32 | } 33 | -------------------------------------------------------------------------------- /test/matcher/with_type.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package matcher 16 | 17 | import ( 18 | o "github.com/onsi/gomega" 19 | "github.com/onsi/gomega/types" 20 | ) 21 | 22 | // WithType succeeds if actual has a Type field and optionally a Flavor field, 23 | // and the specified typeflavor matches at least one of these fields. If you 24 | // want to check only for the specific Type but not accept it as a Flavor, then 25 | // use the WithStrictType matcher instead. 26 | func WithType(typeflavor string) types.GomegaMatcher { 27 | return o.SatisfyAny( 28 | o.HaveField("Type", typeflavor), 29 | o.And(o.HaveExistingField("Flavor"), o.HaveField("Flavor", typeflavor))) 30 | } 31 | -------------------------------------------------------------------------------- /test/matcher/with_type_example_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package matcher 16 | 17 | import ( 18 | . "github.com/onsi/gomega" 19 | "github.com/thediveo/lxkns/model" 20 | "github.com/thediveo/whalewatcher/engineclient/moby" 21 | ) 22 | 23 | func ExampleWithType() { 24 | var container = model.Container{ 25 | Type: moby.Type, 26 | Flavor: "moby", 27 | } 28 | 29 | Expect(container).To(WithType(container.Type)) 30 | Expect(container).To(WithType(container.Flavor)) 31 | //Output: 32 | } 33 | -------------------------------------------------------------------------------- /test/success/success.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package helpers 16 | 17 | import ( 18 | . "github.com/onsi/gomega" 19 | ) 20 | 21 | // Successful takes a return value together with an additional error return 22 | // value, returning only the value and at the same time asserting that there 23 | // error return value is nil. 24 | func Successful[V any](v V, err error) V { 25 | Expect(err).WithOffset(1).NotTo(HaveOccurred()) 26 | return v 27 | } 28 | -------------------------------------------------------------------------------- /web/lxkns/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | build/ 3 | styleguidist/ 4 | -------------------------------------------------------------------------------- /web/lxkns/.env: -------------------------------------------------------------------------------- 1 | VITE_REACT_APP_GIT_VERSION=0.0.0 2 | -------------------------------------------------------------------------------- /web/lxkns/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "env": { 3 | "browser": true, 4 | "es2021": true 5 | }, 6 | "extends": [ 7 | "eslint:recommended", 8 | "plugin:@typescript-eslint/eslint-recommended", 9 | "plugin:@typescript-eslint/recommended", 10 | "plugin:react/recommended", 11 | ], 12 | "settings": { 13 | "react": { 14 | "version": "detect", 15 | }, 16 | }, 17 | "overrides": [ 18 | { 19 | "env": { 20 | "node": true 21 | }, 22 | "files": [ 23 | ".eslintrc.{js,cjs}" 24 | ], 25 | "parserOptions": { 26 | "sourceType": "script" 27 | } 28 | } 29 | ], 30 | "parser": "@typescript-eslint/parser", 31 | "parserOptions": { 32 | "ecmaVersion": "latest", 33 | "sourceType": "module" 34 | }, 35 | "plugins": [ 36 | "@typescript-eslint", 37 | "react" 38 | ], 39 | "rules": { 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /web/lxkns/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | 25 | .nyc_output/ 26 | -------------------------------------------------------------------------------- /web/lxkns/.markdownlint.json: -------------------------------------------------------------------------------- 1 | { 2 | "MD013": false, 3 | "MD026": false, 4 | "MD036": false, 5 | "MD041": false 6 | } -------------------------------------------------------------------------------- /web/lxkns/.storybook/main.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | import type { StorybookConfig } from '@storybook/react-vite' 16 | 17 | const config: StorybookConfig = { 18 | framework: { 19 | name: '@storybook/react-vite', 20 | options: {}, 21 | }, 22 | stories: [ 23 | '../src/**/*.stories.@(js|jsx|ts|tsx)', 24 | '../src/**/*.sb.mdx', 25 | ], 26 | addons: [ 27 | '@storybook/addon-links', 28 | '@storybook/addon-essentials', 29 | '@storybook/addon-interactions', 30 | ], 31 | docs: { 32 | autodocs: 'tag', 33 | }, 34 | core: { 35 | disableTelemetry: true, 36 | disableWhatsNewNotifications: true, 37 | }, 38 | } 39 | 40 | export default config 41 | -------------------------------------------------------------------------------- /web/lxkns/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "arcanis.vscode-zipfs", 4 | "dbaeumer.vscode-eslint" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /web/lxkns/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "search.exclude": { 3 | "**/.yarn": true, 4 | "**/.pnp.*": true 5 | }, 6 | "eslint.nodePath": ".yarn/sdks", 7 | "typescript.tsdk": ".yarn/sdks/typescript/lib", 8 | "typescript.enablePromptUseWorkspaceTsdk": true 9 | } 10 | -------------------------------------------------------------------------------- /web/lxkns/.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules 2 | -------------------------------------------------------------------------------- /web/lxkns/eslint.config.js: -------------------------------------------------------------------------------- 1 | import globals from "globals"; 2 | import tseslint from "typescript-eslint"; 3 | import pluginReactConfig from "eslint-plugin-react/configs/recommended.js"; 4 | 5 | 6 | export default [ 7 | {files: ["**/*.{js,mjs,cjs,ts,jsx,tsx}"]}, 8 | { languageOptions: { parserOptions: { ecmaFeatures: { jsx: true } } } }, 9 | {languageOptions: { globals: globals.browser }}, 10 | ...tseslint.configs.recommended, 11 | pluginReactConfig, 12 | ]; -------------------------------------------------------------------------------- /web/lxkns/icons/Owner.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web/lxkns/icons/namespaces/IPC.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /web/lxkns/icons/namespaces/Network.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /web/lxkns/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | lxkns Namespaces 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /web/lxkns/mock/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: mockdata 2 | 3 | mockdata: 4 | npx ts-node -O '{"module": "commonjs"}' getmockdata.ts "/tmp/$$$$-mockdata.json" && mv -f "/tmp/$$$$-mockdata.json" ../src/models/lxkns/mock/mockdata.json 5 | echo "done moving to src/models/lxkns/mock/mockdata.json" 6 | -------------------------------------------------------------------------------- /web/lxkns/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/web/lxkns/public/favicon.ico -------------------------------------------------------------------------------- /web/lxkns/public/lxkns192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/web/lxkns/public/lxkns192.png -------------------------------------------------------------------------------- /web/lxkns/public/lxkns512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/web/lxkns/public/lxkns512.png -------------------------------------------------------------------------------- /web/lxkns/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "lxkns", 3 | "name": "Linux Namespaces", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "lxkns192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "lxkns512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /web/lxkns/src/app/README.md: -------------------------------------------------------------------------------- 1 | # The `app/` Folder 2 | 3 | This `app/` folder finally defines the Lxkns App (in form of the `App` 4 | component), by stitching together the main elements of the application. Namely, 5 | the ... 6 | 7 | - application bar with app title, drawer menu button, and a few action buttons, 8 | - swipeable drawer for navigation, 9 | - routing for selecting the correct view components based on the current route. 10 | For details on the views, please refer to the `views/` folder. 11 | 12 | Additionally, the App also provides the infrastructure in form of... 13 | 14 | - snack bar for showing (error) toasts, such as when the discovery service 15 | fails. 16 | - `Discovery` component for fetching and providing the latest and greatest lxkns 17 | discovery results. 18 | - [jotai](https://github.com/pmndrs/jotai) state provider for distributing 19 | application state to all the different places in the application. 20 | 21 | That's it. 22 | -------------------------------------------------------------------------------- /web/lxkns/src/app/index.tsx: -------------------------------------------------------------------------------- 1 | export { default } from './App' 2 | -------------------------------------------------------------------------------- /web/lxkns/src/components/appbardrawer/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './AppBarDrawer' 2 | export { DrawerLinkItem } from './DrawerLinkItem' 3 | -------------------------------------------------------------------------------- /web/lxkns/src/components/cgroupinfo/index.ts: -------------------------------------------------------------------------------- 1 | export * from './CgroupInfo' 2 | export { default } from './CgroupInfo' 3 | -------------------------------------------------------------------------------- /web/lxkns/src/components/chapterskeleton/ChapterSkeleton.stories.tsx: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | import type { Meta, StoryObj } from '@storybook/react' 16 | 17 | import { ChapterSkeleton } from './ChapterSkeleton' 18 | 19 | const meta: Meta = { 20 | title: 'Universal/ChapterSkeleton', 21 | component: ChapterSkeleton, 22 | tags: ['autodocs'], 23 | } 24 | 25 | export default meta 26 | 27 | type Story = StoryObj 28 | 29 | export const Basic: Story = { 30 | args: { 31 | sx: { width: "20rem" }, 32 | }, 33 | } 34 | -------------------------------------------------------------------------------- /web/lxkns/src/components/chapterskeleton/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ChapterSkeleton' 2 | -------------------------------------------------------------------------------- /web/lxkns/src/components/containerinfo/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ContainerInfo' 2 | export { default } from './ContainerInfo' 3 | -------------------------------------------------------------------------------- /web/lxkns/src/components/containertree/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './ContainerTree' 2 | export { default } from './ContainerTree' 3 | -------------------------------------------------------------------------------- /web/lxkns/src/components/containertypeicon/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ContainerTypeIcon' 2 | export { default } from './ContainerTypeIcon' 3 | -------------------------------------------------------------------------------- /web/lxkns/src/components/cpulist/index.ts: -------------------------------------------------------------------------------- 1 | export * from './CPUList' 2 | export { default } from './CPUList' 3 | -------------------------------------------------------------------------------- /web/lxkns/src/components/discovery/index.ts: -------------------------------------------------------------------------------- 1 | export { 2 | default, 3 | useDiscovery, 4 | discoveryRefreshIntervalAtom, 5 | discoveryRefreshingAtom 6 | } from './Discovery' 7 | -------------------------------------------------------------------------------- /web/lxkns/src/components/engineinfo/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './EngineInfo' 2 | export { default } from './EngineInfo' 3 | -------------------------------------------------------------------------------- /web/lxkns/src/components/extlink/ExtLink.md: -------------------------------------------------------------------------------- 1 | ```tsx 2 | import { Typography } from "@mui/material"; 3 | 4 | 5 | Here is some text linking to the 6 | end of the Internet. I see 7 | ... elephants ... and a turtle... 8 | ; 9 | ``` 10 | -------------------------------------------------------------------------------- /web/lxkns/src/components/extlink/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ExtLink' 2 | -------------------------------------------------------------------------------- /web/lxkns/src/components/groupedpropagationmembers/index.ts: -------------------------------------------------------------------------------- 1 | export * from './GroupedPropagationMembers' 2 | -------------------------------------------------------------------------------- /web/lxkns/src/components/helpviewer/01-intro.mdx: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | Use the ToC sticky button to switch to another chapter. 4 | -------------------------------------------------------------------------------- /web/lxkns/src/components/helpviewer/03-newchapter.mdx: -------------------------------------------------------------------------------- 1 | # A New chapter 2 | 3 | I wish I would know more. 4 | -------------------------------------------------------------------------------- /web/lxkns/src/components/helpviewer/HelpViewer.xx.mdx.xx: -------------------------------------------------------------------------------- 1 | import { MemoryRouter } from "react-router"; 2 | import { MuiMarkdown } from "components/muimarkdown"; 3 | 4 | const MyMarkdowner = (props) => (); 5 | 6 | import chintro from "./01-intro.mdx"; 7 | import chfoobar from "./02-foobar.mdx"; 8 | import chnew from "./03-newchapter.mdx"; 9 | 10 | const chapters = [ 11 | { title: "Intro", chapter: chintro }, 12 | { title: "Foo Bar", chapter: chfoobar }, 13 | { title: "A New Chapter", chapter: chnew }, 14 | ]; 15 | 16 | 17 | 23 | 24 | -------------------------------------------------------------------------------- /web/lxkns/src/components/helpviewer/index.ts: -------------------------------------------------------------------------------- 1 | export * from './HelpViewer' 2 | -------------------------------------------------------------------------------- /web/lxkns/src/components/mountpointinfo/MountpointInfo.md: -------------------------------------------------------------------------------- 1 | ```tsx 2 | import { ComponentCard } from "styleguidist/ComponentCard"; 3 | import { MountpointInfo } from "components/mountpointinfo"; 4 | import { mountpoint } from "components/mountpointinfo/fakedata"; 5 | const hiddenmountpoint = { 6 | ...mountpoint, 7 | hidden: true, 8 | }; 9 | 10 | <> 11 | 12 | 13 | 14 | 15 | 16 | 17 | ; 18 | ``` 19 | -------------------------------------------------------------------------------- /web/lxkns/src/components/mountpointinfo/fakedata.ts: -------------------------------------------------------------------------------- 1 | import { Namespace } from 'models/lxkns' 2 | import { MountPoint } from 'models/lxkns/mount' 3 | 4 | export const mountpoint: MountPoint = { 5 | fstype: 'ext2000', 6 | hidden: false, 7 | major: 42, 8 | minor: 123, 9 | mountid: 2, 10 | mountoptions: ['foo', 'bar', 'gnampf=uhoh'], 11 | mountpoint: '/media/fake', 12 | parentid: 0, 13 | root: '/', 14 | source: 'none', 15 | superoptions: 'super,options', 16 | tags: {'shared': '123', 'master': '42'}, 17 | children: [], 18 | mountnamespace: { 19 | nsid: 12345678, 20 | "user-id": 12345, 21 | "user-name": "foo1", 22 | 23 | } as Namespace, 24 | } 25 | -------------------------------------------------------------------------------- /web/lxkns/src/components/mountpointinfo/index.ts: -------------------------------------------------------------------------------- 1 | export * from './MountpointInfo' 2 | -------------------------------------------------------------------------------- /web/lxkns/src/components/mountpointinfomodal/MountpointInfoModal.md: -------------------------------------------------------------------------------- 1 | Click on the button to show a modal information dialog with mount point details. 2 | 3 | ```tsx 4 | import { ComponentCard } from "styleguidist/ComponentCard"; 5 | import { Button, Tooltip } from "@mui/material"; 6 | import { 7 | MountpointInfoModalProvider, 8 | useMountpointInfoModal, 9 | } from "components/mountpointinfomodal"; 10 | import { mountpoint } from "components/mountpointinfo/fakedata"; 11 | 12 | const Component = () => { 13 | const setMountpoint = useMountpointInfoModal(); 14 | 15 | return ( 16 | 17 | <>🖝🖜 24 | 25 | ); 26 | }; 27 | 28 | 29 | 30 | ; 31 | ``` 32 | -------------------------------------------------------------------------------- /web/lxkns/src/components/mountpointinfomodal/index.ts: -------------------------------------------------------------------------------- 1 | export * from './MountpointInfoModal' 2 | -------------------------------------------------------------------------------- /web/lxkns/src/components/mountpointpath/MountpointPath.md: -------------------------------------------------------------------------------- 1 | ```tsx 2 | import { ComponentCard } from "styleguidist/ComponentCard"; 3 | import { MountpointPath } from "components/mountpointpath"; 4 | import { mountpoint } from "components/mountpointinfo/fakedata"; 5 | const hiddenmountpoint = { 6 | ...mountpoint, 7 | hidden: true, 8 | }; 9 | 10 | <> 11 |

visible mount point

12 | 13 | 14 | 15 | 16 |

visible mount point, drum="always"

17 | 18 | 19 | 20 | 21 |

hidden mount point

22 | 23 | 24 | 25 | 26 |

hidden mount point, drum="never"

27 | 28 | 29 | 30 | ; 31 | ``` 32 | -------------------------------------------------------------------------------- /web/lxkns/src/components/mountpointpath/index.ts: -------------------------------------------------------------------------------- 1 | export * from './MountpointPath' 2 | -------------------------------------------------------------------------------- /web/lxkns/src/components/mountpointroot/index.ts: -------------------------------------------------------------------------------- 1 | export * from './MountpointRoot' 2 | -------------------------------------------------------------------------------- /web/lxkns/src/components/mounttree/index.ts: -------------------------------------------------------------------------------- 1 | export * from './MountTree' 2 | -------------------------------------------------------------------------------- /web/lxkns/src/components/muimarkdown/example/example.mdx: -------------------------------------------------------------------------------- 1 | # Example Markdown 2 | 3 | This is an example markdown file which gets compiled into MDX. 4 | 5 | - proper ellipsis... 6 | 7 | - correct "typographic quotes" and possessive's (ouch, for demonstration 8 | purposes only :facepalm:). 9 | 10 | - range endashes 0-1. 11 | 12 | - emdashes -- but sadly not endashes. 13 | 14 | ## Header Level 2 15 | 16 | ### Header Level 3 17 | 18 | Some text. 19 | 20 | ### Another Header Level 3 21 | 22 | With some other text. 23 | 24 | #### Header 4 25 | 26 | #### Header 5 27 | 28 | Who writes such documents? 29 | 30 | ## Tables 31 | 32 | Tables always need headers, as otherwise the parser won't detect them. 33 | :frowning: 34 | 35 | | Header 1 | Header 2 | 36 | | --- | --- | 37 | | cell 1 | cell 2 -- get me out of here! | 38 | | cell x | cell y | 39 | -------------------------------------------------------------------------------- /web/lxkns/src/components/muimarkdown/example/minexample.mdx: -------------------------------------------------------------------------------- 1 | # Minimal Example 2 | 3 | Not much to see here, except for some [external 4 | link](https://endoftheinter.net/) and some other [non-existing external 5 | link](http://foobar.example.org). 6 | -------------------------------------------------------------------------------- /web/lxkns/src/components/muimarkdown/index.ts: -------------------------------------------------------------------------------- 1 | export * from './MuiMarkdown' 2 | -------------------------------------------------------------------------------- /web/lxkns/src/components/namespacebadge/index.ts: -------------------------------------------------------------------------------- 1 | export * from './NamespaceBadge' 2 | -------------------------------------------------------------------------------- /web/lxkns/src/components/namespaceicon/index.ts: -------------------------------------------------------------------------------- 1 | export * from './NamespaceIcon' 2 | export * from './iconmap' 3 | -------------------------------------------------------------------------------- /web/lxkns/src/components/namespaceinfo/index.ts: -------------------------------------------------------------------------------- 1 | export * from './NamespaceInfo' 2 | -------------------------------------------------------------------------------- /web/lxkns/src/components/namespaceprocesstree/index.ts: -------------------------------------------------------------------------------- 1 | export * from './NamespaceProcessTree' 2 | -------------------------------------------------------------------------------- /web/lxkns/src/components/namespaceref/index.ts: -------------------------------------------------------------------------------- 1 | export * from './NamespaceRef' 2 | -------------------------------------------------------------------------------- /web/lxkns/src/components/processinfo/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ProcessInfo' 2 | export { default } from './ProcessInfo' 3 | -------------------------------------------------------------------------------- /web/lxkns/src/components/refresher/Refresher.md: -------------------------------------------------------------------------------- 1 | ```tsx 2 | import { ComponentCard } from "styleguidist/ComponentCard"; 3 | import { Provider, useAtom } from "jotai"; 4 | import { discoveryRefreshIntervalAtom } from "components/discovery"; 5 | 6 | const intervals = [ 7 | { interval: null }, 8 | { interval: 666, label: "bad timing" }, 9 | { interval: 1000 }, 10 | ]; 11 | 12 | const Interval = () => { 13 | const [refreshInterval] = useAtom(discoveryRefreshIntervalAtom); 14 | return

INTERVAL: {refreshInterval} (ms)

; 15 | }; 16 | 17 | 18 | 19 | 20 | 21 | 22 | ; 23 | ``` 24 | -------------------------------------------------------------------------------- /web/lxkns/src/components/refresher/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Refresher' 2 | export { default } from './Refresher' 3 | -------------------------------------------------------------------------------- /web/lxkns/src/components/schedinfo/index.ts: -------------------------------------------------------------------------------- 1 | export * from './SchedulerInfo' 2 | export { default } from './SchedulerInfo' 3 | -------------------------------------------------------------------------------- /web/lxkns/src/components/smarta/SmartA.stories.tsx: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | import type { Meta, StoryObj } from '@storybook/react' 16 | 17 | import { SmartA } from './SmartA' 18 | 19 | const meta: Meta = { 20 | title: 'Universal/SmartA', 21 | component: SmartA, 22 | tags: ['autodocs'], 23 | } 24 | 25 | export default meta 26 | 27 | type Story = StoryObj 28 | 29 | export const External: Story = { 30 | args: { 31 | href: 'https://github.com/thediveo/lxkns', 32 | children: '@thediveo/lxkns', 33 | }, 34 | } 35 | 36 | export const Internal: Story = { 37 | args: { 38 | href: '/internal', 39 | children: 'an app-internal route', 40 | }, 41 | } -------------------------------------------------------------------------------- /web/lxkns/src/components/smarta/index.ts: -------------------------------------------------------------------------------- 1 | export * from './SmartA' 2 | -------------------------------------------------------------------------------- /web/lxkns/src/components/taskinfo/index.ts: -------------------------------------------------------------------------------- 1 | export * from './TaskInfo' 2 | export { default } from './TaskInfo' 3 | -------------------------------------------------------------------------------- /web/lxkns/src/components/usernamespacetree/UserNamespaceTree.md: -------------------------------------------------------------------------------- 1 | Renders the tree of hierarchical user namespaces, and additionally also render 2 | the attached processes with the non-user namespaces these processes are attached 3 | to (in addition to the user namespaces). Oh, the fun of Linux-kernel namespaces. 4 | 5 | ```tsx 6 | import { UserNamespaceTree } from "components/usernamespacetree"; 7 | import { discovery } from "views/help/fakehelpdata"; 8 | import { Provider, useAtom } from "jotai"; 9 | 10 | 11 | 12 | ; 13 | ``` 14 | -------------------------------------------------------------------------------- /web/lxkns/src/components/usernamespacetree/index.ts: -------------------------------------------------------------------------------- 1 | export * from './UserNamespaceTree' 2 | -------------------------------------------------------------------------------- /web/lxkns/src/components/usernamespacetreeitem/UserNamespaceTreeItem.md: -------------------------------------------------------------------------------- 1 | Renders an user namespace item as part of a user namespace tree. Beside the user 2 | namespace ID this includes further tidbits of information, such as: 3 | 4 | - number of child and grandchild user namespaces, 5 | - ealdorman process name and PID, or alternatively container name (and maybe 6 | project), 7 | - owning (=creating) user ID and user name. 8 | 9 | ```tsx 10 | import { UserNamespaceTreeItem } from "components/usernamespacetreeitem"; 11 | import { discovery } from "views/help/fakehelpdata"; 12 | import { Provider, useAtom } from "jotai"; 13 | 14 | const userns = Object.values(discovery.namespaces) 15 | .find(ns => ns.type == "user" && ns.initial); 16 | 17 | 18 | 19 | ; 20 | ``` 21 | -------------------------------------------------------------------------------- /web/lxkns/src/components/usernamespacetreeitem/index.ts: -------------------------------------------------------------------------------- 1 | export * from './UserNamespaceTreeItem' 2 | -------------------------------------------------------------------------------- /web/lxkns/src/hooks/id/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "id.js" 3 | } -------------------------------------------------------------------------------- /web/lxkns/src/hooks/interval/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "interval.js" 3 | } -------------------------------------------------------------------------------- /web/lxkns/src/icons/Angryghost.tsx: -------------------------------------------------------------------------------- 1 | // autogenerated from icon svg file "icons/Angryghost.svg", do not edit; 2 | import * as React from 'react'; 3 | import { SvgIcon, SvgIconProps } from '@mui/material'; 4 | export const AngryghostIcon = (props: SvgIconProps) => ; 5 | export default AngryghostIcon; -------------------------------------------------------------------------------- /web/lxkns/src/icons/Children.tsx: -------------------------------------------------------------------------------- 1 | // autogenerated from icon svg file "icons/Children.svg", do not edit; 2 | import * as React from 'react'; 3 | import { SvgIcon, SvgIconProps } from '@mui/material'; 4 | export const ChildrenIcon = (props: SvgIconProps) => ; 5 | export default ChildrenIcon; -------------------------------------------------------------------------------- /web/lxkns/src/icons/Ghost.tsx: -------------------------------------------------------------------------------- 1 | // autogenerated from icon svg file "icons/Ghost.svg", do not edit; 2 | import * as React from 'react'; 3 | import { SvgIcon, SvgIconProps } from '@mui/material'; 4 | export const GhostIcon = (props: SvgIconProps) => ; 5 | export default GhostIcon; -------------------------------------------------------------------------------- /web/lxkns/src/icons/Hiddenmount.tsx: -------------------------------------------------------------------------------- 1 | // autogenerated from icon svg file "icons/Hiddenmount.svg", do not edit; 2 | import * as React from 'react'; 3 | import { SvgIcon, SvgIconProps } from '@mui/material'; 4 | export const HiddenmountIcon = (props: SvgIconProps) => ; 5 | export default HiddenmountIcon; -------------------------------------------------------------------------------- /web/lxkns/src/icons/Init1.tsx: -------------------------------------------------------------------------------- 1 | // autogenerated from icon svg file "icons/Init1.svg", do not edit; 2 | import * as React from 'react'; 3 | import { SvgIcon, SvgIconProps } from '@mui/material'; 4 | export const Init1Icon = (props: SvgIconProps) => ; 5 | export default Init1Icon; -------------------------------------------------------------------------------- /web/lxkns/src/icons/Namespace.tsx: -------------------------------------------------------------------------------- 1 | // autogenerated from icon svg file "icons/Namespace.svg", do not edit; 2 | import * as React from 'react'; 3 | import { SvgIcon, SvgIconProps } from '@mui/material'; 4 | export const NamespaceIcon = (props: SvgIconProps) => ; 5 | export default NamespaceIcon; -------------------------------------------------------------------------------- /web/lxkns/src/icons/Owner.tsx: -------------------------------------------------------------------------------- 1 | // autogenerated from icon svg file "icons/Owner.svg", do not edit; 2 | import * as React from 'react'; 3 | import { SvgIcon, SvgIconProps } from '@mui/material'; 4 | export const OwnerIcon = (props: SvgIconProps) => ; 5 | export default OwnerIcon; -------------------------------------------------------------------------------- /web/lxkns/src/icons/Process.tsx: -------------------------------------------------------------------------------- 1 | // autogenerated from icon svg file "icons/Process.svg", do not edit; 2 | import * as React from 'react'; 3 | import { SvgIcon, SvgIconProps } from '@mui/material'; 4 | export const ProcessIcon = (props: SvgIconProps) => ; 5 | export default ProcessIcon; -------------------------------------------------------------------------------- /web/lxkns/src/icons/Readonly.tsx: -------------------------------------------------------------------------------- 1 | // autogenerated from icon svg file "icons/Readonly.svg", do not edit; 2 | import * as React from 'react'; 3 | import { SvgIcon, SvgIconProps } from '@mui/material'; 4 | export const ReadonlyIcon = (props: SvgIconProps) => ; 5 | export default ReadonlyIcon; -------------------------------------------------------------------------------- /web/lxkns/src/icons/Root.tsx: -------------------------------------------------------------------------------- 1 | // autogenerated from icon svg file "icons/Root.svg", do not edit; 2 | import * as React from 'react'; 3 | import { SvgIcon, SvgIconProps } from '@mui/material'; 4 | export const RootIcon = (props: SvgIconProps) => ; 5 | export default RootIcon; -------------------------------------------------------------------------------- /web/lxkns/src/icons/Thread.tsx: -------------------------------------------------------------------------------- 1 | // autogenerated from icon svg file "icons/Thread.svg", do not edit; 2 | import * as React from 'react'; 3 | import { SvgIcon, SvgIconProps } from '@mui/material'; 4 | export const ThreadIcon = (props: SvgIconProps) => ; 5 | export default ThreadIcon; -------------------------------------------------------------------------------- /web/lxkns/src/icons/containers/Container.tsx: -------------------------------------------------------------------------------- 1 | // autogenerated from icon svg file "icons/containers/Container.svg", do not edit; 2 | import * as React from 'react'; 3 | import { SvgIcon, SvgIconProps } from '@mui/material'; 4 | export const ContainerIcon = (props: SvgIconProps) => ; 5 | export default ContainerIcon; -------------------------------------------------------------------------------- /web/lxkns/src/icons/containers/Containerd.tsx: -------------------------------------------------------------------------------- 1 | // autogenerated from icon svg file "icons/containers/Containerd.svg", do not edit; 2 | import * as React from 'react'; 3 | import { SvgIcon, SvgIconProps } from '@mui/material'; 4 | export const ContainerdIcon = (props: SvgIconProps) => ; 5 | export default ContainerdIcon; -------------------------------------------------------------------------------- /web/lxkns/src/icons/containers/Docker.tsx: -------------------------------------------------------------------------------- 1 | // autogenerated from icon svg file "icons/containers/Docker.svg", do not edit; 2 | import * as React from 'react'; 3 | import { SvgIcon, SvgIconProps } from '@mui/material'; 4 | export const DockerIcon = (props: SvgIconProps) => ; 5 | export default DockerIcon; -------------------------------------------------------------------------------- /web/lxkns/src/icons/containers/IEApp.tsx: -------------------------------------------------------------------------------- 1 | // autogenerated from icon svg file "icons/containers/IEApp.svg", do not edit; 2 | import * as React from 'react'; 3 | import { SvgIcon, SvgIconProps } from '@mui/material'; 4 | export const IEAppIcon = (props: SvgIconProps) => ; 5 | export default IEAppIcon; -------------------------------------------------------------------------------- /web/lxkns/src/icons/containers/IERuntime.tsx: -------------------------------------------------------------------------------- 1 | // autogenerated from icon svg file "icons/containers/IERuntime.svg", do not edit; 2 | import * as React from 'react'; 3 | import { SvgIcon, SvgIconProps } from '@mui/material'; 4 | export const IERuntimeIcon = (props: SvgIconProps) => ; 5 | export default IERuntimeIcon; -------------------------------------------------------------------------------- /web/lxkns/src/icons/containers/K8sPod.tsx: -------------------------------------------------------------------------------- 1 | // autogenerated from icon svg file "icons/containers/K8sPod.svg", do not edit; 2 | import * as React from 'react'; 3 | import { SvgIcon, SvgIconProps } from '@mui/material'; 4 | export const K8sPodIcon = (props: SvgIconProps) => ; 5 | export default K8sPodIcon; -------------------------------------------------------------------------------- /web/lxkns/src/icons/containers/Kind.tsx: -------------------------------------------------------------------------------- 1 | // autogenerated from icon svg file "icons/containers/Kind.svg", do not edit; 2 | import * as React from 'react'; 3 | import { SvgIcon, SvgIconProps } from '@mui/material'; 4 | export const KindIcon = (props: SvgIconProps) => ; 5 | export default KindIcon; -------------------------------------------------------------------------------- /web/lxkns/src/icons/containers/Pod.tsx: -------------------------------------------------------------------------------- 1 | // autogenerated from icon svg file "icons/containers/Pod.svg", do not edit; 2 | import * as React from 'react'; 3 | import { SvgIcon, SvgIconProps } from '@mui/material'; 4 | export const PodIcon = (props: SvgIconProps) => ; 5 | export default PodIcon; -------------------------------------------------------------------------------- /web/lxkns/src/icons/containers/Podman.tsx: -------------------------------------------------------------------------------- 1 | // autogenerated from icon svg file "icons/containers/Podman.svg", do not edit; 2 | import * as React from 'react'; 3 | import { SvgIcon, SvgIconProps } from '@mui/material'; 4 | export const PodmanIcon = (props: SvgIconProps) => ; 5 | export default PodmanIcon; -------------------------------------------------------------------------------- /web/lxkns/src/icons/namespaces/Cgroup.tsx: -------------------------------------------------------------------------------- 1 | // autogenerated from icon svg file "icons/namespaces/Cgroup.svg", do not edit; 2 | import * as React from 'react'; 3 | import { SvgIcon, SvgIconProps } from '@mui/material'; 4 | export const CgroupIcon = (props: SvgIconProps) => ; 5 | export default CgroupIcon; -------------------------------------------------------------------------------- /web/lxkns/src/icons/namespaces/IPC.tsx: -------------------------------------------------------------------------------- 1 | // autogenerated from icon svg file "icons/namespaces/IPC.svg", do not edit; 2 | import * as React from 'react'; 3 | import { SvgIcon, SvgIconProps } from '@mui/material'; 4 | export const IPCIcon = (props: SvgIconProps) => ; 5 | export default IPCIcon; -------------------------------------------------------------------------------- /web/lxkns/src/icons/namespaces/Mount.tsx: -------------------------------------------------------------------------------- 1 | // autogenerated from icon svg file "icons/namespaces/Mount.svg", do not edit; 2 | import * as React from 'react'; 3 | import { SvgIcon, SvgIconProps } from '@mui/material'; 4 | export const MountIcon = (props: SvgIconProps) => ; 5 | export default MountIcon; -------------------------------------------------------------------------------- /web/lxkns/src/icons/namespaces/Network.tsx: -------------------------------------------------------------------------------- 1 | // autogenerated from icon svg file "icons/namespaces/Network.svg", do not edit; 2 | import * as React from 'react'; 3 | import { SvgIcon, SvgIconProps } from '@mui/material'; 4 | export const NetworkIcon = (props: SvgIconProps) => ; 5 | export default NetworkIcon; -------------------------------------------------------------------------------- /web/lxkns/src/icons/namespaces/PID.tsx: -------------------------------------------------------------------------------- 1 | // autogenerated from icon svg file "icons/namespaces/PID.svg", do not edit; 2 | import * as React from 'react'; 3 | import { SvgIcon, SvgIconProps } from '@mui/material'; 4 | export const PIDIcon = (props: SvgIconProps) => ; 5 | export default PIDIcon; -------------------------------------------------------------------------------- /web/lxkns/src/icons/namespaces/UTS.tsx: -------------------------------------------------------------------------------- 1 | // autogenerated from icon svg file "icons/namespaces/UTS.svg", do not edit; 2 | import * as React from 'react'; 3 | import { SvgIcon, SvgIconProps } from '@mui/material'; 4 | export const UTSIcon = (props: SvgIconProps) => ; 5 | export default UTSIcon; -------------------------------------------------------------------------------- /web/lxkns/src/icons/propagation/Peer.tsx: -------------------------------------------------------------------------------- 1 | // autogenerated from icon svg file "icons/propagation/Peer.svg", do not edit; 2 | import * as React from 'react'; 3 | import { SvgIcon, SvgIconProps } from '@mui/material'; 4 | export const PeerIcon = (props: SvgIconProps) => ; 5 | export default PeerIcon; -------------------------------------------------------------------------------- /web/lxkns/src/icons/propagation/Slave.tsx: -------------------------------------------------------------------------------- 1 | // autogenerated from icon svg file "icons/propagation/Slave.svg", do not edit; 2 | import * as React from 'react'; 3 | import { SvgIcon, SvgIconProps } from '@mui/material'; 4 | export const SlaveIcon = (props: SvgIconProps) => ; 5 | export default SlaveIcon; -------------------------------------------------------------------------------- /web/lxkns/src/icons/propagation/Unbindable.tsx: -------------------------------------------------------------------------------- 1 | // autogenerated from icon svg file "icons/propagation/Unbindable.svg", do not edit; 2 | import * as React from 'react'; 3 | import { SvgIcon, SvgIconProps } from '@mui/material'; 4 | export const UnbindableIcon = (props: SvgIconProps) => ; 5 | export default UnbindableIcon; -------------------------------------------------------------------------------- /web/lxkns/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /web/lxkns/src/mdx.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.mdx' { 2 | let MDXComponent: (props: Record) => JSX.Element 3 | export default MDXComponent 4 | } 5 | -------------------------------------------------------------------------------- /web/lxkns/src/models/lxkns/index.ts: -------------------------------------------------------------------------------- 1 | export * from './model.ts' 2 | export * from './fromjson.ts' 3 | export * from './sortfns.ts' 4 | export * from './container.ts' 5 | -------------------------------------------------------------------------------- /web/lxkns/src/models/lxkns/mock/index.ts: -------------------------------------------------------------------------------- 1 | export * from './mockdata' 2 | -------------------------------------------------------------------------------- /web/lxkns/src/models/lxkns/mock/mockdata.ts: -------------------------------------------------------------------------------- 1 | import data from './mockdata.json' 2 | import { fromjson } from '../fromjson' 3 | 4 | export const discovery = fromjson(data) 5 | 6 | export const initProc = discovery.processes['1'] 7 | 8 | export const fakeBindmountedIpc = { 9 | nsid: initProc.namespaces.ipc.nsid, 10 | type: initProc.namespaces.ipc.type, 11 | owner: initProc.namespaces.ipc.owner, 12 | reference: ['/proc/1/ns/mnt', '/run/snapd/ns/foobar.ipc'], 13 | } 14 | 15 | export const fakeBindmountedIpcElsewhere = { 16 | nsid: initProc.namespaces.ipc.nsid, 17 | type: initProc.namespaces.ipc.type, 18 | owner: initProc.namespaces.ipc.owner, 19 | reference: ['/proc/1234/ns/mnt', '/run/snapd/ns/foobar.ipc'], 20 | } 21 | 22 | export const fakeFdIpc = { 23 | nsid: initProc.namespaces.ipc.nsid, 24 | type: initProc.namespaces.ipc.type, 25 | owner: initProc.namespaces.ipc.owner, 26 | reference: ['/proc/666/fd/666'], 27 | } 28 | 29 | export const fakeHiddenPid = { 30 | nsid: initProc.namespaces.pid.nsid, 31 | type: initProc.namespaces.pid.type, 32 | owner: initProc.namespaces.pid.owner, 33 | reference: [], 34 | } 35 | -------------------------------------------------------------------------------- /web/lxkns/src/utils/rgba.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | import colorRgba from 'color-rgba' 16 | 17 | /** 18 | * Returns a CSS "rgba(...)" color string given a CSS color string (which 19 | * optionally might include an alpha value itself) and a separate alpha 20 | * (transparency) value. 21 | * 22 | * @param color color string, such as "#rgb", "#rrggbb", "rgb(r,g,b)", et 23 | * cetera. Even "rgba(r,g,b,a)" is acceptable. 24 | * @param alpha alpha value in the range of [0..1]. 25 | */ 26 | export const rgba = (color: string, alpha: number) => { 27 | const [r, g, b, a] = colorRgba(color) || [0, 0, 0, 0] 28 | return `rgba(${r},${g},${b},${a*alpha})` 29 | } 30 | -------------------------------------------------------------------------------- /web/lxkns/src/views/about/About.mdx: -------------------------------------------------------------------------------- 1 | import Logo from "app/lxkns.svg"; 2 | 3 | # Linux Kernel Namespaces Discovery 4 | 5 | Version
6 | Copyright 2020–24 Harald Albrecht 7 | 8 | This "app" lets you easily see and explore the Linux-kernel namespaces in your 9 | host system. 10 | 11 | Want more detailed (and integrated) help? 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 |
GitHub:[thediveo/lxkns](https://github.com/thediveo/lxkns)
License:[Apache License 2.0](https://github.com/TheDiveO/lxkns/blob/master/LICENSE)
Relies on:[Go](https://go.dev)
[Material UI v5](https://mui.com/)
[React v18](https://react.js/)
34 | -------------------------------------------------------------------------------- /web/lxkns/src/views/about/About.tsx: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | import React from 'react' 16 | 17 | import { Box } from '@mui/material' 18 | import { MuiMarkdown } from 'components/muimarkdown' 19 | import { SmartA } from 'components/smarta' 20 | 21 | import AboutContent from "./About.mdx" 22 | import { MDXComponents } from 'mdx/types' 23 | 24 | 25 | export const About = () => ( 26 | 27 | 28 | 29 | ) -------------------------------------------------------------------------------- /web/lxkns/src/views/about/index.ts: -------------------------------------------------------------------------------- 1 | export * from './About' 2 | -------------------------------------------------------------------------------- /web/lxkns/src/views/allnamespaces/AllNamespaces.tsx: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | import React from 'react' 16 | 17 | import { Discovery } from 'models/lxkns' 18 | import { Action } from 'app/treeaction' 19 | import { UserNamespaceTree } from 'components/usernamespacetree' 20 | import { Box } from '@mui/material' 21 | 22 | 23 | export interface AllNamespacesProps { 24 | /** lxkns discovery data */ 25 | discovery: Discovery 26 | /** tree action */ 27 | action: Action 28 | } 29 | 30 | export const AllNamespaces = ({ discovery, action }: AllNamespacesProps) => ( 31 | 32 | 33 | 34 | ) 35 | -------------------------------------------------------------------------------- /web/lxkns/src/views/allnamespaces/index.ts: -------------------------------------------------------------------------------- 1 | export * from './AllNamespaces' 2 | -------------------------------------------------------------------------------- /web/lxkns/src/views/containers/Containers.tsx: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | import React from 'react' 16 | 17 | import { Discovery } from 'models/lxkns' 18 | import { Action } from 'app/treeaction' 19 | import { Box } from '@mui/material' 20 | import ContainerTree from 'components/containertree' 21 | 22 | 23 | export interface ContainersProps { 24 | /** lxkns discovery data */ 25 | discovery: Discovery 26 | /** tree action */ 27 | action: Action 28 | } 29 | 30 | export const Containers = ({ discovery, action }: ContainersProps) => ( 31 | 32 | 33 | 34 | ) 35 | -------------------------------------------------------------------------------- /web/lxkns/src/views/containers/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Containers' -------------------------------------------------------------------------------- /web/lxkns/src/views/help/fakehelpdata.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Harald Albrecht. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | // use this file except in compliance with the License. You may obtain a copy 5 | // of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | import { cloneDeep } from 'lodash' 16 | import { Discovery, fromjson } from 'models/lxkns' 17 | import fakedata from './fakediscoverydata.json' 18 | 19 | export const discovery: Discovery = fromjson( 20 | // ouch! fromjson() works in-place, so we need to pass it a copy of the 21 | // original data, at least during development with hot reloading. 22 | cloneDeep(fakedata)) 23 | -------------------------------------------------------------------------------- /web/lxkns/src/views/help/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Help' 2 | -------------------------------------------------------------------------------- /web/lxkns/src/views/settings/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Settings' 2 | -------------------------------------------------------------------------------- /web/lxkns/src/views/typednamespaces/index.ts: -------------------------------------------------------------------------------- 1 | export * from './TypedNamespaces' 2 | -------------------------------------------------------------------------------- /web/lxkns/styleguidist/ComponentCard.md: -------------------------------------------------------------------------------- 1 | Welcome to the meta level! `ComponentCard`s are a nifty trick to quickly see 2 | what amount of space components take when rendered. And this without the need to 3 | open the web developer's console and then picking around the page, hoping to 4 | correctly hit the component. So let's render a simple text inside a 5 | `ComponentCard`, and all this inside an outher ~`InceptionCard`~, _erm_, 6 | `ComponentCard`. 7 | 8 | ```tsx 9 | import { ComponentCard } from "styleguidist/ComponentCard"; 10 | 11 | 12 | 13 | Doh! 14 | 15 | ; 16 | ``` 17 | -------------------------------------------------------------------------------- /web/lxkns/styleguidist/assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/web/lxkns/styleguidist/assets/favicon.ico -------------------------------------------------------------------------------- /web/lxkns/styleguidist/assets/public/lxkns192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thediveo/lxkns/3e94972eaf4aa5b410d11849eb3eb109ecc14a83/web/lxkns/styleguidist/assets/public/lxkns192.png -------------------------------------------------------------------------------- /web/lxkns/styleguidist/styles.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | Code: { 3 | code: { 4 | background: '#f5f5f5', 5 | border: '1px solid #ddd', 6 | borderRadius: '3px', 7 | padding: '0 3px', 8 | } 9 | }, 10 | } 11 | -------------------------------------------------------------------------------- /web/lxkns/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": "./src", 4 | "target": "ESNext", 5 | "useDefineForClassFields": true, 6 | "lib": [ 7 | "DOM", 8 | "DOM.Iterable", 9 | "ESNext" 10 | ], 11 | "allowJs": true, 12 | "skipLibCheck": true, 13 | "esModuleInterop": false, 14 | "allowSyntheticDefaultImports": true, 15 | "strict": true, 16 | "forceConsistentCasingInFileNames": true, 17 | "module": "ES2020", 18 | "moduleResolution": "Bundler", 19 | "allowImportingTsExtensions": true, 20 | "resolveJsonModule": true, 21 | "isolatedModules": true, 22 | "noEmit": true, 23 | "jsx": "react-jsx", 24 | "types": [ 25 | "./node_modules/vite/client" 26 | ] 27 | }, 28 | "include": [ 29 | "src/**/*", 30 | ".storybook/*", 31 | ], 32 | "references": [ 33 | { 34 | "path": "./tsconfig.node.json" 35 | } 36 | ] 37 | } -------------------------------------------------------------------------------- /web/lxkns/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "Bundler", 6 | "allowSyntheticDefaultImports": true 7 | }, 8 | "include": [ 9 | "vite.config.ts" 10 | ] 11 | } -------------------------------------------------------------------------------- /web/puml/vscode-plantuml-plugin-is-stupid: -------------------------------------------------------------------------------- 1 | We need this file in order to work around a stupid bug in VSCode PlantUML plugin. --------------------------------------------------------------------------------