diff --git a/Makefile b/Makefile index 6b533d2..5b67492 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ GOGEN = go generate . GETGITVERSION = export GIT_VERSION=$$(awk -n 'match($$0, /^const SemVersion = "(.*)"$$/, v) { print v[1]; }' defs_version.go) -GENAPIDOC = npx @redocly/cli build-docs -o docs/api/index.html api/openapi-spec/ghostwire-v1.yaml +GENAPIDOC = npm_config_yes=true npx @redocly/cli build-docs -o docs/api/index.html api/openapi-spec/ghostwire-v1.yaml tools := gostwire gostdump lsallnifs @@ -80,7 +80,7 @@ deploy: ## deploy Gostwire service exposed on host port 5999 && echo "deploying version" $$GIT_VERSION \ && scripts/docker-build.sh deployments/gostwire/Dockerfile \ -t gostwire \ - --build-arg REACT_APP_GIT_VERSION=$$GIT_VERSION \ + --build-arg GIT_VERSION=$$GIT_VERSION \ --build-context webappsrc=./webui \ ) docker compose -p gostwire -f deployments/gostwire/docker-compose.yaml up @@ -95,7 +95,7 @@ pprofdeploy: ## deploy Gostwire service with pprof support on host port 5000 $(GETGITVERSION) \ && echo "deploying version" $$GIT_VERSION \ && docker buildx build -t gostwire -f deployments/gostwire/Dockerfile \ - --build-arg REACT_APP_GIT_VERSION=$$GIT_VERSION \ + --build-arg GIT_VERSION=$$GIT_VERSION \ --build-arg TAGS="pprof,osusergo,netgo" \ --build-arg LDFLAGS="" \ --build-arg GITTOKEN="${GITTOKEN}" \ @@ -117,3 +117,13 @@ lsallnifs: ## list all network interfaces with their configuration in all networ vuln: ## run go vulnerabilities check @scripts/vuln.sh + +yarnsetup: ## set up yarn v4 correctly + cd webui && \ + rm -f .yarnrc.yml && \ + rm -rf .yarn/ && \ + rm -rf node_modules && \ + yarn set version berry && \ + yarn config set nodeLinker node-modules && \ + yarn install + #yarn eslint --init diff --git a/README.md b/README.md index e6f78f8..00b1229 100644 --- a/README.md +++ b/README.md @@ -18,8 +18,20 @@ _Linux_ hosts – and can be deployed as a REST service or consumed as a Go module. It comes with its unique container engine discovery that auto-discovers multiple container engines in hosts, including engines _inside containers_. -Currently supported container engines are containerd, Docker, and optionally -podman. Ghostwire is Kubernetes-aware and even understands that KinD simulates +Ghostwire not only understands containers, but also Composer projects and +Kubernetes pods. + +Currently supported container engines are: +- [containerd](https://containerd.io), +- [Docker](https://docker.com), +- [CRI-O](https://cri-o.io), +- [podman](https://podman.io) – when set up to be socket-activated by `systemd` + (see also [podman Quick Start: Starting the service with + systemd](https://github.com/containers/podman/blob/main/pkg/bindings/README.md#quick-start)). + Please note that we only support the Docker-compatible API, but not the + podman-proprietary workload features, such as podman pods. + +Ghostwire is also Kubernetes-aware and even understands that KinD simulates Kubernetes nodes in Docker containers. ## Quick Start @@ -62,7 +74,7 @@ all with the containers and processes serving them. Other Docker containers addressable from your container using DNS names for Docker services and containers. -## Real System State, Not Good Intention Configuration Data +## See the Current System State Information is gathered as much as possible from Linux APIs in order to show the current _effective_ state, instead of potentially invalid or stale engineering @@ -86,6 +98,7 @@ repositories: - [Containershark Extcap plugin for Wireshark](https://github.com/siemens/cshargextcap) - support modules: + - [turtlefinder](https://github.com/siemens/turtlefinder) - [csharg (CLI)](https://github.com/siemens/csharg) - [mobydig](https://github.com/siemens/mobydig) - [ieddata](https://github.com/siemens/ieddata) @@ -143,11 +156,8 @@ For more information, please refer to the (docsified) documentation in `docs/`. install --global yarn`) are installed. ```bash -# build gostwire service binary. -make build -# build static webui assets that the service will serve. -(cd webui && yarn install && yarn build) -# start the gostwire service, exposed at port 5000. +make yarnsetup # if not done already so +make build-embedded ./gostwire --debug ``` diff --git a/api/v1/netns.go b/api/v1/netns.go index f04d63e..22561b5 100644 --- a/api/v1/netns.go +++ b/api/v1/netns.go @@ -14,9 +14,12 @@ import ( "github.com/siemens/ghostwire/v2/network" "github.com/siemens/turtlefinder" + "github.com/siemens/turtlefinder/activator/podman" "github.com/thediveo/lxkns/decorator/kuhbernetes" "github.com/thediveo/lxkns/model" "github.com/thediveo/whalewatcher/engineclient/moby" + "github.com/thediveo/whalewatcher/watcher/containerd" + "github.com/thediveo/whalewatcher/watcher/cri" "golang.org/x/text/cases" "golang.org/x/text/language" ) @@ -320,6 +323,8 @@ func v1ContainerType(typ string) string { // identifiers usually use a domain name, such as "docker.com", instead of plain // and unscoped identifiers, such as "docker". var containerTypesToV1 = map[string]string{ - "docker.com": "docker", - "containerd.io": "containerd", + moby.Type: "docker", + containerd.Type: "containerd", + podman.Type: "podman", + cri.Type: "CRI", } diff --git a/api/v1/nif.go b/api/v1/nif.go index 7fe4ac6..b94e4aa 100644 --- a/api/v1/nif.go +++ b/api/v1/nif.go @@ -16,26 +16,27 @@ import ( // networkInterface is the API v1 JSON representation of an individual network // interface. type networkInterface struct { - ID string `json:"id"` - Kind string `json:"kind"` - Name string `json:"name"` - Alias string `json:"alias,omitempty"` - Index int `json:"index"` - Addresses addresses `json:"addresses"` - Operstate string `json:"operstate"` - Physical bool `json:"physical"` - Promiscuous bool `json:"promisc"` - Labels model.Labels `json:"labels,omitempty"` - Master *nifRef `json:"master,omitempty"` - MacvlanMaster *nifRef `json:"macvlan,omitempty"` // admittedly stupid naming. - Macvlans []*nifRef `json:"macvlans,omitempty"` - Slaves []*nifRef `json:"slaves,omitempty"` - Peer *peerNifRef `json:"peer,omitempty"` - TunTap *tuntapConfig `json:"tuntap,omitempty"` - Vxlan *vxlanConfig `json:"vxlan,omitempty"` - Vlan *vlanConfig `json:"vlan,omitempty"` - SRIOVRole network.SRIOVRole `json:"sr-iov-role,omitempty"` - PF *nifRef `json:"pf,omitempty"` + ID string `json:"id"` + Kind string `json:"kind"` + Name string `json:"name"` + Alias string `json:"alias,omitempty"` + Index int `json:"index"` + Addresses addresses `json:"addresses"` + Operstate string `json:"operstate"` + Physical bool `json:"physical"` + DriverInfo network.NifDriverInfo `json:"driverinfo"` + Promiscuous bool `json:"promisc"` + Labels model.Labels `json:"labels,omitempty"` + Master *nifRef `json:"master,omitempty"` + MacvlanMaster *nifRef `json:"macvlan,omitempty"` // admittedly stupid naming. + Macvlans []*nifRef `json:"macvlans,omitempty"` + Slaves []*nifRef `json:"slaves,omitempty"` + Peer *peerNifRef `json:"peer,omitempty"` + TunTap *tuntapConfig `json:"tuntap,omitempty"` + Vxlan *vxlanConfig `json:"vxlan,omitempty"` + Vlan *vlanConfig `json:"vlan,omitempty"` + SRIOVRole network.SRIOVRole `json:"sr-iov-role,omitempty"` + PF *nifRef `json:"pf,omitempty"` } type addresses struct { @@ -196,22 +197,23 @@ func newNif(nif network.Interface) networkInterface { master = newNifRef(vl.Master) } - nifa := nif.Nif() + nifattrs := nif.Nif() return networkInterface{ ID: nifID(nif), - Name: nifa.Name, - Alias: nifa.Alias, - Index: nifa.Index, - Kind: nifa.Kind, + Name: nifattrs.Name, + Alias: nifattrs.Alias, + Index: nifattrs.Index, + Kind: nifattrs.Kind, Addresses: addresses{ - MAC: nifa.L2Addr.String(), - IPv4: nifa.Addrsv4, - IPv6: nifa.Addrsv6, + MAC: nifattrs.L2Addr.String(), + IPv4: nifattrs.Addrsv4, + IPv6: nifattrs.Addrsv6, }, - Physical: nifa.Physical, - Promiscuous: nifa.Promiscuous, - Operstate: nifa.State.Name(), - Labels: nifa.Labels, + Physical: nifattrs.Physical, + DriverInfo: nifattrs.DriverInfo, + Promiscuous: nifattrs.Promiscuous, + Operstate: nifattrs.State.Name(), + Labels: nifattrs.Labels, Master: master, MacvlanMaster: macvlanmaster, Macvlans: macvlans, @@ -220,7 +222,7 @@ func newNif(nif network.Interface) networkInterface { Vxlan: vxlancfg, TunTap: tuntapcfg, Vlan: vlancfg, - SRIOVRole: nifa.SRIOVRole, + SRIOVRole: nifattrs.SRIOVRole, PF: pf, } } diff --git a/decorator/nerdctlnet/nerdctlnet.go b/decorator/nerdctlnet/nerdctlnet.go index e66fa38..f4552aa 100644 --- a/decorator/nerdctlnet/nerdctlnet.go +++ b/decorator/nerdctlnet/nerdctlnet.go @@ -118,7 +118,7 @@ func newNerdctlNetworks(ctx context.Context, engine *model.ContainerEngine, alln defer mntneer.Close() netwConfigsDir, err := mntneer.Resolve(NetworkConfigurationsDir) if err != nil { - log.Errorf("cannot resolve CNI plugins configuration path, reason: %s", + log.Infof("cannot resolve CNI plugins configuration path, reason: %s", err.Error()) return nerdynets } diff --git a/defs_version.go b/defs_version.go index 734d847..b6ace12 100644 --- a/defs_version.go +++ b/defs_version.go @@ -4,4 +4,4 @@ package gostwire // SemVersion is the semantic version string of the ghostwire module. -const SemVersion = "2.1.10-1-gd4c538a" +const SemVersion = "2.1.18-7-g6dab913" diff --git a/deployments/gostwire/Dockerfile b/deployments/gostwire/Dockerfile index 0a4714b..dc73899 100644 --- a/deployments/gostwire/Dockerfile +++ b/deployments/gostwire/Dockerfile @@ -8,10 +8,10 @@ # Nota bene: not all existing value combinations with respect to Alpine and Node # versions might work, so you'll need to check Docker hub for the available base # image versions. -ARG ALPINE_VERSION=3.18 -ARG ALPINE_PATCH=5 -ARG GO_VERSION=1.21.4 -ARG NODE_VERSION=16 +ARG ALPINE_VERSION=3.19 +ARG ALPINE_PATCH=0 +ARG GO_VERSION=1.21.6 +ARG NODE_VERSION=21 # Go build settings ARG LDFLAGS="-s -w -extldflags=-static" @@ -55,6 +55,8 @@ COPY --from=cc-helpers / / RUN xx-apk add --no-cache gcc musl-dev # https://github.com/tonistiigi/xx/blob/master/README.md#go--cgo ENV CGO_ENABLED=1 +# https://github.com/mattn/go-sqlite3/issues/1164 +ENV CGO_CFLAGS=-D_LARGEFILE64_SOURCE # As of Go 1.20 the Go distribution won't contain a pre-build std library # anymore, so do this now and cache it. RUN xx-go build std @@ -104,29 +106,34 @@ RUN --mount=target=. \ # -- 2nd stage --------------------------------------------------------------- # # Build Ghostwire's frontend UI browser application. -FROM --platform=${BUILDPLATFORM} node:${NODE_VERSION}-alpine${ALPINE_VERSION} AS webui -ARG ALPINE_VERSION -ARG REACT_APP_GIT_VERSION - +FROM --platform=${BUILDPLATFORM} node:${NODE_VERSION}-alpine AS webui WORKDIR /webui ENV PATH /webui/node_modules/.bin:$PATH - +RUN yarn set version berry +RUN yarn config set nodeLinker node-modules # stage 2.1 :) install a full-blown node_modules dependency hell; we need to # tell yarn to be more patient. This gives us a nice cached layer. COPY --from=webappsrc \ package.json \ - craco.config.js \ - mdxplugins.js \ yarn.lock \ + .eslintrc.cjs \ tsconfig.json \ + tsconfig.node.json \ + vite.config.ts \ + index.html \ + ghostwire.svg \ ./ -RUN --mount=type=cache,target=/root/.yarn,sharing=locked YARN_CACHE_FOLDER=/root/.yarn \ - yarn --network-timeout 500000 install --production + +RUN yarn workspaces focus --production +RUN yarn eslint --init + # stage 2.2 only now copy in the web ui completely and build the optimized # static artefacts. COPY --from=webappsrc public/ ./public/ COPY --from=webappsrc src/ ./src/ -RUN echo "building: ${REACT_APP_GIT_VERSION}" && yarn imgbuild +COPY --from=webappsrc .env ./ +ARG GIT_VERSION +RUN yarn build # -- 3. stage --------------------------------------------------------------- # diff --git a/docs/api/index.html b/docs/api/index.html index 2ed691f..d3b8d71 100644 --- a/docs/api/index.html +++ b/docs/api/index.html @@ -12,324 +12,312 @@ margin: 0; } -
-