diff --git a/PRD.md b/PRD.md index 8b7748a..6a7e0e7 100644 --- a/PRD.md +++ b/PRD.md @@ -233,7 +233,7 @@ end to end. Specifically: The reference ships ONE runnable example tree at `examples/lgtm-datamesh/`. Principal entry points: -- **`scripts/bootstrap-capstone.sh`** — brings the whole system up on a +- **`scripts/bootstrap-datamesh.sh`** — brings the whole system up on a fresh minikube profile in ten steps. Each step has a success criterion printed; the script stops on first failure with a fix hint. - **`demos/walkthrough.sh`** — the five-act presenter walkthrough that @@ -325,7 +325,7 @@ schema registry, OpenMetadata, Prometheus, Tempo, Grafana, Kiali. Version pins live in the bootstrap and setup scripts; the reconciliation file tracks any deferred upgrades. -The historical decision log at `_plans/archive/capstone-decisions.md` +The historical decision log at `_plans/archive/final-project-decisions.md` captures every version choice with rationale. --- @@ -345,7 +345,7 @@ captures every version choice with rationale. ## 11. Timeline and milestones This reference was extracted from -`patterncatalyst/minikube-on-fedora`'s §17 capstone as of that repo's r28 +`patterncatalyst/minikube-on-fedora`'s §17 final project as of that repo's r28 (June 2026). The original build's milestones (CAP-001 through CAP-047) are preserved in `_plans/archive/`. Forward milestones for this repo are tracked in `_plans/decisions.md` starting from DRA-001 (the extraction @@ -375,8 +375,8 @@ itself). ## 13. Decision log pointer Active decisions live in `_plans/decisions.md`, numbered from DRA-001. -Historical decisions from the capstone era live in -`_plans/archive/capstone-decisions.md`, numbered CAP-001 through CAP-047. +Historical decisions from the final-project era live in +`_plans/archive/final-project-decisions.md`, numbered CAP-001 through CAP-047. The two series are deliberately distinct to keep the audit trail unambiguous. diff --git a/README.md b/README.md index 6d3c9f6..6e12c16 100644 --- a/README.md +++ b/README.md @@ -104,7 +104,7 @@ end to end, verified order-independent (see conceptual deck) and *Data Mesh on OpenShift* (the implementation deck). - **`assets/diagrams/`** — paired SVG + Excalidraw sources for every figure. - **`_plans/`** — active decisions and reconciliation tracking. - Historical material from the capstone era is preserved under + Historical material from the final-project era is preserved under `_plans/archive/`. - **`scripts/`** — top-level helper scripts: cross-reference and Liquid collision linters, a Fedora prerequisites audit, setup helpers for @@ -126,7 +126,7 @@ for a read-only host check), then: ```bash cd examples/lgtm-datamesh -./scripts/bootstrap-capstone.sh # the whole stack, ten gated tiers +./scripts/bootstrap-datamesh.sh # the whole stack, ten gated tiers ./demos/walkthrough.sh # the five-act presenter walkthrough ``` @@ -139,7 +139,7 @@ An optional OpenShift Local (CRC) appendix uses podman. ## Origin -This repo is a fork of the §17 capstone from +This repo is a fork of the §17 final project from [`patterncatalyst/minikube-on-fedora`](https://github.com/patterncatalyst/minikube-on-fedora). The parent repo's tutorial (§1–§16) remains the canonical Minikube-on-Fedora guide; this repo is the data-mesh reference broken out for its own audience. diff --git a/_config.yml b/_config.yml index ca21765..54d69b8 100644 --- a/_config.yml +++ b/_config.yml @@ -36,7 +36,7 @@ permalink: pretty # Collections — _docs and _plans are not Jekyll defaults; this enables them. # Unlike the upstream minikube-tutorial repo, this site's _docs IS the # data-mesh content (it's not nested under a parent tutorial). There's no -# separate _capstone collection. +# separate _datamesh collection. collections: docs: output: true @@ -68,7 +68,7 @@ exclude: - scripts/ - README.md - LICENSE - - _plans/archive/ # archived capstone plans contain inline {% %} prose Liquid can't parse + - _plans/archive/ # archived final-project plans contain inline {% %} prose Liquid can't parse - PRD.md - LESSONS-LEARNED.md - GETTING-STARTED.md diff --git a/_docs/00-index.md b/_docs/00-index.md index abed3e9..9a45a53 100644 --- a/_docs/00-index.md +++ b/_docs/00-index.md @@ -62,7 +62,7 @@ the value it delivers and the implementation pieces that realize it. catalog is a mesh requirement rather than an add-on. - [**6 · The data planes**]({{ '/docs/05-data-planes/' | relative_url }}) — The synchronous read layer (REST, gRPC, a GraphQL gateway) and the asynchronous event - backbone — and why the capstone uses all of them. + backbone — and why the final project uses all of them. - [**7 · Progressive delivery & mTLS**]({{ '/docs/06-progressive-delivery-mtls/' | relative_url }}) — Evolving a contract in the open with a v1→v2 canary, mTLS with no application changes, and the decision to mesh selectively rather than namespace-wide. diff --git a/_docs/01-concepts.md b/_docs/01-concepts.md index e4a069a..2b9f337 100644 --- a/_docs/01-concepts.md +++ b/_docs/01-concepts.md @@ -72,7 +72,7 @@ rather than leaving analytical data as a stale downstream copy. ![Operational vs. analytical data planes]({{ '/assets/diagrams/17-operational-vs-analytical.svg' | relative_url }}) -This capstone models the **operational** side concretely — services that own their +This final project models the **operational** side concretely — services that own their data and emit events — and shows how analytical consumers attach to that operational flow through the event backbone, rather than through a nightly extract. That's the loop the mesh is meant to keep closed. @@ -81,7 +81,7 @@ loop the mesh is meant to keep closed. Dehghani's data mesh rests on four interlocking principles. They depend on each other — implement one without the others and you get a distributed mess rather than a mesh — -and each shows up explicitly in this capstone: +and each shows up explicitly in this final project: ![The four principles and how they map to Kubernetes primitives]({{ '/assets/diagrams/17-data-mesh-four-principles.svg' | relative_url }}) @@ -122,7 +122,7 @@ re-centralized into an approval bottleneck. ## The pattern is not the tools A data mesh isn't a product, a tool, or a vendor offering — it's an organizational and -architectural pattern. The tools this capstone uses are *expressions* of the pattern, +architectural pattern. The tools this final project uses are *expressions* of the pattern, chosen because each one makes a principle concrete and runnable, not because any of them *is* the mesh. That distinction matters enough that it's the first [anti-pattern]({{ '/docs/09-anti-patterns/' | relative_url }}): the most diff --git a/_docs/02-kubernetes-substrate.md b/_docs/02-kubernetes-substrate.md index 6e0b05c..b820c46 100644 --- a/_docs/02-kubernetes-substrate.md +++ b/_docs/02-kubernetes-substrate.md @@ -11,11 +11,11 @@ By the end of this chapter you can: - Map each of Dehghani's four principles to the specific Kubernetes primitive that realizes it (namespaces/RBAC, Deployments/CRDs, operators, admission control). -- Describe the three horizontal tiers of this capstone's architecture and which +- Describe the three horizontal tiers of this final project's architecture and which protocol crosses each boundary. -- Explain why this capstone runs on minikube with the docker driver and containerd +- Explain why this final project runs on minikube with the docker driver and containerd runtime, and what trade-off a single-node cluster makes. -- State how the capstone exposes host access (NodePorts published on `127.0.0.1` at +- State how the final project exposes host access (NodePorts published on `127.0.0.1` at profile creation) and what command recreates the profile if the published ports need to change. @@ -23,7 +23,7 @@ By the end of this chapter you can: The [previous page]({{ '/docs/01-concepts/' | relative_url }}) ended on a claim: a data mesh is a pattern, not a tool, and the tools are -expressions of it. So why build the capstone on Kubernetes at all? Because the four +expressions of it. So why build the final project on Kubernetes at all? Because the four principles map onto Kubernetes primitives unusually cleanly — cleanly enough that "implement a data mesh on Kubernetes" stops feeling like a translation exercise and starts feeling like the primitives were waiting for it. This page makes that mapping @@ -84,12 +84,12 @@ the system, which is exactly what "computational governance" means. ## The shape of the system -With the mapping in hand, here's the system this capstone builds. It has three +With the mapping in hand, here's the system this final project builds. It has three horizontal tiers: **external clients** at the top, the **service mesh** running the domain services in the middle, and the **self-serve platform** providing shared infrastructure underneath. -![Capstone architecture — data mesh on minikube]({{ '/assets/diagrams/17-capstone-data-mesh.svg' | relative_url }}) +![The final project's architecture — data mesh on minikube]({{ '/assets/diagrams/17-final-project-data-mesh.svg' | relative_url }}) The diagram doubles as a map of the protocol decisions, which the [data planes page]({{ '/docs/05-data-planes/' | relative_url }}) develops @@ -109,7 +109,7 @@ return to as the rest of the set works through the parts. ## A note on minikube specifically -This capstone runs on minikube — a single-node Kubernetes cluster — which is the right +This final project runs on minikube — a single-node Kubernetes cluster — which is the right choice for *learning* the pattern and wrong for running it in production. A single node means every tier shares one machine's resources, which keeps the whole mesh runnable on a laptop but also concentrates failure modes that a real multi-node cluster would @@ -125,13 +125,13 @@ the runc runtime, sized by `MINIKUBE_MEMORY`, `MINIKUBE_CPUS` and `MINIKUBE_DISK ### Host access -Host access follows the same single-node logic. The capstone's UIs and service +Host access follows the same single-node logic. The final project's UIs and service endpoints are NodePorts published on `127.0.0.1` when the minikube profile is created (`--ports=127.0.0.1::`), never SSH tunnels or port-forwarding. The ports are fixed at creation, so changing the published set means recreating the -profile with `./scripts/setup-capstone-profile.sh --replace`. `--replace` deletes and -recreates the cluster, so run `./scripts/bootstrap-capstone.sh` again afterwards. +profile with `./scripts/setup-datamesh-profile.sh --replace`. `--replace` deletes and +recreates the cluster, so run `./scripts/bootstrap-datamesh.sh` again afterwards. Run the workshop in isolation: shut down CRC, other minikube profiles, and other workloads first, so the host ports are free. `./scripts/show-endpoints.sh` prints what @@ -144,11 +144,11 @@ is published and reachable. - *Platform Engineering on Kubernetes* by Mauricio Salatino — the self-serve platform principle built out as an operating model, not just a set of operators. - *Cloud Native Patterns* by Cornelia Davis — the broader cloud-native platform - patterns this capstone's shared infrastructure tier follows. + patterns this final project's shared infrastructure tier follows. - [Kubernetes documentation](https://kubernetes.io/docs/) — namespaces, RBAC, CRDs, and admission control, straight from the source. - [minikube documentation](https://minikube.sigs.k8s.io/docs/) — driver and runtime - options, including the docker driver and containerd runtime this capstone uses. + options, including the docker driver and containerd runtime this final project uses. Next, the services themselves: what a data product looks like in this build, the order-service template the others follow, and how each one is packaged and shipped. diff --git a/_docs/03-services-and-data-products.md b/_docs/03-services-and-data-products.md index bb2f661..587628c 100644 --- a/_docs/03-services-and-data-products.md +++ b/_docs/03-services-and-data-products.md @@ -19,7 +19,7 @@ By the end of this chapter you can: With the [principles]({{ '/docs/01-concepts/' | relative_url }}) and the [Kubernetes mapping]({{ '/docs/02-kubernetes-substrate/' | relative_url }}) -in place, this page gets concrete: what the data products in this capstone actually +in place, this page gets concrete: what the data products in this final project actually are, the one service we build end-to-end as a template for the rest, and how a data product is packaged and shipped as a container image. This is the first implementation-heavy page — the conceptual scaffolding is behind us. @@ -34,7 +34,7 @@ make it discoverable and governed. ![Anatomy of a data product — ports in, ports out, transformation and governance inside]({{ '/assets/diagrams/17-data-product-anatomy.svg' | relative_url }}) -In this capstone, that abstraction is concrete: **each domain service *is* a data +In this final project, that abstraction is concrete: **each domain service *is* a data product.** It owns a slice of the database (its input/internal state), it serves data through its APIs (output ports), it emits events as other domains' input, and it publishes a contract and metadata so it can be discovered and depended on. The service @@ -72,7 +72,7 @@ real without running five separate databases on a single learning node. ## Build one service end to end first -Rather than build all six services a layer at a time, the capstone takes a single +Rather than build all six services a layer at a time, the final project takes a single service all the way through first — a *walking skeleton*. The point is to prove the entire spine works before widening: build the image, get it to the cluster, deploy via helm, have the operator-managed Postgres come up, the service connect, and data @@ -92,12 +92,12 @@ rather than carrying the dependency manager into the runtime. The image itself is multi-stage: a builder stage resolves dependencies, and a slim runtime stage copies only the resolved environment and the application code, runs as a -non-root user, and serves the app. Standard production hygiene — the capstone just +non-root user, and serves the app. Standard production hygiene — the final project just applies it from the start rather than retrofitting it. ## The one part that fights back: getting images to the kubelet -This is worth its own section because it's the single part of the capstone that +This is worth its own section because it's the single part of the final project that reliably trips people up. The profile is a Docker container (the docker driver) running containerd, and that container has its own image store, separate from the Docker Engine on your host. An image you build locally is invisible to the kubelet until you put it @@ -106,7 +106,7 @@ cluster. ### Build with Docker Engine, then load the image -The capstone's answer is simple: **build with Docker Engine, then load the +The final project's answer is simple: **build with Docker Engine, then load the image into the profile with `minikube image load`**. There is no registry to run and no addresses to reconcile, and it works the same on a native engine and on a VM-based one (Docker Desktop, for example). That portability is the reason for the choice: @@ -115,15 +115,15 @@ the host's network, which a VM-based engine's does not. ### Tags and pull policy -Images are tagged `capstone/:v1` and the charts set `imagePullPolicy: Never`. The +Images are tagged `datamesh/:v1` and the charts set `imagePullPolicy: Never`. The policy matters in both directions. If an image was never loaded, the pod fails at once with `ErrImageNeverPull` instead of quietly trying Docker Hub for a name that exists nowhere. And because `:v1` is a mutable tag, a rebuild does not change what running pods use, so `scripts/build-image.sh` restarts the Deployments that use the image it just loaded. -None of this is unique to the capstone — any local cluster has some version of the gap between the host's images and the node's — but -the capstone is where it bites, because it's the first place you build and deploy your +None of this is unique to the final project — any local cluster has some version of the gap between the host's images and the node's — but +the final project is where it bites, because it's the first place you build and deploy your *own* images at scale. Get the image workflow right once here, and every service afterward is the same three commands. (The deeper operational sharp edges of running all this on a single node are collected as gotchas, separate from this build-level diff --git a/_docs/04-contracts-and-catalog.md b/_docs/04-contracts-and-catalog.md index 810e4e7..1b574e0 100644 --- a/_docs/04-contracts-and-catalog.md +++ b/_docs/04-contracts-and-catalog.md @@ -34,9 +34,9 @@ a field gets renamed, a type changes, and a consumer three domains away breaks w warning. The mesh's answer is to give every contract a versioned home in a single registry, regardless of its format. -![Each service's contract surface — OpenAPI, Protobuf, schema, SDL]({{ '/assets/diagrams/17-capstone-contracts.svg' | relative_url }}) +![Each service's contract surface — OpenAPI, Protobuf, schema, SDL]({{ '/assets/diagrams/17-final-project-contracts.svg' | relative_url }}) -This capstone uses **Apicurio** as that registry, holding all four contract types as +This final project uses **Apicurio** as that registry, holding all four contract types as their native artifacts: the event schemas, the gRPC Protobuf definitions, the REST OpenAPI documents, and the gateway's GraphQL SDL. One registry, every contract — so there's a single place to ask "what is this product's shape, and what version am I @@ -47,7 +47,7 @@ depending on?" Here's the distinction that makes the registry more than a documentation folder, and it's worth getting clear because the two jobs have very different coupling. -![How a contract flows — the runtime path versus the discovery path]({{ '/assets/diagrams/17-capstone-contract-flow.svg' | relative_url }}) +![How a contract flows — the runtime path versus the discovery path]({{ '/assets/diagrams/17-final-project-contract-flow.svg' | relative_url }}) ### Runtime contracts @@ -81,7 +81,7 @@ ultimately came from. That's the catalog's job. ![Contracts in the registry, discovery and lineage in the catalog]({{ '/assets/diagrams/17-contracts-registry-catalog.svg' | relative_url }}) -This capstone layers **OpenMetadata** on top as the catalog. It ingests from the +This final project layers **OpenMetadata** on top as the catalog. It ingests from the registry (the contracts), from the database (the schemas each domain owns), and from the event backbone (the topics), and assembles the picture a consumer actually needs: the products that exist, their schemas, their owners, and — crucially — their diff --git a/_docs/05-data-planes.md b/_docs/05-data-planes.md index 5b0daf5..ea75bb9 100644 --- a/_docs/05-data-planes.md +++ b/_docs/05-data-planes.md @@ -1,7 +1,7 @@ --- title: "The data planes" order: 6 -description: The async backbone of Kafka events and the read layer of GraphQL composing REST and gRPC — when to reach for each, and why the capstone uses all of them. +description: The async backbone of Kafka events and the read layer of GraphQL composing REST and gRPC — when to reach for each, and why the final project uses all of them. duration: 25 min --- @@ -10,7 +10,7 @@ duration: 25 min By the end of this chapter you can: - Match each of the four protocols — REST, gRPC, GraphQL, and events — to the job it's best suited for, and explain the "fitness, not hierarchy" framing. -- Distinguish gateway orchestration from true subgraph federation and state the trade-off this capstone accepts by choosing orchestration. +- Distinguish gateway orchestration from true subgraph federation and state the trade-off this final project accepts by choosing orchestration. - Trace the `order.placed` event flow from producer to consumers and explain why the producer doesn't block on any of them. - Explain why the synchronous read layer and the asynchronous event backbone are complementary planes rather than competing ones. @@ -22,12 +22,12 @@ each expose a contract, and the them discoverable. This page is about how data actually *moves* between them — the planes the mesh runs on. There are two: a **synchronous read layer** (REST, gRPC, and a GraphQL gateway composing across them) and an **asynchronous event backbone** (the -streaming spine that lets domains react to each other). The capstone uses all of them +streaming spine that lets domains react to each other). The final project uses all of them because each one fits a different kind of data movement. ## Protocols by fitness, not by hierarchy -It would be simpler to pick one protocol and use it everywhere. The capstone +It would be simpler to pick one protocol and use it everywhere. The final project doesn't, because each protocol is *best at a different job*, and a data mesh exercises all those jobs. This isn't a ranking where one protocol wins; it's a matter of fitness for context: @@ -43,7 +43,7 @@ one protocol wins; it's a matter of fitness for context: - **Events for everything asynchronous.** When something *happens* and other domains need to react without the producer waiting on them, the event backbone carries it. -The capstone makes this concrete in one place: the gateway's resolvers literally call +The final project makes this concrete in one place: the gateway's resolvers literally call REST and gRPC side by side, and GraphQL stitches the result — so you can see all three synchronous protocols cooperating rather than competing. @@ -64,14 +64,14 @@ There's an important precision here about *how* the gateway composes, because th two ways to build a unified GraphQL graph and they're often conflated. In **true subgraph federation**, each service exposes its own GraphQL subgraph and a gateway plans queries across them into a supergraph — each domain owns and evolves its slice of -the graph independently. That's the production-scale pattern. This capstone uses the +the graph independently. That's the production-scale pattern. This final project uses the simpler **gateway orchestration** approach instead: one stateless gateway exposes the unified graph, and its resolvers fetch from the services over their *existing* REST and gRPC interfaces, with no GraphQL added to the domain services at all. ### Why orchestration, not federation, here -The capstone is a learning implementation. Gateway +The final project is a learning implementation. Gateway orchestration demonstrates the *value* GraphQL adds (one client query, multiple backends, client-shaped response) with one new service and zero changes to the five domain services, and it makes the protocol comparison vivid because the resolvers call @@ -98,7 +98,7 @@ Instead it emits an event, and the interested domains consume it on their own sc ![Domain events and change-data-capture feeding the analytical side]({{ '/assets/diagrams/17-ingestion-streaming-sourcing.svg' | relative_url }}) -This capstone builds that spine on a Kafka cluster managed by an operator, and models +This final project builds that spine on a Kafka cluster managed by an operator, and models the canonical pattern with the smallest real flow: order-service emits an `order.placed` event, keyed by order id, and notification-service consumes it. That one flow is the whole "something happened, downstreams react" shape in miniature — the diff --git a/_docs/06-progressive-delivery-mtls.md b/_docs/06-progressive-delivery-mtls.md index 4ba3d34..3f3bee8 100644 --- a/_docs/06-progressive-delivery-mtls.md +++ b/_docs/06-progressive-delivery-mtls.md @@ -21,7 +21,7 @@ Data products evolve. A product that can never change its contract is a product will build on for long — but a product that changes its contract *carelessly* breaks every consumer downstream. This page is about evolving safely: shifting traffic gradually between an old and a new version of a product's contract, with the service -mesh both routing the split and securing the traffic. It's also where the capstone +mesh both routing the split and securing the traffic. It's also where the final project makes an architectural decision that the rest of the set has been alluding to — to mesh **selectively** rather than meshing everything — and explains why, from experience. @@ -31,7 +31,7 @@ experience. ## Canarying a contract, not just a binary The interesting thing to canary in a data mesh isn't a new build of the same service — -it's a new version of the *contract*. This capstone takes order-service through a +it's a new version of the *contract*. This final project takes order-service through a v1→v2 change: v2 adds a `currency` field to the order response, the canonical "evolve the contract without breaking clients" move. v1 keeps serving the old shape; v2 serves the new one; and Istio splits live traffic between them by weight, so you can @@ -60,7 +60,7 @@ This was verified end to end: with the split set to 90/10, a run of 100 requests the expected band, both subsets healthy in the mesh. The contract evolved in the open, under controlled traffic, exactly as the pattern intends. -![The capstone's mesh in canary mode — sidecars beside each product, mTLS between them, weights moving traffic from v1 to v2]({{ '/assets/diagrams/17-service-mesh.svg' | relative_url }}) +![The final project's mesh in canary mode — sidecars beside each product, mTLS between them, weights moving traffic from v1 to v2]({{ '/assets/diagrams/17-service-mesh.svg' | relative_url }}) ## mTLS without code changes @@ -78,7 +78,7 @@ Here's the architectural choice this page exists to make, and it runs against th convenient default. Istio offers a one-label switch — mark a namespace `istio-injection=enabled` and *every* pod created in it gets a sidecar automatically. It's tempting: one label, whole-namespace mTLS, nothing to think about per workload. -The capstone's position, learned the hard way, is that namespace-wide injection is the +The final project's position, learned the hard way, is that namespace-wide injection is the wrong default for a mesh that contains more than just mesh-appropriate services — and that you should instead opt specific workloads *into* the mesh. @@ -108,7 +108,7 @@ a job, or anything else — workloads that have nothing to do with the mesh are coupled to its health. Selective injection contains that blast radius: only the -workloads that actually need the mesh depend on it. So the capstone meshes the services +workloads that actually need the mesh depend on it. So the final project meshes the services that participate in mesh-managed traffic — the ones doing the canary, the ones that benefit from mTLS and traffic management — and keeps the database, the batch jobs, and other operator-managed infrastructure *out* of the mesh by opting them out explicitly. @@ -116,7 +116,7 @@ other operator-managed infrastructure *out* of the mesh by opting them out expli The trade-off is real: namespace-wide injection is simpler to reason about and gives blanket mTLS with one label, while selective injection is more work to configure and means you have -to decide, per workload, whether it belongs in the mesh. The capstone takes that +to decide, per workload, whether it belongs in the mesh. The final project takes that configuration cost in exchange for resilience and correctness — because the failures above aren't hypothetical, they're what happens otherwise. diff --git a/_docs/07-elastic-and-resilient.md b/_docs/07-elastic-and-resilient.md index 2afff2a..822a3c7 100644 --- a/_docs/07-elastic-and-resilient.md +++ b/_docs/07-elastic-and-resilient.md @@ -45,7 +45,7 @@ have many such products, each materializing only when something actually asks fo That's a different economics from "every service holds a baseline of resources forever," and it's particularly apt for a mesh of many domain products with uneven, bursty demand. -This capstone wires up **two** scalers of different kinds, on two different products: +This final project wires up **two** scalers of different kinds, on two different products: - **Consumer-lag scaling on notification-service.** notification-service is an event consumer — its real workload is the backlog of events waiting in its consumer @@ -68,7 +68,7 @@ and HTTP-scaling a service whose traffic is being split by weight would have the mechanisms fighting over the same pods. The gateway is a natural synchronous-read load target with no such conflict. Matching each scaler to the right product — lag-based for the consumer, request-based for the gateway, and neither on the canaried service — is -the kind of fitting-the-mechanism-to-the-workload judgment the whole capstone keeps +the kind of fitting-the-mechanism-to-the-workload judgment the whole final project keeps returning to. ![Why the HTTP scaler goes on the gateway and not on the canaried order-service — matching the scaler to the workload]({{ '/assets/diagrams/17-keda-http.svg' | relative_url }}) @@ -100,7 +100,7 @@ backbone lets a consumer that was down catch up on the backlog it missed, and declarative deployment means re-applying the desired state is always a valid recovery move. -The capstone runs on a single node, which makes recoverability both more visible and +The final project runs on a single node, which makes recoverability both more visible and more demanding than a multi-node cluster would — a single node concentrates the failure modes that several nodes would spread out and absorb. Operating a long-lived single-node cluster well turns out to require real care: knowing when to let the diff --git a/_docs/08-observability.md b/_docs/08-observability.md index 05a760f..90950bb 100644 --- a/_docs/08-observability.md +++ b/_docs/08-observability.md @@ -57,7 +57,7 @@ the traffic flowing between products — and a Prometheus that scrapes them gets detailed picture of inter-product traffic without a single line of metrics code in the services. -This capstone leans on exactly that: the metrics half of observability adds +This final project leans on exactly that: the metrics half of observability adds *nothing* to the application code, because the mesh is already measuring the traffic it carries. Grafana then turns those metrics into the dashboards you'd actually watch — the gateway's request volume rising, KEDA spinning up replicas in response, the canary's @@ -76,7 +76,7 @@ Distributed tracing assigns a request an identity that propagates as it crosses boundaries, so the work each product does on its behalf becomes a connected tree of **spans** — one request, many products, one trace. -This capstone collects traces in Tempo and instruments the **gateway** as the trace +This final project collects traces in Tempo and instruments the **gateway** as the trace source. The gateway is the entry point for the federated read path, so a single GraphQL query there produces the most instructive trace there is in this system: an HTTP server span for the query itself, a REST client span for the @@ -118,7 +118,7 @@ split and all. None of these is the system — they're the *instruments* through which you understand a system too distributed for any single vantage point to capture. That's the -acceptance bar the capstone is built toward: not just that the mesh runs, but that you +acceptance bar the final project is built toward: not just that the mesh runs, but that you can watch it run — see a request thread across products, see a product scale to meet demand, see a contract roll out version by version, and see where every product's data came from. diff --git a/_docs/09-anti-patterns.md b/_docs/09-anti-patterns.md index be4a6c6..e1a0fd2 100644 --- a/_docs/09-anti-patterns.md +++ b/_docs/09-anti-patterns.md @@ -188,7 +188,7 @@ Before committing, weigh data size, organizational complexity, existing tooling, and culture, and be willing to conclude that a full mesh isn't the right fit — or that only some of its principles are. -*In this build:* the capstone is a *learning* implementation — a small, +*In this build:* the final project is a *learning* implementation — a small, runnable mesh that makes the principles concrete. It's sized to teach the shape, not to argue that every reader should run a mesh in production. diff --git a/_docs/10-summary.md b/_docs/10-summary.md index 9dc1caa..c4a0e20 100644 --- a/_docs/10-summary.md +++ b/_docs/10-summary.md @@ -72,7 +72,7 @@ of capacity another domain needs. The reference's order, inventory, payment, shipping, and notification domains each live in their own namespace. The reference uses a single -shared `capstone` namespace for the demo's clarity, but the production +shared `datamesh` namespace for the demo's clarity, but the production shape is one namespace per domain — the reference's helm chart structure supports that directly. @@ -98,7 +98,7 @@ and how to address it. The implementation pieces that realize this in the reference: every service's Deployment + Service makes the product *addressable* — a -domain consumer reaches `order-service.capstone.svc.cluster.local` and +domain consumer reaches `order-service.datamesh.svc.cluster.local` and gets the order product. The Apicurio schema registry holds the *versioned contracts* — OpenAPI for REST, Protobuf for gRPC, AsyncAPI for the Kafka events — and rejects breaking changes at registration @@ -246,7 +246,7 @@ your own data mesh on Kubernetes, the pattern is: 2. **Run the example tree** to see the cross-product behaviors live — the trace tree across three products, the canary contract evolution under live traffic, the autoscaler reacting to a Kafka backlog. -3. **Use the decision log** at `_plans/archive/capstone-decisions.md` +3. **Use the decision log** at `_plans/archive/final-project-decisions.md` to understand the *reasoning* for each implementation choice, not just the choice itself. The rejected alternatives are where the institutional memory of the build lives. diff --git a/_docs/11-running-on-openshift-crc.md b/_docs/11-running-on-openshift-crc.md index 90bd742..0839d90 100644 --- a/_docs/11-running-on-openshift-crc.md +++ b/_docs/11-running-on-openshift-crc.md @@ -18,7 +18,7 @@ By the end of this chapter you can: ## Why this matters [Chapter 3]({{ '/docs/02-kubernetes-substrate/' | relative_url }}) built the case for -Kubernetes as the mesh's substrate and brought the capstone up on minikube via Helm — +Kubernetes as the mesh's substrate and brought the final project up on minikube via Helm — NodePorts published to loopback, a local image registry. That's a real deployment, and everything in the reading set up to the [summary]({{ '/docs/10-summary/' | relative_url }}) assumes it. But "deploy it to Kubernetes" and "deploy it to OpenShift" are not the same @@ -40,7 +40,7 @@ built to the three constraints OpenShift imposes, plus the build/push/deploy seq that gets it running. One scoping note up front, visible in the chart's own `Chart.yaml`: this is the **live -core** of the capstone — the seven services, Postgres, Kafka, and Apicurio — not the +core** of the final project — the seven services, Postgres, Kafka, and Apicurio — not the full minikube stack. OpenMetadata, Prefect, the LGTM observability stack, KEDA autoscaling, and the Istio mesh are out of this chart *by default*. A later section of this appendix, "The full platform tier, live," brings all five of @@ -188,7 +188,7 @@ the hood. ### 2. Routes, not published NodePorts -The minikube path this capstone uses elsewhere in the reading set exposes services via +The minikube path this final project uses elsewhere in the reading set exposes services via NodePorts published to `127.0.0.1` when the profile is created, because minikube has no cluster-native router. OpenShift has one built in: a `Route` object hands a Service a real external hostname, served by the cluster's router, with nothing to publish on the diff --git a/_plans/archive/README.md b/_plans/archive/README.md index 92728be..04d4255 100644 --- a/_plans/archive/README.md +++ b/_plans/archive/README.md @@ -1,9 +1,9 @@ --- -title: "Archive — decisions and reconciliation from the capstone era" +title: "Archive — decisions and reconciliation from the final-project era" render_with_liquid: false --- -# Archive — capstone-era plans +# Archive — final-project-era plans > **Superseded host access.** Archived files describe host access through SSH > tunnels and `kubectl port-forward`, which this repo no longer uses. They are @@ -13,7 +13,7 @@ render_with_liquid: false These files are the historical decision log and reconciliation record from when the data-mesh reference architecture lived inside the `minikube-on-fedora` -tutorial as its §17 capstone. They're preserved here for the audit trail — +tutorial as its §17 final project. They're preserved here for the audit trail — how each design choice was made, the reasoning behind it, and the verification status of each claim at the time the work was done. @@ -27,16 +27,16 @@ the parent tutorial's content, which isn't part of this repo. The files: -- `capstone-decisions.md` — the architectural and editorial decisions from +- `final-project-decisions.md` — the architectural and editorial decisions from CAP-001 through CAP-047, with rationale, evidence, and rejected alternatives for each. - `reconciliation-plan.md` — the reconciliation rows tracking which claims were `unverified` / `verified (Fedora 44)` / `superseded` at each iteration of the build. -- `capstone-roadmap.md`, `iteration-plan.md`, `phase-c-plan.md`, +- `final-project-roadmap.md`, `iteration-plan.md`, `phase-c-plan.md`, `phase-d-deck-plan.md`, `prd-reconciliation.md` — phase plans and the PRD reconciliation from the original project. The original repo (`patterncatalyst/minikube-on-fedora`) remains canonical -for the parent tutorial; this archive captures the §17 capstone slice as it +for the parent tutorial; this archive captures the §17 final-project slice as it stood when it was forked into this standalone reference. diff --git a/_plans/archive/capstone-decisions.md b/_plans/archive/final-project-decisions.md similarity index 99% rename from _plans/archive/capstone-decisions.md rename to _plans/archive/final-project-decisions.md index c906c57..a79a535 100644 --- a/_plans/archive/capstone-decisions.md +++ b/_plans/archive/final-project-decisions.md @@ -1498,7 +1498,7 @@ build from, and refined the plan. - **Phase E acceptance = the demo vision:** presenter replays with CLI narration AND graphical views (live Tempo trace/spans, OpenMetadata lineage, Kiali canary live-vs-after, correlated metrics). -- Full plan recorded in `_plans/capstone-roadmap.md`. +- Full plan recorded in `_plans/final-project-roadmap.md`. **Sequencing.** A → B → C → D → E (features → narrative → deck → walkthrough). **Next:** Phase A, scoped in detail at the next session start. @@ -2338,7 +2338,7 @@ no log, no response) failed to forward. addition to the existing `KIALI_PF`). Preflight gains two checks that the trace act needs: `graphql-gateway` Deployment available and `graphql-gateway` Service exists. Header comment updated. - * `_plans/capstone-decisions.md` — CAP-046 status updated to + * `_plans/final-project-decisions.md` — CAP-046 status updated to "superseded by CAP-047"; CAP-047 (this entry) added. * `_plans/reconciliation-plan.md` — the prior CAP-046 row marked "superseded by CAP-047"; new CAP-047 rows added (one for the diff --git a/_plans/archive/capstone-roadmap.md b/_plans/archive/final-project-roadmap.md similarity index 100% rename from _plans/archive/capstone-roadmap.md rename to _plans/archive/final-project-roadmap.md diff --git a/_plans/archive/prd-reconciliation.md b/_plans/archive/prd-reconciliation.md index 9e05659..8cd339c 100644 --- a/_plans/archive/prd-reconciliation.md +++ b/_plans/archive/prd-reconciliation.md @@ -219,7 +219,7 @@ specific decision and why). That's the recommended order. --- -## Addendum: project reopened (§16 examples hub + §17 capstone) +## Addendum: project reopened (§16 examples hub + §17 final project) The summary above describes the original 15-section project at its first close (**107 verified facts**). The project subsequently @@ -230,13 +230,13 @@ moved on: per-example pages, with a `sync-example-pages.sh` script that renders `examples/*/README.md` into browsable pages. Onboarding docs moved under `onboarding/`. -- **§17 — Capstone: a data mesh on minikube** (r19 onward, in +- **§17 — Final project: a data mesh on minikube** (r19 onward, in progress): a five-service data mesh (order / inventory / payment / shipping / notification) demonstrating REST + gRPC + GraphQL + - Kafka, deployed via a helm umbrella chart to a dedicated `capstone` + Kafka, deployed via a helm umbrella chart to a dedicated `datamesh` profile, with Postgres (CloudNativePG), Apicurio, OpenMetadata, observability, and Prefect. Architectural choices are tracked - separately in `_plans/capstone-decisions.md` (CAP-001 … CAP-010). + separately in `_plans/final-project-decisions.md` (CAP-001 … CAP-010). **Current verified count: 112** (was 107). The five new facts come from r21c — the order-service walking skeleton, verified end-to-end @@ -244,7 +244,7 @@ on Fedora 44 (image build → in-cluster registry → operator-managed Postgres → REST round-trip → row persisted). **A divergence worth recording, in the spirit of this document:** the -capstone took six iterations (r21 → r21c) to stand up its *first* +final project took six iterations (r21 → r21c) to stand up its *first* service, almost entirely due to image-distribution friction on the rootless-podman + containerd driver — not the application code, the helm charts, or the operators, all of which worked on first or second @@ -257,7 +257,7 @@ primary in seconds. A reminder that the risks you plan for and the risks that bite are often different ones. The §13 vendor-neutrality divergence noted above also deepened in the -capstone: §17 names specific tools throughout (Strimzi, KEDA, Istio, +final project: §17 names specific tools throughout (Strimzi, KEDA, Istio, CloudNativePG, Apicurio, OpenMetadata, Prefect, Strawberry) because a working data mesh requires concrete choices. These are presented as "a defensible set of choices for this stack," not endorsements, with diff --git a/_plans/archive/reconciliation-plan.md b/_plans/archive/reconciliation-plan.md index 367c7c7..dd48b50 100644 --- a/_plans/archive/reconciliation-plan.md +++ b/_plans/archive/reconciliation-plan.md @@ -2098,7 +2098,7 @@ have to derive them. every other service follows. **Decisions captured this iteration** (in the new - `_plans/capstone-decisions.md`): + `_plans/final-project-decisions.md`): - CAP-001 Poetry for Python dependency management - CAP-002 CloudNativePG operator, installed separately (cluster-wide install called out as a teaching point) @@ -2111,7 +2111,7 @@ have to derive them. - plus the ten r19 decisions back-filled as CAP-R19-1..10 **What r21 ships:** - - `_plans/capstone-decisions.md` — ADR-lite decision log, + - `_plans/final-project-decisions.md` — ADR-lite decision log, single source of truth for capstone choices - `examples/17-capstone/scripts/setup-postgres-operator.sh` — installs CloudNativePG via helm; prints the cluster-wide @@ -2195,11 +2195,11 @@ have to derive them. > Two merges: (1) append the r21a entry to Section D of > `_plans/reconciliation-plan.md`; (2) add CAP-007 to - > `_plans/capstone-decisions.md`. + > `_plans/final-project-decisions.md`. --- - ## For `_plans/capstone-decisions.md` — add CAP-007 + ## For `_plans/final-project-decisions.md` — add CAP-007 ## CAP-007 — Build images on the host with podman, then `minikube image load` @@ -2293,11 +2293,11 @@ have to derive them. > Two small merges: (1) append the r21b entry to Section D of > `_plans/reconciliation-plan.md`; (2) append the note below to CAP-005 in - > `_plans/capstone-decisions.md`. + > `_plans/final-project-decisions.md`. --- - ## For `_plans/capstone-decisions.md` — append to CAP-005's consequences + ## For `_plans/final-project-decisions.md` — append to CAP-005's consequences - **r21b amendment:** the UBI 9 python-312 image's default user (1001) cannot write to `/opt/venv` (`/opt` is root-owned), which broke the build @@ -2348,7 +2348,7 @@ have to derive them. # Decision log + reconciliation additions — r21c > Three merges: - > 1. Revise CAP-007 and add CAP-009, CAP-010 in `_plans/capstone-decisions.md` + > 1. Revise CAP-007 and add CAP-009, CAP-010 in `_plans/final-project-decisions.md` > 2. Append the r21c entry to Section D of `_plans/reconciliation-plan.md` > and promote the r21 rows to `verified (Fedora 44)` > 3. Splice the §17 friction callout into `_docs/17-capstone.md` @@ -2356,7 +2356,7 @@ have to derive them. --- - ## For `_plans/capstone-decisions.md` + ## For `_plans/final-project-decisions.md` ### CAP-007 (revised in r21c) — image distribution via the in-cluster registry @@ -3359,7 +3359,7 @@ final reader shouldn't see. Items: `presentation/` with the Data Mesh 101 deck + 15 paired SVG/Excalidraw diagrams under `data-mesh-101/`, and a README capturing the Red Hat design system (palette/fonts/layout) and the diagram→section mapping. Added - `_plans/capstone-roadmap.md` (phases A–E with the user's refinements: A/B as + `_plans/final-project-roadmap.md` (phases A–E with the user's refinements: A/B as backable-out demos, C as a one-page→section-set restructure, D as a deck reusing the 101 design system, E's demo-vision acceptance criteria). No code/cluster surface — groundwork only. Verify: site builds with the new `presentation/` diff --git a/_plans/decisions.md b/_plans/decisions.md index 2d818f7..d9278dd 100644 --- a/_plans/decisions.md +++ b/_plans/decisions.md @@ -9,9 +9,9 @@ This is the active decision log for the data-mesh reference architecture as a standalone repo. Each significant architectural or editorial choice gets a numbered entry below, with rationale and rejected alternatives. -The historical decisions from the project's earlier life as the §17 capstone +The historical decisions from the project's earlier life as the §17 final project of `patterncatalyst/minikube-on-fedora` are preserved in -`_plans/archive/capstone-decisions.md`. New decisions specific to this +`_plans/archive/final-project-decisions.md`. New decisions specific to this repo's standalone life start from DRA-001 below to avoid number-collisions with the archive's CAP-NNN series. @@ -33,10 +33,10 @@ specifically people learning minikube) was a mismatch with the parent project's title. **Decision.** Fork the data-mesh content into its own repo: -`patterncatalyst/datamesh-reference-arch-python`. The capstone-era pages +`patterncatalyst/datamesh-reference-arch-python`. The final-project-era pages become this repo's primary content collection. The runnable example tree moves to `examples/lgtm-datamesh/`. Presentations and assets come along. -The historical decision log lives at `_plans/archive/capstone-decisions.md` +The historical decision log lives at `_plans/archive/final-project-decisions.md` as the audit trail of how the implementation was built. **Consequences.** @@ -57,7 +57,7 @@ as the audit trail of how the implementation was built. **Status:** decided; implemented at `examples/lgtm-datamesh/openshift/helm/datamesh/`. -**Context.** The minikube path this capstone uses elsewhere in the reading set +**Context.** The minikube path this final project uses elsewhere in the reading set (Chapter 3) ships one umbrella Helm chart built around plain-Kubernetes assumptions — pinned `runAsUser` values, NodePort exposure, an external local registry. OpenShift's SCC, Route, and registry model (documented in this @@ -194,7 +194,7 @@ credentials for images that never need to leave the cluster. **Status:** decided; recorded in `Chart.yaml` and this appendix's "document-only counterparts" section. -**Context.** The full minikube stack this capstone documents elsewhere +**Context.** The full minikube stack this final project documents elsewhere includes the live core (seven services, Postgres, Kafka, Apicurio) plus OpenMetadata, Prefect, the full LGTM observability stack, KEDA, and Istio. Sizing a single CRC instance to run all of that concurrently with OpenShift's @@ -423,7 +423,7 @@ plainly that "tracing is off" for this chart — the OTEL_* env vars are omitted because no LGTM stack is deployed. This appendix's platform tier changes that: it deploys an observability backend and wants that "tracing is off" default reversed, but a full split Loki+Grafana+Tempo+Mimir -deployment (the shape `charts/capstone/`'s minikube path and the +deployment (the shape `charts/datamesh/`'s minikube path and the `modernizing-enterprise-applications` repo's earlier, pre-all-in-one history both used in places) is more moving parts than this reference build's platform tier needs, and the live core already runs un-instrumented — there @@ -477,7 +477,7 @@ alerts) exists yet in this build to justify the cost. **Status:** decided; implemented at `openshift/platform/keda/`. -**Context.** The minikube capstone scales two workloads with KEDA: core +**Context.** The minikube final project scales two workloads with KEDA: core KEDA's Kafka-lag trigger scales `notification-service` on consumer-group backlog, and the separate `kedacore/keda-add-ons-http` Helm chart scales `graphql-gateway` on in-flight HTTP request concurrency, including from @@ -526,8 +526,8 @@ supportability guarantee only covers what the operator itself ships. **Status:** decided; implemented at `openshift/platform/prefect/`. **Context.** Prefect 3.x OSS needs a Postgres backend for flow/task-run -state. The minikube capstone's `charts/capstone/values.yaml` `prefect` block -already documents the same choice there ("shares the capstone-postgres +state. The minikube final project's `charts/datamesh/values.yaml` `prefect` block +already documents the same choice there ("shares the datamesh-postgres cluster, separate database"), rather than bundling Prefect's own Postgres instance — consistent with this chart's existing DRA-003 stance of one shared Postgres per cluster. @@ -581,7 +581,7 @@ on a live cluster. **not applied to a live cluster** — authored offline, same posture as DRA-010's Istio placeholders. -**Context.** The minikube capstone's OpenMetadata deploy (CAP-022, +**Context.** The minikube final project's OpenMetadata deploy (CAP-022, `examples/lgtm-datamesh/openmetadata/`, `scripts/setup-openmetadata.sh`) already established the shape this chart ports: MySQL and Airflow disabled, a single-node Bitnami OpenSearch for search, Postgres reused as the backend @@ -746,10 +746,10 @@ and admission was the extra hardening fields this decision removes. ## DRA-017 — Host access: NodePorts published on 127.0.0.1 at profile creation **Status:** decided; implemented in `examples/lgtm-datamesh/demos/lib/endpoints.sh`, -`scripts/setup-capstone-profile.sh`, and `scripts/show-endpoints.sh`; enforced by +`scripts/setup-datamesh-profile.sh`, and `scripts/show-endpoints.sh`; enforced by `scripts/forbidden-syntax.sh`. -**Context.** Host access to the capstone minikube cluster (profile `capstone`, +**Context.** Host access to the final project's minikube cluster (profile `datamesh`, rootless podman) used SSH tunnels and `kubectl port-forward`. Both break or disconnect: a forwarded connection pins one pod and dies when it is replaced, and a tunnel process drops when the cluster idles or is under @@ -758,7 +758,7 @@ load. The failures surfaced as flaky smokes and dead UIs, not as clear errors **Decision.** Every host-facing service is a fixed NodePort, and the profile publishes each one to the host when it is created: -`minikube start -p capstone --ports=127.0.0.1::,...`. The +`minikube start -p datamesh --ports=127.0.0.1::,...`. The host:nodePort pairs come from the single map in `examples/lgtm-datamesh/demos/lib/endpoints.sh`. Host ports and URLs are unchanged (Grafana stays at `http://127.0.0.1:3000`). Every pair carries the @@ -781,9 +781,9 @@ status table of what is published and reachable. **Consequences.** - Published ports are fixed at creation. Adding a port means recreating the - profile; `setup-capstone-profile.sh` refuses an older profile without the - ports, and `./scripts/setup-capstone-profile.sh --replace` recreates it - (`--replace` deletes the cluster; re-run `./scripts/bootstrap-capstone.sh` afterwards). + profile; `setup-datamesh-profile.sh` refuses an older profile without the + ports, and `./scripts/setup-datamesh-profile.sh --replace` recreates it + (`--replace` deletes the cluster; re-run `./scripts/bootstrap-datamesh.sh` afterwards). - `scripts/forbidden-syntax.sh` runs in CI and fails on tunnel and port-forward wording, the retired helper names, and `--ports` values without a `127.0.0.1:` prefix. A line that must mention them (stating the @@ -797,9 +797,9 @@ status table of what is published and reachable. ## DRA-018 — In-node runtime: CRI-O with crun on the rootless-podman driver -**Status:** Superseded by DRA-019 (2026-10-08): the minikube capstone moved to Docker Engine + containerd. +**Status:** Superseded by DRA-019 (2026-10-08): the minikube final project moved to Docker Engine + containerd. -**Context.** The capstone profile ran `--driver=podman --container-runtime=containerd`. That mixes OCI runtimes: rootless podman runs the node container with crun, while containerd inside the node runs pods with runc. A fresh profile on minikube v1.38.1 also showed two node-image problems, independent of the runtime choice: +**Context.** The datamesh profile ran `--driver=podman --container-runtime=containerd`. That mixes OCI runtimes: rootless podman runs the node container with crun, while containerd inside the node runs pods with runc. A fresh profile on minikube v1.38.1 also showed two node-image problems, independent of the runtime choice: - The node image starts Docker once at first boot, before minikube masks it. Docker 29 enables IP forwarding in the node's network namespace and sets the iptables `FORWARD` policy to `DROP`. kindnet expects `ACCEPT`, so every pod-to-pod and pod-to-Service packet is dropped. CoreDNS times out and the Istio ingress gateway never becomes Ready. - Under CRI-O with crun, `minikube addons enable` fails its paused-container check, because that check calls `runc list` and `/run/runc` does not exist. @@ -808,9 +808,9 @@ status table of what is published and reachable. **Decision.** - One OCI runtime end to end: podman driver, CRI-O in the node, crun under both. minikube's CRI-O defaults to `default_runtime = "crun"`. -- `setup-capstone-profile.sh` enables addons in `minikube start --addons=metrics-server,registry,storage-provisioner-rancher`, not with `minikube addons enable`. +- `setup-datamesh-profile.sh` enables addons in `minikube start --addons=metrics-server,registry,storage-provisioner-rancher`, not with `minikube addons enable`. - `local-path` (the Rancher local-path provisioner, which creates volume directories `0777`) is the default StorageClass; `standard` stays available but is no longer the default. -- `ensure_node_forwarding` (in `demos/lib/endpoints.sh`) resets the node's `FORWARD` policy to `ACCEPT` when it finds `DROP`. `setup-capstone-profile.sh` runs it after creating or starting the profile, and `cluster-up.sh` runs it after every start. The rule lives in the node container's network namespace, not on the host. +- `ensure_node_forwarding` (in `demos/lib/endpoints.sh`) resets the node's `FORWARD` policy to `ACCEPT` when it finds `DROP`. `setup-datamesh-profile.sh` runs it after creating or starting the profile, and `cluster-up.sh` runs it after every start. The rule lives in the node container's network namespace, not on the host. **Rejected alternatives.** @@ -820,7 +820,7 @@ status table of what is published and reachable. **Consequences.** -- Existing profiles created with containerd must be recreated: `./scripts/setup-capstone-profile.sh --replace` (deletes the cluster; re-run `./scripts/bootstrap-capstone.sh` afterwards). +- Existing profiles created with containerd must be recreated: `./scripts/setup-datamesh-profile.sh --replace` (deletes the cluster; re-run `./scripts/bootstrap-datamesh.sh` afterwards). - If a future node image stops starting Docker at boot, `ensure_node_forwarding` becomes a no-op. - Any script that enables an addon later must pass it at start, or will hit the paused-check failure. @@ -836,7 +836,7 @@ status table of what is published and reachable. - Start flags: `--driver=docker --container-runtime=containerd --addons=metrics-server`, with sizing from `MINIKUBE_MEMORY` (24g), `MINIKUBE_CPUS` (16) and `MINIKUBE_DISK` (80g). One OCI runtime, runc, end to end. - Docker Engine is required: native docker-ce on Linux; the scripts are supported on Fedora and RHEL hosts (bare metal or VM), and a VM-based engine such as Docker Desktop is an option, never a requirement. The setup pre-flight rejects rootless Docker, `MINIKUBE_ROOTLESS`, and profiles created with another driver or runtime. -- Images are built with Docker Engine and loaded with `minikube image load` via `scripts/build-image.sh`. No registry. Names are `capstone/:v1` with `imagePullPolicy: Never`, not `IfNotPresent`, so a missing image fails fast instead of falling through to `docker.io/capstone/*`. `build-image.sh` restarts the Deployments that use a rebuilt image. +- Images are built with Docker Engine and loaded with `minikube image load` via `scripts/build-image.sh`. No registry. Names are `datamesh/:v1` with `imagePullPolicy: Never`, not `IfNotPresent`, so a missing image fails fast instead of falling through to `docker.io/datamesh/*`. `build-image.sh` restarts the Deployments that use a rebuilt image. - `ensure_node_forwarding` stays as a guard, with a runtime-neutral comment; it is a no-op if the `FORWARD` policy is already `ACCEPT`. - The default `standard` StorageClass is used. If CloudNativePG `initdb` reports `Permission denied`, the fallback is local-path (`storage-provisioner-rancher`). - Podman is scoped to the optional CRC appendix: per-command `--tls-verify`, host DNS for `*.apps-crc.testing`, and Red Hat tooling. @@ -848,12 +848,12 @@ status table of what is published and reachable. - Require Docker Desktop: not available or wanted on Linux; Docker Engine is enough. - Keep the registry addon: it is non-persistent, and VM-based engines cannot push to a loopback registry. - `minikube docker-env`: works only with the docker runtime, not containerd. -- `imagePullPolicy: IfNotPresent`: a missing image would fall through to `docker.io/capstone/*`. +- `imagePullPolicy: IfNotPresent`: a missing image would fall through to `docker.io/datamesh/*`. - Docker for the CRC push: the appendix follows Red Hat's podman tooling. **Consequences.** -- Profiles created with podman must be recreated: `./scripts/setup-capstone-profile.sh --replace`, then re-run `./scripts/bootstrap-capstone.sh`. +- Profiles created with podman must be recreated: `./scripts/setup-datamesh-profile.sh --replace`, then re-run `./scripts/bootstrap-datamesh.sh`. - Membership in the `docker` group is root-equivalent on the host. - CI gate scan 5 in `scripts/forbidden-syntax.sh` enforces the podman scope. - Live verification (2026-10-08/09): passed on Docker Engine 29.8.0 provided by Docker Desktop with the docker driver and containerd 2.2.1; see `_plans/reconciliation.md`. `ensure_node_forwarding` did not fire (the node's `FORWARD` policy was already `ACCEPT`). The live run also surfaced three fixes now in the scripts: bootstrap's service list ordering, endpoint checks accepting `LoadBalancer` Services, and `build-image.sh` waiting for its rollouts and for replaced pods to terminate. gRPC clients set `GRPC_DNS_RESOLVER=native`. A native (non-VM) Docker Engine run is still to do. @@ -898,10 +898,10 @@ ports what applies here. | OpenTelemetry distro / OTLP exporter | unpinned | 0.66b1 / 1.45.1 | | CRC appendix: postgres, kafka, otel-lgtm, Prefect | `postgres:16-alpine`, `kafka:3.8.0`, `otel-lgtm:0.8.1`, `prefect:3-latest` | `postgres:18.6-alpine`, `kafka:4.3.1`, `otel-lgtm:0.36.0`, `prefect:3.8.8-python3.14` | -- **Kubernetes.** `setup-capstone-profile.sh` passes `--kubernetes-version` +- **Kubernetes.** `setup-datamesh-profile.sh` passes `--kubernetes-version` (override with `KUBE_VERSION`) and refuses an existing profile whose driver, runtime or Kubernetes version differs; `--replace` recreates it. -- **Istio.** The capstone `setup-istio.sh` checks that `istioctl` on PATH +- **Istio.** The final project's `setup-istio.sh` checks that `istioctl` on PATH matches `ISTIO_VERSION` in the repo-root `scripts/setup-istio.sh`, because the binary and `~/.local/share/istio-current` are shared with other repos. - **KEDA HTTP.** `interceptor.readinessTimeout=180s` replaces the deprecated @@ -923,12 +923,12 @@ ports what applies here. committed gRPC stubs were generated for. - **Host ports.** Unchanged. This repo already publishes Prometheus on 9091 (Cockpit owns 9090 on Fedora Server and RHEL), so the parent repo's - 9090 → 19090 move does not apply. The profile name stays `capstone`. + 9090 → 19090 move does not apply. The profile name stays `datamesh`. - **Demos** (live-run fixes from the parent repo): the Kafka demos hold notification-service at one replica with `autoscaling.keda.sh/paused-replicas` (`demos/lib/keda.sh`) and release it on exit; `demo-order.sh` deploys inventory-service before ordering. Already present here: `GRPC_DNS_RESOLVER=native`, - the walkthrough's OpenMetadata check in the `capstone` namespace, and an + the walkthrough's OpenMetadata check in the `datamesh` namespace, and an in-stock SKU. The walkthrough's trace act enters through the interceptor, so it needs no gateway hold. There is no Jaeger in this stack. - **CRC appendix.** Image pins move to the newest stable tags. Operator @@ -947,9 +947,9 @@ ports what applies here. **Consequences.** -- An existing `capstone` profile on another Kubernetes version must be - recreated: `./scripts/setup-capstone-profile.sh --replace`, then - `./scripts/bootstrap-capstone.sh`. +- An existing `datamesh` profile on another Kubernetes version must be + recreated: `./scripts/setup-datamesh-profile.sh --replace`, then + `./scripts/bootstrap-datamesh.sh`. - A CRC install on postgres 16 needs a fresh PVC; Postgres 18 can't open a 16 data directory. - OpenSearch is held one minor back until OpenMetadata or its dependencies diff --git a/_plans/openshift-crc-appendix-plan.md b/_plans/openshift-crc-appendix-plan.md index 77b33f2..50ab4e4 100644 --- a/_plans/openshift-crc-appendix-plan.md +++ b/_plans/openshift-crc-appendix-plan.md @@ -10,7 +10,7 @@ Branch: `feat/openshift-crc-appendix`. ## Goal Add an appendix chapter to the datamesh-reference-arch-python tutorial teaching how to run the -existing capstone (today: minikube via helm) on a local **CRC / OpenShift Local** cluster, +existing final project (today: minikube via helm) on a local **CRC / OpenShift Local** cluster, adapting to OpenShift idioms, and **LIVE-VERIFIED** on the local CRC instance. Modeled on the modernizing-enterprise-applications Part 9 deployment chapters (real runnable assets, applied live, documenting "dry-run passed / live apply broke" learnings). diff --git a/_plans/reconciliation.md b/_plans/reconciliation.md index 070f7e4..f9d8a11 100644 --- a/_plans/reconciliation.md +++ b/_plans/reconciliation.md @@ -10,15 +10,15 @@ its standalone form. Each row records a claim made by this repo (in prose, in code, in a diagram) and its verification state. The pattern matches the archived plan: claims default to `unverified` until cluster-tested. -The historical reconciliation rows from the capstone era are preserved in +The historical reconciliation rows from the final-project era are preserved in `_plans/archive/reconciliation-plan.md`. | Status | Claim | Where | Verification | |---|---|---|---| -| **verified** | The stack runs end to end on the newest stable platform (DRA-020): Kubernetes v1.36.5 on minikube 1.39.0, Istio 1.31.1, KEDA 2.21.0 + HTTP add-on 0.16.0, Strimzi 1.2.0 with Kafka 4.3.1, CloudNativePG 0.29.1 with Postgres 18.6, Apicurio 3.3.3, OpenMetadata 2.0.5 with OpenSearch 3.4.0, services on UBI 10 + Python 3.14 | `examples/lgtm-datamesh/` (DRA-020) | Offline-grounded 2026-10-09: every chart renders at its pin; the Kafka, KafkaNodePool, KafkaTopic, Cluster, ScaledObject and HTTPScaledObject CRs validate against the Strimzi 1.2.0, CNPG 0.29.1 and KEDA 2.21.0 / HTTP 0.16.0 CRD schemas; all seven service images and a scaffolded service build with `docker build` and import on Python 3.14.8. Verified live 2026-10-09 on Fedora 44 with Docker Engine 29.8.2 (context `default`), minikube 1.39.0, a fresh `capstone` profile: `bootstrap-capstone.sh` (OpenMetadata ingestion and lineage included) → 16 `demos/demo-*.sh` green, `verify-grafana.sh`, `demo-canary.sh up 90 10` → `demo-canary-verify.sh` → `down`, `demo-add-data-product.sh up` → `down`, `restore-baseline.sh` between groups, `walkthrough.sh` 5/5 acts; then `minikube stop` → `cluster-up.sh` with all six images still in the node. Not run: `demo-service.sh` (needs a scaffolded service) and the canary `shift` step. | +| **verified** | The stack runs end to end on the newest stable platform (DRA-020): Kubernetes v1.36.5 on minikube 1.39.0, Istio 1.31.1, KEDA 2.21.0 + HTTP add-on 0.16.0, Strimzi 1.2.0 with Kafka 4.3.1, CloudNativePG 0.29.1 with Postgres 18.6, Apicurio 3.3.3, OpenMetadata 2.0.5 with OpenSearch 3.4.0, services on UBI 10 + Python 3.14 | `examples/lgtm-datamesh/` (DRA-020) | Offline-grounded 2026-10-09: every chart renders at its pin; the Kafka, KafkaNodePool, KafkaTopic, Cluster, ScaledObject and HTTPScaledObject CRs validate against the Strimzi 1.2.0, CNPG 0.29.1 and KEDA 2.21.0 / HTTP 0.16.0 CRD schemas; all seven service images and a scaffolded service build with `docker build` and import on Python 3.14.8. Verified live 2026-10-09 on Fedora 44 with Docker Engine 29.8.2 (context `default`), minikube 1.39.0, a fresh `datamesh` profile: `bootstrap-datamesh.sh` (OpenMetadata ingestion and lineage included) → 16 `demos/demo-*.sh` green, `verify-grafana.sh`, `demo-canary.sh up 90 10` → `demo-canary-verify.sh` → `down`, `demo-add-data-product.sh up` → `down`, `restore-baseline.sh` between groups, `walkthrough.sh` 5/5 acts; then `minikube stop` → `cluster-up.sh` with all six images still in the node. Not run: `demo-service.sh` (needs a scaffolded service) and the canary `shift` step. | | **unverified** | The CRC appendix runs on its bumped image pins (`postgres:18.6-alpine`, `kafka:4.3.1`, Apicurio 3.3.3, otel-lgtm 0.36.0, Prefect 3.8.8, OpenMetadata 2.0.5) | `examples/lgtm-datamesh/openshift/` (DRA-020) | `postgres:18.6-alpine` (chart `PGDATA` layout) and Kafka 4.3.1 (chart KRaft env) started under `docker run` 2026-10-09. Operator CSVs and the OSSM3 Istio version were not re-checked (no cluster); both are re-checked at the next CRC run. | -| **verified** | This repo's `examples/lgtm-datamesh/` tree builds and runs the data-mesh reference end to end, producing the same five-act walkthrough verified in the parent repo as of r28 | `examples/lgtm-datamesh/` | Verified 2026-07-04/05 on a fresh Fedora 44 host (rootless podman, minikube 1.38.1, fresh `capstone` profile): `./scripts/bootstrap-capstone.sh` then `./demos/walkthrough.sh` → 5/5 acts green, twice (once in-order, once in the shuffled suite). Caveats that verification surfaced and this repo fixed: six demo-script bugs (`5403d06`–`e22b318`), plus two host prerequisites the README didn't list — legacy `ip_tables`/`iptable_nat` kernel modules loaded on the host (Fedora is nftables-only; the rootless node can't modprobe), and minikube ≥ 1.36 (1.35's registry addon pins a dead `kube-registry-proxy` digest). | +| **verified** | This repo's `examples/lgtm-datamesh/` tree builds and runs the data-mesh reference end to end, producing the same five-act walkthrough verified in the parent repo as of r28 | `examples/lgtm-datamesh/` | Verified 2026-07-04/05 on a fresh Fedora 44 host (rootless podman, minikube 1.38.1, fresh `datamesh` profile): `./scripts/bootstrap-datamesh.sh` then `./demos/walkthrough.sh` → 5/5 acts green, twice (once in-order, once in the shuffled suite). Caveats that verification surfaced and this repo fixed: six demo-script bugs (`5403d06`–`e22b318`), plus two host prerequisites the README didn't list — legacy `ip_tables`/`iptable_nat` kernel modules loaded on the host (Fedora is nftables-only; the rootless node can't modprobe), and minikube ≥ 1.36 (1.35's registry addon pins a dead `kube-registry-proxy` digest). | | **verified** | Every demo script passes against the bootstrapped stack: all 19 `demos/demo-*.sh`, the `demo-canary.sh` cycle (up 90/10 → shift 50/50 → down), and the `demo-add-data-product.sh` cycle (up → down) | `examples/lgtm-datamesh/demos/` | Verified 2026-07-04/05, same host: two full-suite runs (24 scripted invocations each) green, with fixes landed and re-verified between them. Fix verification exercised the failure paths live (historical: re-attaching a dropped forwarded connection, since replaced by published NodePorts, DRA-017; gateway wake from scale-to-zero, interceptor cold-start 502 retry). | | **verified** | The smokes are order-independent when `scripts/restore-baseline.sh` is run between groups (the smokes' pass-cleanup, CAP-008, otherwise couples them) | `examples/lgtm-datamesh/scripts/restore-baseline.sh` | Verified 2026-07-05: full suite re-run in a deliberately shuffled order (gateway-heavy first, `demo-order` immediately after the cleanup-happy group — its prior failure position) with `restore-baseline.sh` between groups → all green. The shuffle also exposed one latent race (`demo-kafka`, fixed in `e22b318`) that two in-order runs had passed on timing. | | **verified** | `README.md`'s "Prerequisites (verified configuration)" section is sufficient for a fresh-host bring-up | `examples/lgtm-datamesh/README.md` | Gap found in the 2026-07 campaign (missing: legacy iptables kernel modules, minimum minikube version, full Istio distribution for Kiali) and closed 2026-07-05: the section now lists exactly the host state the campaign's fresh Fedora 44 bring-up required. Verified against that run's blockers rather than a second fresh host; a future fresh-host bring-up following only the README would re-confirm end to end. | -| **verified** | Host access to the `capstone` profile works through NodePorts published on `127.0.0.1` at profile creation, with unchanged host ports; an older profile is refused and recreated with `--replace`; nothing else (CRC, other profiles) runs during the workshop | `examples/lgtm-datamesh/demos/lib/endpoints.sh`, `scripts/setup-capstone-profile.sh`, `scripts/show-endpoints.sh` (DRA-017) | Verified 2026-10-08/09 on Fedora 44, minikube v1.38.1, Docker Engine 29.8.0 provided by Docker Desktop (a VM-based engine: 28 GiB, 10 CPUs; `MINIKUBE_CPUS=8 MINIKUBE_MEMORY=24g`), docker driver + containerd 2.2.1 (runc). Fresh profile: 14 loopback bindings, none on 0.0.0.0; a LAN-IP request is refused; node `FORWARD` policy already `ACCEPT` (the guard did not fire). `bootstrap-capstone.sh` green through 10/10 tiers on the default `standard` StorageClass; all 6 images loaded with `minikube image load`. `show-endpoints.sh` and `cluster-status.sh` green. Every demo passed against the bootstrapped stack (order, service inventory, reviews, notifications, kafka, avro, grpc, graphql, discovery, keda-http, keda-kafka, observability, tracing, trace-flow, verify-grafana, kiali, openmetadata, om-lineage, canary up/verify/shift/down, add-data-product up/down, debug-ephemeral); the walkthrough ran 5/5. Several demos uninstall what they deploy, so dependents ran after a re-bootstrap. `minikube stop` + `cluster-up.sh`: endpoints and all images survived; walkthrough 5/5 once OpenMetadata finished starting. Not yet run on a native (non-VM) Docker Engine. | +| **verified** | Host access to the `datamesh` profile works through NodePorts published on `127.0.0.1` at profile creation, with unchanged host ports; an older profile is refused and recreated with `--replace`; nothing else (CRC, other profiles) runs during the workshop | `examples/lgtm-datamesh/demos/lib/endpoints.sh`, `scripts/setup-datamesh-profile.sh`, `scripts/show-endpoints.sh` (DRA-017) | Verified 2026-10-08/09 on Fedora 44, minikube v1.38.1, Docker Engine 29.8.0 provided by Docker Desktop (a VM-based engine: 28 GiB, 10 CPUs; `MINIKUBE_CPUS=8 MINIKUBE_MEMORY=24g`), docker driver + containerd 2.2.1 (runc). Fresh profile: 14 loopback bindings, none on 0.0.0.0; a LAN-IP request is refused; node `FORWARD` policy already `ACCEPT` (the guard did not fire). `bootstrap-datamesh.sh` green through 10/10 tiers on the default `standard` StorageClass; all 6 images loaded with `minikube image load`. `show-endpoints.sh` and `cluster-status.sh` green. Every demo passed against the bootstrapped stack (order, service inventory, reviews, notifications, kafka, avro, grpc, graphql, discovery, keda-http, keda-kafka, observability, tracing, trace-flow, verify-grafana, kiali, openmetadata, om-lineage, canary up/verify/shift/down, add-data-product up/down, debug-ephemeral); the walkthrough ran 5/5. Several demos uninstall what they deploy, so dependents ran after a re-bootstrap. `minikube stop` + `cluster-up.sh`: endpoints and all images survived; walkthrough 5/5 once OpenMetadata finished starting. Not yet run on a native (non-VM) Docker Engine. | diff --git a/assets/diagrams/17-contracts-registry-catalog.excalidraw b/assets/diagrams/17-contracts-registry-catalog.excalidraw index 3c65a13..685f174 100644 --- a/assets/diagrams/17-contracts-registry-catalog.excalidraw +++ b/assets/diagrams/17-contracts-registry-catalog.excalidraw @@ -431,11 +431,11 @@ "locked": false, "fontSize": 9.5, "fontFamily": 3, - "text": "capstone.inventory.v1", + "text": "datamesh.inventory.v1", "textAlign": "middle", "verticalAlign": "top", "containerId": null, - "originalText": "capstone.inventory.v1", + "originalText": "datamesh.inventory.v1", "lineHeight": 1.25 }, { diff --git a/assets/diagrams/17-contracts-registry-catalog.svg b/assets/diagrams/17-contracts-registry-catalog.svg index a95cf7e..8bc6f9c 100644 --- a/assets/diagrams/17-contracts-registry-catalog.svg +++ b/assets/diagrams/17-contracts-registry-catalog.svg @@ -1 +1 @@ -Contracts, the registry, and the catalogevery protocol's contract lives in Apicurio; OpenMetadata builds lineage from itPROTOCOL SURFACES — EACH SERVICE'S CONTRACTREST (order-service)contract = OpenAPI document/openapi.json○ discovery contractgRPC (inventory-service)contract = Protobuf (.proto)capstone.inventory.v1○ discovery contractGraphQL (graphql-gateway)contract = GraphQL SDLschema.graphql○ discovery contractKafka events (order→notification)contract = Avro schemaorder.placed● RUNTIME contractApicurio Registry — the contract metadata (one home, many formats)OpenAPI artifactsREST surfaces○ discoveryProtobuf artifactsgRPC service defs○ discoveryGraphQL SDLgateway schema○ discoveryAvro schemasevent payloads● RUNTIMEpublish (discovery) / register (runtime)OpenMetadata — lineage & discovery metadataingests contracts + data sources, assembles the “who produces / who consumes” graphlineage graphorder-service—[ order.placed ]→ notification-servicePostgres schemasper service (CNPG)Kafka topics(Strimzi)ingest contractsingest data sources alongside the contracts → lineage \ No newline at end of file +Contracts, the registry, and the catalogevery protocol's contract lives in Apicurio; OpenMetadata builds lineage from itPROTOCOL SURFACES — EACH SERVICE'S CONTRACTREST (order-service)contract = OpenAPI document/openapi.json○ discovery contractgRPC (inventory-service)contract = Protobuf (.proto)datamesh.inventory.v1○ discovery contractGraphQL (graphql-gateway)contract = GraphQL SDLschema.graphql○ discovery contractKafka events (order→notification)contract = Avro schemaorder.placed● RUNTIME contractApicurio Registry — the contract metadata (one home, many formats)OpenAPI artifactsREST surfaces○ discoveryProtobuf artifactsgRPC service defs○ discoveryGraphQL SDLgateway schema○ discoveryAvro schemasevent payloads● RUNTIMEpublish (discovery) / register (runtime)OpenMetadata — lineage & discovery metadataingests contracts + data sources, assembles the “who produces / who consumes” graphlineage graphorder-service—[ order.placed ]→ notification-servicePostgres schemasper service (CNPG)Kafka topics(Strimzi)ingest contractsingest data sources alongside the contracts → lineage \ No newline at end of file diff --git a/assets/diagrams/17-capstone-contract-flow.excalidraw b/assets/diagrams/17-final-project-contract-flow.excalidraw similarity index 100% rename from assets/diagrams/17-capstone-contract-flow.excalidraw rename to assets/diagrams/17-final-project-contract-flow.excalidraw diff --git a/assets/diagrams/17-capstone-contract-flow.svg b/assets/diagrams/17-final-project-contract-flow.svg similarity index 100% rename from assets/diagrams/17-capstone-contract-flow.svg rename to assets/diagrams/17-final-project-contract-flow.svg diff --git a/assets/diagrams/17-capstone-contracts.excalidraw b/assets/diagrams/17-final-project-contracts.excalidraw similarity index 100% rename from assets/diagrams/17-capstone-contracts.excalidraw rename to assets/diagrams/17-final-project-contracts.excalidraw diff --git a/assets/diagrams/17-capstone-contracts.svg b/assets/diagrams/17-final-project-contracts.svg similarity index 99% rename from assets/diagrams/17-capstone-contracts.svg rename to assets/diagrams/17-final-project-contracts.svg index 6d3cc15..d87f7cc 100644 --- a/assets/diagrams/17-capstone-contracts.svg +++ b/assets/diagrams/17-final-project-contracts.svg @@ -46,7 +46,7 @@ gRPC (inventory-service) contract = Protobuf (.proto) - capstone.inventory.v1 + datamesh.inventory.v1 diff --git a/assets/diagrams/17-capstone-data-mesh.excalidraw b/assets/diagrams/17-final-project-data-mesh.excalidraw similarity index 91% rename from assets/diagrams/17-capstone-data-mesh.excalidraw rename to assets/diagrams/17-final-project-data-mesh.excalidraw index 7bf5ab6..eaa8d4f 100644 --- a/assets/diagrams/17-capstone-data-mesh.excalidraw +++ b/assets/diagrams/17-final-project-data-mesh.excalidraw @@ -31,11 +31,11 @@ "locked": false, "fontSize": 20, "fontFamily": 1, - "text": "§17 Capstone — A data mesh on minikube", + "text": "§17 Final Project — A data mesh on minikube", "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "§17 Capstone — A data mesh on minikube", + "originalText": "§17 Final Project — A data mesh on minikube", "lineHeight": 1.25 }, { @@ -66,11 +66,11 @@ "locked": false, "fontSize": 14, "fontFamily": 1, - "text": "This file is a starting-point stub. The authoritative diagram is at\nassets/diagrams/17-capstone-data-mesh.svg — open that for the\nrendered version. To edit collaboratively, recreate the diagram in\nExcalidraw using the SVG as reference, then export back to SVG.", + "text": "This file is a starting-point stub. The authoritative diagram is at\nassets/diagrams/17-final-project-data-mesh.svg — open that for the\nrendered version. To edit collaboratively, recreate the diagram in\nExcalidraw using the SVG as reference, then export back to SVG.", "textAlign": "left", "verticalAlign": "top", "containerId": null, - "originalText": "This file is a starting-point stub. The authoritative diagram is at\nassets/diagrams/17-capstone-data-mesh.svg — open that for the\nrendered version. To edit collaboratively, recreate the diagram in\nExcalidraw using the SVG as reference, then export back to SVG.", + "originalText": "This file is a starting-point stub. The authoritative diagram is at\nassets/diagrams/17-final-project-data-mesh.svg — open that for the\nrendered version. To edit collaboratively, recreate the diagram in\nExcalidraw using the SVG as reference, then export back to SVG.", "lineHeight": 1.25 }, { diff --git a/assets/diagrams/17-capstone-data-mesh.svg b/assets/diagrams/17-final-project-data-mesh.svg similarity index 99% rename from assets/diagrams/17-capstone-data-mesh.svg rename to assets/diagrams/17-final-project-data-mesh.svg index 164de29..c91acc1 100644 --- a/assets/diagrams/17-capstone-data-mesh.svg +++ b/assets/diagrams/17-final-project-data-mesh.svg @@ -47,7 +47,7 @@ - §17 Capstone — A data mesh on minikube + §17 Final Project — A data mesh on minikube diff --git a/demos.html b/demos.html index cc67697..cc871e2 100644 --- a/demos.html +++ b/demos.html @@ -247,7 +247,7 @@

HTTP request scaling (KEDA)

Self-serve platform · Prometheus

Metrics stack health

- Prometheus scraping capstone targets, Grafana dashboard + Prometheus scraping final-project targets, Grafana dashboard provisioned with mesh and request-rate panels. The platform delivers observability.

@@ -321,7 +321,7 @@

Canary demo (repeatable)

Federated governance · topology

Kiali mesh topology

- Kiali API answers, Prometheus reachable, capstone + Kiali API answers, Prometheus reachable, datamesh namespace visible in the graph. The mesh is observable as a first-class surface.

@@ -338,7 +338,7 @@

Running a demo

All demos assume you are in the examples/lgtm-datamesh/ directory with kubectl - context set to capstone. See the + context set to datamesh. See the setup & prerequisites page for installation and bootstrap.

@@ -348,13 +348,13 @@

Running a demo

What to look at after running a demo

The tools are NodePorts published on 127.0.0.1 when - the capstone profile is created, so the URLs below + the datamesh profile is created, so the URLs below are available as soon as the stack is up. Run ./scripts/show-endpoints.sh to see which are reachable. Ports are fixed at creation; recreate an older profile - with ./scripts/setup-capstone-profile.sh --replace. + with ./scripts/setup-datamesh-profile.sh --replace. --replace deletes and recreates the cluster, so run - ./scripts/bootstrap-capstone.sh again afterwards. + ./scripts/bootstrap-datamesh.sh again afterwards.

  • diff --git a/examples/lgtm-datamesh/README.md b/examples/lgtm-datamesh/README.md index 738f7da..211fd38 100644 --- a/examples/lgtm-datamesh/README.md +++ b/examples/lgtm-datamesh/README.md @@ -25,7 +25,7 @@ Before running anything, verify these four prerequisites: 2. **inotify limits** — raised above Fedora defaults 3. **Tooling** — minikube >= 1.39.0, kubectl 1.36, helm, istioctl 1.31.1 + full Istio distribution (see [Required tooling](#required-tooling)) -4. **Bootstrap** — `./scripts/bootstrap-capstone.sh` +4. **Bootstrap** — `./scripts/bootstrap-datamesh.sh` Once that's green, the presenter walkthrough exercises end-to-end behavior across five acts (trace, scale, canary, lineage, topology): @@ -43,7 +43,7 @@ examples/lgtm-datamesh/ ├── README.md ← this file ├── README.archive.md ← the original capstone-era README ├── charts/ ← helm charts for every component -│ └── capstone/ ← umbrella chart +│ └── datamesh/ ← umbrella chart ├── scripts/ ← bootstrap, setup-* helpers per component, │ restore-baseline, teardown ├── proto/ ← protobuf definitions for the gRPC services @@ -73,13 +73,13 @@ RAM-constrained. | Requirement | Minimum | Notes | |-------------|---------|-------| | OS | Fedora 44 | Docker Engine (docker-ce) as the container runtime | -| RAM | 64 GB | the `capstone` minikube profile uses 24 GB; rest is host headroom | +| RAM | 64 GB | the `datamesh` minikube profile uses 24 GB; rest is host headroom | | Disk | 1 TB | about 100 GB free under the Docker data root (`/var/lib/docker`) | | CPU | 16 vCPU recommended | not strictly required but the stack is heavy | ### Container engine & host tuning -The capstone runs on **Docker Engine** (native docker-ce). The +The datamesh stack runs on **Docker Engine** (native docker-ce). The scripts are supported on Fedora and RHEL hosts (bare metal or VM). A VM-based engine such as Docker Desktop also works if its VM is sized for the node; it is never required. @@ -88,22 +88,22 @@ Start flags: `--driver=docker --container-runtime=containerd host. Podman: used only by the optional OpenShift (CRC) appendix. -**Upgrading from an earlier (rootless podman) capstone profile.** +**Upgrading from an earlier (rootless podman) datamesh profile.** Delete the old profile first, then clear the setting, then run setup: ```bash -MINIKUBE_ROOTLESS=true minikube delete -p capstone # forbidden-ok +MINIKUBE_ROOTLESS=true minikube delete -p datamesh # forbidden-ok minikube config unset rootless # forbidden-ok -./scripts/setup-capstone-profile.sh +./scripts/setup-datamesh-profile.sh ``` Profile sizing defaults can be overridden before bootstrap: ```bash -MINIKUBE_CPUS=16 MINIKUBE_MEMORY=24g MINIKUBE_DISK=80g ./scripts/bootstrap-capstone.sh +MINIKUBE_CPUS=16 MINIKUBE_MEMORY=24g MINIKUBE_DISK=80g ./scripts/bootstrap-datamesh.sh ``` -**inotify limits.** The capstone runs many controllers; Fedora's default +**inotify limits.** The datamesh stack runs many controllers; Fedora's default of 128 instances is not enough: ```bash @@ -146,7 +146,7 @@ The bootstrap script audits all prerequisites before doing any work. Bring the whole system up on a fresh minikube profile: ```bash -./scripts/bootstrap-capstone.sh +./scripts/bootstrap-datamesh.sh ``` Bootstrap runs 10 tiers: minikube profile (images are then built and loaded with @@ -181,7 +181,7 @@ between them. Press Enter to advance. ### Individual demos All demos assume you are in the `examples/lgtm-datamesh/` directory with -kubectl context set to `capstone`. +kubectl context set to `datamesh`. | Script | What it demonstrates | Principle | Tutorial page | |--------|---------------------|-----------|---------------| @@ -212,12 +212,12 @@ kubectl context set to `capstone`. ### Observing the results -Host access uses NodePorts published on `127.0.0.1` when the `capstone` +Host access uses NodePorts published on `127.0.0.1` when the `datamesh` minikube profile is created (`--ports=127.0.0.1::`, built from `demos/lib/endpoints.sh`). Nothing runs in the background and nothing needs to be started per demo. Ports are fixed at creation, so an -older profile without them is refused by `scripts/setup-capstone-profile.sh`; -recreate it with `./scripts/setup-capstone-profile.sh --replace`. `--replace` deletes and recreates the cluster, so run `./scripts/bootstrap-capstone.sh` again afterwards. Run the +older profile without them is refused by `scripts/setup-datamesh-profile.sh`; +recreate it with `./scripts/setup-datamesh-profile.sh --replace`. `--replace` deletes and recreates the cluster, so run `./scripts/bootstrap-datamesh.sh` again afterwards. Run the workshop in isolation: shut down CRC, other minikube profiles, and other workloads first so the host ports are free. @@ -239,7 +239,7 @@ Default credentials: | Tool | User | Password | |------|------|----------| -| Grafana | `admin` | `capstone` | +| Grafana | `admin` | `datamesh` | | OpenMetadata | `admin@open-metadata.org` | `admin` | ## Restoring baseline @@ -264,7 +264,7 @@ state. the same prerequisites as above, formatted for the web. - The [demo & example reference](/demos/) page — every demo mapped to its data-mesh principle with descriptions and source links. -- The historical decision log (`_plans/archive/capstone-decisions.md` +- The historical decision log (`_plans/archive/final-project-decisions.md` at the repo root) — every architectural choice from CAP-001 through CAP-047 with rationale and rejected alternatives. - The active decision log (`_plans/decisions.md` at the repo root) — diff --git a/examples/lgtm-datamesh/charts/capstone/charts/kafka-ui/Chart.yaml b/examples/lgtm-datamesh/charts/capstone/charts/kafka-ui/Chart.yaml deleted file mode 100644 index a6c4bfa..0000000 --- a/examples/lgtm-datamesh/charts/capstone/charts/kafka-ui/Chart.yaml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: v2 -name: kafka-ui -description: Kafka UI (kafbat) for the §17 capstone — a data-mesh infrastructure console to browse Kafka topics, messages, consumer groups, and (via Apicurio ccompat) schemas. -type: application -version: 0.1.0 -appVersion: "v1.5.0" diff --git a/examples/lgtm-datamesh/charts/capstone/Chart.yaml b/examples/lgtm-datamesh/charts/datamesh/Chart.yaml similarity index 79% rename from examples/lgtm-datamesh/charts/capstone/Chart.yaml rename to examples/lgtm-datamesh/charts/datamesh/Chart.yaml index be0ff26..4ef8798 100644 --- a/examples/lgtm-datamesh/charts/capstone/Chart.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/Chart.yaml @@ -1,13 +1,13 @@ apiVersion: v2 -name: capstone -description: §17 capstone data-mesh umbrella chart — orchestrates platform components (Strimzi, KEDA, Istio, observability, Apicurio, OpenMetadata, Prefect, Postgres) and the five domain services (order, inventory, payment, shipping, notification). +name: datamesh +description: §17 final project data-mesh umbrella chart — orchestrates platform components (Strimzi, KEDA, Istio, observability, Apicurio, OpenMetadata, Prefect, Postgres) and the five domain services (order, inventory, payment, shipping, notification). type: application version: 0.1.0-skeleton appVersion: "r20" keywords: - data-mesh - tutorial - - capstone + - datamesh - minikube - fedora sources: diff --git a/examples/lgtm-datamesh/charts/capstone/charts/apicurio/Chart.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/apicurio/Chart.yaml similarity index 51% rename from examples/lgtm-datamesh/charts/capstone/charts/apicurio/Chart.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/apicurio/Chart.yaml index 9653e59..28df9cf 100644 --- a/examples/lgtm-datamesh/charts/capstone/charts/apicurio/Chart.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/charts/apicurio/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: apicurio -description: Apicurio Registry 3 (schema registry) for the §17 capstone — in-memory storage (dev). Holds the order.placed Avro contract; multi-format home for all protocol contracts (CAP-018). +description: Apicurio Registry 3 (schema registry) for the §17 final project — in-memory storage (dev). Holds the order.placed Avro contract; multi-format home for all protocol contracts (CAP-018). type: application version: 0.1.0 appVersion: "3.3.3" diff --git a/examples/lgtm-datamesh/charts/capstone/charts/apicurio/templates/deployment.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/apicurio/templates/deployment.yaml similarity index 95% rename from examples/lgtm-datamesh/charts/capstone/charts/apicurio/templates/deployment.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/apicurio/templates/deployment.yaml index 7b2f36c..a4361cd 100644 --- a/examples/lgtm-datamesh/charts/capstone/charts/apicurio/templates/deployment.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/charts/apicurio/templates/deployment.yaml @@ -5,7 +5,7 @@ metadata: namespace: {{ .Release.Namespace }} labels: app.kubernetes.io/name: apicurio - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh app.kubernetes.io/component: schema-registry spec: replicas: {{ .Values.replicas }} @@ -16,7 +16,7 @@ spec: metadata: labels: app.kubernetes.io/name: apicurio - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh spec: containers: - name: apicurio diff --git a/examples/lgtm-datamesh/charts/capstone/charts/apicurio/templates/service.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/apicurio/templates/service.yaml similarity index 93% rename from examples/lgtm-datamesh/charts/capstone/charts/apicurio/templates/service.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/apicurio/templates/service.yaml index 7d338a5..ab68c49 100644 --- a/examples/lgtm-datamesh/charts/capstone/charts/apicurio/templates/service.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/charts/apicurio/templates/service.yaml @@ -5,7 +5,7 @@ metadata: namespace: {{ .Release.Namespace }} labels: app.kubernetes.io/name: apicurio - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh spec: type: {{ .Values.service.type | default "ClusterIP" }} selector: diff --git a/examples/lgtm-datamesh/charts/capstone/charts/apicurio/values.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/apicurio/values.yaml similarity index 100% rename from examples/lgtm-datamesh/charts/capstone/charts/apicurio/values.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/apicurio/values.yaml diff --git a/examples/lgtm-datamesh/charts/capstone/charts/graphql-gateway/Chart.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/graphql-gateway/Chart.yaml similarity index 100% rename from examples/lgtm-datamesh/charts/capstone/charts/graphql-gateway/Chart.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/graphql-gateway/Chart.yaml diff --git a/examples/lgtm-datamesh/charts/capstone/charts/graphql-gateway/templates/deployment.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/graphql-gateway/templates/deployment.yaml similarity index 96% rename from examples/lgtm-datamesh/charts/capstone/charts/graphql-gateway/templates/deployment.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/graphql-gateway/templates/deployment.yaml index 1aa9b7e..ad0f9a8 100644 --- a/examples/lgtm-datamesh/charts/capstone/charts/graphql-gateway/templates/deployment.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/charts/graphql-gateway/templates/deployment.yaml @@ -5,7 +5,7 @@ metadata: namespace: {{ .Release.Namespace }} labels: app.kubernetes.io/name: graphql-gateway - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh app.kubernetes.io/component: gateway spec: replicas: {{ .Values.replicas }} @@ -16,7 +16,7 @@ spec: metadata: labels: app.kubernetes.io/name: graphql-gateway - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh annotations: # r26b: keep the gateway OUT of the mesh. The namespace is # injection-labeled (r26), but the KEDA HTTP add-on's interceptor fronts @@ -56,7 +56,7 @@ spec: - name: OTEL_TRACES_SAMPLER_ARG value: {{ .Values.tracing.sampleRatio | quote }} - name: OTEL_RESOURCE_ATTRIBUTES - value: "service.namespace=capstone" + value: "service.namespace=datamesh" {{- end }} resources: requests: diff --git a/examples/lgtm-datamesh/charts/capstone/charts/graphql-gateway/templates/service.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/graphql-gateway/templates/service.yaml similarity index 89% rename from examples/lgtm-datamesh/charts/capstone/charts/graphql-gateway/templates/service.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/graphql-gateway/templates/service.yaml index 1d42a6c..e927261 100644 --- a/examples/lgtm-datamesh/charts/capstone/charts/graphql-gateway/templates/service.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/charts/graphql-gateway/templates/service.yaml @@ -5,7 +5,7 @@ metadata: namespace: {{ .Release.Namespace }} labels: app.kubernetes.io/name: graphql-gateway - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh spec: type: ClusterIP selector: diff --git a/examples/lgtm-datamesh/charts/capstone/charts/graphql-gateway/values.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/graphql-gateway/values.yaml similarity index 98% rename from examples/lgtm-datamesh/charts/capstone/charts/graphql-gateway/values.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/graphql-gateway/values.yaml index 06aaf0d..13534ff 100644 --- a/examples/lgtm-datamesh/charts/capstone/charts/graphql-gateway/values.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/charts/graphql-gateway/values.yaml @@ -4,7 +4,7 @@ replicas: 1 image: # Image is loaded into the node by build-image.sh (minikube image load); no registry. - repository: capstone/graphql-gateway + repository: datamesh/graphql-gateway tag: v1 # Never: images are loaded into the node by build-image.sh (minikube image load) and never pulled; build-image.sh restarts the Deployment so a rebuilt :v1 is used. pullPolicy: Never diff --git a/examples/lgtm-datamesh/charts/capstone/charts/inventory-service/Chart.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/inventory-service/Chart.yaml similarity index 76% rename from examples/lgtm-datamesh/charts/capstone/charts/inventory-service/Chart.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/inventory-service/Chart.yaml index 6cf7790..fed8767 100644 --- a/examples/lgtm-datamesh/charts/capstone/charts/inventory-service/Chart.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/charts/inventory-service/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: inventory-service -description: inventory-service data product — FastAPI service backed by the capstone Postgres (inventory schema). r22 ships the health skeleton; domain surface added later. +description: inventory-service data product — FastAPI service backed by the datamesh Postgres (inventory schema). r22 ships the health skeleton; domain surface added later. type: application version: 0.1.0 appVersion: "0.1.0" diff --git a/examples/lgtm-datamesh/charts/capstone/charts/inventory-service/templates/deployment.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/inventory-service/templates/deployment.yaml similarity index 96% rename from examples/lgtm-datamesh/charts/capstone/charts/inventory-service/templates/deployment.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/inventory-service/templates/deployment.yaml index 419a64c..21e04d5 100644 --- a/examples/lgtm-datamesh/charts/capstone/charts/inventory-service/templates/deployment.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/charts/inventory-service/templates/deployment.yaml @@ -5,7 +5,7 @@ metadata: namespace: {{ .Release.Namespace }} labels: app.kubernetes.io/name: inventory-service - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh app.kubernetes.io/component: data-product spec: replicas: {{ .Values.replicas }} @@ -16,7 +16,7 @@ spec: metadata: labels: app.kubernetes.io/name: inventory-service - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh spec: containers: - name: inventory-service @@ -70,7 +70,7 @@ spec: - name: OTEL_TRACES_SAMPLER_ARG value: {{ .Values.tracing.sampleRatio | quote }} - name: OTEL_RESOURCE_ATTRIBUTES - value: "service.namespace=capstone" + value: "service.namespace=datamesh" {{- end }} resources: requests: diff --git a/examples/lgtm-datamesh/charts/capstone/charts/inventory-service/templates/service.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/inventory-service/templates/service.yaml similarity index 94% rename from examples/lgtm-datamesh/charts/capstone/charts/inventory-service/templates/service.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/inventory-service/templates/service.yaml index 8ec2d42..1f24a5c 100644 --- a/examples/lgtm-datamesh/charts/capstone/charts/inventory-service/templates/service.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/charts/inventory-service/templates/service.yaml @@ -5,7 +5,7 @@ metadata: namespace: {{ .Release.Namespace }} labels: app.kubernetes.io/name: inventory-service - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh spec: type: {{ .Values.service.type | default "ClusterIP" }} selector: diff --git a/examples/lgtm-datamesh/charts/capstone/charts/inventory-service/values.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/inventory-service/values.yaml similarity index 93% rename from examples/lgtm-datamesh/charts/capstone/charts/inventory-service/values.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/inventory-service/values.yaml index b0a99f4..c2a8e19 100644 --- a/examples/lgtm-datamesh/charts/capstone/charts/inventory-service/values.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/charts/inventory-service/values.yaml @@ -4,7 +4,7 @@ replicas: 1 image: # Image is loaded into the node by build-image.sh (minikube image load); no registry. - repository: capstone/inventory-service + repository: datamesh/inventory-service tag: v1 # Never: images are loaded into the node by build-image.sh (minikube image load) and never pulled; build-image.sh restarts the Deployment so a rebuilt :v1 is used. pullPolicy: Never @@ -22,8 +22,8 @@ service: # Postgres connection. The CloudNativePG operator generates a Secret named # "-app" holding the app user's credentials; we reference it by key. postgres: - clusterName: capstone-postgres - appSecret: capstone-postgres-app + clusterName: datamesh-postgres + appSecret: datamesh-postgres-app schema: inventory tracing: diff --git a/examples/lgtm-datamesh/charts/datamesh/charts/kafka-ui/Chart.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/kafka-ui/Chart.yaml new file mode 100644 index 0000000..8ed1ef8 --- /dev/null +++ b/examples/lgtm-datamesh/charts/datamesh/charts/kafka-ui/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: kafka-ui +description: Kafka UI (kafbat) for the §17 final project — a data-mesh infrastructure console to browse Kafka topics, messages, consumer groups, and (via Apicurio ccompat) schemas. +type: application +version: 0.1.0 +appVersion: "v1.5.0" diff --git a/examples/lgtm-datamesh/charts/capstone/charts/kafka-ui/templates/deployment.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/kafka-ui/templates/deployment.yaml similarity index 96% rename from examples/lgtm-datamesh/charts/capstone/charts/kafka-ui/templates/deployment.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/kafka-ui/templates/deployment.yaml index 9947253..1a4cc8f 100644 --- a/examples/lgtm-datamesh/charts/capstone/charts/kafka-ui/templates/deployment.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/charts/kafka-ui/templates/deployment.yaml @@ -5,7 +5,7 @@ metadata: namespace: {{ .Release.Namespace }} labels: app.kubernetes.io/name: kafka-ui - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh app.kubernetes.io/component: kafka-console spec: replicas: {{ .Values.replicas }} @@ -16,7 +16,7 @@ spec: metadata: labels: app.kubernetes.io/name: kafka-ui - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh annotations: # Opt out of the mesh: kafka-ui talks to the (non-meshed) Kafka bootstrap # and Apicurio; a sidecar would only complicate that. Matches the other diff --git a/examples/lgtm-datamesh/charts/capstone/charts/kafka-ui/templates/service.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/kafka-ui/templates/service.yaml similarity index 93% rename from examples/lgtm-datamesh/charts/capstone/charts/kafka-ui/templates/service.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/kafka-ui/templates/service.yaml index 7d1830d..fe0caad 100644 --- a/examples/lgtm-datamesh/charts/capstone/charts/kafka-ui/templates/service.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/charts/kafka-ui/templates/service.yaml @@ -5,7 +5,7 @@ metadata: namespace: {{ .Release.Namespace }} labels: app.kubernetes.io/name: kafka-ui - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh spec: type: {{ .Values.service.type | default "ClusterIP" }} selector: diff --git a/examples/lgtm-datamesh/charts/capstone/charts/kafka-ui/values.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/kafka-ui/values.yaml similarity index 89% rename from examples/lgtm-datamesh/charts/capstone/charts/kafka-ui/values.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/kafka-ui/values.yaml index a3f79a3..139ad2d 100644 --- a/examples/lgtm-datamesh/charts/capstone/charts/kafka-ui/values.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/charts/kafka-ui/values.yaml @@ -10,8 +10,8 @@ image: pullPolicy: IfNotPresent kafka: - clusterName: capstone-kafka - bootstrapServers: capstone-kafka-kafka-bootstrap:9092 + clusterName: datamesh-kafka + bootstrapServers: datamesh-kafka-kafka-bootstrap:9092 # Apicurio's Confluent-compatible endpoint, so the UI renders Avro schemas too. schemaRegistry: http://apicurio:8080/apis/ccompat/v7 diff --git a/examples/lgtm-datamesh/charts/capstone/charts/kafka/Chart.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/kafka/Chart.yaml similarity index 61% rename from examples/lgtm-datamesh/charts/capstone/charts/kafka/Chart.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/kafka/Chart.yaml index 882cf98..6f1ad12 100644 --- a/examples/lgtm-datamesh/charts/capstone/charts/kafka/Chart.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/charts/kafka/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: kafka -description: Single-node KRaft Kafka cluster (Strimzi CRs) for the §17 capstone async spine. Dev-scale — ephemeral storage, replication factor 1. +description: Single-node KRaft Kafka cluster (Strimzi CRs) for the §17 final project async spine. Dev-scale — ephemeral storage, replication factor 1. type: application version: 0.1.0 appVersion: "0.1.0" diff --git a/examples/lgtm-datamesh/charts/capstone/charts/kafka/templates/kafka.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/kafka/templates/kafka.yaml similarity index 100% rename from examples/lgtm-datamesh/charts/capstone/charts/kafka/templates/kafka.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/kafka/templates/kafka.yaml diff --git a/examples/lgtm-datamesh/charts/capstone/charts/kafka/templates/nodepool.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/kafka/templates/nodepool.yaml similarity index 100% rename from examples/lgtm-datamesh/charts/capstone/charts/kafka/templates/nodepool.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/kafka/templates/nodepool.yaml diff --git a/examples/lgtm-datamesh/charts/capstone/charts/kafka/templates/topic.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/kafka/templates/topic.yaml similarity index 100% rename from examples/lgtm-datamesh/charts/capstone/charts/kafka/templates/topic.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/kafka/templates/topic.yaml diff --git a/examples/lgtm-datamesh/charts/capstone/charts/kafka/values.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/kafka/values.yaml similarity index 82% rename from examples/lgtm-datamesh/charts/capstone/charts/kafka/values.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/kafka/values.yaml index 10f36f4..4808750 100644 --- a/examples/lgtm-datamesh/charts/capstone/charts/kafka/values.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/charts/kafka/values.yaml @@ -1,9 +1,9 @@ -# Single-node KRaft Kafka cluster for the capstone async spine. +# Single-node KRaft Kafka cluster for the datamesh async spine. # Dev-scale: one dual-role node, ephemeral storage, replication factor 1. # Production would use separate broker/controller pools, persistent storage, # replication factor 3, and min.insync.replicas 2 (noted in §17 prose). -clusterName: capstone-kafka +clusterName: datamesh-kafka # Apache Kafka version (Strimzi 1.2.0 supports 4.2.0, 4.2.1, 4.3.0, 4.3.1). version: "4.3.1" replicas: 1 diff --git a/examples/lgtm-datamesh/charts/capstone/charts/notification-service/Chart.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/notification-service/Chart.yaml similarity index 76% rename from examples/lgtm-datamesh/charts/capstone/charts/notification-service/Chart.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/notification-service/Chart.yaml index 1b755c8..11aff1a 100644 --- a/examples/lgtm-datamesh/charts/capstone/charts/notification-service/Chart.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/charts/notification-service/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: notification-service -description: notification-service data product — FastAPI service backed by the capstone Postgres (notifications schema). r22 ships the health skeleton; domain surface added later. +description: notification-service data product — FastAPI service backed by the datamesh Postgres (notifications schema). r22 ships the health skeleton; domain surface added later. type: application version: 0.1.0 appVersion: "0.1.0" diff --git a/examples/lgtm-datamesh/charts/capstone/charts/notification-service/templates/deployment.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/notification-service/templates/deployment.yaml similarity index 97% rename from examples/lgtm-datamesh/charts/capstone/charts/notification-service/templates/deployment.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/notification-service/templates/deployment.yaml index 4b338ee..7e14787 100644 --- a/examples/lgtm-datamesh/charts/capstone/charts/notification-service/templates/deployment.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/charts/notification-service/templates/deployment.yaml @@ -5,7 +5,7 @@ metadata: namespace: {{ .Release.Namespace }} labels: app.kubernetes.io/name: notification-service - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh app.kubernetes.io/component: data-product spec: replicas: {{ .Values.replicas }} @@ -16,7 +16,7 @@ spec: metadata: labels: app.kubernetes.io/name: notification-service - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh annotations: # r26b: keep this KEDA-scaled consumer OUT of the mesh. The namespace is # injection-labeled (r26, for the order-service canary), so without this @@ -111,7 +111,7 @@ spec: - name: OTEL_TRACES_SAMPLER_ARG value: {{ .Values.tracing.sampleRatio | quote }} - name: OTEL_RESOURCE_ATTRIBUTES - value: "service.namespace=capstone" + value: "service.namespace=datamesh" {{- end }} resources: requests: diff --git a/examples/lgtm-datamesh/charts/capstone/charts/notification-service/templates/service.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/notification-service/templates/service.yaml similarity index 93% rename from examples/lgtm-datamesh/charts/capstone/charts/notification-service/templates/service.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/notification-service/templates/service.yaml index adb6286..905dbdc 100644 --- a/examples/lgtm-datamesh/charts/capstone/charts/notification-service/templates/service.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/charts/notification-service/templates/service.yaml @@ -5,7 +5,7 @@ metadata: namespace: {{ .Release.Namespace }} labels: app.kubernetes.io/name: notification-service - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh spec: type: {{ .Values.service.type | default "ClusterIP" }} selector: diff --git a/examples/lgtm-datamesh/charts/capstone/charts/notification-service/values.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/notification-service/values.yaml similarity index 92% rename from examples/lgtm-datamesh/charts/capstone/charts/notification-service/values.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/notification-service/values.yaml index 72c829f..c69d8f9 100644 --- a/examples/lgtm-datamesh/charts/capstone/charts/notification-service/values.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/charts/notification-service/values.yaml @@ -4,7 +4,7 @@ replicas: 1 image: # Image is loaded into the node by build-image.sh (minikube image load); no registry. - repository: capstone/notification-service + repository: datamesh/notification-service tag: v1 # Never: images are loaded into the node by build-image.sh (minikube image load) and never pulled; build-image.sh restarts the Deployment so a rebuilt :v1 is used. pullPolicy: Never @@ -21,13 +21,13 @@ service: # Postgres connection. The CloudNativePG operator generates a Secret named # "-app" holding the app user's credentials; we reference it by key. postgres: - clusterName: capstone-postgres - appSecret: capstone-postgres-app + clusterName: datamesh-postgres + appSecret: datamesh-postgres-app schema: notifications # Kafka (r25) — consumes order.placed events. kafka: - bootstrap: capstone-kafka-kafka-bootstrap:9092 + bootstrap: datamesh-kafka-kafka-bootstrap:9092 orderTopic: order-placed group: notification-service diff --git a/examples/lgtm-datamesh/charts/capstone/charts/order-service/Chart.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/order-service/Chart.yaml similarity index 75% rename from examples/lgtm-datamesh/charts/capstone/charts/order-service/Chart.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/order-service/Chart.yaml index 811c392..c523443 100644 --- a/examples/lgtm-datamesh/charts/capstone/charts/order-service/Chart.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/charts/order-service/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: order-service -description: order-service data product — FastAPI REST service backed by the capstone Postgres (orders schema). r21 ships REST + Postgres; gRPC/GraphQL/Kafka added later. +description: order-service data product — FastAPI REST service backed by the datamesh Postgres (orders schema). r21 ships REST + Postgres; gRPC/GraphQL/Kafka added later. type: application version: 0.1.0 appVersion: "0.1.0" diff --git a/examples/lgtm-datamesh/charts/capstone/charts/order-service/templates/deployment.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/order-service/templates/deployment.yaml similarity index 97% rename from examples/lgtm-datamesh/charts/capstone/charts/order-service/templates/deployment.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/order-service/templates/deployment.yaml index a4efd5f..75b9de2 100644 --- a/examples/lgtm-datamesh/charts/capstone/charts/order-service/templates/deployment.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/charts/order-service/templates/deployment.yaml @@ -5,7 +5,7 @@ metadata: namespace: {{ .Release.Namespace }} labels: app.kubernetes.io/name: order-service - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh app.kubernetes.io/component: data-product spec: replicas: {{ .Values.replicas }} @@ -22,7 +22,7 @@ spec: metadata: labels: app.kubernetes.io/name: order-service - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh # r26: subset label for the Istio canary. The DestinationRule's `v1` # subset matches version=v1; the v2 overlay Deployment carries # version=v2. The Service selector keys on app.kubernetes.io/name, so @@ -103,7 +103,7 @@ spec: - name: OTEL_TRACES_SAMPLER_ARG value: {{ .Values.tracing.sampleRatio | quote }} - name: OTEL_RESOURCE_ATTRIBUTES - value: "service.namespace=capstone" + value: "service.namespace=datamesh" {{- end }} resources: requests: diff --git a/examples/lgtm-datamesh/charts/capstone/charts/order-service/templates/service.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/order-service/templates/service.yaml similarity index 93% rename from examples/lgtm-datamesh/charts/capstone/charts/order-service/templates/service.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/order-service/templates/service.yaml index 8aedf7b..1906acd 100644 --- a/examples/lgtm-datamesh/charts/capstone/charts/order-service/templates/service.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/charts/order-service/templates/service.yaml @@ -5,7 +5,7 @@ metadata: namespace: {{ .Release.Namespace }} labels: app.kubernetes.io/name: order-service - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh spec: type: {{ .Values.service.type | default "ClusterIP" }} selector: diff --git a/examples/lgtm-datamesh/charts/capstone/charts/order-service/values.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/order-service/values.yaml similarity index 93% rename from examples/lgtm-datamesh/charts/capstone/charts/order-service/values.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/order-service/values.yaml index 2141a23..ab1ccd2 100644 --- a/examples/lgtm-datamesh/charts/capstone/charts/order-service/values.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/charts/order-service/values.yaml @@ -4,7 +4,7 @@ replicas: 1 image: # Image is loaded into the node by build-image.sh (minikube image load); no registry. - repository: capstone/order-service + repository: datamesh/order-service tag: v1 # Never: images are loaded into the node by build-image.sh (minikube image load) and never pulled; build-image.sh restarts the Deployment so a rebuilt :v1 is used. pullPolicy: Never @@ -23,7 +23,7 @@ inventory: # Kafka (r25) — order.placed events published here. kafka: - bootstrap: capstone-kafka-kafka-bootstrap:9092 + bootstrap: datamesh-kafka-kafka-bootstrap:9092 orderTopic: order-placed # Apicurio schema registry (r25b) — order.placed registered + serialized as Avro. @@ -35,10 +35,10 @@ apicurio: # "-app" holding the app user's credentials. We reference it by # key so we never hardcode the password. postgres: - clusterName: capstone-postgres + clusterName: datamesh-postgres # CNPG's "-app" secret contains: username, password, dbname, # host, port, uri, jdbc-uri. We map the ones order-service needs. - appSecret: capstone-postgres-app + appSecret: datamesh-postgres-app schema: orders tracing: diff --git a/examples/lgtm-datamesh/charts/capstone/charts/payment-service/Chart.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/payment-service/Chart.yaml similarity index 75% rename from examples/lgtm-datamesh/charts/capstone/charts/payment-service/Chart.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/payment-service/Chart.yaml index c02b51a..567a388 100644 --- a/examples/lgtm-datamesh/charts/capstone/charts/payment-service/Chart.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/charts/payment-service/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: payment-service -description: payment-service data product — FastAPI service backed by the capstone Postgres (payments schema). r22 ships the health skeleton; domain surface added later. +description: payment-service data product — FastAPI service backed by the datamesh Postgres (payments schema). r22 ships the health skeleton; domain surface added later. type: application version: 0.1.0 appVersion: "0.1.0" diff --git a/examples/lgtm-datamesh/charts/capstone/charts/payment-service/templates/deployment.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/payment-service/templates/deployment.yaml similarity index 97% rename from examples/lgtm-datamesh/charts/capstone/charts/payment-service/templates/deployment.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/payment-service/templates/deployment.yaml index 43cc9eb..dc4e439 100644 --- a/examples/lgtm-datamesh/charts/capstone/charts/payment-service/templates/deployment.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/charts/payment-service/templates/deployment.yaml @@ -5,7 +5,7 @@ metadata: namespace: {{ .Release.Namespace }} labels: app.kubernetes.io/name: payment-service - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh app.kubernetes.io/component: data-product spec: replicas: {{ .Values.replicas }} @@ -16,7 +16,7 @@ spec: metadata: labels: app.kubernetes.io/name: payment-service - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh spec: containers: - name: payment-service diff --git a/examples/lgtm-datamesh/charts/capstone/charts/payment-service/templates/service.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/payment-service/templates/service.yaml similarity index 89% rename from examples/lgtm-datamesh/charts/capstone/charts/payment-service/templates/service.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/payment-service/templates/service.yaml index 0cb0458..4a4090e 100644 --- a/examples/lgtm-datamesh/charts/capstone/charts/payment-service/templates/service.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/charts/payment-service/templates/service.yaml @@ -5,7 +5,7 @@ metadata: namespace: {{ .Release.Namespace }} labels: app.kubernetes.io/name: payment-service - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh spec: type: ClusterIP selector: diff --git a/examples/lgtm-datamesh/charts/capstone/charts/payment-service/values.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/payment-service/values.yaml similarity index 92% rename from examples/lgtm-datamesh/charts/capstone/charts/payment-service/values.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/payment-service/values.yaml index 2d2253d..934f5b0 100644 --- a/examples/lgtm-datamesh/charts/capstone/charts/payment-service/values.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/charts/payment-service/values.yaml @@ -4,7 +4,7 @@ replicas: 1 image: # Image is loaded into the node by build-image.sh (minikube image load); no registry. - repository: capstone/payment-service + repository: datamesh/payment-service tag: v1 # Never: images are loaded into the node by build-image.sh (minikube image load) and never pulled; build-image.sh restarts the Deployment so a rebuilt :v1 is used. pullPolicy: Never @@ -16,8 +16,8 @@ service: # Postgres connection. The CloudNativePG operator generates a Secret named # "-app" holding the app user's credentials; we reference it by key. postgres: - clusterName: capstone-postgres - appSecret: capstone-postgres-app + clusterName: datamesh-postgres + appSecret: datamesh-postgres-app schema: payments resources: diff --git a/examples/lgtm-datamesh/charts/capstone/charts/postgres/Chart.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/postgres/Chart.yaml similarity index 61% rename from examples/lgtm-datamesh/charts/capstone/charts/postgres/Chart.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/postgres/Chart.yaml index 70ef6b0..f3a7d03 100644 --- a/examples/lgtm-datamesh/charts/capstone/charts/postgres/Chart.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/charts/postgres/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: postgres -description: CloudNativePG Cluster CR for the capstone shared Postgres. One cluster, one application database (`capstone`), with a schema per service (CAP-003). The CloudNativePG operator must already be installed (scripts/setup-postgres-operator.sh). +description: CloudNativePG Cluster CR for the datamesh shared Postgres. One cluster, one application database (`datamesh`), with a schema per service (CAP-003). The CloudNativePG operator must already be installed (scripts/setup-postgres-operator.sh). type: application version: 0.1.0 appVersion: "r21" diff --git a/examples/lgtm-datamesh/charts/capstone/charts/postgres/templates/cluster.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/postgres/templates/cluster.yaml similarity index 94% rename from examples/lgtm-datamesh/charts/capstone/charts/postgres/templates/cluster.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/postgres/templates/cluster.yaml index ba67455..a3ca20e 100644 --- a/examples/lgtm-datamesh/charts/capstone/charts/postgres/templates/cluster.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/charts/postgres/templates/cluster.yaml @@ -4,7 +4,7 @@ metadata: name: {{ .Values.cluster.name }} namespace: {{ .Release.Namespace }} labels: - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh app.kubernetes.io/component: database spec: instances: {{ .Values.cluster.instances }} @@ -17,7 +17,7 @@ spec: # injected Envoy intercepts and re-wraps those connections, breaking CNPG's # TLS handshakes — the postgres container crash-loops (exit 2) and the operator # can't reach the instance status endpoint ("HTTP communication issue"). This - # is the selective-injection model the capstone documents: mesh only + # is the selective-injection model the datamesh documents: mesh only # order-service for the canary, never the operator-managed infra. CNPG # propagates inheritedMetadata onto the instance pods. inheritedMetadata: diff --git a/examples/lgtm-datamesh/charts/capstone/charts/postgres/values.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/postgres/values.yaml similarity index 94% rename from examples/lgtm-datamesh/charts/capstone/charts/postgres/values.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/postgres/values.yaml index 4b4843a..9d7a7cb 100644 --- a/examples/lgtm-datamesh/charts/capstone/charts/postgres/values.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/charts/postgres/values.yaml @@ -3,15 +3,15 @@ # pods, services, and secrets. cluster: - name: capstone-postgres + name: datamesh-postgres instances: 1 # single-instance dev cluster (NOT production-shaped) imageName: "ghcr.io/cloudnative-pg/postgresql:18.6-standard-trixie" # pinned: the CNPG standard image, newest 18.x storage: size: 5Gi # r21 skeleton; bump for sustained multi-service use # The application database the operator bootstraps. Each service uses its # own SCHEMA within this database (CAP-003), not its own database. - database: capstone - owner: capstone_app + database: datamesh + owner: datamesh_app # Resource requests/limits for the Postgres pod itself. # CAP-038: 512Mi was too tight — Postgres + the CNPG instance-manager + startup # crash-recovery (WAL replay) OOM-killed at that ceiling, especially after an diff --git a/examples/lgtm-datamesh/charts/capstone/charts/review-service/Chart.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/review-service/Chart.yaml similarity index 75% rename from examples/lgtm-datamesh/charts/capstone/charts/review-service/Chart.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/review-service/Chart.yaml index 66b17aa..52feef2 100644 --- a/examples/lgtm-datamesh/charts/capstone/charts/review-service/Chart.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/charts/review-service/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: review-service -description: review-service data product — FastAPI service backed by the capstone Postgres (reviews schema). r22 ships the health skeleton; domain surface added later. +description: review-service data product — FastAPI service backed by the datamesh Postgres (reviews schema). r22 ships the health skeleton; domain surface added later. type: application version: 0.1.0 appVersion: "0.1.0" diff --git a/examples/lgtm-datamesh/charts/capstone/charts/review-service/templates/deployment.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/review-service/templates/deployment.yaml similarity index 97% rename from examples/lgtm-datamesh/charts/capstone/charts/review-service/templates/deployment.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/review-service/templates/deployment.yaml index 7f6776a..638c68b 100644 --- a/examples/lgtm-datamesh/charts/capstone/charts/review-service/templates/deployment.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/charts/review-service/templates/deployment.yaml @@ -5,7 +5,7 @@ metadata: namespace: {{ .Release.Namespace }} labels: app.kubernetes.io/name: review-service - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh app.kubernetes.io/component: data-product spec: replicas: {{ .Values.replicas }} @@ -16,7 +16,7 @@ spec: metadata: labels: app.kubernetes.io/name: review-service - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh spec: containers: - name: review-service diff --git a/examples/lgtm-datamesh/charts/capstone/charts/review-service/templates/service.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/review-service/templates/service.yaml similarity index 93% rename from examples/lgtm-datamesh/charts/capstone/charts/review-service/templates/service.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/review-service/templates/service.yaml index f77b8dc..79ff3f2 100644 --- a/examples/lgtm-datamesh/charts/capstone/charts/review-service/templates/service.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/charts/review-service/templates/service.yaml @@ -5,7 +5,7 @@ metadata: namespace: {{ .Release.Namespace }} labels: app.kubernetes.io/name: review-service - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh spec: type: {{ .Values.service.type | default "ClusterIP" }} selector: diff --git a/examples/lgtm-datamesh/charts/capstone/charts/review-service/values.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/review-service/values.yaml similarity index 92% rename from examples/lgtm-datamesh/charts/capstone/charts/review-service/values.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/review-service/values.yaml index a26cf45..35a5ff6 100644 --- a/examples/lgtm-datamesh/charts/capstone/charts/review-service/values.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/charts/review-service/values.yaml @@ -4,7 +4,7 @@ replicas: 1 image: # Image is loaded into the node by build-image.sh (minikube image load); no registry. - repository: capstone/review-service + repository: datamesh/review-service tag: v1 # Never: images are loaded into the node by build-image.sh (minikube image load) and never pulled; build-image.sh restarts the Deployment so a rebuilt :v1 is used. pullPolicy: Never @@ -20,8 +20,8 @@ service: # Postgres connection. The CloudNativePG operator generates a Secret named # "-app" holding the app user's credentials; we reference it by key. postgres: - clusterName: capstone-postgres - appSecret: capstone-postgres-app + clusterName: datamesh-postgres + appSecret: datamesh-postgres-app schema: reviews resources: diff --git a/examples/lgtm-datamesh/charts/capstone/charts/shipping-service/Chart.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/shipping-service/Chart.yaml similarity index 75% rename from examples/lgtm-datamesh/charts/capstone/charts/shipping-service/Chart.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/shipping-service/Chart.yaml index 8a180d1..ccb6406 100644 --- a/examples/lgtm-datamesh/charts/capstone/charts/shipping-service/Chart.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/charts/shipping-service/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: shipping-service -description: shipping-service data product — FastAPI service backed by the capstone Postgres (shipping schema). r22 ships the health skeleton; domain surface added later. +description: shipping-service data product — FastAPI service backed by the datamesh Postgres (shipping schema). r22 ships the health skeleton; domain surface added later. type: application version: 0.1.0 appVersion: "0.1.0" diff --git a/examples/lgtm-datamesh/charts/capstone/charts/shipping-service/templates/deployment.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/shipping-service/templates/deployment.yaml similarity index 97% rename from examples/lgtm-datamesh/charts/capstone/charts/shipping-service/templates/deployment.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/shipping-service/templates/deployment.yaml index e62897e..5a0158c 100644 --- a/examples/lgtm-datamesh/charts/capstone/charts/shipping-service/templates/deployment.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/charts/shipping-service/templates/deployment.yaml @@ -5,7 +5,7 @@ metadata: namespace: {{ .Release.Namespace }} labels: app.kubernetes.io/name: shipping-service - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh app.kubernetes.io/component: data-product spec: replicas: {{ .Values.replicas }} @@ -16,7 +16,7 @@ spec: metadata: labels: app.kubernetes.io/name: shipping-service - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh spec: containers: - name: shipping-service diff --git a/examples/lgtm-datamesh/charts/capstone/charts/shipping-service/templates/service.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/shipping-service/templates/service.yaml similarity index 89% rename from examples/lgtm-datamesh/charts/capstone/charts/shipping-service/templates/service.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/shipping-service/templates/service.yaml index fb8d01b..3ac6e75 100644 --- a/examples/lgtm-datamesh/charts/capstone/charts/shipping-service/templates/service.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/charts/shipping-service/templates/service.yaml @@ -5,7 +5,7 @@ metadata: namespace: {{ .Release.Namespace }} labels: app.kubernetes.io/name: shipping-service - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh spec: type: ClusterIP selector: diff --git a/examples/lgtm-datamesh/charts/capstone/charts/shipping-service/values.yaml b/examples/lgtm-datamesh/charts/datamesh/charts/shipping-service/values.yaml similarity index 92% rename from examples/lgtm-datamesh/charts/capstone/charts/shipping-service/values.yaml rename to examples/lgtm-datamesh/charts/datamesh/charts/shipping-service/values.yaml index 77ae606..9e7dcde 100644 --- a/examples/lgtm-datamesh/charts/capstone/charts/shipping-service/values.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/charts/shipping-service/values.yaml @@ -4,7 +4,7 @@ replicas: 1 image: # Image is loaded into the node by build-image.sh (minikube image load); no registry. - repository: capstone/shipping-service + repository: datamesh/shipping-service tag: v1 # Never: images are loaded into the node by build-image.sh (minikube image load) and never pulled; build-image.sh restarts the Deployment so a rebuilt :v1 is used. pullPolicy: Never @@ -16,8 +16,8 @@ service: # Postgres connection. The CloudNativePG operator generates a Secret named # "-app" holding the app user's credentials; we reference it by key. postgres: - clusterName: capstone-postgres - appSecret: capstone-postgres-app + clusterName: datamesh-postgres + appSecret: datamesh-postgres-app schema: shipping resources: diff --git a/examples/lgtm-datamesh/charts/capstone/values.yaml b/examples/lgtm-datamesh/charts/datamesh/values.yaml similarity index 89% rename from examples/lgtm-datamesh/charts/capstone/values.yaml rename to examples/lgtm-datamesh/charts/datamesh/values.yaml index 553d6c4..428e9be 100644 --- a/examples/lgtm-datamesh/charts/capstone/values.yaml +++ b/examples/lgtm-datamesh/charts/datamesh/values.yaml @@ -1,37 +1,37 @@ -# §17 capstone umbrella chart values. +# §17 final project umbrella chart values. # # Every component has an `enabled` flag so the deploy can be staged # incrementally. Default values represent the steady-state full-deploy # configuration; flip `enabled: false` to omit a component from a # partial-stack deploy. # -# Resource defaults are sized for a 24 GB / 16 CPU `capstone` minikube -# profile (see scripts/setup-capstone-profile.sh). Adjust if you've +# Resource defaults are sized for a 24 GB / 16 CPU `datamesh` minikube +# profile (see scripts/setup-datamesh-profile.sh). Adjust if you've # given the profile more or less. # ───────────────────────────────────────────────────────────────────────────── # Global settings (consumed by subcharts via helm's `global` mechanism) # ───────────────────────────────────────────────────────────────────────────── global: - # Single namespace for the capstone deploy. Istio injection is enabled here. - namespace: capstone + # Single namespace for the datamesh deploy. Istio injection is enabled here. + namespace: datamesh # Image-pull policy across all services. IfNotPresent works for both # locally-built (minikube image cache) and registry-sourced images. imagePullPolicy: IfNotPresent # OTLP endpoint for all services. Points at the OTEL Collector service - # within the capstone namespace. - otlpEndpoint: "otel-collector.capstone.svc.cluster.local:4317" + # within the datamesh namespace. + otlpEndpoint: "otel-collector.datamesh.svc.cluster.local:4317" # Apicurio Registry endpoint for schema + API contract publication. - apicurioEndpoint: "http://apicurio.capstone.svc.cluster.local:8080" + apicurioEndpoint: "http://apicurio.datamesh.svc.cluster.local:8080" # Kafka bootstrap endpoint (Strimzi-managed). Matches §12's naming. - kafkaBootstrap: "my-kafka-kafka-bootstrap.capstone.svc.cluster.local:9092" + kafkaBootstrap: "my-kafka-kafka-bootstrap.datamesh.svc.cluster.local:9092" # Postgres connection target (single cluster, schema per service). - postgresHost: "capstone-postgres-rw.capstone.svc.cluster.local" + postgresHost: "datamesh-postgres-rw.datamesh.svc.cluster.local" postgresPort: 5432 # ───────────────────────────────────────────────────────────────────────────── @@ -40,7 +40,7 @@ global: strimziCluster: enabled: true # Kafka cluster CR — the Strimzi operator must already be installed - # (per §12 pattern). The cluster runs in the capstone namespace. + # (per §12 pattern). The cluster runs in the datamesh namespace. # NOTE: this block is not read by any template. The Kafka version is set in # charts/kafka/values.yaml (`version`, a subchart value; override with # `--set kafka.version=...`), where the Kafka CR template consumes it. @@ -103,14 +103,14 @@ observability: size: 5Gi grafana: enabled: true - adminPassword: capstone-demo # demo only; rotate for any real use + adminPassword: datamesh-demo # demo only; rotate for any real use persistence: size: 1Gi prefect: enabled: true # Self-hosted Prefect 3.x OSS server. Stores flow state in Postgres - # (shares the capstone-postgres cluster, separate database). + # (shares the datamesh-postgres cluster, separate database). server: replicas: 1 resources: diff --git a/examples/lgtm-datamesh/demos/debug-ephemeral.sh b/examples/lgtm-datamesh/demos/debug-ephemeral.sh index 1c70345..9a196ab 100755 --- a/examples/lgtm-datamesh/demos/debug-ephemeral.sh +++ b/examples/lgtm-datamesh/demos/debug-ephemeral.sh @@ -18,14 +18,14 @@ # Ephemeral containers cannot be removed (they live with the pod), so each run # uses a unique container name. Re-running is safe; it just adds another. # -# Prereqs: a running capstone cluster with notification-service deployed +# Prereqs: a running datamesh cluster with notification-service deployed # (e.g. after ./demos/demo-notifications.sh, or deploy it first). # # Usage: ./demos/debug-ephemeral.sh set -uo pipefail -NS="capstone" +NS="datamesh" APP="notification-service" DEBUG_IMAGE="registry.access.redhat.com/ubi10/ubi:10.2-1791444044" # has curl + ps; any tool image works STAMP="$(date +%s)" diff --git a/examples/lgtm-datamesh/demos/demo-add-data-product.sh b/examples/lgtm-datamesh/demos/demo-add-data-product.sh index 77293d8..215c5ae 100755 --- a/examples/lgtm-datamesh/demos/demo-add-data-product.sh +++ b/examples/lgtm-datamesh/demos/demo-add-data-product.sh @@ -15,7 +15,7 @@ # This is a TEMPORARY demo product; `down` leaves no trace. Reuses the proven # discovery machinery (publish pattern, ingest-openmetadata.sh, get_token.py). # -# Assumes the capstone is up (Apicurio, OpenMetadata, Postgres, inventory-service +# Assumes the datamesh is up (Apicurio, OpenMetadata, Postgres, inventory-service # all running — the products lineage target is inventory.stock). Run from # examples/lgtm-datamesh/: ./demos/demo-add-data-product.sh up (then ... down) @@ -23,16 +23,16 @@ set -uo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "${SCRIPT_DIR}/lib/endpoints.sh" -NS="capstone" +NS="datamesh" RELEASE="review-service" -CHART="charts/capstone/charts/review-service" +CHART="charts/datamesh/charts/review-service" SERVICE_DIR="services/review-service" IMAGE="review-service"; TAG="v1" GROUP="default" ARTIFACT_ID="review-service-openapi" -REVIEWS_SCHEMA_FQN="capstone-postgres.capstone.reviews" -REVIEWS_TABLE_FQN="capstone-postgres.capstone.reviews.reviews" +REVIEWS_SCHEMA_FQN="datamesh-postgres.datamesh.reviews" +REVIEWS_TABLE_FQN="datamesh-postgres.datamesh.reviews.reviews" L_REVIEW="$TP_REVIEW"; L_APIC="$TP_APICURIO"; L_OM="$TP_OM" @@ -56,11 +56,11 @@ MODE="${1:-}" # ─── Pre-flight ────────────────────────────────────────────────────────────── step "Pre-flight" -[[ "$(kubectl config current-context 2>/dev/null)" == "capstone" ]] \ - || fail "kubectl context is not 'capstone'" +[[ "$(kubectl config current-context 2>/dev/null)" == "datamesh" ]] \ + || fail "kubectl context is not 'datamesh'" for svc in apicurio openmetadata; do kubectl get svc "$svc" -n "$NS" >/dev/null 2>&1 \ - || fail "$svc not found — bring the capstone up (./scripts/cluster-up.sh)" + || fail "$svc not found — bring the datamesh up (./scripts/cluster-up.sh)" done if [[ "$MODE" == "up" ]]; then @@ -165,10 +165,10 @@ else # 5. Drop the Postgres schema (so a future re-ingest won't re-add it) step "Dropping the reviews Postgres schema" - primary="$(kubectl get pods -n "$NS" -l cnpg.io/cluster=capstone-postgres,cnpg.io/instanceRole=primary -o name 2>/dev/null | head -1)" + primary="$(kubectl get pods -n "$NS" -l cnpg.io/cluster=datamesh-postgres,cnpg.io/instanceRole=primary -o name 2>/dev/null | head -1)" if [[ -n "$primary" ]]; then kubectl exec -n "$NS" "$primary" -c postgres -- \ - psql -U postgres -d capstone -c 'DROP SCHEMA IF EXISTS reviews CASCADE' >/dev/null 2>&1 \ + psql -U postgres -d datamesh -c 'DROP SCHEMA IF EXISTS reviews CASCADE' >/dev/null 2>&1 \ && ok "reviews schema dropped" || warn "could not drop reviews schema (verify-point: pod/user)" else warn "could not find the Postgres primary to drop the schema" diff --git a/examples/lgtm-datamesh/demos/demo-avro.sh b/examples/lgtm-datamesh/demos/demo-avro.sh index 31468e0..66881ef 100755 --- a/examples/lgtm-datamesh/demos/demo-avro.sh +++ b/examples/lgtm-datamesh/demos/demo-avro.sh @@ -18,14 +18,14 @@ set -uo pipefail -PROFILE="capstone"; NS="capstone" +PROFILE="datamesh"; NS="datamesh" ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"; cd "$ROOT" source "${ROOT}/demos/lib/endpoints.sh" source "${ROOT}/demos/lib/images.sh" source "${ROOT}/demos/lib/keda.sh" -PG_RELEASE="capstone-postgres"; PG_CHART="charts/capstone/charts/postgres" -KAFKA_RELEASE="capstone-kafka"; KAFKA_CHART="charts/capstone/charts/kafka"; KAFKA_CR="capstone-kafka" -APICURIO_RELEASE="apicurio"; APICURIO_CHART="charts/capstone/charts/apicurio" +PG_RELEASE="datamesh-postgres"; PG_CHART="charts/datamesh/charts/postgres" +KAFKA_RELEASE="datamesh-kafka"; KAFKA_CHART="charts/datamesh/charts/kafka"; KAFKA_CR="datamesh-kafka" +APICURIO_RELEASE="apicurio"; APICURIO_CHART="charts/datamesh/charts/apicurio" SUBJECT="order-placed-value" LOCAL_ORDER=$TP_ORDER; LOCAL_NOTIF=$TP_NOTIF; LOCAL_APIC=$TP_APICURIO # 8080 order, 8083 notification, 8084 apicurio PURGE_DB=0; [[ "${1:-}" == "--purge-db" ]] && PURGE_DB=1 @@ -46,12 +46,12 @@ fail() { } # ── 1. image guard ───────────────────────────────────────────────────────── -step "Sanity: chart image.repository is capstone/ with pullPolicy Never" +step "Sanity: chart image.repository is datamesh/ with pullPolicy Never" for svc in "${APP_SERVICES[@]}"; do - if chart_repo_ok "charts/capstone/charts/${svc}/values.yaml" "$svc"; then + if chart_repo_ok "charts/datamesh/charts/${svc}/values.yaml" "$svc"; then printf ' ✓ %s → %s\n' "$svc" "$(image_ref "$svc")" else - fail "${svc} chart must use image.repository capstone/${svc} with pullPolicy Never" + fail "${svc} chart must use image.repository datamesh/${svc} with pullPolicy Never" fi done @@ -93,7 +93,7 @@ done for svc in "${APP_SERVICES[@]}"; do step "Deploying ${svc}" - helm upgrade --install "$svc" "charts/capstone/charts/${svc}" -n "$NS" || fail "${svc} install failed" + helm upgrade --install "$svc" "charts/datamesh/charts/${svc}" -n "$NS" || fail "${svc} install failed" kubectl rollout status "deployment/${svc}" -n "$NS" --timeout=120s || fail "${svc} rollout failed" done diff --git a/examples/lgtm-datamesh/demos/demo-canary-verify.sh b/examples/lgtm-datamesh/demos/demo-canary-verify.sh index b86d288..e2db836 100755 --- a/examples/lgtm-datamesh/demos/demo-canary-verify.sh +++ b/examples/lgtm-datamesh/demos/demo-canary-verify.sh @@ -19,7 +19,7 @@ # ./demos/demo-canary-verify.sh # # Prerequisites: -# - capstone profile running, kubectl context = capstone +# - datamesh profile running, kubectl context = datamesh # - scripts/setup-istio.sh has run (Istio installed, namespace injection on) # - order-service (v1) deployed via the umbrella chart WITH the r26 selector # (version=v1). If the live Deployment predates r26, this smoke detects the @@ -31,8 +31,8 @@ set -uo pipefail -NS="capstone" -PROFILE="capstone" +NS="datamesh" +PROFILE="datamesh" ISTIO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../istio" && pwd)" source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/lib/endpoints.sh" LOCAL_PORT="$TP_INGRESS" @@ -99,7 +99,7 @@ kubectl get deployment istiod -n istio-system >/dev/null 2>&1 \ || fail "Istio not installed — run scripts/setup-istio.sh first" kubectl get deployment order-service -n "$NS" >/dev/null 2>&1 \ || fail "order-service (v1) not deployed — install it first: - helm upgrade --install order-service charts/capstone/charts/order-service -n $NS" + helm upgrade --install order-service charts/datamesh/charts/order-service -n $NS" # Selector migration check (r26 immutability): v1 Deployment must select version=v1. SEL_VERSION="$(kubectl get deployment order-service -n "$NS" \ @@ -107,7 +107,7 @@ SEL_VERSION="$(kubectl get deployment order-service -n "$NS" \ if [[ "$SEL_VERSION" != "v1" ]]; then fail "order-service Deployment predates r26 (selector lacks version=v1). One-time migration: kubectl delete deployment order-service -n $NS - helm upgrade --install order-service charts/capstone/charts/order-service -n $NS + helm upgrade --install order-service charts/datamesh/charts/order-service -n $NS then re-run this smoke. (Deployment selectors are immutable, so v1 must be recreated.)" fi printf ' ✓ v1 selector carries version=v1\n' @@ -142,7 +142,7 @@ apply_weights 90 10 step "Checking the published istio-ingressgateway endpoint (host ${LOCAL_PORT})" ensure_endpoint ingress wait_http "${GW}/version" 30 \ - || fail "ingress gateway not reachable on ${GW} (run ./scripts/show-endpoints.sh; if the port is missing, ./scripts/setup-capstone-profile.sh --replace, which deletes the cluster; re-run ./scripts/bootstrap-capstone.sh afterwards)" + || fail "ingress gateway not reachable on ${GW} (run ./scripts/show-endpoints.sh; if the port is missing, ./scripts/setup-datamesh-profile.sh --replace, which deletes the cluster; re-run ./scripts/bootstrap-datamesh.sh afterwards)" step "Driving ${REQUESTS} requests at the 90/10 split" measure_split "90/10" 1 30 # ~10 expected; generous band for 100 samples diff --git a/examples/lgtm-datamesh/demos/demo-canary.sh b/examples/lgtm-datamesh/demos/demo-canary.sh index 65c27f1..90b2425 100755 --- a/examples/lgtm-datamesh/demos/demo-canary.sh +++ b/examples/lgtm-datamesh/demos/demo-canary.sh @@ -21,8 +21,8 @@ set -uo pipefail -NS="capstone" -PROFILE="capstone" +NS="datamesh" +PROFILE="datamesh" ISTIO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../istio" && pwd)" V2_MANIFEST="$ISTIO_DIR/order-service-v2.yaml" ROUTING="$ISTIO_DIR/routing.yaml" diff --git a/examples/lgtm-datamesh/demos/demo-discovery.sh b/examples/lgtm-datamesh/demos/demo-discovery.sh index 84207ad..458359d 100755 --- a/examples/lgtm-datamesh/demos/demo-discovery.sh +++ b/examples/lgtm-datamesh/demos/demo-discovery.sh @@ -17,14 +17,14 @@ set -uo pipefail -PROFILE="capstone"; NS="capstone" +PROFILE="datamesh"; NS="datamesh" ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"; cd "$ROOT" source "${ROOT}/demos/lib/endpoints.sh" source "${ROOT}/demos/lib/images.sh" -PG_RELEASE="capstone-postgres"; PG_CHART="charts/capstone/charts/postgres" -KAFKA_RELEASE="capstone-kafka"; KAFKA_CHART="charts/capstone/charts/kafka"; KAFKA_CR="capstone-kafka" -APICURIO_RELEASE="apicurio"; APICURIO_CHART="charts/capstone/charts/apicurio" -PROTO_PATH="proto/capstone/inventory/v1/inventory.proto" +PG_RELEASE="datamesh-postgres"; PG_CHART="charts/datamesh/charts/postgres" +KAFKA_RELEASE="datamesh-kafka"; KAFKA_CHART="charts/datamesh/charts/kafka"; KAFKA_CR="datamesh-kafka" +APICURIO_RELEASE="apicurio"; APICURIO_CHART="charts/datamesh/charts/apicurio" +PROTO_PATH="proto/datamesh/inventory/v1/inventory.proto" GROUP="default" LOCAL_ORDER=$TP_ORDER; LOCAL_GW=$TP_GATEWAY; LOCAL_APIC=$TP_APICURIO # 8080 order, 8081 gateway-via-interceptor, 8084 apicurio PURGE_DB=0; [[ "${1:-}" == "--purge-db" ]] && PURGE_DB=1 @@ -45,12 +45,12 @@ fail() { } # ── image guard ──────────────────────────────────────────────────────────── -step "Sanity: chart image.repository is capstone/ with pullPolicy Never" +step "Sanity: chart image.repository is datamesh/ with pullPolicy Never" for svc in "${DEPLOY[@]}"; do - if chart_repo_ok "charts/capstone/charts/${svc}/values.yaml" "$svc"; then + if chart_repo_ok "charts/datamesh/charts/${svc}/values.yaml" "$svc"; then printf ' ✓ %s → %s\n' "$svc" "$(image_ref "$svc")" else - fail "${svc} chart must use image.repository capstone/${svc} with pullPolicy Never" + fail "${svc} chart must use image.repository datamesh/${svc} with pullPolicy Never" fi done [[ -f "$PROTO_PATH" ]] || fail "proto not found at ${PROTO_PATH} — run ./scripts/gen-protos.sh? (the .proto is committed)" @@ -86,7 +86,7 @@ done (( pg_ready )) || fail "Postgres primary did not become Ready" for svc in "${DEPLOY[@]}"; do step "Deploying ${svc}" - helm upgrade --install "$svc" "charts/capstone/charts/${svc}" -n "$NS" >/dev/null || fail "${svc} install failed" + helm upgrade --install "$svc" "charts/datamesh/charts/${svc}" -n "$NS" >/dev/null || fail "${svc} install failed" kubectl rollout status "deployment/${svc}" -n "$NS" --timeout=120s || fail "${svc} rollout failed" done diff --git a/examples/lgtm-datamesh/demos/demo-graphql.sh b/examples/lgtm-datamesh/demos/demo-graphql.sh index 77b0c7c..fb089bb 100755 --- a/examples/lgtm-datamesh/demos/demo-graphql.sh +++ b/examples/lgtm-datamesh/demos/demo-graphql.sh @@ -6,7 +6,7 @@ # # Flow: # 1. confirm committed gRPC stubs exist for the gateway -# 2. sanity: charts use local capstone/ images +# 2. sanity: charts use local datamesh/ images # 3. build + load inventory-service, order-service, graphql-gateway # 4. ensure Postgres Ready; deploy all three # 5. place an in-stock order via order-service REST to get an order id @@ -18,11 +18,11 @@ set -uo pipefail -PROFILE="capstone"; NS="capstone" +PROFILE="datamesh"; NS="datamesh" ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"; cd "$ROOT" source "${ROOT}/demos/lib/endpoints.sh" source "${ROOT}/demos/lib/images.sh" -PG_RELEASE="capstone-postgres"; PG_CHART="charts/capstone/charts/postgres" +PG_RELEASE="datamesh-postgres"; PG_CHART="charts/datamesh/charts/postgres" LOCAL_ORDER=$TP_ORDER; LOCAL_GQL=$TP_GATEWAY # 8080 order-service, 8081 gateway via KEDA interceptor PURGE_DB=0; [[ "${1:-}" == "--purge-db" ]] && PURGE_DB=1 @@ -43,23 +43,23 @@ fail() { # ── 1. stubs present (gateway needs the inventory client stubs) ─────────────── step "Checking for committed gRPC stubs" for svc in inventory-service order-service graphql-gateway; do - [[ -f "services/${svc}/gen/capstone/inventory/v1/inventory_pb2_grpc.py" ]] \ + [[ -f "services/${svc}/gen/datamesh/inventory/v1/inventory_pb2_grpc.py" ]] \ || fail "missing stubs for ${svc} — run ./scripts/gen-protos.sh" done printf ' ✓ stubs present\n' # ── 2. image-name guard ────────────────────────────────────────────────── -step "Sanity: chart image.repository is capstone/ with pullPolicy Never" +step "Sanity: chart image.repository is datamesh/ with pullPolicy Never" for svc in "${SERVICES[@]}"; do - if chart_repo_ok "charts/capstone/charts/${svc}/values.yaml" "$svc"; then + if chart_repo_ok "charts/datamesh/charts/${svc}/values.yaml" "$svc"; then printf ' ✓ %s → %s\n' "$svc" "$(image_ref "$svc")" else - fail "${svc} chart must use image.repository capstone/${svc} with pullPolicy Never" + fail "${svc} chart must use image.repository datamesh/${svc} with pullPolicy Never" fi done # ── 3. build + load all three ───────────────────────────────────────────────── -minikube status -p "$PROFILE" >/dev/null 2>&1 || fail "profile '$PROFILE' not running — ./scripts/setup-capstone-profile.sh" +minikube status -p "$PROFILE" >/dev/null 2>&1 || fail "profile '$PROFILE' not running — ./scripts/setup-datamesh-profile.sh" kubectl config use-context "$PROFILE" >/dev/null for svc in "${SERVICES[@]}"; do step "Building + loading ${svc}" @@ -82,7 +82,7 @@ done for svc in inventory-service order-service graphql-gateway; do step "Deploying ${svc}" - helm upgrade --install "$svc" "charts/capstone/charts/${svc}" -n "$NS" || fail "${svc} install failed" + helm upgrade --install "$svc" "charts/datamesh/charts/${svc}" -n "$NS" || fail "${svc} install failed" kubectl rollout status "deployment/${svc}" -n "$NS" --timeout=120s || fail "${svc} rollout failed" done @@ -91,7 +91,7 @@ step "Checking endpoints: order-service (${LOCAL_ORDER}) + gateway via the KEDA ensure_endpoint order wait_http "http://127.0.0.1:${LOCAL_ORDER}/" 20 || true # graphql-gateway is KEDA-scaled-to-zero; wake it the real way — a request driven -# through the HTTP interceptor (Host: graphql-gateway.capstone) — not a client-side forward. +# through the HTTP interceptor (Host: graphql-gateway.datamesh) — not a client-side forward. wake_gateway "$NS" || printf ' ⚠ gateway not Available yet — will retry on the query\n' step "Placing an in-stock order (WIDGET-001 x2) via order-service REST" @@ -113,7 +113,7 @@ for attempt in 1 2 3 4 5; do -H 'Content-Type: application/json' \ -d "$GQL_QUERY")" && break # The gateway is KEDA-scaled-to-zero and reached THROUGH the HTTP interceptor - # (Host: graphql-gateway.capstone). A cold start — or a scale-down between the + # (Host: graphql-gateway.datamesh). A cold start — or a scale-down between the # rollout gate and this query — can 502 the first attempts; re-wake and retry. printf ' query attempt %d failed — waking the gateway through the interceptor and retrying\n' "$attempt" wake_gateway "$NS" || true diff --git a/examples/lgtm-datamesh/demos/demo-grpc.sh b/examples/lgtm-datamesh/demos/demo-grpc.sh index 0a7e72d..8bc4379 100755 --- a/examples/lgtm-datamesh/demos/demo-grpc.sh +++ b/examples/lgtm-datamesh/demos/demo-grpc.sh @@ -22,11 +22,11 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "${SCRIPT_DIR}/lib/endpoints.sh" source "${SCRIPT_DIR}/lib/images.sh" -PROFILE="capstone"; NS="capstone" +PROFILE="datamesh"; NS="datamesh" ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"; cd "$ROOT" -PG_RELEASE="capstone-postgres"; PG_CHART="charts/capstone/charts/postgres" -INV_CHART="charts/capstone/charts/inventory-service" -ORD_CHART="charts/capstone/charts/order-service" +PG_RELEASE="datamesh-postgres"; PG_CHART="charts/datamesh/charts/postgres" +INV_CHART="charts/datamesh/charts/inventory-service" +ORD_CHART="charts/datamesh/charts/order-service" LOCAL_PORT=$TP_ORDER PURGE_DB=0; [[ "${1:-}" == "--purge-db" ]] && PURGE_DB=1 @@ -45,24 +45,24 @@ fail() { # ── 1. stubs present? ───────────────────────────────────────────────────────── step "Checking for committed gRPC stubs" for svc in inventory-service order-service; do - if [[ ! -f "services/${svc}/gen/capstone/inventory/v1/inventory_pb2_grpc.py" ]]; then + if [[ ! -f "services/${svc}/gen/datamesh/inventory/v1/inventory_pb2_grpc.py" ]]; then fail "missing stubs for ${svc} — generate them first: ./scripts/gen-protos.sh" fi done printf ' ✓ stubs present in both services\n' -# ── 1b. charts use local capstone/ images? ────────────────────────────── -step "Sanity: chart image.repository is capstone/ with pullPolicy Never" +# ── 1b. charts use local datamesh/ images? ────────────────────────────── +step "Sanity: chart image.repository is datamesh/ with pullPolicy Never" for svc in inventory-service order-service; do - if chart_repo_ok "charts/capstone/charts/${svc}/values.yaml" "$svc"; then + if chart_repo_ok "charts/datamesh/charts/${svc}/values.yaml" "$svc"; then printf ' ✓ %s → %s\n' "$svc" "$(image_ref "$svc")" else - fail "${svc} chart must use image.repository capstone/${svc} with pullPolicy Never" + fail "${svc} chart must use image.repository datamesh/${svc} with pullPolicy Never" fi done # ── 2. build + load both images ─────────────────────────────────────────────── -minikube status -p "$PROFILE" >/dev/null 2>&1 || fail "profile '$PROFILE' not running — ./scripts/setup-capstone-profile.sh" +minikube status -p "$PROFILE" >/dev/null 2>&1 || fail "profile '$PROFILE' not running — ./scripts/setup-datamesh-profile.sh" kubectl config use-context "$PROFILE" >/dev/null step "Building + loading inventory-service" ./scripts/build-image.sh services/inventory-service inventory-service v1 || fail "inventory build/load failed" diff --git a/examples/lgtm-datamesh/demos/demo-kafka.sh b/examples/lgtm-datamesh/demos/demo-kafka.sh index 8063422..da0fa95 100755 --- a/examples/lgtm-datamesh/demos/demo-kafka.sh +++ b/examples/lgtm-datamesh/demos/demo-kafka.sh @@ -17,14 +17,14 @@ set -uo pipefail -PROFILE="capstone"; NS="capstone" +PROFILE="datamesh"; NS="datamesh" ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"; cd "$ROOT" source "${ROOT}/demos/lib/endpoints.sh" source "${ROOT}/demos/lib/images.sh" source "${ROOT}/demos/lib/keda.sh" -PG_RELEASE="capstone-postgres"; PG_CHART="charts/capstone/charts/postgres" -KAFKA_RELEASE="capstone-kafka"; KAFKA_CHART="charts/capstone/charts/kafka" -KAFKA_CR="capstone-kafka" +PG_RELEASE="datamesh-postgres"; PG_CHART="charts/datamesh/charts/postgres" +KAFKA_RELEASE="datamesh-kafka"; KAFKA_CHART="charts/datamesh/charts/kafka" +KAFKA_CR="datamesh-kafka" LOCAL_ORDER=$TP_ORDER; LOCAL_NOTIF=$TP_NOTIF # 8080 order-service, 8083 notification-service PURGE_DB=0; [[ "${1:-}" == "--purge-db" ]] && PURGE_DB=1 @@ -39,22 +39,22 @@ fail() { kubectl logs -n "$NS" -l "app.kubernetes.io/name=${svc}" --tail=30 2>&1 || true done printf '\n--- kafka ---\n' >&2 - kubectl get kafka,kafkanodepool,kafkatopic,pods -n "$NS" -l 'strimzi.io/cluster=capstone-kafka' 2>&1 || true + kubectl get kafka,kafkanodepool,kafkatopic,pods -n "$NS" -l 'strimzi.io/cluster=datamesh-kafka' 2>&1 || true printf '\nResources left in place. Clean up with:\n helm uninstall %s %s -n %s\n' "${APP_SERVICES[*]}" "$KAFKA_RELEASE" "$NS" >&2 exit 1 } # ── 1. image guard ───────────────────────────────────────────────────────── -step "Sanity: chart image.repository is capstone/ with pullPolicy Never" +step "Sanity: chart image.repository is datamesh/ with pullPolicy Never" for svc in "${APP_SERVICES[@]}"; do - if chart_repo_ok "charts/capstone/charts/${svc}/values.yaml" "$svc"; then + if chart_repo_ok "charts/datamesh/charts/${svc}/values.yaml" "$svc"; then printf ' ✓ %s → %s\n' "$svc" "$(image_ref "$svc")" else - fail "${svc} chart must use image.repository capstone/${svc} with pullPolicy Never" + fail "${svc} chart must use image.repository datamesh/${svc} with pullPolicy Never" fi done -minikube status -p "$PROFILE" >/dev/null 2>&1 || fail "profile '$PROFILE' not running — ./scripts/setup-capstone-profile.sh" +minikube status -p "$PROFILE" >/dev/null 2>&1 || fail "profile '$PROFILE' not running — ./scripts/setup-datamesh-profile.sh" kubectl config use-context "$PROFILE" >/dev/null # ── 2. Strimzi operator ─────────────────────────────────────────────────────── @@ -95,7 +95,7 @@ done for svc in "${APP_SERVICES[@]}"; do step "Deploying ${svc}" - helm upgrade --install "$svc" "charts/capstone/charts/${svc}" -n "$NS" || fail "${svc} install failed" + helm upgrade --install "$svc" "charts/datamesh/charts/${svc}" -n "$NS" || fail "${svc} install failed" kubectl rollout status "deployment/${svc}" -n "$NS" --timeout=120s || fail "${svc} rollout failed" done diff --git a/examples/lgtm-datamesh/demos/demo-keda-http.sh b/examples/lgtm-datamesh/demos/demo-keda-http.sh index ef2fede..6855077 100755 --- a/examples/lgtm-datamesh/demos/demo-keda-http.sh +++ b/examples/lgtm-datamesh/demos/demo-keda-http.sh @@ -19,12 +19,12 @@ set -uo pipefail -NS="capstone" -PROFILE="capstone" +NS="datamesh" +PROFILE="datamesh" KEDA_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../keda" && pwd)" source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/lib/endpoints.sh" SEL="app.kubernetes.io/name=graphql-gateway" -HOST="graphql-gateway.capstone" +HOST="graphql-gateway.datamesh" LOCAL_PORT="$TP_GATEWAY" PROXY_SVC="keda-add-ons-http-interceptor-proxy" declare -a LOAD_PIDS=() @@ -65,7 +65,7 @@ for t in kubectl curl; do command -v "$t" >/dev/null || fail "$t not in PATH"; d kubectl get svc "$PROXY_SVC" -n keda >/dev/null 2>&1 \ || fail "KEDA HTTP add-on not installed (no $PROXY_SVC in keda ns) — run scripts/setup-keda.sh" kubectl get deployment graphql-gateway -n "$NS" >/dev/null 2>&1 \ - || fail "graphql-gateway not deployed — helm upgrade --install graphql-gateway charts/capstone/charts/graphql-gateway -n $NS" + || fail "graphql-gateway not deployed — helm upgrade --install graphql-gateway charts/datamesh/charts/graphql-gateway -n $NS" step "Applying the HTTPScaledObject" kubectl apply -f "$KEDA_DIR/gateway-httpscaledobject.yaml" >/dev/null \ diff --git a/examples/lgtm-datamesh/demos/demo-keda-kafka.sh b/examples/lgtm-datamesh/demos/demo-keda-kafka.sh index 6007979..5865a8f 100755 --- a/examples/lgtm-datamesh/demos/demo-keda-kafka.sh +++ b/examples/lgtm-datamesh/demos/demo-keda-kafka.sh @@ -20,8 +20,8 @@ set -uo pipefail -NS="capstone" -PROFILE="capstone" +NS="datamesh" +PROFILE="datamesh" KEDA_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../keda" && pwd)" DEP="notification-service" SEL="app.kubernetes.io/name=notification-service" @@ -68,7 +68,7 @@ step "Pre-flight checks" kubectl get deployment keda-operator -n keda >/dev/null 2>&1 \ || fail "KEDA not installed — run scripts/setup-keda.sh first" kubectl get deployment "$DEP" -n "$NS" >/dev/null 2>&1 \ - || fail "$DEP not deployed — helm upgrade --install notification-service charts/capstone/charts/notification-service -n $NS" + || fail "$DEP not deployed — helm upgrade --install notification-service charts/datamesh/charts/notification-service -n $NS" step "Applying the Kafka consumer-lag ScaledObject" kubectl apply -f "$KEDA_DIR/notification-scaledobject.yaml" >/dev/null \ @@ -83,9 +83,9 @@ printf ' ✓ scaled to ZERO (consumer idle, costing nothing)\n' # ─── 2. Create lag → scale up ──────────────────────────────────────────────── step "Producing a ${BURST}-message burst to '${TOPIC}' to create lag" -BROKER="$(kubectl get pods -n "$NS" -l strimzi.io/cluster=capstone-kafka -o name 2>/dev/null \ +BROKER="$(kubectl get pods -n "$NS" -l strimzi.io/cluster=datamesh-kafka -o name 2>/dev/null \ | grep -E 'kafka-.*-[0-9]+$' | head -1 | cut -d/ -f2)" -[[ -n "$BROKER" ]] || fail "could not find a capstone-kafka broker pod" +[[ -n "$BROKER" ]] || fail "could not find a datamesh-kafka broker pod" printf ' using broker pod: %s\n' "$BROKER" seq 1 "$BURST" | kubectl exec -i -n "$NS" "$BROKER" -- \ /opt/kafka/bin/kafka-console-producer.sh \ diff --git a/examples/lgtm-datamesh/demos/demo-kiali.sh b/examples/lgtm-datamesh/demos/demo-kiali.sh index d157a16..8b8ad37 100755 --- a/examples/lgtm-datamesh/demos/demo-kiali.sh +++ b/examples/lgtm-datamesh/demos/demo-kiali.sh @@ -1,8 +1,8 @@ #!/usr/bin/env bash # -# demo-kiali.sh — verify Kiali (CAP-0NN) is up and wired to the capstone +# demo-kiali.sh — verify Kiali (CAP-0NN) is up and wired to the datamesh # observability stack: the deployment is Ready, the API answers, Prometheus is -# reachable from Kiali's point of view, and the `capstone` namespace is visible +# reachable from Kiali's point of view, and the `datamesh` namespace is visible # to the graph. # # This checks the PLUMBING, not a pretty graph — it confirms Kiali can render @@ -26,7 +26,7 @@ source "${SCRIPT_DIR}/lib/endpoints.sh" ISTIO_SYSTEM="istio-system" OBS_NS="observability" -APP_NS="capstone" +APP_NS="datamesh" KIALI_PORT="$TP_KIALI" KIALI_WEBROOT="/kiali" # must match server.web_root in setup-kiali.sh (addon probe path) @@ -68,7 +68,7 @@ wait_ready kiali "$ISTIO_SYSTEM" 180 || fail "kiali did not become Ready" printf ' ✓ kiali is Ready\n' # ─── 2. Confirm the single-stack wiring landed in the ConfigMap ────────────── -step "Checking Kiali is wired to the capstone Prometheus (single-stack)" +step "Checking Kiali is wired to the datamesh Prometheus (single-stack)" CFG="$(kubectl get configmap kiali -n "$ISTIO_SYSTEM" -o jsonpath='{.data.config\.yaml}' 2>/dev/null)" [[ -n "$CFG" ]] || fail "kiali ConfigMap has no config.yaml key (version mismatch? see VERIFY-POINTS)" if printf '%s' "$CFG" | grep -q "prometheus-server.${OBS_NS}"; then @@ -82,10 +82,10 @@ step "Checking the Kiali endpoint and probing its API" ensure_endpoint kiali wait_http "http://127.0.0.1:${KIALI_PORT}${KIALI_WEBROOT}/healthz" 20 || true curl -fsS "http://127.0.0.1:${KIALI_PORT}${KIALI_WEBROOT}/healthz" >/dev/null 2>&1 \ - || fail "Kiali /healthz did not respond on the published NodePort (run ./scripts/show-endpoints.sh; if the port is missing, ./scripts/setup-capstone-profile.sh --replace, which deletes the cluster; re-run ./scripts/bootstrap-capstone.sh afterwards)" + || fail "Kiali /healthz did not respond on the published NodePort (run ./scripts/show-endpoints.sh; if the port is missing, ./scripts/setup-datamesh-profile.sh --replace, which deletes the cluster; re-run ./scripts/bootstrap-datamesh.sh afterwards)" printf ' ✓ Kiali /healthz responds\n' -# ─── 4. Kiali can see the capstone namespace ───────────────────────────────── +# ─── 4. Kiali can see the datamesh namespace ───────────────────────────────── step "Confirming Kiali sees the $APP_NS namespace" NS_JSON="$(curl -fsS "http://127.0.0.1:${KIALI_PORT}${KIALI_WEBROOT}/api/namespaces" 2>/dev/null || echo "")" [[ -n "$NS_JSON" ]] || fail "Kiali /api/namespaces returned nothing" @@ -111,7 +111,7 @@ else fi # ─── Done ──────────────────────────────────────────────────────────────────── -step "PASS — Kiali is up, wired to the capstone stack, and sees the $APP_NS namespace." +step "PASS — Kiali is up, wired to the datamesh stack, and sees the $APP_NS namespace." printf '\nView the live topology (run a demo first to create traffic):\n' printf ' ./scripts/show-endpoints.sh # then open http://127.0.0.1:%s%s\n' "$KIALI_PORT" "$KIALI_WEBROOT" printf ' open http://127.0.0.1:%s%s/ (Graph → namespace: %s)\n' "$KIALI_PORT" "$KIALI_WEBROOT" "$APP_NS" diff --git a/examples/lgtm-datamesh/demos/demo-notifications.sh b/examples/lgtm-datamesh/demos/demo-notifications.sh index e465145..e6a6917 100755 --- a/examples/lgtm-datamesh/demos/demo-notifications.sh +++ b/examples/lgtm-datamesh/demos/demo-notifications.sh @@ -20,14 +20,14 @@ set -uo pipefail -PROFILE="capstone"; NS="capstone" +PROFILE="datamesh"; NS="datamesh" ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"; cd "$ROOT" source "${ROOT}/demos/lib/endpoints.sh" source "${ROOT}/demos/lib/images.sh" source "${ROOT}/demos/lib/keda.sh" -PG_RELEASE="capstone-postgres"; PG_CHART="charts/capstone/charts/postgres" -KAFKA_RELEASE="capstone-kafka"; KAFKA_CHART="charts/capstone/charts/kafka"; KAFKA_CR="capstone-kafka" -APICURIO_RELEASE="apicurio"; APICURIO_CHART="charts/capstone/charts/apicurio" +PG_RELEASE="datamesh-postgres"; PG_CHART="charts/datamesh/charts/postgres" +KAFKA_RELEASE="datamesh-kafka"; KAFKA_CHART="charts/datamesh/charts/kafka"; KAFKA_CR="datamesh-kafka" +APICURIO_RELEASE="apicurio"; APICURIO_CHART="charts/datamesh/charts/apicurio" LOCAL_ORDER=$TP_ORDER; LOCAL_NOTIF=$TP_NOTIF # 8080 order-service, 8083 notification-service PURGE_DB=0; [[ "${1:-}" == "--purge-db" ]] && PURGE_DB=1 @@ -59,12 +59,12 @@ check_received() { } # ── image guard ──────────────────────────────────────────────────────────── -step "Sanity: chart image.repository is capstone/ with pullPolicy Never" +step "Sanity: chart image.repository is datamesh/ with pullPolicy Never" for svc in "${DEPLOY[@]}"; do - if chart_repo_ok "charts/capstone/charts/${svc}/values.yaml" "$svc"; then + if chart_repo_ok "charts/datamesh/charts/${svc}/values.yaml" "$svc"; then printf ' ✓ %s → %s\n' "$svc" "$(image_ref "$svc")" else - fail "${svc} chart must use image.repository capstone/${svc} with pullPolicy Never" + fail "${svc} chart must use image.repository datamesh/${svc} with pullPolicy Never" fi done minikube status -p "$PROFILE" >/dev/null 2>&1 || fail "profile '$PROFILE' not running" @@ -100,7 +100,7 @@ done # ── deploy (notification rollout success == migration init container ran) ───── for svc in "${DEPLOY[@]}"; do step "Deploying ${svc}" - helm upgrade --install "$svc" "charts/capstone/charts/${svc}" -n "$NS" >/dev/null || fail "${svc} install failed" + helm upgrade --install "$svc" "charts/datamesh/charts/${svc}" -n "$NS" >/dev/null || fail "${svc} install failed" kubectl rollout status "deployment/${svc}" -n "$NS" --timeout=150s || fail "${svc} rollout failed" done printf ' ✓ notification-service rolled out — its `migrate` init container (alembic upgrade head) succeeded\n' @@ -108,7 +108,7 @@ printf ' ✓ notification-service rolled out — its `migrate` init container # ── confirm the table exists (migration really created it) ──────────────────── step "Verifying the notifications table exists in Postgres" PG_PRIMARY="$(kubectl get pods -n "$NS" -l "cnpg.io/cluster=${PG_RELEASE},cnpg.io/instanceRole=primary" -o jsonpath='{.items[0].metadata.name}')" -TBL="$(kubectl exec -n "$NS" "$PG_PRIMARY" -c postgres -- psql -d capstone -tAqc \ +TBL="$(kubectl exec -n "$NS" "$PG_PRIMARY" -c postgres -- psql -d datamesh -tAqc \ "select to_regclass('notifications.notifications')" 2>/dev/null || echo '')" [[ "$TBL" == "notifications.notifications" ]] || fail "notifications.notifications table not found (got: '${TBL}')" printf ' ✓ table notifications.notifications present\n' diff --git a/examples/lgtm-datamesh/demos/demo-observability.sh b/examples/lgtm-datamesh/demos/demo-observability.sh index 68672a9..091e10f 100755 --- a/examples/lgtm-datamesh/demos/demo-observability.sh +++ b/examples/lgtm-datamesh/demos/demo-observability.sh @@ -1,9 +1,9 @@ #!/usr/bin/env bash # # demo-observability.sh — verify the metrics stack (r29, CAP-027) is actually -# working: Prometheus is up and scraping (kube-state-metrics gives us capstone +# working: Prometheus is up and scraping (kube-state-metrics gives us datamesh # workload metrics; the Istio series exists), and Grafana is up with the -# capstone dashboard provisioned. +# datamesh dashboard provisioned. # # This checks the PLUMBING, not pretty graphs — it confirms the data is flowing # so the dashboard has something to draw. Run the scaling/canary demos to make @@ -61,15 +61,15 @@ step "Checking the Prometheus endpoint ($PROM_PORT → prometheus-server)" ensure_endpoint prometheus wait_http "http://127.0.0.1:${PROM_PORT}/-/ready" 15 || true -step "Confirming kube-state-metrics gives us capstone workload replicas" -# kube_deployment_spec_replicas for capstone deployments proves both that +step "Confirming kube-state-metrics gives us datamesh workload replicas" +# kube_deployment_spec_replicas for datamesh deployments proves both that # kube-state-metrics is up AND that Prometheus is scraping it. This is the series # the dashboard's scaling panel draws. PROM_Q="http://127.0.0.1:${PROM_PORT}/api/v1/query" -result="$(curl -sG "$PROM_Q" --data-urlencode 'query=kube_deployment_spec_replicas{namespace="capstone"}' 2>/dev/null)" +result="$(curl -sG "$PROM_Q" --data-urlencode 'query=kube_deployment_spec_replicas{namespace="datamesh"}' 2>/dev/null)" printf '%s' "$result" | grep -q '"result":\[{' \ - || fail "Prometheus returned no kube_deployment_spec_replicas for namespace=capstone (is kube-state-metrics scraping? are the services deployed?)" -printf ' ✓ Prometheus has capstone replica metrics (kube-state-metrics scraping)\n' + || fail "Prometheus returned no kube_deployment_spec_replicas for namespace=datamesh (is kube-state-metrics scraping? are the services deployed?)" +printf ' ✓ Prometheus has datamesh replica metrics (kube-state-metrics scraping)\n' step "Confirming the Istio request series is present (order-service is meshed)" # The series should EXIST even at 0 req/s once the sidecar has reported once. @@ -97,10 +97,10 @@ printf '%s' "$health" | grep -q '"database": *"ok"' \ GRAF_USER="$(kubectl get secret grafana -n "$NS" -o jsonpath='{.data.admin-user}' 2>/dev/null | base64 -d)" GRAF_PASS="$(kubectl get secret grafana -n "$NS" -o jsonpath='{.data.admin-password}' 2>/dev/null | base64 -d)" code="$(curl -s -o /dev/null -w '%{http_code}' --max-time 5 \ - -u "${GRAF_USER}:${GRAF_PASS}" "http://127.0.0.1:${GRAF_PORT}/api/dashboards/uid/capstone-scaling" 2>/dev/null)" + -u "${GRAF_USER}:${GRAF_PASS}" "http://127.0.0.1:${GRAF_PORT}/api/dashboards/uid/datamesh-scaling" 2>/dev/null)" [[ "$code" == "200" ]] \ - || fail "Grafana dashboard 'capstone-scaling' not provisioned (HTTP $code from the dashboards API)" -printf ' ✓ Grafana healthy and the "Capstone — Scaling & Traffic" dashboard is provisioned\n' + || fail "Grafana dashboard 'datamesh-scaling' not provisioned (HTTP $code from the dashboards API)" +printf ' ✓ Grafana healthy and the "Datamesh — Scaling & Traffic" dashboard is provisioned\n' step "SUCCESS" printf 'Metrics stack verified. Open the dashboard and drive a demo to watch it move:\n' diff --git a/examples/lgtm-datamesh/demos/demo-om-lineage.sh b/examples/lgtm-datamesh/demos/demo-om-lineage.sh index bd8fea7..f0a29cc 100755 --- a/examples/lgtm-datamesh/demos/demo-om-lineage.sh +++ b/examples/lgtm-datamesh/demos/demo-om-lineage.sh @@ -6,12 +6,12 @@ # Does NOT run ingestion — that's scripts/ingest-openmetadata.sh. This proves # the result, over the server API (via the published NodePort, the demo-openmetadata.sh # pattern): -# * the Database Service capstone-postgres exists -# * the Messaging Service capstone-kafka exists +# * the Database Service datamesh-postgres exists +# * the Messaging Service datamesh-kafka exists # * the three spine entities exist: -# - table capstone-postgres.capstone.orders.orders -# - topic capstone-kafka.order-placed -# - table capstone-postgres.capstone.notifications.notifications +# - table datamesh-postgres.datamesh.orders.orders +# - topic datamesh-kafka.order-placed +# - table datamesh-postgres.datamesh.notifications.notifications # * lineage on the topic has an upstream (orders) AND a downstream # (notifications) edge — i.e. orders -> order-placed -> notifications # @@ -20,7 +20,7 @@ # ./demos/demo-om-lineage.sh # # Prerequisites: -# - capstone profile running, kubectl context = capstone +# - datamesh profile running, kubectl context = datamesh # - scripts/setup-openmetadata.sh AND scripts/ingest-openmetadata.sh have run # # VERIFY-POINTS (OpenMetadata 2.0.5 API; confirm at build time): @@ -33,16 +33,16 @@ set -uo pipefail # NOT -e: failures are handled so we can diagnose SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "${SCRIPT_DIR}/lib/endpoints.sh" -NS="capstone" -PROFILE="capstone" +NS="datamesh" +PROFILE="datamesh" LOCAL_PORT="$TP_OM" OM="http://127.0.0.1:${LOCAL_PORT}" ADMIN_EMAIL="admin@open-metadata.org" ADMIN_PASSWORD="admin" # demo default (r27) -ORDERS_FQN="capstone-postgres.capstone.orders.orders" -TOPIC_FQN="capstone-kafka.order-placed" -NOTIFS_FQN="capstone-postgres.capstone.notifications.notifications" +ORDERS_FQN="datamesh-postgres.datamesh.orders.orders" +TOPIC_FQN="datamesh-kafka.order-placed" +NOTIFS_FQN="datamesh-postgres.datamesh.notifications.notifications" TOKEN="" @@ -99,12 +99,12 @@ printf ' ✓ authenticated\n' # ─── Services ──────────────────────────────────────────────────────────────── step "Confirming the ingested services exist" -om_get "/api/v1/services/databaseServices/name/capstone-postgres" >/dev/null \ - || fail "Database Service 'capstone-postgres' not found — did om-ingest-postgres run?" -printf ' ✓ database service capstone-postgres\n' -om_get "/api/v1/services/messagingServices/name/capstone-kafka" >/dev/null \ - || fail "Messaging Service 'capstone-kafka' not found — did om-ingest-kafka run?" -printf ' ✓ messaging service capstone-kafka\n' +om_get "/api/v1/services/databaseServices/name/datamesh-postgres" >/dev/null \ + || fail "Database Service 'datamesh-postgres' not found — did om-ingest-postgres run?" +printf ' ✓ database service datamesh-postgres\n' +om_get "/api/v1/services/messagingServices/name/datamesh-kafka" >/dev/null \ + || fail "Messaging Service 'datamesh-kafka' not found — did om-ingest-kafka run?" +printf ' ✓ messaging service datamesh-kafka\n' # ─── Spine entities ────────────────────────────────────────────────────────── diff --git a/examples/lgtm-datamesh/demos/demo-openmetadata.sh b/examples/lgtm-datamesh/demos/demo-openmetadata.sh index 5a4bad5..e6728ad 100755 --- a/examples/lgtm-datamesh/demos/demo-openmetadata.sh +++ b/examples/lgtm-datamesh/demos/demo-openmetadata.sh @@ -10,7 +10,7 @@ # * the server answers its version API (proves it booted AND reached its # Postgres backend — OpenMetadata won't serve without a working DB) # * the version it reports is the pinned 2.0.5 -# * the dedicated `openmetadata` database really exists in capstone-postgres +# * the dedicated `openmetadata` database really exists in datamesh-postgres # and was populated by the server's migrations (sanity that Postgres reuse, # not bundled MySQL, is what's backing it) # @@ -19,7 +19,7 @@ # ./demos/demo-openmetadata.sh # # Prerequisites: -# - capstone profile running, kubectl context = capstone +# - datamesh profile running, kubectl context = datamesh # - scripts/setup-openmetadata.sh has been run (OpenMetadata installed) set -uo pipefail # NOT -e: failures are handled explicitly so we can diagnose @@ -27,9 +27,9 @@ set -uo pipefail # NOT -e: failures are handled explicitly so we can diagnose SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "${SCRIPT_DIR}/lib/endpoints.sh" -NS="capstone" -PROFILE="capstone" -PG_CLUSTER="capstone-postgres" +NS="datamesh" +PROFILE="datamesh" +PG_CLUSTER="datamesh-postgres" OM_DB="openmetadata" EXPECTED_VERSION="2.0.5" LOCAL_PORT="$TP_OM" @@ -39,7 +39,7 @@ step() { printf '\n==> %s\n' "$1"; } dump_diagnostics() { step "DIAGNOSTIC DUMP (failure — resources left in place for inspection)" - printf '\n--- pods (capstone) ---\n' + printf '\n--- pods (datamesh) ---\n' kubectl get pods -n "$NS" -o wide 2>&1 local pod pod=$(kubectl get pods -n "$NS" -l app.kubernetes.io/name=openmetadata \ @@ -100,7 +100,7 @@ step "Confirming the openmetadata database exists in ${PG_CLUSTER} and was popul PG_PRIMARY="$(kubectl get pods -n "$NS" \ -l "cnpg.io/cluster=${PG_CLUSTER},cnpg.io/instanceRole=primary" \ -o jsonpath='{.items[0].metadata.name}' 2>/dev/null || echo "")" -[[ -n "$PG_PRIMARY" ]] || fail "no capstone-postgres primary pod found" +[[ -n "$PG_PRIMARY" ]] || fail "no datamesh-postgres primary pod found" # The server's migrations create many tables in the openmetadata database. # A non-zero count proves Postgres reuse is the live backend. diff --git a/examples/lgtm-datamesh/demos/demo-order.sh b/examples/lgtm-datamesh/demos/demo-order.sh index 4af8077..2d7ef6b 100755 --- a/examples/lgtm-datamesh/demos/demo-order.sh +++ b/examples/lgtm-datamesh/demos/demo-order.sh @@ -10,7 +10,7 @@ # r21a changes: # - builds with `docker build` and loads into the profile via # scripts/build-image.sh (minikube image load); charts use -# capstone/:v1 with imagePullPolicy: Never. +# datamesh/:v1 with imagePullPolicy: Never. # - on failure, LEAVES the failed resources in place and dumps a # diagnostic bundle inline (pod status, describe events, logs) instead # of tearing everything down — so a failed run hands you the evidence @@ -20,20 +20,20 @@ # ./demos/demo-order.sh # # Prerequisites: -# - capstone minikube profile running (scripts/setup-capstone-profile.sh) +# - datamesh minikube profile running (scripts/setup-datamesh-profile.sh) # - CloudNativePG operator installed (scripts/setup-postgres-operator.sh) -# - kubectl context = capstone +# - kubectl context = datamesh set -uo pipefail # NOT -e: we manage failures explicitly so we can diagnose SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "${SCRIPT_DIR}/lib/endpoints.sh" -NS="capstone" -PROFILE="capstone" -RELEASE_PG="capstone-postgres" +NS="datamesh" +PROFILE="datamesh" +RELEASE_PG="datamesh-postgres" RELEASE_ORDER="order-service" -PG_CHART="charts/capstone/charts/postgres" -ORDER_CHART="charts/capstone/charts/order-service" +PG_CHART="charts/datamesh/charts/postgres" +ORDER_CHART="charts/datamesh/charts/order-service" SERVICE_DIR="services/order-service" IMAGE_NAME="order-service" IMAGE_TAG="v1" @@ -57,7 +57,7 @@ dump_diagnostics() { kubectl logs -n "$NS" "$pod" --previous --tail=60 2>&1 || true fi printf '\n--- images loaded in the profile ---\n' - minikube -p "$PROFILE" image ls 2>&1 | grep capstone/ || echo "(no capstone/ images loaded)" + minikube -p "$PROFILE" image ls 2>&1 | grep datamesh/ || echo "(no datamesh/ images loaded)" printf '\nResources left running. To clean up manually:\n' printf ' helm uninstall %s inventory-service -n %s\n' "$RELEASE_ORDER" "$NS" printf ' helm uninstall %s -n %s # also removes Postgres\n' "$RELEASE_PG" "$NS" @@ -131,7 +131,7 @@ step "Building + loading inventory-service" ./scripts/build-image.sh services/inventory-service inventory-service "$IMAGE_TAG" \ || fail "inventory-service build/load failed" step "Deploying inventory-service (seeds demo stock, including WIDGET-001)" -helm upgrade --install inventory-service charts/capstone/charts/inventory-service -n "$NS" \ +helm upgrade --install inventory-service charts/datamesh/charts/inventory-service -n "$NS" \ || fail "helm install of inventory-service chart failed" kubectl rollout status deployment/inventory-service -n "$NS" --timeout=120s \ || fail "inventory-service did not roll out" @@ -185,7 +185,7 @@ step "Verify the row actually persisted in Postgres (direct query)" pg_pod=$(kubectl get pods -n "$NS" -l "cnpg.io/cluster=$RELEASE_PG,cnpg.io/instanceRole=primary" \ -o jsonpath='{.items[0].metadata.name}') row_count=$(kubectl exec -n "$NS" "$pg_pod" -- \ - psql -U postgres -d capstone -tAc \ + psql -U postgres -d datamesh -tAc \ "SELECT count(*) FROM orders.orders WHERE id = '$order_id';" 2>/dev/null | tr -d '[:space:]') [[ "$row_count" == "1" ]] || fail "expected 1 row in orders.orders, found '$row_count'" printf ' confirmed: 1 row in orders.orders for id=%s\n' "$order_id" diff --git a/examples/lgtm-datamesh/demos/demo-reviews.sh b/examples/lgtm-datamesh/demos/demo-reviews.sh index 90ea51d..d9b3db7 100755 --- a/examples/lgtm-datamesh/demos/demo-reviews.sh +++ b/examples/lgtm-datamesh/demos/demo-reviews.sh @@ -2,12 +2,12 @@ # # demo-reviews.sh — verify the review-service data product (Phase A). # -# Builds + deploys review-service against the capstone Postgres and asserts its +# Builds + deploys review-service against the datamesh Postgres and asserts its # REST surface end-to-end: probes, the seeded rows, create, fetch-by-id, and the # ?sku= filter. This proves the new data product stands and serves before we # layer discovery (Apicurio contract + OpenMetadata catalog/lineage) on top. # -# Assumes the capstone cluster is up with Postgres (cluster-up.sh / the capstone +# Assumes the datamesh cluster is up with Postgres (cluster-up.sh / the datamesh # deploy). Leaves resources in place + dumps diagnostics on failure; cleans up # review-service on success (Postgres is shared and left alone). # @@ -17,10 +17,10 @@ set -uo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "${SCRIPT_DIR}/lib/endpoints.sh" -NS="capstone" -PROFILE="capstone" +NS="datamesh" +PROFILE="datamesh" RELEASE="review-service" -CHART="charts/capstone/charts/review-service" +CHART="charts/datamesh/charts/review-service" SERVICE_DIR="services/review-service" IMAGE_NAME="review-service" IMAGE_TAG="v1" @@ -54,8 +54,8 @@ trap on_exit EXIT step "Pre-flight checks" [[ "$(kubectl config current-context 2>/dev/null)" == "$PROFILE" ]] \ || fail "kubectl context is not '$PROFILE' — run: kubectl config use-context $PROFILE" -kubectl get cluster.postgresql.cnpg.io capstone-postgres -n "$NS" >/dev/null 2>&1 \ - || fail "capstone-postgres not found — bring the capstone up first (./scripts/cluster-up.sh)" +kubectl get cluster.postgresql.cnpg.io datamesh-postgres -n "$NS" >/dev/null 2>&1 \ + || fail "datamesh-postgres not found — bring the datamesh up first (./scripts/cluster-up.sh)" command -v helm >/dev/null || fail "helm not in PATH" # ─── Build + deploy ────────────────────────────────────────────────────────── diff --git a/examples/lgtm-datamesh/demos/demo-service.sh b/examples/lgtm-datamesh/demos/demo-service.sh index df97fa3..df3793e 100755 --- a/examples/lgtm-datamesh/demos/demo-service.sh +++ b/examples/lgtm-datamesh/demos/demo-service.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # # demo-service.sh — build, deploy, and verify the health surface of a -# scaffolded capstone service (r22). Generic counterpart to demo-order.sh +# scaffolded datamesh service (r22). Generic counterpart to demo-order.sh # (which also asserts order-service's domain endpoints). # # What it does: @@ -26,15 +26,15 @@ SERVICE="${BASE}-service" PURGE_DB=0 [[ "${2:-}" == "--purge-db" ]] && PURGE_DB=1 -PROFILE="capstone" -NS="capstone" +PROFILE="datamesh" +NS="datamesh" ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" cd "$ROOT" SVC_DIR="services/${SERVICE}" -CHART="charts/capstone/charts/${SERVICE}" -PG_RELEASE="capstone-postgres" -PG_CHART="charts/capstone/charts/postgres" # the Cluster CR chart (r21) +CHART="charts/datamesh/charts/${SERVICE}" +PG_RELEASE="datamesh-postgres" +PG_CHART="charts/datamesh/charts/postgres" # the Cluster CR chart (r21) # The endpoint name is the short service name ($BASE), e.g. "order", "review". LOCAL_PORT="$(endpoint_port "$BASE")" || { echo "no endpoint mapping for $BASE"; exit 1; } @@ -57,21 +57,21 @@ diagnostics() { printf '\n--- previous logs (if crashed) ---\n' >&2 kubectl logs -n "$NS" -l "app.kubernetes.io/name=${SERVICE}" --previous --tail=50 2>&1 || true printf '\n--- images loaded in the profile ---\n' >&2 - minikube -p "$PROFILE" image ls 2>&1 | grep capstone/ >&2 || echo "(no capstone/ images loaded)" >&2 + minikube -p "$PROFILE" image ls 2>&1 | grep datamesh/ >&2 || echo "(no datamesh/ images loaded)" >&2 } [[ -d "$SVC_DIR" ]] || fail "service dir $SVC_DIR not found — scaffold it first: ./scripts/scaffold-service.sh $BASE " [[ -d "$CHART" ]] || fail "chart dir $CHART not found" -step "Sanity: chart image.repository is capstone/ with pullPolicy Never" +step "Sanity: chart image.repository is datamesh/ with pullPolicy Never" if chart_repo_ok "$CHART/values.yaml" "$SERVICE"; then printf ' \xe2\x9c\x93 %s -> %s\n' "$SERVICE" "$(image_ref "$SERVICE")" else - fail "$SERVICE chart must use image.repository capstone/$SERVICE with pullPolicy Never" + fail "$SERVICE chart must use image.repository datamesh/$SERVICE with pullPolicy Never" fi step "Pre-flight: profile + context" -minikube status -p "$PROFILE" >/dev/null 2>&1 || fail "profile '$PROFILE' not running — ./scripts/setup-capstone-profile.sh" +minikube status -p "$PROFILE" >/dev/null 2>&1 || fail "profile '$PROFILE' not running — ./scripts/setup-datamesh-profile.sh" kubectl config use-context "$PROFILE" >/dev/null step "Build + load ${SERVICE}:v1 into the profile" @@ -121,7 +121,7 @@ SCHEMA="$(helm get values "$SERVICE" -n "$NS" -a 2>/dev/null | awk '/schema:/{pr SCHEMA="${SCHEMA:-$BASE}" PRIMARY="$(kubectl get pods -n "$NS" -l "cnpg.io/cluster=${PG_RELEASE},cnpg.io/instanceRole=primary" -o jsonpath='{.items[0].metadata.name}' 2>/dev/null)" if [[ -n "$PRIMARY" ]]; then - if kubectl exec -n "$NS" "$PRIMARY" -- psql -U postgres -d capstone -tAc \ + if kubectl exec -n "$NS" "$PRIMARY" -- psql -U postgres -d datamesh -tAc \ "SELECT 1 FROM information_schema.schemata WHERE schema_name='${SCHEMA}'" 2>/dev/null | grep -q 1; then printf ' confirmed: schema "%s" exists\n' "$SCHEMA" else diff --git a/examples/lgtm-datamesh/demos/demo-trace-flow.sh b/examples/lgtm-datamesh/demos/demo-trace-flow.sh index 2e7c85b..86a1650 100755 --- a/examples/lgtm-datamesh/demos/demo-trace-flow.sh +++ b/examples/lgtm-datamesh/demos/demo-trace-flow.sh @@ -19,9 +19,9 @@ set -uo pipefail source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/lib/endpoints.sh" -NS="capstone" +NS="datamesh" OBS_NS="observability" -HOST="graphql-gateway.capstone" +HOST="graphql-gateway.datamesh" PROXY_SVC="keda-add-ons-http-interceptor-proxy" GQL_PORT="$TP_GATEWAY" TEMPO_PORT="$TP_TEMPO" @@ -44,7 +44,7 @@ kubectl get svc tempo -n "$OBS_NS" >/dev/null 2>&1 \ kubectl get deploy graphql-gateway -n "$NS" \ -o jsonpath='{.spec.template.spec.containers[0].env[*].name}' 2>/dev/null \ | grep -q OTEL_EXPORTER_OTLP_ENDPOINT \ - || fail "graphql-gateway has no OTEL_* env — deploy the r29c chart (helm upgrade --install graphql-gateway charts/capstone/charts/graphql-gateway -n $NS) and rebuild its image" + || fail "graphql-gateway has no OTEL_* env — deploy the r29c chart (helm upgrade --install graphql-gateway charts/datamesh/charts/graphql-gateway -n $NS) and rebuild its image" printf ' ✓ interceptor, Tempo, and OTEL-enabled gateway present\n' # ─── Drive a GraphQL query through the interceptor ─────────────────────────── diff --git a/examples/lgtm-datamesh/demos/lib/endpoints.sh b/examples/lgtm-datamesh/demos/lib/endpoints.sh index 56e8530..09fcd95 100644 --- a/examples/lgtm-datamesh/demos/lib/endpoints.sh +++ b/examples/lgtm-datamesh/demos/lib/endpoints.sh @@ -1,10 +1,10 @@ #!/usr/bin/env bash # -# endpoints.sh — the ONE source of truth for host access to the capstone cluster. +# endpoints.sh — the ONE source of truth for host access to the datamesh cluster. # # Every host-facing service is a fixed NodePort. The minikube profile publishes # each NodePort to the host on loopback when the profile is created: -# minikube start -p capstone --ports=127.0.0.1::,... +# minikube start -p datamesh --ports=127.0.0.1::,... # so `http://127.0.0.1:` reaches the Service directly. No helper # process runs and nothing needs to be brought up per demo. # @@ -17,8 +17,8 @@ # add a service, add one row to _endpoint_row, its name to ENDPOINT_NAMES, and # (if it's one of our charts) set its Service nodePort to the matching value. # Published ports are fixed at profile creation: changing the map requires -# recreating the profile (./scripts/setup-capstone-profile.sh --replace), which -# deletes and recreates the cluster, so run ./scripts/bootstrap-capstone.sh again. +# recreating the profile (./scripts/setup-datamesh-profile.sh --replace), which +# deletes and recreates the cluster, so run ./scripts/bootstrap-datamesh.sh again. # # Safe to `source` under `set -euo pipefail`: only definitions, no side effects. @@ -45,7 +45,7 @@ TP_INVENTORY=8087; NP_INVENTORY=30087 TP_INGRESS=8088; NP_INGRESS=30088 # istio-ingressgateway :80 TP_KAFKAUI=8089; NP_KAFKAUI=30089 # Kafka UI (topic/schema browser) -EP_PROFILE="${MINIKUBE_PROFILE:-capstone}" +EP_PROFILE="${MINIKUBE_PROFILE:-datamesh}" ENDPOINT_NAMES=(grafana prometheus tempo tempo-otlp kiali openmetadata apicurio kafka-ui order gateway notification review inventory ingress) @@ -59,14 +59,14 @@ _endpoint_row() { tempo) echo "$TP_TEMPO $NP_TEMPO observability tempo Tempo" ;; tempo-otlp) echo "$TP_TEMPO_OTLP $NP_TEMPO_OTLP observability tempo Tempo-OTLP" ;; kiali) echo "$TP_KIALI $NP_KIALI istio-system kiali Kiali" ;; - openmetadata) echo "$TP_OM $NP_OM capstone openmetadata OpenMetadata" ;; - apicurio) echo "$TP_APICURIO $NP_APICURIO capstone apicurio Apicurio" ;; - kafka-ui) echo "$TP_KAFKAUI $NP_KAFKAUI capstone kafka-ui Kafka-UI" ;; - order) echo "$TP_ORDER $NP_ORDER capstone order-service order-service" ;; + openmetadata) echo "$TP_OM $NP_OM datamesh openmetadata OpenMetadata" ;; + apicurio) echo "$TP_APICURIO $NP_APICURIO datamesh apicurio Apicurio" ;; + kafka-ui) echo "$TP_KAFKAUI $NP_KAFKAUI datamesh kafka-ui Kafka-UI" ;; + order) echo "$TP_ORDER $NP_ORDER datamesh order-service order-service" ;; gateway) echo "$TP_GATEWAY $NP_GATEWAY keda keda-add-ons-http-interceptor-proxy gateway-interceptor" ;; - notification) echo "$TP_NOTIF $NP_NOTIF capstone notification-service notification-service" ;; - review) echo "$TP_REVIEW $NP_REVIEW capstone review-service review-service" ;; - inventory) echo "$TP_INVENTORY $NP_INVENTORY capstone inventory-service inventory-service" ;; + notification) echo "$TP_NOTIF $NP_NOTIF datamesh notification-service notification-service" ;; + review) echo "$TP_REVIEW $NP_REVIEW datamesh review-service review-service" ;; + inventory) echo "$TP_INVENTORY $NP_INVENTORY datamesh inventory-service inventory-service" ;; ingress) echo "$TP_INGRESS $NP_INGRESS istio-system istio-ingressgateway istio-ingressgateway" ;; *) return 1 ;; esac @@ -177,8 +177,8 @@ assert_host_ports_free() { # _port_bindings_json → PortBindings JSON of the profile container (empty on error) _port_bindings_json() { - # The capstone profile is a docker-driver container named after the profile - # (setup-capstone-profile.sh); its published ports live in HostConfig. + # The datamesh profile is a docker-driver container named after the profile + # (setup-datamesh-profile.sh); its published ports live in HostConfig. docker container inspect --format '{{json .HostConfig.PortBindings}}' "$EP_PROFILE" 2>/dev/null || true } @@ -251,8 +251,8 @@ check_published_ports() { printf 'endpoints: profile "%s" does not publish the required ports:\n' "$EP_PROFILE" printf '%s' "$msg" printf 'Ports are fixed when the profile is created and cannot be added to a running one.\n' - printf 'Recreate it with: ./scripts/setup-capstone-profile.sh --replace\n' - printf '(--replace deletes and recreates the cluster; run ./scripts/bootstrap-capstone.sh again afterwards.)\n' + printf 'Recreate it with: ./scripts/setup-datamesh-profile.sh --replace\n' + printf '(--replace deletes and recreates the cluster; run ./scripts/bootstrap-datamesh.sh again afterwards.)\n' } >&2 return 1 } @@ -277,8 +277,8 @@ ensure_endpoint() { if ! published_ports | grep -qx "${np} ${hp}"; then printf 'endpoints: %s: 127.0.0.1:%s -> nodePort %s is not published by profile "%s"\n' \ "$name" "$hp" "$np" "$EP_PROFILE" >&2 - printf 'Recreate it with: ./scripts/setup-capstone-profile.sh --replace\n' >&2 - printf '(--replace deletes and recreates the cluster; run ./scripts/bootstrap-capstone.sh again afterwards.)\n' >&2 + printf 'Recreate it with: ./scripts/setup-datamesh-profile.sh --replace\n' >&2 + printf '(--replace deletes and recreates the cluster; run ./scripts/bootstrap-datamesh.sh again afterwards.)\n' >&2 overall=1; continue fi out="$(kubectl --context "$EP_PROFILE" get svc -n "$ns" "$svc" \ @@ -324,12 +324,12 @@ wait_http() { } # wake_gateway — wake the KEDA-scaled-to-zero graphql-gateway the REAL way, by -# driving a request through the HTTP interceptor (Host: graphql-gateway.capstone), +# driving a request through the HTTP interceptor (Host: graphql-gateway.datamesh), # then waiting for the Deployment to be Available. Verifies the gateway endpoint # first. Echoes nothing; returns 0 if the gateway is Available. -GATEWAY_HOST="graphql-gateway.capstone" +GATEWAY_HOST="graphql-gateway.datamesh" wake_gateway() { - local ns="${1:-capstone}" + local ns="${1:-datamesh}" ensure_endpoint gateway || return 1 wait_http "http://127.0.0.1:${TP_GATEWAY}/" 15 || true # Pre-warm: this request's job is to trigger scale-from-zero; response and diff --git a/examples/lgtm-datamesh/demos/lib/images.sh b/examples/lgtm-datamesh/demos/lib/images.sh index 34fb496..e2a625a 100644 --- a/examples/lgtm-datamesh/demos/lib/images.sh +++ b/examples/lgtm-datamesh/demos/lib/images.sh @@ -1,10 +1,10 @@ #!/usr/bin/env bash # -# images.sh — image pipeline helpers for the capstone cluster. +# images.sh — image pipeline helpers for the datamesh cluster. # # There is no registry. Images are built on the host with `docker build`, # loaded into the node's containerd with `minikube image load`, and named -# capstone/:v1. Charts reference them with `imagePullPolicy: Never`, so +# datamesh/:v1. Charts reference them with `imagePullPolicy: Never`, so # the kubelet only ever uses what was loaded into the profile. # # source "$(dirname "${BASH_SOURCE[0]}")/lib/images.sh" @@ -13,14 +13,14 @@ # # Safe to `source` under `set -euo pipefail`: only definitions, no side effects. -IMAGE_PREFIX="capstone" +IMAGE_PREFIX="datamesh" IMAGE_TAG_DEFAULT="v1" -IMAGE_PROFILE="${MINIKUBE_PROFILE:-capstone}" +IMAGE_PROFILE="${MINIKUBE_PROFILE:-datamesh}" -CAPSTONE_SERVICES=(graphql-gateway inventory-service notification-service +DATAMESH_SERVICES=(graphql-gateway inventory-service notification-service order-service payment-service shipping-service) -# image_ref [tag] → capstone/: +# image_ref [tag] → datamesh/: image_ref() { printf '%s/%s:%s\n' "$IMAGE_PREFIX" "$1" "${2:-$IMAGE_TAG_DEFAULT}"; } # image_in_profile [tag] → 0 if the image is loaded in the profile's containerd @@ -42,7 +42,7 @@ docker_engine_ok() { return 1 } -# chart_repo_ok → 0 if image.repository is capstone/ +# chart_repo_ok → 0 if image.repository is datamesh/ # and pullPolicy is Never; else prints what was found on stderr and returns 1. chart_repo_ok() { local file="$1" svc="$2" repo pol diff --git a/examples/lgtm-datamesh/demos/verify-grafana.sh b/examples/lgtm-datamesh/demos/verify-grafana.sh index 852a6ab..2af0845 100755 --- a/examples/lgtm-datamesh/demos/verify-grafana.sh +++ b/examples/lgtm-datamesh/demos/verify-grafana.sh @@ -3,14 +3,14 @@ # verify-grafana.sh — automated test that all Grafana dashboards, datasources, # and panels are provisioned correctly. # -# Run from examples/lgtm-datamesh/ with the capstone profile's published +# Run from examples/lgtm-datamesh/ with the datamesh profile's published # NodePorts available (Grafana on http://127.0.0.1:3000): # ./demos/verify-grafana.sh set -uo pipefail GRAFANA="http://127.0.0.1:3000" -PASS="capstone" +PASS="datamesh" AUTH="admin:${PASS}" step() { printf '\n==> %s\n' "$1"; } @@ -66,19 +66,19 @@ else fail "No dashboards found" fi -if echo "$dashboards" | python3 -c 'import sys,json; ds=json.load(sys.stdin); sys.exit(0 if any("capstone" in d.get("title","").lower() or "scaling" in d.get("title","").lower() for d in ds) else 1)' 2>/dev/null; then - ok "Capstone — Scaling & Traffic dashboard found" +if echo "$dashboards" | python3 -c 'import sys,json; ds=json.load(sys.stdin); sys.exit(0 if any("datamesh" in d.get("title","").lower() or "scaling" in d.get("title","").lower() for d in ds) else 1)' 2>/dev/null; then + ok "Datamesh — Scaling & Traffic dashboard found" else - fail "Capstone — Scaling & Traffic dashboard missing" + fail "Datamesh — Scaling & Traffic dashboard missing" fi # ── 4. Panel verification ─────────────────────────────────────────────────── -step "Panel verification (Capstone — Scaling & Traffic)" +step "Panel verification (Datamesh — Scaling & Traffic)" -dash_detail="$(curl -4 -fsS --max-time 5 -u "$AUTH" "${GRAFANA}/api/dashboards/uid/capstone-scaling" 2>/dev/null)" +dash_detail="$(curl -4 -fsS --max-time 5 -u "$AUTH" "${GRAFANA}/api/dashboards/uid/datamesh-scaling" 2>/dev/null)" if [[ -z "$dash_detail" ]] || echo "$dash_detail" | grep -q '"message"'; then - fail "Could not fetch dashboard capstone-scaling" + fail "Could not fetch dashboard datamesh-scaling" else panel_count="$(echo "$dash_detail" | python3 -c 'import sys,json; d=json.load(sys.stdin); print(len(d.get("dashboard",{}).get("panels",[])))' 2>/dev/null)" if [[ "$panel_count" -ge 2 ]]; then diff --git a/examples/lgtm-datamesh/demos/walkthrough.sh b/examples/lgtm-datamesh/demos/walkthrough.sh index 49c29d6..d303e69 100755 --- a/examples/lgtm-datamesh/demos/walkthrough.sh +++ b/examples/lgtm-datamesh/demos/walkthrough.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # -# walkthrough.sh — the capstone's replayable presenter walkthrough (Phase E). +# walkthrough.sh — the datamesh's replayable presenter walkthrough (Phase E). # # Five acts, each shelling out to an existing demo script with narration # between them. Presenter-driven: Enter to advance between acts so you control @@ -22,7 +22,7 @@ # (kedacore/http-add-on#1668) that blocked the interceptor path in v0.12.2 and # v0.14.0 was fixed upstream in v0.15.0; the KEDA HTTP add-on is now at v0.16.0 # (setup-keda.sh). The trace act therefore wakes the gateway the real way — a -# request through the interceptor (Host: graphql-gateway.capstone) over the +# request through the interceptor (Host: graphql-gateway.datamesh) over the # published NodePort. It runs demo-trace-flow.sh. # # Usage: @@ -37,12 +37,12 @@ set -uo pipefail # ─── Setup ─────────────────────────────────────────────────────────────────── # resolve repo paths regardless of where this is invoked from, then cd to the -# capstone root so the demo scripts see the relative paths they expect. +# datamesh root so the demo scripts see the relative paths they expect. SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -CAPSTONE_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" -cd "$CAPSTONE_ROOT" +DATAMESH_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" +cd "$DATAMESH_ROOT" -NS="capstone" +NS="datamesh" OBS_NS="observability" ISTIO_SYSTEM="istio-system" @@ -63,7 +63,7 @@ PREFLIGHT=1 usage() { cat <<'USAGE' -walkthrough.sh — the capstone's five-act presenter walkthrough +walkthrough.sh — the datamesh's five-act presenter walkthrough ./demos/walkthrough.sh # all five acts, Enter to advance ./demos/walkthrough.sh --only ACT # run one act in isolation @@ -180,9 +180,9 @@ preflight() { check "kubectl reachable" \ "kubectl version --request-timeout=5s >/dev/null 2>&1" \ "is the cluster up? try: ./scripts/cluster-up.sh" - check "capstone namespace exists" \ + check "datamesh namespace exists" \ "ns_exists $NS" \ - "run the full bring-up: ./scripts/bootstrap-capstone.sh" + "run the full bring-up: ./scripts/bootstrap-datamesh.sh" if want_act trace || want_act lineage || want_act topology; then check "Tempo Ready" \ @@ -198,10 +198,10 @@ preflight() { # the request through the interceptor wakes it. check "graphql-gateway Deployment exists" \ "kubectl -n $NS get deploy graphql-gateway >/dev/null 2>&1" \ - "helm upgrade --install graphql-gateway charts/capstone/charts/graphql-gateway -n $NS (or re-run bootstrap-capstone.sh)" + "helm upgrade --install graphql-gateway charts/datamesh/charts/graphql-gateway -n $NS (or re-run bootstrap-datamesh.sh)" check "graphql-gateway Service exists" \ "kubectl -n $NS get svc graphql-gateway >/dev/null 2>&1" \ - "kubectl -n $NS get svc graphql-gateway (or re-run bootstrap-capstone.sh)" + "kubectl -n $NS get svc graphql-gateway (or re-run bootstrap-datamesh.sh)" fi if want_act trace || want_act canary || want_act topology; then check "Prometheus Ready" \ @@ -224,12 +224,12 @@ preflight() { "./scripts/setup-openmetadata.sh" check "OpenMetadata ingestion has run (catalog populated)" \ "kubectl get job -n $NS om-ingest-postgres om-ingest-kafka om-declare-lineage --no-headers 2>/dev/null | wc -l | grep -q '^3$'" \ - "./scripts/ingest-openmetadata.sh (or re-run bootstrap-capstone.sh, which now does this)" + "./scripts/ingest-openmetadata.sh (or re-run bootstrap-datamesh.sh, which now does this)" fi if want_act topology; then check "Kiali Ready (CAP-042)" \ "ready_by_label $ISTIO_SYSTEM 'app.kubernetes.io/name=kiali'" \ - "./scripts/setup-kiali.sh (or re-run bootstrap-capstone.sh, which now does this)" + "./scripts/setup-kiali.sh (or re-run bootstrap-datamesh.sh, which now does this)" fi if (( fail > 0 )); then @@ -271,7 +271,7 @@ prompt_enter "press Enter to start" # Drive one GraphQL query through the gateway and confirm the fan-out trace # (graphql-gateway → order-service REST → inventory gRPC) lands in Tempo. The # gateway is KEDA-scaled-to-zero and woken the REAL way — a request routed -# through the KEDA HTTP interceptor (Host: graphql-gateway.capstone) over the +# through the KEDA HTTP interceptor (Host: graphql-gateway.datamesh) over the # published NodePort. This act IS demos/demo-trace-flow.sh. if want_act trace; then @@ -280,7 +280,7 @@ if want_act trace; then narrate "we drive a single query through graphql-gateway" narrate "the resolver makes a REST call to order-service and a gRPC call to inventory-service" narrate "all three spans land in Tempo, stitched by a shared trace id" - info "entry path: the KEDA HTTP interceptor wakes the gateway from zero (Host: graphql-gateway.capstone)" + info "entry path: the KEDA HTTP interceptor wakes the gateway from zero (Host: graphql-gateway.datamesh)" info "underlying script: demos/demo-trace-flow.sh" prompt_enter "press Enter to run" run_act "trace" ./demos/demo-trace-flow.sh || exit 1 @@ -311,7 +311,7 @@ fi if want_act canary; then if ! kubectl get deployment order-service -n "$NS" >/dev/null 2>&1; then info "order-service not deployed — restoring for canary act" - helm upgrade --install order-service charts/capstone/charts/order-service -n "$NS" >/dev/null + helm upgrade --install order-service charts/datamesh/charts/order-service -n "$NS" >/dev/null kubectl rollout status deploy/order-service -n "$NS" --timeout=120s >/dev/null fi fi @@ -357,13 +357,13 @@ fi if want_act topology; then act_header "topology" "Live mesh topology in Kiali" \ "Kiali's traffic graph is the live view of the mesh: products, the edges between them, and — if the canary is up — the split rendered as parallel paths." - narrate "first, confirm Kiali itself is healthy and sees the capstone namespace" + narrate "first, confirm Kiali itself is healthy and sees the datamesh namespace" info "underlying script: demos/demo-kiali.sh" prompt_enter "press Enter to verify Kiali" run_act "topology (smoke)" ./demos/demo-kiali.sh || exit 1 narrate "Kiali is already published on 127.0.0.1 (./scripts/show-endpoints.sh)" - info " http://127.0.0.1:20001/kiali (Graph → namespace: capstone)" + info " http://127.0.0.1:20001/kiali (Graph → namespace: datamesh)" narrate "to make EDGES appear in the graph, generate some traffic:" info " in another shell: for i in {1..40}; do ./demos/demo-trace-flow.sh >/dev/null; done" diff --git a/examples/lgtm-datamesh/istio/order-service-v2.yaml b/examples/lgtm-datamesh/istio/order-service-v2.yaml index 79338a6..8c3497f 100644 --- a/examples/lgtm-datamesh/istio/order-service-v2.yaml +++ b/examples/lgtm-datamesh/istio/order-service-v2.yaml @@ -18,10 +18,10 @@ apiVersion: apps/v1 kind: Deployment metadata: name: order-service-v2 - namespace: capstone + namespace: datamesh labels: app.kubernetes.io/name: order-service - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh app.kubernetes.io/component: data-product version: v2 spec: @@ -34,7 +34,7 @@ spec: metadata: labels: app.kubernetes.io/name: order-service - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh version: v2 annotations: sidecar.istio.io/inject: "true" @@ -46,7 +46,7 @@ spec: spec: containers: - name: order-service - image: "capstone/order-service:v1" # same image as v1 + image: "datamesh/order-service:v1" # same image as v1 imagePullPolicy: Never ports: - name: http @@ -59,7 +59,7 @@ spec: - name: INVENTORY_GRPC_ADDR value: "inventory-service:50051" - name: KAFKA_BOOTSTRAP - value: "capstone-kafka-kafka-bootstrap:9092" + value: "datamesh-kafka-kafka-bootstrap:9092" - name: KAFKA_ORDER_TOPIC value: "order-placed" - name: APICURIO_URL @@ -67,23 +67,23 @@ spec: - name: KAFKA_ORDER_SUBJECT value: "order-placed-value" - name: PG_HOST - value: "capstone-postgres-rw.capstone.svc.cluster.local" + value: "datamesh-postgres-rw.datamesh.svc.cluster.local" - name: PG_PORT value: "5432" - name: PG_DATABASE valueFrom: secretKeyRef: - name: capstone-postgres-app + name: datamesh-postgres-app key: dbname - name: PG_USER valueFrom: secretKeyRef: - name: capstone-postgres-app + name: datamesh-postgres-app key: username - name: PG_PASSWORD valueFrom: secretKeyRef: - name: capstone-postgres-app + name: datamesh-postgres-app key: password resources: requests: diff --git a/examples/lgtm-datamesh/istio/routing.yaml b/examples/lgtm-datamesh/istio/routing.yaml index 01d6997..41a2f5a 100644 --- a/examples/lgtm-datamesh/istio/routing.yaml +++ b/examples/lgtm-datamesh/istio/routing.yaml @@ -23,7 +23,7 @@ apiVersion: networking.istio.io/v1 kind: Gateway metadata: name: order-service-gateway - namespace: capstone + namespace: datamesh spec: selector: istio: ingressgateway # the default istio-ingressgateway in istio-system @@ -39,7 +39,7 @@ apiVersion: networking.istio.io/v1 kind: VirtualService metadata: name: order-service - namespace: capstone + namespace: datamesh spec: hosts: - "*" @@ -60,7 +60,7 @@ apiVersion: networking.istio.io/v1 kind: DestinationRule metadata: name: order-service - namespace: capstone + namespace: datamesh spec: host: order-service subsets: diff --git a/examples/lgtm-datamesh/keda/gateway-httpscaledobject.yaml b/examples/lgtm-datamesh/keda/gateway-httpscaledobject.yaml index 0c4ede8..0164812 100644 --- a/examples/lgtm-datamesh/keda/gateway-httpscaledobject.yaml +++ b/examples/lgtm-datamesh/keda/gateway-httpscaledobject.yaml @@ -6,7 +6,7 @@ # including from ZERO. With no traffic the gateway costs nothing; the first # query through the add-on's interceptor wakes it (the interceptor holds the # request until a replica is Ready), and sustained concurrency scales it out. -# The §12 HTTP-add-on pattern, now on a capstone data product. +# The §12 HTTP-add-on pattern, now on a datamesh data product. # # This is the OTHER half of "elastic data products" from the Kafka-lag scaler: # event consumers scale on backlog, synchronous services scale on request load. @@ -29,10 +29,10 @@ apiVersion: http.keda.sh/v1alpha1 kind: HTTPScaledObject metadata: name: graphql-gateway-http - namespace: capstone + namespace: datamesh spec: hosts: - - graphql-gateway.capstone # Host header the interceptor routes on + - graphql-gateway.datamesh # Host header the interceptor routes on scaleTargetRef: name: graphql-gateway # Deployment to scale kind: Deployment diff --git a/examples/lgtm-datamesh/keda/notification-scaledobject.yaml b/examples/lgtm-datamesh/keda/notification-scaledobject.yaml index 2f81837..cfd0bfc 100644 --- a/examples/lgtm-datamesh/keda/notification-scaledobject.yaml +++ b/examples/lgtm-datamesh/keda/notification-scaledobject.yaml @@ -5,7 +5,7 @@ # (consumer group `notification-service`) and persists a notification per order. # This makes it an "elastic data product" — KEDA polls the group's lag and runs # exactly as many consumers as the backlog warrants, down to ZERO when the topic -# is quiet. The §12 Kafka pattern, now applied to a capstone data product. +# is quiet. The §12 Kafka pattern, now applied to a datamesh data product. # # Scale-to-zero works because KEDA reads lag directly from Kafka (committed # offset vs. log-end offset for the group) even when no consumer is running, so @@ -20,7 +20,7 @@ apiVersion: keda.sh/v1alpha1 kind: ScaledObject metadata: name: notification-service-scaler - namespace: capstone + namespace: datamesh spec: scaleTargetRef: name: notification-service # the Deployment KEDA scales @@ -33,9 +33,9 @@ spec: metadata: # FQDN, not the short name: the KEDA operator runs in the `keda` # namespace and resolves DNS relative to ITS namespace, so the short - # `capstone-kafka-kafka-bootstrap` (which works from inside `capstone`) + # `datamesh-kafka-kafka-bootstrap` (which works from inside `datamesh`) # fails with "no such host". The fully-qualified name always resolves. - bootstrapServers: capstone-kafka-kafka-bootstrap.capstone.svc.cluster.local:9092 + bootstrapServers: datamesh-kafka-kafka-bootstrap.datamesh.svc.cluster.local:9092 consumerGroup: notification-service topic: order-placed lagThreshold: "5" # one replica per 5 messages of lag diff --git a/examples/lgtm-datamesh/observability/grafana-values.yaml b/examples/lgtm-datamesh/observability/grafana-values.yaml index 07d5c47..fb746cd 100644 --- a/examples/lgtm-datamesh/observability/grafana-values.yaml +++ b/examples/lgtm-datamesh/observability/grafana-values.yaml @@ -1,4 +1,4 @@ -# grafana-values.yaml — lean Grafana for the capstone (r29, CAP-027). Provisions +# grafana-values.yaml — lean Grafana for the datamesh (r29, CAP-027). Provisions # the Prometheus datasource and one dashboard whose top panel is the whole point # of this section: desired vs ready replicas over time, so the KEDA scaling you # triggered in the demos becomes something you can actually watch (including the @@ -7,12 +7,12 @@ # Reach it after install with: # NodePort 30300, published on 127.0.0.1:3000 at profile creation # (map: demos/lib/endpoints.sh) -# open http://127.0.0.1:3000 (admin / capstone) +# open http://127.0.0.1:3000 (admin / datamesh) # # A Tempo datasource for traces is added in r29b. adminUser: admin -adminPassword: capstone # demo only — not a real secret +adminPassword: datamesh # demo only — not a real secret persistence: enabled: false # dashboards are provisioned from config, not saved state @@ -55,22 +55,22 @@ dashboardProviders: dashboardproviders.yaml: apiVersion: 1 providers: - - name: capstone + - name: datamesh orgId: 1 - folder: Capstone + folder: Datamesh type: file disableDeletion: false editable: true options: - path: /var/lib/grafana/dashboards/capstone + path: /var/lib/grafana/dashboards/datamesh dashboards: - capstone: + datamesh: scaling: json: | { - "uid": "capstone-scaling", - "title": "Capstone — Scaling & Traffic", + "uid": "datamesh-scaling", + "title": "Datamesh — Scaling & Traffic", "schemaVersion": 39, "version": 1, "editable": true, @@ -100,13 +100,13 @@ dashboards: { "refId": "A", "datasource": { "type": "prometheus", "uid": "prometheus" }, - "expr": "kube_deployment_spec_replicas{namespace=\"capstone\", deployment=~\"graphql-gateway|notification-service\"}", + "expr": "kube_deployment_spec_replicas{namespace=\"datamesh\", deployment=~\"graphql-gateway|notification-service\"}", "legendFormat": "{{deployment}} desired" }, { "refId": "B", "datasource": { "type": "prometheus", "uid": "prometheus" }, - "expr": "kube_deployment_status_replicas_ready{namespace=\"capstone\", deployment=~\"graphql-gateway|notification-service\"}", + "expr": "kube_deployment_status_replicas_ready{namespace=\"datamesh\", deployment=~\"graphql-gateway|notification-service\"}", "legendFormat": "{{deployment}} ready" } ] diff --git a/examples/lgtm-datamesh/observability/prometheus-values.yaml b/examples/lgtm-datamesh/observability/prometheus-values.yaml index 382db89..1be4489 100644 --- a/examples/lgtm-datamesh/observability/prometheus-values.yaml +++ b/examples/lgtm-datamesh/observability/prometheus-values.yaml @@ -1,4 +1,4 @@ -# prometheus-values.yaml — lean, single-node Prometheus for the capstone (r29, +# prometheus-values.yaml — lean, single-node Prometheus for the datamesh (r29, # CAP-027). This is NOT a production monitoring setup: short retention, no # persistence, and only the components we actually use. The point is to SEE the # cluster — workload replica counts (the KEDA scaling signal) and Istio request diff --git a/examples/lgtm-datamesh/observability/tempo-values.yaml b/examples/lgtm-datamesh/observability/tempo-values.yaml index 2d65b9c..5a8a3c3 100644 --- a/examples/lgtm-datamesh/observability/tempo-values.yaml +++ b/examples/lgtm-datamesh/observability/tempo-values.yaml @@ -1,5 +1,5 @@ # tempo-values.yaml — Grafana Tempo in monolithic (single-binary) mode (r29b, -# CAP-028): the capstone's trace backend. Local storage, OTLP receivers on, lean. +# CAP-028): the datamesh's trace backend. Local storage, OTLP receivers on, lean. # Monolithic mode is Tempo's own recommendation for small/demo/test setups — # one container with distributor, ingester, querier, and compactor together. # diff --git a/examples/lgtm-datamesh/openmetadata/ingestion/job-kafka.yaml b/examples/lgtm-datamesh/openmetadata/ingestion/job-kafka.yaml index 3d407bd..e6bbd35 100644 --- a/examples/lgtm-datamesh/openmetadata/ingestion/job-kafka.yaml +++ b/examples/lgtm-datamesh/openmetadata/ingestion/job-kafka.yaml @@ -7,11 +7,11 @@ apiVersion: batch/v1 kind: Job metadata: name: om-ingest-kafka - namespace: capstone + namespace: datamesh labels: - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh app.kubernetes.io/component: openmetadata-ingestion - capstone.ingestion/source: kafka + datamesh.ingestion/source: kafka spec: backoffLimit: 2 template: @@ -25,7 +25,7 @@ spec: # this opts them out. (r34) sidecar.istio.io/inject: "false" labels: - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh app.kubernetes.io/component: openmetadata-ingestion spec: restartPolicy: Never diff --git a/examples/lgtm-datamesh/openmetadata/ingestion/job-lineage.yaml b/examples/lgtm-datamesh/openmetadata/ingestion/job-lineage.yaml index 218ae5a..2d398fe 100644 --- a/examples/lgtm-datamesh/openmetadata/ingestion/job-lineage.yaml +++ b/examples/lgtm-datamesh/openmetadata/ingestion/job-lineage.yaml @@ -9,11 +9,11 @@ apiVersion: batch/v1 kind: Job metadata: name: om-declare-lineage - namespace: capstone + namespace: datamesh labels: - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh app.kubernetes.io/component: openmetadata-ingestion - capstone.ingestion/source: lineage + datamesh.ingestion/source: lineage spec: backoffLimit: 2 template: @@ -27,7 +27,7 @@ spec: # this opts them out. (r34) sidecar.istio.io/inject: "false" labels: - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh app.kubernetes.io/component: openmetadata-ingestion spec: restartPolicy: Never diff --git a/examples/lgtm-datamesh/openmetadata/ingestion/job-postgres.yaml b/examples/lgtm-datamesh/openmetadata/ingestion/job-postgres.yaml index 9600cf7..f9c0c61 100644 --- a/examples/lgtm-datamesh/openmetadata/ingestion/job-postgres.yaml +++ b/examples/lgtm-datamesh/openmetadata/ingestion/job-postgres.yaml @@ -15,11 +15,11 @@ apiVersion: batch/v1 kind: Job metadata: name: om-ingest-postgres - namespace: capstone + namespace: datamesh labels: - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh app.kubernetes.io/component: openmetadata-ingestion - capstone.ingestion/source: postgres + datamesh.ingestion/source: postgres spec: backoffLimit: 2 template: @@ -33,7 +33,7 @@ spec: # this opts them out. (r34) sidecar.istio.io/inject: "false" labels: - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh app.kubernetes.io/component: openmetadata-ingestion spec: restartPolicy: Never @@ -65,7 +65,7 @@ spec: - name: PG_PASSWORD valueFrom: secretKeyRef: - name: capstone-postgres-app # CNPG-generated app secret + name: datamesh-postgres-app # CNPG-generated app secret key: password volumeMounts: - name: ingestion-config diff --git a/examples/lgtm-datamesh/openmetadata/ingestion/kafka.yaml b/examples/lgtm-datamesh/openmetadata/ingestion/kafka.yaml index 091d0fc..3ff03e8 100644 --- a/examples/lgtm-datamesh/openmetadata/ingestion/kafka.yaml +++ b/examples/lgtm-datamesh/openmetadata/ingestion/kafka.yaml @@ -1,8 +1,8 @@ -# kafka.yaml — OpenMetadata ingestion workflow: the capstone Kafka source. +# kafka.yaml — OpenMetadata ingestion workflow: the datamesh Kafka source. # # Run by the openmetadata/ingestion image as `metadata ingest -c `, # inside a one-off Job. Catalogs the Strimzi cluster's topics as Topic entities -# under a Messaging Service named `capstone-kafka`. +# under a Messaging Service named `datamesh-kafka`. # # DECISION C (CAP-023): BARE ingestion — bootstrap servers only, no schema # registry. Topics are discovered as entities; their Avro schemas are NOT @@ -16,7 +16,7 @@ # # Connection fact (verified against the kafka subchart and the services' # config): the Strimzi plain listener is reachable in-cluster at -# capstone-kafka-kafka-bootstrap:9092 +# datamesh-kafka-kafka-bootstrap:9092 # # VERIFY-POINT (OpenMetadata 2.0.5 Kafka connector schema; confirm at build # time): `bootstrapServers` and `MessagingMetadata` are the expected keys; the @@ -25,18 +25,18 @@ source: type: kafka - serviceName: capstone-kafka + serviceName: datamesh-kafka serviceConnection: config: type: Kafka - bootstrapServers: capstone-kafka-kafka-bootstrap:9092 + bootstrapServers: datamesh-kafka-kafka-bootstrap:9092 # schemaRegistryURL deliberately omitted (decision C — bare). The # consumer-side runtime contract still lives in Apicurio; the catalog # link to it is r27c's job. sourceConfig: config: type: MessagingMetadata - # The capstone has one topic today; an explicit include keeps the catalog + # The datamesh has one topic today; an explicit include keeps the catalog # tidy and makes the lineage spine obvious. Drop the filter to ingest all. topicFilterPattern: includes: diff --git a/examples/lgtm-datamesh/openmetadata/ingestion/lineage.py b/examples/lgtm-datamesh/openmetadata/ingestion/lineage.py index f645a57..b42cb34 100755 --- a/examples/lgtm-datamesh/openmetadata/ingestion/lineage.py +++ b/examples/lgtm-datamesh/openmetadata/ingestion/lineage.py @@ -3,20 +3,20 @@ DECISION D (CAP-023): lineage is declared explicitly via the first-class lineage REST API (PUT /api/v1/lineage), not inferred. OpenMetadata derives -lineage automatically only from query logs / dbt, which the capstone doesn't +lineage automatically only from query logs / dbt, which the datamesh doesn't have; and a Table→Topic→Table chain crosses entity types, which the API handles cleanly. This runs as the THIRD ingestion Job, after the Postgres and Kafka Jobs, because the three entities must already exist to be linked. The spine (one directed edge per producer/consumer relationship): - capstone-postgres.capstone.orders.orders (Table, order-service) + datamesh-postgres.datamesh.orders.orders (Table, order-service) │ produces ▼ - capstone-kafka.order-placed (Topic) + datamesh-kafka.order-placed (Topic) │ consumed by ▼ - capstone-postgres.capstone.notifications.notifications (Table, notification-svc) + datamesh-postgres.datamesh.notifications.notifications (Table, notification-svc) Stdlib only (urllib/json), so it runs in the ingestion image unchanged. Idempotent: PUT /api/v1/lineage upserts an edge, so re-running is a no-op. @@ -40,9 +40,9 @@ HOST = os.environ.get("OM_HOST", "http://openmetadata:8585") TOKEN = os.environ.get("OM_JWT", "") -ORDERS_FQN = "capstone-postgres.capstone.orders.orders" -TOPIC_FQN = "capstone-kafka.order-placed" -NOTIFS_FQN = "capstone-postgres.capstone.notifications.notifications" +ORDERS_FQN = "datamesh-postgres.datamesh.orders.orders" +TOPIC_FQN = "datamesh-kafka.order-placed" +NOTIFS_FQN = "datamesh-postgres.datamesh.notifications.notifications" def _headers() -> dict: diff --git a/examples/lgtm-datamesh/openmetadata/ingestion/postgres.yaml b/examples/lgtm-datamesh/openmetadata/ingestion/postgres.yaml index 0ff9340..ddc56dd 100644 --- a/examples/lgtm-datamesh/openmetadata/ingestion/postgres.yaml +++ b/examples/lgtm-datamesh/openmetadata/ingestion/postgres.yaml @@ -1,21 +1,21 @@ -# postgres.yaml — OpenMetadata ingestion workflow: the capstone Postgres source. +# postgres.yaml — OpenMetadata ingestion workflow: the datamesh Postgres source. # # Run by the openmetadata/ingestion image as `metadata ingest -c `, # inside a one-off Kubernetes Job (CAP-022 chose Jobs over Airflow; CAP-023 -# packages them). This catalogs every service schema in the `capstone` +# packages them). This catalogs every service schema in the `datamesh` # database — orders, notifications, and the other domain products — as Table -# entities under a single Database Service named `capstone-postgres`. +# entities under a single Database Service named `datamesh-postgres`. # # Two placeholders are substituted by the Job at runtime, NOT stored here: -# __PG_PASSWORD__ ← key `password` of the CNPG secret `capstone-postgres-app` +# __PG_PASSWORD__ ← key `password` of the CNPG secret `datamesh-postgres-app` # __OM_JWT__ ← an admin bearer token the Job fetches in-cluster # Keeping them out of the file means no credential is committed to the repo or # baked into the ConfigMap. # -# Connection facts (all verified against the capstone charts): -# * read-write Service capstone-postgres-rw:5432 -# * database capstone -# * login role capstone_app (owns every service schema — CAP-003 — +# Connection facts (all verified against the datamesh charts): +# * read-write Service datamesh-postgres-rw:5432 +# * database datamesh +# * login role datamesh_app (owns every service schema — CAP-003 — # so one role reads them all) # # VERIFY-POINTS (OpenMetadata 2.0.5 connector schema; confirm at build time — @@ -27,22 +27,22 @@ source: type: postgres - serviceName: capstone-postgres + serviceName: datamesh-postgres serviceConnection: config: type: Postgres - username: capstone_app + username: datamesh_app authType: password: __PG_PASSWORD__ - hostPort: capstone-postgres-rw:5432 - database: capstone + hostPort: datamesh-postgres-rw:5432 + database: datamesh sslMode: require sourceConfig: config: type: DatabaseMetadata # Ingest only the product schemas; skip Postgres' own system schemas. # (The `openmetadata` operational database is a separate database and is - # never reached because `database: capstone` scopes ingestion to one db — + # never reached because `database: datamesh` scopes ingestion to one db — # the catalog does not catalog itself.) schemaFilterPattern: excludes: diff --git a/examples/lgtm-datamesh/openmetadata/ingestion/reviews_lineage.py b/examples/lgtm-datamesh/openmetadata/ingestion/reviews_lineage.py index 9bf8563..5abebb0 100755 --- a/examples/lgtm-datamesh/openmetadata/ingestion/reviews_lineage.py +++ b/examples/lgtm-datamesh/openmetadata/ingestion/reviews_lineage.py @@ -5,10 +5,10 @@ the identifier the inventory domain owns — so we connect them in OpenMetadata with a single directed edge: - capstone-postgres.capstone.inventory.stock (Table, inventory-service) + datamesh-postgres.datamesh.inventory.stock (Table, inventory-service) │ referenced by ▼ - capstone-postgres.capstone.reviews.reviews (Table, review-service) + datamesh-postgres.datamesh.reviews.reviews (Table, review-service) This is kept SEPARATE from the permanent lineage.py (which declares the orders -> order-placed -> notifications spine) because review-service is a @@ -37,8 +37,8 @@ HOST = os.environ.get("OM_HOST", "http://openmetadata:8585") TOKEN = os.environ.get("OM_JWT", "") -PRODUCTS_FQN = "capstone-postgres.capstone.inventory.stock" -REVIEWS_FQN = "capstone-postgres.capstone.reviews.reviews" +PRODUCTS_FQN = "datamesh-postgres.datamesh.inventory.stock" +REVIEWS_FQN = "datamesh-postgres.datamesh.reviews.reviews" def _headers() -> dict: diff --git a/examples/lgtm-datamesh/openmetadata/om-app-values.yaml b/examples/lgtm-datamesh/openmetadata/om-app-values.yaml index 2287613..1ae8c49 100644 --- a/examples/lgtm-datamesh/openmetadata/om-app-values.yaml +++ b/examples/lgtm-datamesh/openmetadata/om-app-values.yaml @@ -1,4 +1,4 @@ -# om-app-values.yaml — OpenMetadata *server* config for the capstone. +# om-app-values.yaml — OpenMetadata *server* config for the datamesh. # # OVERRIDE file, merged by Helm onto the upstream open-metadata/openmetadata # chart defaults (chart 2.0.5). Only the keys that differ from the chart @@ -10,7 +10,7 @@ # pipelineServiceClientConfig.enabled both -> false. The server boots and # serves the catalog/UI without any pipeline orchestrator; ingestion is run # as one-off Jobs (r27b). -# * Backend = capstone CloudNativePG Postgres, NOT the bundled MySQL. The +# * Backend = datamesh CloudNativePG Postgres, NOT the bundled MySQL. The # `database` block is flipped from the chart's MySQL defaults to Postgres # and pointed at the existing cluster's read-write service. The # `openmetadata` database + role and the referenced secret are provisioned @@ -38,14 +38,14 @@ openmetadata: pipelineServiceClientConfig: enabled: false - # ── Backend database: reuse capstone Postgres ───────────────────────── + # ── Backend database: reuse datamesh Postgres ───────────────────────── # Flipped from the chart's MySQL defaults to PostgreSQL. Points at the # CloudNativePG read-write service. The password comes from the # `openmetadata-db-app-secret` that setup-openmetadata.sh creates (a name # distinct from the chart's own generated `openmetadata-db-secret`); the - # matching role + database are provisioned in the capstone-postgres cluster. + # matching role + database are provisioned in the datamesh-postgres cluster. database: - host: capstone-postgres-rw + host: datamesh-postgres-rw port: 5432 driverClass: org.postgresql.Driver dbScheme: postgresql diff --git a/examples/lgtm-datamesh/openmetadata/om-deps-values.yaml b/examples/lgtm-datamesh/openmetadata/om-deps-values.yaml index d001d68..6b32b6e 100644 --- a/examples/lgtm-datamesh/openmetadata/om-deps-values.yaml +++ b/examples/lgtm-datamesh/openmetadata/om-deps-values.yaml @@ -1,4 +1,4 @@ -# om-deps-values.yaml — trimmed OpenMetadata *dependencies* for the capstone. +# om-deps-values.yaml — trimmed OpenMetadata *dependencies* for the datamesh. # # This is an OVERRIDE file, merged by Helm onto the upstream # open-metadata/openmetadata-dependencies chart defaults (chart 2.0.5). We @@ -6,9 +6,9 @@ # the chart default. # # Decisions (CAP-022): -# * MySQL -> DISABLED. OpenMetadata's backend is the capstone CloudNativePG +# * MySQL -> DISABLED. OpenMetadata's backend is the datamesh CloudNativePG # Postgres instead (a dedicated `openmetadata` database in the existing -# `capstone-postgres` cluster). See setup-openmetadata.sh. +# `datamesh-postgres` cluster). See setup-openmetadata.sh. # * Airflow -> DISABLED. Ingestion runs as one-off Kubernetes Jobs # (`metadata ingest -c `), not via an orchestrator (r27b wires the # first ingestion). This drops the entire Airflow tier (api-server, @@ -29,7 +29,7 @@ global: security: allowInsecureImages: true -# Replaced by reuse of the capstone Postgres (CloudNativePG). +# Replaced by reuse of the datamesh Postgres (CloudNativePG). mysql: enabled: false diff --git a/examples/lgtm-datamesh/openshift/README.md b/examples/lgtm-datamesh/openshift/README.md index 1ac9bb3..55fe385 100644 --- a/examples/lgtm-datamesh/openshift/README.md +++ b/examples/lgtm-datamesh/openshift/README.md @@ -1,7 +1,7 @@ -# Deploying the capstone data mesh to OpenShift +# Deploying the datamesh data mesh to OpenShift -This directory is the **OpenShift counterpart** to [`charts/capstone/`](../charts/capstone/). -The `charts/capstone/` umbrella chart runs the full §17 capstone stack — 7 +This directory is the **OpenShift counterpart** to [`charts/datamesh/`](../charts/datamesh/). +The `charts/datamesh/` umbrella chart runs the full §17 final project stack — 7 data-product services, Strimzi Kafka, CloudNativePG Postgres, Apicurio, OpenMetadata, Prefect, the LGTM observability stack, KEDA autoscaling, and Istio — on minikube. This tree runs only the **live core** of that system — @@ -36,9 +36,9 @@ openshift/ └── evidence/ # live CRC verification output (captured separately) ``` -## What changes from `charts/capstone/` → OpenShift +## What changes from `charts/datamesh/` → OpenShift -1. **No operators assumed.** `charts/capstone/` relies on the Strimzi Kafka +1. **No operators assumed.** `charts/datamesh/` relies on the Strimzi Kafka operator and the CloudNativePG Postgres operator both being pre-installed. This chart doesn't assume either is on the target cluster: Postgres and Kafka are **plain StatefulSets** (single-broker KRaft for Kafka, no @@ -50,15 +50,15 @@ openshift/ and let the platform assign one. Postgres and Kafka *do* need specific UIDs (70 / 1000) their upstream images hardcode, so they run under a dedicated ServiceAccount (`datamesh-infra`) bound to the `nonroot-v2` SCC. -3. **Routes, not NodePorts.** On minikube, `charts/capstone/` exposes services +3. **Routes, not NodePorts.** On minikube, `charts/datamesh/` exposes services via NodePorts published to 127.0.0.1 (minikube has no router). OpenShift has one: external access here is two `Route` objects (graphql-gateway, apicurio) served by the cluster's router. 4. **The integrated registry.** Images are pushed to OpenShift's internal registry (`image-registry.openshift-image-registry.svc:5000/datamesh/...`) - and referenced from there, instead of the minikube path, where `charts/capstone/` subcharts use - `capstone/` images loaded with `minikube image load` (no registry). -5. **Tracing is off.** `charts/capstone/` wires every service to OTLP/Tempo. + and referenced from there, instead of the minikube path, where `charts/datamesh/` subcharts use + `datamesh/` images loaded with `minikube image load` (no registry). +5. **Tracing is off.** `charts/datamesh/` wires every service to OTLP/Tempo. Since the LGTM stack isn't deployed here, the OTEL_* env vars are simply omitted — the services' `opentelemetry-instrument` entrypoint (where present) is a documented no-op with no OTEL_* env set. @@ -104,7 +104,7 @@ probes — is carried over unchanged. ./openshift/build-and-push.sh -r "$REG" -n datamesh ``` -Podman is used only for this OpenShift (CRC) path; the minikube capstone uses Docker Engine. +Podman is used only for this OpenShift (CRC) path; the minikube datamesh uses Docker Engine. This builds each `services//Containerfile` with podman and pushes it to `$REG/datamesh/:v1` — the exact ref `values.yaml`'s `image.registry`/`image.tag` compose. @@ -146,5 +146,5 @@ curl -ksI "https://$(oc get route apicurio -n datamesh -o jsonpath='{.spec.host} ```sh helm uninstall datamesh -n datamesh # PVCs (postgres-data, kafka-data) are retained by design; delete them to wipe state: -oc delete pvc -l app.kubernetes.io/part-of=capstone -n datamesh +oc delete pvc -l app.kubernetes.io/part-of=datamesh -n datamesh ``` diff --git a/examples/lgtm-datamesh/openshift/build-and-push.sh b/examples/lgtm-datamesh/openshift/build-and-push.sh index 3317316..1390bb9 100755 --- a/examples/lgtm-datamesh/openshift/build-and-push.sh +++ b/examples/lgtm-datamesh/openshift/build-and-push.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # -# build-and-push.sh — build the 7 capstone Python service images and push +# build-and-push.sh — build the 7 datamesh Python service images and push # them (plus mirrored copies of the postgres/kafka infra images) to an # OpenShift cluster's integrated image registry. # diff --git a/examples/lgtm-datamesh/openshift/helm/datamesh/Chart.yaml b/examples/lgtm-datamesh/openshift/helm/datamesh/Chart.yaml index 00c28c6..0145c21 100644 --- a/examples/lgtm-datamesh/openshift/helm/datamesh/Chart.yaml +++ b/examples/lgtm-datamesh/openshift/helm/datamesh/Chart.yaml @@ -1,9 +1,9 @@ apiVersion: v2 name: datamesh description: >- - The §17 capstone data mesh (7 Python data-product services + GraphQL gateway, + The §17 final project data mesh (7 Python data-product services + GraphQL gateway, with Postgres, single-broker KRaft Kafka, and the Apicurio schema registry) - deployed to OpenShift. The OpenShift counterpart to charts/capstone/ — same + deployed to OpenShift. The OpenShift counterpart to charts/datamesh/ — same live-core topology, but using Routes for ingress, the internal image registry for images, and SCCs instead of pinned UIDs. OpenMetadata, Prefect, the LGTM observability stack, KEDA autoscaling, and the Istio mesh are intentionally diff --git a/examples/lgtm-datamesh/openshift/helm/datamesh/templates/_helpers.tpl b/examples/lgtm-datamesh/openshift/helm/datamesh/templates/_helpers.tpl index 60f9b4f..15800d4 100644 --- a/examples/lgtm-datamesh/openshift/helm/datamesh/templates/_helpers.tpl +++ b/examples/lgtm-datamesh/openshift/helm/datamesh/templates/_helpers.tpl @@ -1,9 +1,9 @@ {{/* Common labels applied to every object, following the k8s recommended label set -the charts/capstone subcharts already use (app.kubernetes.io/part-of: capstone). +the charts/datamesh subcharts already use (app.kubernetes.io/part-of: datamesh). */}} {{- define "datamesh.labels" -}} -app.kubernetes.io/part-of: capstone +app.kubernetes.io/part-of: datamesh app.kubernetes.io/managed-by: {{ .Release.Service }} helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }} {{- end -}} diff --git a/examples/lgtm-datamesh/openshift/helm/datamesh/templates/apicurio.yaml b/examples/lgtm-datamesh/openshift/helm/datamesh/templates/apicurio.yaml index 478ce3c..d769ce0 100644 --- a/examples/lgtm-datamesh/openshift/helm/datamesh/templates/apicurio.yaml +++ b/examples/lgtm-datamesh/openshift/helm/datamesh/templates/apicurio.yaml @@ -1,6 +1,6 @@ {{- $root := . -}} # Apicurio Registry 3 — schema/contract registry (CAP-018). Port of -# charts/capstone/charts/apicurio/, dropping the minikube NodePort +# charts/datamesh/charts/apicurio/, dropping the minikube NodePort # scheme for a ClusterIP Service + Route. No storage env: the apicurio-registry # 3.x image defaults to the in-memory variant (order-service re-registers the # order.placed Avro schema on each restart, which is harmless for a demo). @@ -20,7 +20,7 @@ spec: metadata: labels: app.kubernetes.io/name: apicurio - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh spec: containers: - name: apicurio @@ -34,7 +34,7 @@ spec: limits: { memory: 1Gi } # startupProbe gives the Quarkus JVM ample time to boot (up to ~150s) # before liveness/readiness begin. TCP probe avoids guessing the - # health path (same as charts/capstone/charts/apicurio/). + # health path (same as charts/datamesh/charts/apicurio/). startupProbe: tcpSocket: { port: http } periodSeconds: 5 diff --git a/examples/lgtm-datamesh/openshift/helm/datamesh/templates/app-deployment.yaml b/examples/lgtm-datamesh/openshift/helm/datamesh/templates/app-deployment.yaml index 8edcc55..80f4fb4 100644 --- a/examples/lgtm-datamesh/openshift/helm/datamesh/templates/app-deployment.yaml +++ b/examples/lgtm-datamesh/openshift/helm/datamesh/templates/app-deployment.yaml @@ -25,7 +25,7 @@ spec: metadata: labels: app.kubernetes.io/name: {{ $name }} - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh {{- if $root.Values.mesh.enabled }} # istio.io/rev LABEL (not an annotation) — the OSSM3/Sail revisioned # webhook's injection trigger (DRA-010). @@ -44,7 +44,7 @@ spec: # Init container runs Alembic migrations before the app starts, so the # schema + tables exist and the app issues no DDL (retires create_all — # CAP-021). Same image, same DB env as the app. Ported from - # charts/capstone/charts/notification-service/templates/deployment.yaml. + # charts/datamesh/charts/notification-service/templates/deployment.yaml. initContainers: - name: migrate image: "{{ $root.Values.image.registry }}/{{ $name }}:{{ $root.Values.image.tag }}" diff --git a/examples/lgtm-datamesh/openshift/helm/datamesh/templates/configmap-app.yaml b/examples/lgtm-datamesh/openshift/helm/datamesh/templates/configmap-app.yaml index 8e2d3bb..f10f5d2 100644 --- a/examples/lgtm-datamesh/openshift/helm/datamesh/templates/configmap-app.yaml +++ b/examples/lgtm-datamesh/openshift/helm/datamesh/templates/configmap-app.yaml @@ -1,7 +1,7 @@ {{- $dns := include "datamesh.dns" . -}} # Shared env contract for the app Deployments that need cross-service -# addresses — the Helm port of the endpoints charts/capstone/values.yaml's -# `global:` block hardcodes to the `capstone` namespace. Every address here is +# addresses — the Helm port of the endpoints charts/datamesh/values.yaml's +# `global:` block hardcodes to the `datamesh` namespace. Every address here is # built from the release namespace ({{ .Release.Namespace }}) so the chart is # namespace-portable (installed as `datamesh` per the README, but not # hardcoded to it). diff --git a/examples/lgtm-datamesh/openshift/helm/datamesh/templates/kafka.yaml b/examples/lgtm-datamesh/openshift/helm/datamesh/templates/kafka.yaml index 987b523..b48fb10 100644 --- a/examples/lgtm-datamesh/openshift/helm/datamesh/templates/kafka.yaml +++ b/examples/lgtm-datamesh/openshift/helm/datamesh/templates/kafka.yaml @@ -1,6 +1,6 @@ {{- $dns := include "datamesh.dns" . -}} # Single-broker KRaft Kafka (no ZooKeeper). Plain StatefulSet — NOT the -# Strimzi `Kafka`/`KafkaNodePool` CRs charts/capstone/charts/kafka/ uses, since +# Strimzi `Kafka`/`KafkaNodePool` CRs charts/datamesh/charts/kafka/ uses, since # the Strimzi operator isn't assumed to be installed on the target OpenShift # cluster. Preserves the modernization appendix's live-apply fixes: # publishNotReadyAddresses (a single KRaft node must resolve its own @@ -11,7 +11,7 @@ # datamesh-infra (nonroot-v2) so uid 1000 is permitted on OpenShift. # # KAFKA_AUTO_CREATE_TOPICS_ENABLE=true stands in for the Strimzi KafkaTopic CR -# (charts/capstone/charts/kafka/templates/topic.yaml) — order-service's first +# (charts/datamesh/charts/kafka/templates/topic.yaml) — order-service's first # publish to `{{ .Values.kafka.topic }}` creates it. apiVersion: v1 kind: Service @@ -50,7 +50,7 @@ spec: metadata: labels: app.kubernetes.io/name: kafka - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh spec: serviceAccountName: {{ .Values.infra.serviceAccountName }} securityContext: diff --git a/examples/lgtm-datamesh/openshift/helm/datamesh/templates/postgres.yaml b/examples/lgtm-datamesh/openshift/helm/datamesh/templates/postgres.yaml index 505e7fe..2014c3a 100644 --- a/examples/lgtm-datamesh/openshift/helm/datamesh/templates/postgres.yaml +++ b/examples/lgtm-datamesh/openshift/helm/datamesh/templates/postgres.yaml @@ -1,7 +1,7 @@ {{- $dns := include "datamesh.dns" . -}} -# Shared Postgres (db `capstone`, one schema per data-product service). Plain +# Shared Postgres (db `datamesh`, one schema per data-product service). Plain # StatefulSet — NOT the CloudNativePG `Cluster` CR -# charts/capstone/charts/postgres/ uses, since the CNPG operator isn't assumed +# charts/datamesh/charts/postgres/ uses, since the CNPG operator isn't assumed # to be installed on the target OpenShift cluster. Preserves the modernization # appendix's live-apply fixes: `args` (not `command`) so the entrypoint's # initdb runs; PGDATA in a subdir the postgres user owns; fsGroup 70 for PVC @@ -59,7 +59,7 @@ spec: metadata: labels: app.kubernetes.io/name: postgres - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh spec: serviceAccountName: {{ .Values.infra.serviceAccountName }} securityContext: diff --git a/examples/lgtm-datamesh/openshift/helm/datamesh/templates/route.yaml b/examples/lgtm-datamesh/openshift/helm/datamesh/templates/route.yaml index 3d2fe68..cf6344e 100644 --- a/examples/lgtm-datamesh/openshift/helm/datamesh/templates/route.yaml +++ b/examples/lgtm-datamesh/openshift/helm/datamesh/templates/route.yaml @@ -3,7 +3,7 @@ {{- if $svc.route }} --- # OpenShift Route — the platform-native ingress. Replaces the NodePort -# scheme charts/capstone/charts//values.yaml's `service.nodePort` uses on +# scheme charts/datamesh/charts//values.yaml's `service.nodePort` uses on # minikube (NodePorts published to 127.0.0.1 at profile creation); on OpenShift, # Routes: the cluster's router (the # `ingress` cluster operator) gives this Service a real external hostname, diff --git a/examples/lgtm-datamesh/openshift/helm/datamesh/templates/secret-app.yaml b/examples/lgtm-datamesh/openshift/helm/datamesh/templates/secret-app.yaml index fac8c23..2f8474d 100644 --- a/examples/lgtm-datamesh/openshift/helm/datamesh/templates/secret-app.yaml +++ b/examples/lgtm-datamesh/openshift/helm/datamesh/templates/secret-app.yaml @@ -1,5 +1,5 @@ # Dev-only Postgres credential — the Helm port of the CloudNativePG-generated -# "-app" Secret that charts/capstone/charts/postgres/ relies on the +# "-app" Secret that charts/datamesh/charts/postgres/ relies on the # operator to create. This chart runs Postgres as a plain StatefulSet (no # operator), so it republishes the same shape (username/password/dbname keys) # as a hand-authored Secret the Deployments' secretKeyRef points at. diff --git a/examples/lgtm-datamesh/openshift/helm/datamesh/values.yaml b/examples/lgtm-datamesh/openshift/helm/datamesh/values.yaml index 3399269..27d5992 100644 --- a/examples/lgtm-datamesh/openshift/helm/datamesh/values.yaml +++ b/examples/lgtm-datamesh/openshift/helm/datamesh/values.yaml @@ -1,10 +1,10 @@ -# values.yaml — the knobs for deploying the capstone data mesh's live core to +# values.yaml — the knobs for deploying the datamesh data mesh's live core to # OpenShift. # # The seven application workloads are described declaratively in `services` # below; templates/app-deployment.yaml and app-service.yaml range over this # map, so the whole topology is one template driven by data (the same idiom -# charts/capstone/charts// spells out one subchart per service). +# charts/datamesh/charts// spells out one subchart per service). # # SCOPE: this chart packages only the live core — the 7 services, Postgres, # Kafka, and Apicurio. OpenMetadata, Prefect, the LGTM observability stack @@ -14,22 +14,22 @@ # Container image settings. On OpenShift the images live in the integrated # registry; in-cluster pulls use the registry's Service DNS, which is what a # Deployment's imagePullPolicy sees. Override `registry` for an external -# registry (Quay, etc.). Matches the capstone's existing `:v1` mutable-tag -# convention (charts/capstone/values.yaml), but IfNotPresent here since +# registry (Quay, etc.). Matches the datamesh's existing `:v1` mutable-tag +# convention (charts/datamesh/values.yaml), but IfNotPresent here since # OpenShift builds push a new image per `oc` build, not a dev inner-loop. image: registry: "image-registry.openshift-image-registry.svc:5000/datamesh" tag: "v1" pullPolicy: IfNotPresent -# Dev-only Postgres credential. One shared cluster, database `capstone`, one -# schema per service (mirrors charts/capstone/charts/postgres/values.yaml: -# cluster.database=capstone, cluster.owner=capstone_app). +# Dev-only Postgres credential. One shared cluster, database `datamesh`, one +# schema per service (mirrors charts/datamesh/charts/postgres/values.yaml: +# cluster.database=datamesh, cluster.owner=datamesh_app). # PRODUCTION: replace with a SealedSecret / ExternalSecret — never plaintext here. postgres: - username: "capstone_app" - password: "capstone_dev_only" - database: "capstone" + username: "datamesh_app" + password: "datamesh_dev_only" + database: "datamesh" # Mirrored into the internal registry: the CRC VM cannot reach Docker Hub, so # the upstream docker.io/library/postgres:18.6-alpine was pulled on the host # and pushed here. On a cluster with Docker Hub egress, use the upstream ref @@ -41,13 +41,13 @@ postgres: kafka: # Mirrored like postgres above (upstream: docker.io/apache/kafka:4.3.1). # Plain KRaft StatefulSet — NOT the Strimzi `Kafka`/`KafkaNodePool` CRs the - # minikube capstone (charts/capstone/charts/kafka/) uses; Strimzi isn't + # minikube datamesh (charts/datamesh/charts/kafka/) uses; Strimzi isn't # assumed to be installed on the target OpenShift cluster. image: "image-registry.openshift-image-registry.svc:5000/datamesh/kafka:4.3.1" # image: "docker.io/apache/kafka:4.3.1" clusterId: "MkU3OEVBNTcwNTJENDM2Qk" storage: "2Gi" - # Matches charts/capstone/charts/order-service's KAFKA_ORDER_TOPIC default. + # Matches charts/datamesh/charts/order-service's KAFKA_ORDER_TOPIC default. topic: "order-placed" # Apicurio Registry 3 — schema/contract registry (CAP-018). quay.io is @@ -121,7 +121,7 @@ services: db: shipping # Resource tiers referenced by each service's `size` (values carried over from -# charts/capstone/charts//values.yaml requests/limits). +# charts/datamesh/charts//values.yaml requests/limits). resources: small: requests: { cpu: 100m, memory: 192Mi } diff --git a/examples/lgtm-datamesh/openshift/platform/install-platform.sh b/examples/lgtm-datamesh/openshift/platform/install-platform.sh index c2d4296..5362b78 100755 --- a/examples/lgtm-datamesh/openshift/platform/install-platform.sh +++ b/examples/lgtm-datamesh/openshift/platform/install-platform.sh @@ -47,11 +47,11 @@ CNI_NS="istio-cni" # The core Postgres StatefulSet (../helm/datamesh/templates/postgres.yaml) # pod is always "postgres-0" (replicas: 1). Its initdb superuser is NOT # "postgres" — the upstream postgres image's POSTGRES_USER env makes the -# *named* user the superuser, and values.yaml sets that to "capstone_app". +# *named* user the superuser, and values.yaml sets that to "datamesh_app". PG_POD="postgres-0" PG_CONTAINER="postgres" -PG_SUPERUSER="capstone_app" # ../helm/datamesh/values.yaml postgres.username -PG_SUPERDB="capstone" # ../helm/datamesh/values.yaml postgres.database — connect here to CREATE DATABASE +PG_SUPERUSER="datamesh_app" # ../helm/datamesh/values.yaml postgres.username +PG_SUPERDB="datamesh" # ../helm/datamesh/values.yaml postgres.database — connect here to CREATE DATABASE # DEMO passwords — fine for a local reference build, not production (same # caveat as scripts/setup-openmetadata.sh's OM_PASSWORD). diff --git a/examples/lgtm-datamesh/openshift/platform/keda/README.md b/examples/lgtm-datamesh/openshift/platform/keda/README.md index d7503b8..28289df 100644 --- a/examples/lgtm-datamesh/openshift/platform/keda/README.md +++ b/examples/lgtm-datamesh/openshift/platform/keda/README.md @@ -23,7 +23,7 @@ oc get scaledobject -n datamesh ## Why there's no HTTP-scaled object here -The minikube capstone also scales `graphql-gateway` on in-flight HTTP +The minikube datamesh also scales `graphql-gateway` on in-flight HTTP request volume via the **KEDA HTTP add-on** (`http.keda.sh/v1alpha1` `HTTPScaledObject`, installed by the separate `kedacore/keda-add-ons-http` Helm chart — see `examples/lgtm-datamesh/keda/gateway-httpscaledobject.yaml` diff --git a/examples/lgtm-datamesh/openshift/platform/keda/kedacontroller.yaml b/examples/lgtm-datamesh/openshift/platform/keda/kedacontroller.yaml index 0e2bb78..3667eee 100644 --- a/examples/lgtm-datamesh/openshift/platform/keda/kedacontroller.yaml +++ b/examples/lgtm-datamesh/openshift/platform/keda/kedacontroller.yaml @@ -1,7 +1,7 @@ # kedacontroller.yaml — the KedaController operand for the Custom Metrics # Autoscaler (CMA) operator, Red Hat's KEDA distribution (OpenShift's # supported equivalent of upstream `helm install kedacore/keda` used on the -# minikube capstone — see ../subscriptions/cma-subscription.yaml for the +# minikube datamesh — see ../subscriptions/cma-subscription.yaml for the # Subscription that installs the operator itself). # # PREREQUISITE: the operator's CSV in namespace openshift-keda must be diff --git a/examples/lgtm-datamesh/openshift/platform/keda/notification-scaledobject.yaml b/examples/lgtm-datamesh/openshift/platform/keda/notification-scaledobject.yaml index d40f164..ded728b 100644 --- a/examples/lgtm-datamesh/openshift/platform/keda/notification-scaledobject.yaml +++ b/examples/lgtm-datamesh/openshift/platform/keda/notification-scaledobject.yaml @@ -4,7 +4,7 @@ # Ported from examples/lgtm-datamesh/keda/notification-scaledobject.yaml # (the minikube/Strimzi version). The ScaledObject spec is identical KEDA # API (keda.sh/v1alpha1) — only the target names change: -# * namespace: datamesh (not capstone) +# * namespace: datamesh (not datamesh) # * scaleTargetRef: Deployment `notification-service` — same name, created # by openshift/helm/datamesh/templates/app-deployment.yaml (the `services` # map in values.yaml ranges over service names 1:1 into Deployment names). diff --git a/examples/lgtm-datamesh/openshift/platform/mesh/order-service-v2.yaml b/examples/lgtm-datamesh/openshift/platform/mesh/order-service-v2.yaml index fa6ea97..a71bed4 100644 --- a/examples/lgtm-datamesh/openshift/platform/mesh/order-service-v2.yaml +++ b/examples/lgtm-datamesh/openshift/platform/mesh/order-service-v2.yaml @@ -1,5 +1,5 @@ # order-service-v2.yaml — the canary's v2 subset (ported from -# ../../../istio/order-service-v2.yaml, retargeted from minikube/`capstone` +# ../../../istio/order-service-v2.yaml, retargeted from minikube/`datamesh` # to OpenShift/`datamesh`). # # Deployed ALONGSIDE the Helm-managed v1 order-service (app-deployment.yaml, @@ -31,7 +31,7 @@ metadata: namespace: datamesh labels: app.kubernetes.io/name: order-service - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh version: v2 spec: replicas: 1 @@ -48,7 +48,7 @@ spec: metadata: labels: app.kubernetes.io/name: order-service - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh version: v2 # istio.io/rev LABEL — same OSSM3/Sail injection trigger as the v1 # Deployment (DRA-010); kept as a literal `default` here rather than diff --git a/examples/lgtm-datamesh/openshift/platform/observability/lgtm-deployment.yaml b/examples/lgtm-datamesh/openshift/platform/observability/lgtm-deployment.yaml index 7a8596f..74102e2 100644 --- a/examples/lgtm-datamesh/openshift/platform/observability/lgtm-deployment.yaml +++ b/examples/lgtm-datamesh/openshift/platform/observability/lgtm-deployment.yaml @@ -27,7 +27,7 @@ metadata: namespace: datamesh labels: app.kubernetes.io/name: lgtm - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh spec: replicas: 1 selector: @@ -37,7 +37,7 @@ spec: metadata: labels: app.kubernetes.io/name: lgtm - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh # Deliberately NOT given istio.io/rev — the observability backend # itself stays unmeshed, same reasoning as Postgres/Kafka/Apicurio # (none of those are relabeled when mesh.enabled either): it's the diff --git a/examples/lgtm-datamesh/openshift/platform/observability/lgtm-route.yaml b/examples/lgtm-datamesh/openshift/platform/observability/lgtm-route.yaml index 3b88788..c28ddae 100644 --- a/examples/lgtm-datamesh/openshift/platform/observability/lgtm-route.yaml +++ b/examples/lgtm-datamesh/openshift/platform/observability/lgtm-route.yaml @@ -10,7 +10,7 @@ metadata: namespace: datamesh labels: app.kubernetes.io/name: lgtm - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh spec: to: kind: Service diff --git a/examples/lgtm-datamesh/openshift/platform/observability/lgtm-service.yaml b/examples/lgtm-datamesh/openshift/platform/observability/lgtm-service.yaml index c2c397d..b528bbf 100644 --- a/examples/lgtm-datamesh/openshift/platform/observability/lgtm-service.yaml +++ b/examples/lgtm-datamesh/openshift/platform/observability/lgtm-service.yaml @@ -24,7 +24,7 @@ metadata: namespace: datamesh labels: app.kubernetes.io/name: lgtm - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh spec: type: ClusterIP selector: diff --git a/examples/lgtm-datamesh/openshift/platform/openmetadata/README.md b/examples/lgtm-datamesh/openshift/platform/openmetadata/README.md index 9cc31ff..33f33b3 100644 --- a/examples/lgtm-datamesh/openshift/platform/openmetadata/README.md +++ b/examples/lgtm-datamesh/openshift/platform/openmetadata/README.md @@ -30,8 +30,8 @@ footnotes. `AIRFLOW_PASSWORD` env var needs to exist (see the file's own comment); the value is never read since pipelines are disabled. - `route.yaml` — edge Route to the server Service, port 8585. -- `ingestion-job.yaml` — ConfigMap + Job that ingests the `capstone` Postgres - database's schemas (via the existing `datamesh-postgres-app` / `capstone_app` +- `ingestion-job.yaml` — ConfigMap + Job that ingests the `datamesh` Postgres + database's schemas (via the existing `datamesh-postgres-app` / `datamesh_app` credential — a different database/role than OpenMetadata's own backend above), giving the catalog at least one asset. @@ -46,7 +46,7 @@ footnotes. password — update both if that script's password ever changes. - Namespace `datamesh` and the `datamesh-postgres-app` Secret must already exist (they do — part of the verified core); `ingestion-job.yaml` uses that - existing credential to read the `capstone` app database. + existing credential to read the `datamesh` app database. ## Install order diff --git a/examples/lgtm-datamesh/openshift/platform/openmetadata/airflow-secrets.yaml b/examples/lgtm-datamesh/openshift/platform/openmetadata/airflow-secrets.yaml index 79c120f..1a8ef53 100644 --- a/examples/lgtm-datamesh/openshift/platform/openmetadata/airflow-secrets.yaml +++ b/examples/lgtm-datamesh/openshift/platform/openmetadata/airflow-secrets.yaml @@ -18,7 +18,7 @@ metadata: namespace: datamesh labels: app.kubernetes.io/name: openmetadata - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh type: Opaque stringData: openmetadata-airflow-password: "unused" diff --git a/examples/lgtm-datamesh/openshift/platform/openmetadata/ingestion-job.yaml b/examples/lgtm-datamesh/openshift/platform/openmetadata/ingestion-job.yaml index 850a2a3..e4e34c3 100644 --- a/examples/lgtm-datamesh/openshift/platform/openmetadata/ingestion-job.yaml +++ b/examples/lgtm-datamesh/openshift/platform/openmetadata/ingestion-job.yaml @@ -1,4 +1,4 @@ -# ingestion-job.yaml — one-off Job that ingests the capstone Postgres schemas +# ingestion-job.yaml — one-off Job that ingests the datamesh Postgres schemas # into OpenMetadata, so the catalog has at least one asset. Ported from # examples/lgtm-datamesh/openmetadata/ingestion/{job-postgres.yaml,postgres.yaml,get_token.py} # (the minikube source splits the Job, the ConfigMap it mounts, and the @@ -6,7 +6,7 @@ # this is the same pattern consolidated into one manifest for this authoring # step). # -# Target is the `capstone` database (the live app data — orders, inventory, +# Target is the `datamesh` database (the live app data — orders, inventory, # notifications, ... schemas), NOT the `openmetadata` database. `openmetadata` # is OM's own operational store (set in om-app-values.yaml) and is # deliberately never ingested — the catalog doesn't catalog itself, same as @@ -14,11 +14,11 @@ # # Retargeted from the minikube source: # * hostPort: postgres.datamesh.svc.cluster.local:5432 (plain StatefulSet -# Service here, not the CNPG capstone-postgres-rw Service). -# * username: capstone_app / password: secretKeyRef datamesh-postgres-app +# Service here, not the CNPG datamesh-postgres-rw Service). +# * username: datamesh_app / password: secretKeyRef datamesh-postgres-app # (same Secret+keys the app Deployments use — # openshift/helm/datamesh/templates/secret-app.yaml), not a dedicated -# CNPG-generated capstone-postgres-app secret. +# CNPG-generated datamesh-postgres-app secret. # * sslMode: disable — this Postgres has no TLS listener configured # (unlike CNPG's always-on self-signed cert). VERIFY-POINT: if ingestion # can't connect, there is no fallback needed in the other direction since @@ -37,7 +37,7 @@ metadata: name: om-ingestion-config namespace: datamesh labels: - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh app.kubernetes.io/component: openmetadata-ingestion data: get_token.py: | @@ -88,11 +88,11 @@ data: serviceConnection: config: type: Postgres - username: capstone_app + username: datamesh_app authType: password: __PG_PASSWORD__ hostPort: postgres.datamesh.svc.cluster.local:5432 - database: capstone + database: datamesh sslMode: disable sourceConfig: config: @@ -120,7 +120,7 @@ metadata: name: om-ingest-postgres namespace: datamesh labels: - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh app.kubernetes.io/component: openmetadata-ingestion spec: backoffLimit: 2 @@ -132,7 +132,7 @@ spec: # container at startup and block the Job from ever completing. sidecar.istio.io/inject: "false" labels: - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh app.kubernetes.io/component: openmetadata-ingestion spec: restartPolicy: Never diff --git a/examples/lgtm-datamesh/openshift/platform/openmetadata/om-app-values.yaml b/examples/lgtm-datamesh/openshift/platform/openmetadata/om-app-values.yaml index d38e968..9a93560 100644 --- a/examples/lgtm-datamesh/openshift/platform/openmetadata/om-app-values.yaml +++ b/examples/lgtm-datamesh/openshift/platform/openmetadata/om-app-values.yaml @@ -12,11 +12,11 @@ # Changed from the minikube source — the backend database: # * host: postgres.datamesh.svc.cluster.local (the plain StatefulSet # Service in openshift/helm/datamesh/templates/postgres.yaml), NOT -# capstone-postgres-rw (that's the CNPG read-write Service the minikube +# datamesh-postgres-rw (that's the CNPG read-write Service the minikube # deploy uses; this cluster has no CNPG operator/Cluster). # * databaseName: openmetadata — a second database on the same Postgres # instance, with a DEDICATED `openmetadata` login role (NOT the shared -# `capstone_app` role the core app secret uses) — both created by +# `datamesh_app` role the core app secret uses) — both created by # ../install-platform.sh's `provision_openmetadata_db` (confirmed by # reading that script: OPENMETADATA_ROLE=OPENMETADATA_DB="openmetadata"), # same shape as the minikube source's setup-openmetadata.sh. diff --git a/examples/lgtm-datamesh/openshift/platform/openmetadata/opensearch-scc.yaml b/examples/lgtm-datamesh/openshift/platform/openmetadata/opensearch-scc.yaml index f561c96..c6ee385 100644 --- a/examples/lgtm-datamesh/openshift/platform/openmetadata/opensearch-scc.yaml +++ b/examples/lgtm-datamesh/openshift/platform/openmetadata/opensearch-scc.yaml @@ -24,7 +24,7 @@ metadata: namespace: datamesh labels: app.kubernetes.io/name: openmetadata-opensearch - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding @@ -33,7 +33,7 @@ metadata: namespace: datamesh labels: app.kubernetes.io/name: openmetadata-opensearch - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh subjects: - kind: ServiceAccount name: openmetadata-opensearch diff --git a/examples/lgtm-datamesh/openshift/platform/openmetadata/postgres-credentials-secret.yaml b/examples/lgtm-datamesh/openshift/platform/openmetadata/postgres-credentials-secret.yaml index 2484ee3..ab836e4 100644 --- a/examples/lgtm-datamesh/openshift/platform/openmetadata/postgres-credentials-secret.yaml +++ b/examples/lgtm-datamesh/openshift/platform/openmetadata/postgres-credentials-secret.yaml @@ -25,7 +25,7 @@ metadata: namespace: datamesh labels: app.kubernetes.io/name: openmetadata - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh type: Opaque stringData: openmetadata-db-password: "openmetadata" diff --git a/examples/lgtm-datamesh/openshift/platform/openmetadata/route.yaml b/examples/lgtm-datamesh/openshift/platform/openmetadata/route.yaml index 71f1309..fdd51f0 100644 --- a/examples/lgtm-datamesh/openshift/platform/openmetadata/route.yaml +++ b/examples/lgtm-datamesh/openshift/platform/openmetadata/route.yaml @@ -11,7 +11,7 @@ metadata: namespace: datamesh labels: app.kubernetes.io/name: openmetadata - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh spec: to: kind: Service diff --git a/examples/lgtm-datamesh/openshift/platform/prefect/example-flow-configmap.yaml b/examples/lgtm-datamesh/openshift/platform/prefect/example-flow-configmap.yaml index 20aa03b..5aef125 100644 --- a/examples/lgtm-datamesh/openshift/platform/prefect/example-flow-configmap.yaml +++ b/examples/lgtm-datamesh/openshift/platform/prefect/example-flow-configmap.yaml @@ -9,7 +9,7 @@ metadata: namespace: datamesh labels: app.kubernetes.io/name: prefect-example-flow - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh data: flow.py: | """Tiny 2-task flow to prove the datamesh Prefect server+worker wiring diff --git a/examples/lgtm-datamesh/openshift/platform/prefect/postgres-credentials-secret.yaml b/examples/lgtm-datamesh/openshift/platform/prefect/postgres-credentials-secret.yaml index 0f40ee9..2a3db35 100644 --- a/examples/lgtm-datamesh/openshift/platform/prefect/postgres-credentials-secret.yaml +++ b/examples/lgtm-datamesh/openshift/platform/prefect/postgres-credentials-secret.yaml @@ -19,7 +19,7 @@ metadata: namespace: datamesh labels: app.kubernetes.io/name: prefect-server - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh type: Opaque stringData: username: "prefect" diff --git a/examples/lgtm-datamesh/openshift/platform/prefect/server-deployment.yaml b/examples/lgtm-datamesh/openshift/platform/prefect/server-deployment.yaml index 2d0127b..69910c3 100644 --- a/examples/lgtm-datamesh/openshift/platform/prefect/server-deployment.yaml +++ b/examples/lgtm-datamesh/openshift/platform/prefect/server-deployment.yaml @@ -3,7 +3,7 @@ # Reuses the core datamesh Postgres instance (openshift/helm/datamesh/templates/postgres.yaml, # Service `postgres`) rather than bundling a second Postgres — see # decisions.md DRA-013. The `prefect` database + a DEDICATED `prefect` login -# role (NOT the shared `capstone_app` role the core app secret uses) are +# role (NOT the shared `datamesh_app` role the core app secret uses) are # provisioned by ../install-platform.sh's `provision_prefect_db` — confirmed # by reading that script directly (PREFECT_DB=PREFECT_ROLE="prefect", # PREFECT_PASSWORD="prefect", a hardcoded demo value, same caveat as @@ -29,7 +29,7 @@ metadata: namespace: datamesh labels: app.kubernetes.io/name: prefect-server - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh spec: replicas: 1 selector: @@ -39,7 +39,7 @@ spec: metadata: labels: app.kubernetes.io/name: prefect-server - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh spec: containers: - name: prefect-server diff --git a/examples/lgtm-datamesh/openshift/platform/prefect/server-route.yaml b/examples/lgtm-datamesh/openshift/platform/prefect/server-route.yaml index b52bcd8..f71af9e 100644 --- a/examples/lgtm-datamesh/openshift/platform/prefect/server-route.yaml +++ b/examples/lgtm-datamesh/openshift/platform/prefect/server-route.yaml @@ -8,7 +8,7 @@ metadata: namespace: datamesh labels: app.kubernetes.io/name: prefect-server - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh spec: to: kind: Service diff --git a/examples/lgtm-datamesh/openshift/platform/prefect/server-service.yaml b/examples/lgtm-datamesh/openshift/platform/prefect/server-service.yaml index 4095e93..7fde80c 100644 --- a/examples/lgtm-datamesh/openshift/platform/prefect/server-service.yaml +++ b/examples/lgtm-datamesh/openshift/platform/prefect/server-service.yaml @@ -6,7 +6,7 @@ metadata: namespace: datamesh labels: app.kubernetes.io/name: prefect-server - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh spec: type: ClusterIP selector: diff --git a/examples/lgtm-datamesh/openshift/platform/prefect/worker-deployment.yaml b/examples/lgtm-datamesh/openshift/platform/prefect/worker-deployment.yaml index 37501d7..60c0114 100644 --- a/examples/lgtm-datamesh/openshift/platform/prefect/worker-deployment.yaml +++ b/examples/lgtm-datamesh/openshift/platform/prefect/worker-deployment.yaml @@ -16,7 +16,7 @@ metadata: namespace: datamesh labels: app.kubernetes.io/name: prefect-worker - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh spec: replicas: 1 selector: @@ -26,7 +26,7 @@ spec: metadata: labels: app.kubernetes.io/name: prefect-worker - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh spec: containers: - name: prefect-worker diff --git a/examples/lgtm-datamesh/proto/capstone/inventory/v1/inventory.proto b/examples/lgtm-datamesh/proto/datamesh/inventory/v1/inventory.proto similarity index 88% rename from examples/lgtm-datamesh/proto/capstone/inventory/v1/inventory.proto rename to examples/lgtm-datamesh/proto/datamesh/inventory/v1/inventory.proto index cc6e362..ba9a24a 100644 --- a/examples/lgtm-datamesh/proto/capstone/inventory/v1/inventory.proto +++ b/examples/lgtm-datamesh/proto/datamesh/inventory/v1/inventory.proto @@ -1,8 +1,8 @@ syntax = "proto3"; -// Package mirrors the directory tree (capstone/inventory/v1) and namespaces +// Package mirrors the directory tree (datamesh/inventory/v1) and namespaces // the contract so it can't collide with other services' protos (CAP-R19-4). -package capstone.inventory.v1; +package datamesh.inventory.v1; // InventoryService answers stock questions for the order flow. r23 ships the // single synchronous call order-service needs when placing an order; more diff --git a/examples/lgtm-datamesh/scripts/bootstrap-capstone.sh b/examples/lgtm-datamesh/scripts/bootstrap-datamesh.sh similarity index 92% rename from examples/lgtm-datamesh/scripts/bootstrap-capstone.sh rename to examples/lgtm-datamesh/scripts/bootstrap-datamesh.sh index 376d691..a4a638d 100755 --- a/examples/lgtm-datamesh/scripts/bootstrap-capstone.sh +++ b/examples/lgtm-datamesh/scripts/bootstrap-datamesh.sh @@ -1,12 +1,12 @@ #!/usr/bin/env bash # -# bootstrap-capstone.sh — stand up the ENTIRE §17 capstone from a fresh node, in +# bootstrap-datamesh.sh — stand up the ENTIRE §17 final project from a fresh node, in # the correct order, with a health gate between each tier. This is the one-command # bring-up that did not exist before (the README froze at r20 and the real order # was scattered across setup-* scripts, smokes, and helm installs) — which is why # every recovery had been manual archaeology. # -# Use it after `minikube delete -p capstone` (a clean rebuild), or any time you +# Use it after `minikube delete -p datamesh` (a clean rebuild), or any time you # want the full stack from nothing. Idempotent: helm upgrade --install, kubectl # apply, kubectl wait, and build-only-if-missing, so re-running resumes safely. # @@ -20,26 +20,26 @@ # the final follow-on rather than run inline — those need a warm server # and are better as explicit steps (and the ingestion Jobs opt out of the mesh, r34). # -# Run from examples/lgtm-datamesh/: ./scripts/bootstrap-capstone.sh +# Run from examples/lgtm-datamesh/: ./scripts/bootstrap-datamesh.sh set -uo pipefail -NS="capstone" -PROFILE="${MINIKUBE_PROFILE:-capstone}" +NS="datamesh" +PROFILE="${MINIKUBE_PROFILE:-datamesh}" ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"; cd "$ROOT" -PG_RELEASE="capstone-postgres"; PG_CHART="charts/capstone/charts/postgres" -KAFKA_RELEASE="capstone-kafka"; KAFKA_CHART="charts/capstone/charts/kafka"; KAFKA_CR="capstone-kafka" -APICURIO_RELEASE="apicurio"; APICURIO_CHART="charts/capstone/charts/apicurio" -KAFKAUI_RELEASE="kafka-ui"; KAFKAUI_CHART="charts/capstone/charts/kafka-ui" +PG_RELEASE="datamesh-postgres"; PG_CHART="charts/datamesh/charts/postgres" +KAFKA_RELEASE="datamesh-kafka"; KAFKA_CHART="charts/datamesh/charts/kafka"; KAFKA_CR="datamesh-kafka" +APICURIO_RELEASE="apicurio"; APICURIO_CHART="charts/datamesh/charts/apicurio" +KAFKAUI_RELEASE="kafka-ui"; KAFKAUI_CHART="charts/datamesh/charts/kafka-ui" # Canonical host ports + helpers (ensure_endpoint, wait_http). Host access is a # published NodePort on 127.0.0.1, fixed when the profile is created. source "${ROOT}/demos/lib/endpoints.sh" -# Image helpers (image_in_profile, CAPSTONE_SERVICES). No registry: images are +# Image helpers (image_in_profile, DATAMESH_SERVICES). No registry: images are # built with docker and loaded into the profile. source "${ROOT}/demos/lib/images.sh" -SERVICES=("${CAPSTONE_SERVICES[@]}") # defined in images.sh; must follow the source +SERVICES=("${DATAMESH_SERVICES[@]}") # defined in images.sh; must follow the source step() { printf '\n\033[1m==> %s\033[0m\n' "$1"; } ok() { printf ' \xe2\x9c\x93 %s\n' "$1"; } @@ -49,7 +49,7 @@ wait_rollout() { kubectl rollout status "$1" -n "$NS" --timeout="${2:-300s}"; } # ── Tier 1: profile ────────────────────────────────────────────────────────── step "1/10 Profile" -./scripts/setup-capstone-profile.sh || fail "profile setup failed" +./scripts/setup-datamesh-profile.sh || fail "profile setup failed" [[ "$(kubectl config current-context 2>/dev/null)" == "$PROFILE" ]] || kubectl config use-context "$PROFILE" ok "profile up, context set" @@ -138,7 +138,7 @@ helm upgrade --install "$APICURIO_RELEASE" "$APICURIO_CHART" -n "$NS" || fail "a # published NodePort at 127.0.0.1:8089. Additive; opts out of the mesh (no sidecar). helm upgrade --install "$KAFKAUI_RELEASE" "$KAFKAUI_CHART" -n "$NS" || fail "kafka-ui install failed" for svc in "${SERVICES[@]}"; do - helm upgrade --install "$svc" "charts/capstone/charts/$svc" -n "$NS" || fail "$svc install failed" + helm upgrade --install "$svc" "charts/datamesh/charts/$svc" -n "$NS" || fail "$svc install failed" done # Scalers (gateway scale-to-zero + notification consumer-lag). kubectl apply -f keda/notification-scaledobject.yaml >/dev/null 2>&1 || true @@ -166,7 +166,7 @@ curl -fs -o /dev/null --max-time 8 -X POST "http://127.0.0.1:${TP_ORDER}/orders" # (it points at the existing Prometheus/Grafana/Tempo, single-stack — CAP-042). step "9/10 Kiali (mesh-topology console for the walkthrough)" ./scripts/setup-kiali.sh || fail "kiali setup failed" -ok "kiali installed (wired to the capstone observability stack)" +ok "kiali installed (wired to the datamesh observability stack)" # ── Tier 10: catalog ingestion (populate OpenMetadata + declare lineage) ──── # Three one-off Jobs: catalog the Postgres schemas as Tables, catalog the Kafka diff --git a/examples/lgtm-datamesh/scripts/build-image.sh b/examples/lgtm-datamesh/scripts/build-image.sh index 7ca83bc..ae7044b 100755 --- a/examples/lgtm-datamesh/scripts/build-image.sh +++ b/examples/lgtm-datamesh/scripts/build-image.sh @@ -1,13 +1,13 @@ #!/usr/bin/env bash # # build-image.sh — build a service image with Docker and load it into the -# capstone minikube profile. There is no registry. +# datamesh minikube profile. There is no registry. # # WHY `minikube image load`: it works the same with a native Docker Engine # (Linux) and a VM-based one (Docker Desktop is one example), because the # image is streamed into the node's containerd rather than pulled over a # network address. Loaded images persist across `minikube stop` / `start`. -# Charts reference capstone/: with imagePullPolicy: Never, so the +# Charts reference datamesh/: with imagePullPolicy: Never, so the # kubelet only ever uses what was loaded into the profile. # (CAP-007, CAP-009 and CAP-010 are superseded by DRA-019.) # @@ -19,8 +19,8 @@ # Environment: # SKIP_BUILD=1 skip `docker build`; load the existing local image # BUILD_IMAGE_NO_RESTART=1 do not restart Deployments that use the image -# MINIKUBE_PROFILE minikube profile (default: capstone) -# NS namespace of the Deployments to restart (default: capstone) +# MINIKUBE_PROFILE minikube profile (default: datamesh) +# NS namespace of the Deployments to restart (default: datamesh) set -euo pipefail @@ -31,8 +31,8 @@ source "${SCRIPT_DIR}/../demos/lib/images.sh" CONTEXT="${1:?usage: build-image.sh [tag]}" NAME="${2:?usage: build-image.sh [tag]}" TAG="${3:-v1}" -PROFILE="${MINIKUBE_PROFILE:-capstone}" -NS="${NS:-capstone}" +PROFILE="${MINIKUBE_PROFILE:-datamesh}" +NS="${NS:-datamesh}" step() { printf '\n==> %s\n' "$1"; } fail() { printf 'ERROR: %s\n' "$1" >&2; exit 1; } @@ -72,7 +72,7 @@ trap '[[ -n "$tmp" ]] && rm -f "$tmp"' EXIT if ! minikube -p "$PROFILE" image load "$IMAGE" || ! image_in_profile "$NAME" "$TAG"; then step "Direct load did not land the image; falling back to a tar archive" - tmp="$(mktemp "${TMPDIR:-/tmp}/capstone-image.XXXXXX")" + tmp="$(mktemp "${TMPDIR:-/tmp}/datamesh-image.XXXXXX")" mv "$tmp" "${tmp}.tar"; tmp="${tmp}.tar" docker image save -o "$tmp" "$IMAGE" minikube -p "$PROFILE" image load "$tmp" diff --git a/examples/lgtm-datamesh/scripts/cluster-status.sh b/examples/lgtm-datamesh/scripts/cluster-status.sh index 31d6061..90e9a3b 100755 --- a/examples/lgtm-datamesh/scripts/cluster-status.sh +++ b/examples/lgtm-datamesh/scripts/cluster-status.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # -# cluster-status.sh — one-shot health report for the capstone cluster. +# cluster-status.sh — one-shot health report for the datamesh cluster. # # Answers, in a single command, the questions we kept running ten commands to # answer during the r29c debugging marathon: @@ -19,7 +19,7 @@ set -uo pipefail -PROFILE="${MINIKUBE_PROFILE:-capstone}" +PROFILE="${MINIKUBE_PROFILE:-datamesh}" TAG="v1" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" @@ -69,11 +69,11 @@ step "Service images in the profile" source "${SCRIPT_DIR}/../demos/lib/endpoints.sh" source "${SCRIPT_DIR}/../demos/lib/images.sh" missing=() -for svc in "${CAPSTONE_SERVICES[@]}"; do +for svc in "${DATAMESH_SERVICES[@]}"; do image_in_profile "$svc" "$TAG" || missing+=("$svc") done if [[ ${#missing[@]} -eq 0 ]]; then - ok "all ${#CAPSTONE_SERVICES[@]} service images present (${IMAGE_PREFIX}/:${TAG}) in profile '$PROFILE'" + ok "all ${#DATAMESH_SERVICES[@]} service images present (${IMAGE_PREFIX}/:${TAG}) in profile '$PROFILE'" else bad "missing from the profile (pods will fail with ErrImageNeverPull): ${missing[*]}" warn "rebuild + load them with: ./scripts/cluster-up.sh (or per-image: ./scripts/build-image.sh services/ ${TAG})" @@ -96,12 +96,12 @@ report_ns() { fi } step "Workloads" -report_ns capstone "capstone (services)" +report_ns datamesh "datamesh (services)" report_ns observability "observability (Prometheus/Grafana/Tempo)" report_ns keda "keda (autoscaler + HTTP add-on)" # KEDA HTTPScaledObject — the gateway is meant to scale to zero, so 0 pods is fine. -hso="$(kubectl get httpscaledobject -n capstone graphql-gateway-http \ +hso="$(kubectl get httpscaledobject -n datamesh graphql-gateway-http \ -o jsonpath='{.status.conditions[?(@.type=="Ready")].status}' 2>/dev/null || true)" if [[ "$hso" == "True" ]]; then ok "KEDA HTTPScaledObject for graphql-gateway is Ready (gateway may be scaled to zero — expected)" diff --git a/examples/lgtm-datamesh/scripts/cluster-up.sh b/examples/lgtm-datamesh/scripts/cluster-up.sh index abc8f0f..3dd9026 100755 --- a/examples/lgtm-datamesh/scripts/cluster-up.sh +++ b/examples/lgtm-datamesh/scripts/cluster-up.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # -# cluster-up.sh — bring the capstone cluster up cleanly, and heal the two +# cluster-up.sh — bring the datamesh cluster up cleanly, and heal the two # failure modes that bit us hard during r29c: # # 1. A wedged control plane. After a long uptime with many redeploys, etcd can @@ -25,7 +25,7 @@ # ./scripts/cluster-up.sh set -uo pipefail -PROFILE="${MINIKUBE_PROFILE:-capstone}" +PROFILE="${MINIKUBE_PROFILE:-datamesh}" TAG="v1" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"; cd "$ROOT" # build-image.sh takes cwd-relative services/ @@ -55,7 +55,7 @@ else # spending minutes starting a node that can never be reached from the host. if profile_container_exists; then check_published_ports \ - || fail "stopped profile does not publish the required NodePorts on 127.0.0.1 — recreate it (deletes the cluster; re-run ./scripts/bootstrap-capstone.sh afterwards): ./scripts/setup-capstone-profile.sh --replace" + || fail "stopped profile does not publish the required NodePorts on 127.0.0.1 — recreate it (deletes the cluster; re-run ./scripts/bootstrap-datamesh.sh afterwards): ./scripts/setup-datamesh-profile.sh --replace" fi # A stopped profile holds no listeners: every host port must be free, or # docker fails with a raw bind error. A node container that is still running @@ -67,13 +67,13 @@ else assert_host_ports_free "$own_ports" || fail "host ports are not free (see above); stop other clusters and compose stacks, then re-run" printf ' starting (this also clears a stopped/wedged node)...\n' minikube start -p "$PROFILE" >/dev/null 2>&1 \ - || fail "minikube start failed — run ./scripts/setup-capstone-profile.sh for first-time provisioning" + || fail "minikube start failed — run ./scripts/setup-datamesh-profile.sh for first-time provisioning" ok "profile started" fi # Host access is NodePorts published on 127.0.0.1 at profile creation; verify. check_published_ports \ - || fail "profile does not publish the required NodePorts on 127.0.0.1 — recreate it with ./scripts/setup-capstone-profile.sh --replace (deletes the cluster; re-run ./scripts/bootstrap-capstone.sh afterwards)" + || fail "profile does not publish the required NodePorts on 127.0.0.1 — recreate it with ./scripts/setup-datamesh-profile.sh --replace (deletes the cluster; re-run ./scripts/bootstrap-datamesh.sh afterwards)" ok "NodePorts published on 127.0.0.1" ensure_node_forwarding || fail "could not reset the node FORWARD policy (pod traffic would be dropped)" @@ -112,12 +112,12 @@ fi # ─── 3. Rebuild + load ONLY images missing from the profile ────────────────── step "Checking the profile for missing service images" missing=() -for svc in "${CAPSTONE_SERVICES[@]}"; do +for svc in "${DATAMESH_SERVICES[@]}"; do image_in_profile "$svc" "$TAG" || missing+=("$svc") done if [[ ${#missing[@]} -eq 0 ]]; then - ok "all ${#CAPSTONE_SERVICES[@]} images present (:${TAG}) — nothing to rebuild" + ok "all ${#DATAMESH_SERVICES[@]} images present (:${TAG}) — nothing to rebuild" else warn "missing: ${missing[*]} — rebuilding (only these)" for svc in "${missing[@]}"; do @@ -130,11 +130,11 @@ fi # ─── 4. Bounce pods stuck on image pulls so they pick up now-loaded images ─── step "Restarting any pods stuck on image pulls" -stuck="$(kubectl get pods -n capstone 2>/dev/null \ +stuck="$(kubectl get pods -n datamesh 2>/dev/null \ | grep -iE 'ImagePullBackOff|ErrImagePull|ErrImageNeverPull' | awk '{print $1}' || true)" if [[ -n "$stuck" ]]; then printf '%s\n' "$stuck" | while read -r pod; do - [[ -n "$pod" ]] && kubectl delete pod -n capstone "$pod" >/dev/null 2>&1 \ + [[ -n "$pod" ]] && kubectl delete pod -n datamesh "$pod" >/dev/null 2>&1 \ && printf ' restarted %s\n' "$pod" done ok "bounced stuck pods (they will start from the loaded images)" diff --git a/examples/lgtm-datamesh/scripts/gen-protos.sh b/examples/lgtm-datamesh/scripts/gen-protos.sh index 833e0bd..da0b938 100755 --- a/examples/lgtm-datamesh/scripts/gen-protos.sh +++ b/examples/lgtm-datamesh/scripts/gen-protos.sh @@ -35,7 +35,7 @@ rm -rf "$STAGING" mkdir -p "$STAGING" step "Generating Python stubs" -PROTO_FILE="$ROOT/proto/capstone/inventory/v1/inventory.proto" +PROTO_FILE="$ROOT/proto/datamesh/inventory/v1/inventory.proto" OUT="$ROOT/$STAGING" if command -v buf >/dev/null 2>&1; then printf ' using buf\n' @@ -61,7 +61,7 @@ else - dnf: sudo dnf install pipx && pipx install grpcio-tools" fi -[[ -d "$STAGING/capstone" ]] || fail "generation produced no capstone/ package in $STAGING" +[[ -d "$STAGING/datamesh" ]] || fail "generation produced no datamesh/ package in $STAGING" step "Distributing stubs to services: ${SERVICES[*]}" for svc in "${SERVICES[@]}"; do @@ -69,11 +69,11 @@ for svc in "${SERVICES[@]}"; do [[ -d "services/${svc}" ]] || fail "service dir services/${svc} not found" rm -rf "$dest" mkdir -p "$dest" - cp -r "$STAGING/capstone" "$dest/capstone" + cp -r "$STAGING/datamesh" "$dest/datamesh" # Add __init__.py at each package level so the tree is importable even # without relying on implicit namespace packages. find "$dest" -type d -exec sh -c 'touch "$1/__init__.py"' _ {} \; - printf ' ✓ %s\n' "$dest/capstone/inventory/v1/" + printf ' ✓ %s\n' "$dest/datamesh/inventory/v1/" done rm -rf "$STAGING" @@ -82,8 +82,8 @@ step "Done" cat < order-placed -> notifications # @@ -19,10 +19,10 @@ # and the lineage PUT is idempotent, so re-running is safe. # # Prerequisites: -# * capstone profile running, kubectl context = capstone +# * datamesh profile running, kubectl context = datamesh # * scripts/setup-openmetadata.sh has been run (the server is up and serving) -# * the data sources exist: the capstone-postgres Cluster with the service -# schemas, and the capstone-kafka cluster with the order-placed topic +# * the data sources exist: the datamesh-postgres Cluster with the service +# schemas, and the datamesh-kafka cluster with the order-placed topic # (i.e. the app has been deployed and at least one order placed). Ingestion # reflects whatever exists at run time. # @@ -34,7 +34,7 @@ set -euo pipefail -NS="capstone" +NS="datamesh" JOB_TIMEOUT="10m" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" @@ -55,9 +55,9 @@ for f in postgres.yaml kafka.yaml get_token.py lineage.py \ done current_context="$(kubectl config current-context 2>/dev/null || echo "")" -if [[ "$current_context" != "capstone" ]]; then - printf 'WARNING: current kubectl context is "%s", not "capstone".\n' "$current_context" >&2 - printf 'Switch with: kubectl config use-context capstone\n' >&2 +if [[ "$current_context" != "datamesh" ]]; then + printf 'WARNING: current kubectl context is "%s", not "datamesh".\n' "$current_context" >&2 + printf 'Switch with: kubectl config use-context datamesh\n' >&2 printf 'Continue anyway? [y/N] ' >&2 read -r answer [[ "$answer" =~ ^[Yy] ]] || exit 1 @@ -112,7 +112,7 @@ printf '\n==> Catalog populated and lineage declared.\n\n' printf 'Browse it:\n' printf ' ./scripts/show-endpoints.sh # OpenMetadata is published on 127.0.0.1:8585\n' printf ' open http://127.0.0.1:8585 (admin@open-metadata.org / admin)\n' -printf ' → Services shows capstone-postgres (Database) and capstone-kafka (Messaging)\n' +printf ' → Services shows datamesh-postgres (Database) and datamesh-kafka (Messaging)\n' printf ' → the order-placed topic'\''s Lineage tab shows orders upstream, notifications downstream\n\n' printf 'Verify end-to-end:\n' printf ' ./demos/demo-om-lineage.sh\n' diff --git a/examples/lgtm-datamesh/scripts/publish-discovery-contracts.sh b/examples/lgtm-datamesh/scripts/publish-discovery-contracts.sh index b64cc73..fc282a3 100755 --- a/examples/lgtm-datamesh/scripts/publish-discovery-contracts.sh +++ b/examples/lgtm-datamesh/scripts/publish-discovery-contracts.sh @@ -20,17 +20,17 @@ # ORDER_URL e.g. http://127.0.0.1:8080 (published NodePort 30080) # GATEWAY_URL e.g. http://127.0.0.1:8081 (published NodePort 30081, KEDA interceptor) # GATEWAY_HOST Host header routing the interceptor to the gateway -# (default graphql-gateway.capstone) — required because the +# (default graphql-gateway.datamesh) — required because the # gateway is KEDA-scaled-to-zero and only reachable via the # interceptor, which routes by Host. -# PROTO_PATH e.g. proto/capstone/inventory/v1/inventory.proto +# PROTO_PATH e.g. proto/datamesh/inventory/v1/inventory.proto set -euo pipefail APICURIO_URL="${APICURIO_URL:?set APICURIO_URL}" ORDER_URL="${ORDER_URL:?set ORDER_URL}" GATEWAY_URL="${GATEWAY_URL:?set GATEWAY_URL}" -GATEWAY_HOST="${GATEWAY_HOST:-graphql-gateway.capstone}" +GATEWAY_HOST="${GATEWAY_HOST:-graphql-gateway.datamesh}" PROTO_PATH="${PROTO_PATH:?set PROTO_PATH}" GROUP="${APICURIO_GROUP:-default}" diff --git a/examples/lgtm-datamesh/scripts/restore-baseline.sh b/examples/lgtm-datamesh/scripts/restore-baseline.sh index 65c7342..e2c8c86 100755 --- a/examples/lgtm-datamesh/scripts/restore-baseline.sh +++ b/examples/lgtm-datamesh/scripts/restore-baseline.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # -# restore-baseline.sh — put the capstone workloads back in their bootstrap +# restore-baseline.sh — put the datamesh workloads back in their bootstrap # state: all six service releases installed and the two KEDA scalers applied. # # Why this exists: the smokes clean up the service releases they deployed when @@ -12,7 +12,7 @@ # # Scope: bootstrap tier 8 only (services + scalers). The platform tiers # (Postgres, Kafka, Apicurio, observability, OpenMetadata) are checked and -# warned about, not installed — that's bootstrap-capstone.sh's job. +# warned about, not installed — that's bootstrap-datamesh.sh's job. # # Idempotent: helm upgrade --install + kubectl apply throughout. # @@ -20,7 +20,7 @@ set -uo pipefail -NS="capstone" +NS="datamesh" ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"; cd "$ROOT" SERVICES=(graphql-gateway inventory-service notification-service order-service payment-service shipping-service) @@ -39,21 +39,21 @@ is_keda_managed() { return 1 } -kubectl get ns "$NS" >/dev/null 2>&1 || fail "namespace $NS not found — run bootstrap-capstone.sh first" +kubectl get ns "$NS" >/dev/null 2>&1 || fail "namespace $NS not found — run bootstrap-datamesh.sh first" # ── platform sanity (warn only) ─────────────────────────────────────────────── step "Platform check (warn-only — bootstrap owns these tiers)" -kubectl get pods -n "$NS" -l "cnpg.io/cluster=capstone-postgres,cnpg.io/instanceRole=primary" --no-headers 2>/dev/null | grep -q Running \ - && ok "Postgres primary Running" || warn "Postgres primary not Running — re-run bootstrap-capstone.sh" -kubectl get kafka capstone-kafka -n "$NS" >/dev/null 2>&1 \ - && ok "Kafka CR present" || warn "Kafka CR missing — re-run bootstrap-capstone.sh" +kubectl get pods -n "$NS" -l "cnpg.io/cluster=datamesh-postgres,cnpg.io/instanceRole=primary" --no-headers 2>/dev/null | grep -q Running \ + && ok "Postgres primary Running" || warn "Postgres primary not Running — re-run bootstrap-datamesh.sh" +kubectl get kafka datamesh-kafka -n "$NS" >/dev/null 2>&1 \ + && ok "Kafka CR present" || warn "Kafka CR missing — re-run bootstrap-datamesh.sh" kubectl get deploy apicurio -n "$NS" >/dev/null 2>&1 \ - && ok "Apicurio present" || warn "Apicurio missing — re-run bootstrap-capstone.sh (or demo-discovery.sh deploys it)" + && ok "Apicurio present" || warn "Apicurio missing — re-run bootstrap-datamesh.sh (or demo-discovery.sh deploys it)" # ── the six service releases ────────────────────────────────────────────────── step "Installing/refreshing the six service releases" for svc in "${SERVICES[@]}"; do - helm upgrade --install "$svc" "charts/capstone/charts/$svc" -n "$NS" >/dev/null \ + helm upgrade --install "$svc" "charts/datamesh/charts/$svc" -n "$NS" >/dev/null \ || fail "$svc install failed" ok "$svc" done diff --git a/examples/lgtm-datamesh/scripts/scaffold-service.sh b/examples/lgtm-datamesh/scripts/scaffold-service.sh index 9dc05e5..151ad99 100755 --- a/examples/lgtm-datamesh/scripts/scaffold-service.sh +++ b/examples/lgtm-datamesh/scripts/scaffold-service.sh @@ -1,13 +1,13 @@ #!/usr/bin/env bash # -# scaffold-service.sh — stamp out a new capstone service skeleton from the +# scaffold-service.sh — stamp out a new datamesh service skeleton from the # proven order-service template (r21c). # # What it generates (a "walking skeleton" service — CAP-006): # - services/-service/ FastAPI app with /health + /healthz, # async SQLAlchemy wired to its own # Postgres schema, UBI 9 Containerfile -# - charts/capstone/charts/-service/ helm subchart (Deployment + +# - charts/datamesh/charts/-service/ helm subchart (Deployment + # Service), image loaded into the # node (minikube image load) # @@ -41,7 +41,7 @@ SERVICE="${BASE}-service" # Resolve repo-relative paths from the example root (parent of scripts/). ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" SVC_DIR="${ROOT}/services/${SERVICE}" -CHART_DIR="${ROOT}/charts/capstone/charts/${SERVICE}" +CHART_DIR="${ROOT}/charts/datamesh/charts/${SERVICE}" step() { printf '\n==> %s\n' "$1"; } fail() { printf 'ERROR: %s\n' "$1" >&2; exit 1; } @@ -60,7 +60,7 @@ cat > "${SVC_DIR}/pyproject.toml" <<'EOF' [tool.poetry] name = "__SERVICE__" version = "0.1.0" -description = "__SERVICE__ data product for the §17 capstone — health skeleton (domain surface added in later iterations)" +description = "__SERVICE__ data product for the §17 final project — health skeleton (domain surface added in later iterations)" authors = ["patterncatalyst"] readme = "README.md" package-mode = false @@ -135,7 +135,7 @@ EOF cat > "${SVC_DIR}/README.md" <<'EOF' # __SERVICE__ -A §17 capstone data product. Owns the `__SCHEMA__` Postgres schema +A §17 final project data product. Owns the `__SCHEMA__` Postgres schema (per-service ownership, CAP-003). **r22 scope (skeleton):** the service starts, ensures its schema exists, and @@ -152,8 +152,8 @@ appropriate to the service). ```bash # from examples/lgtm-datamesh/ ./scripts/build-image.sh services/__SERVICE__ __SERVICE__ v1 -helm upgrade --install __SERVICE__ charts/capstone/charts/__SERVICE__ -n capstone -kubectl rollout status deployment/__SERVICE__ -n capstone --timeout=120s +helm upgrade --install __SERVICE__ charts/datamesh/charts/__SERVICE__ -n datamesh +kubectl rollout status deployment/__SERVICE__ -n datamesh --timeout=120s ``` Or run the health smoke test, which does all of the above and asserts the @@ -168,8 +168,8 @@ cat > "${SVC_DIR}/app/config.py" <<'EOF' """Configuration for __SERVICE__, sourced from environment variables. In-cluster, the Postgres connection comes from the CloudNativePG-generated -Secret (`capstone-postgres-app`), surfaced as env vars by the helm subchart. -Locally, the defaults allow running against a local Postgres (e.g. `docker run --rm -p 127.0.0.1:5432:5432 -e POSTGRES_USER=capstone_app -e POSTGRES_PASSWORD=changeme -e POSTGRES_DB=capstone postgres:16`). +Secret (`datamesh-postgres-app`), surfaced as env vars by the helm subchart. +Locally, the defaults allow running against a local Postgres (e.g. `docker run --rm -p 127.0.0.1:5432:5432 -e POSTGRES_USER=datamesh_app -e POSTGRES_PASSWORD=changeme -e POSTGRES_DB=datamesh postgres:16`). """ from pydantic_settings import BaseSettings, SettingsConfigDict @@ -185,9 +185,9 @@ class Settings(BaseSettings): # Postgres connection. In-cluster these come from the CNPG app Secret. pg_host: str = "127.0.0.1" pg_port: int = 5432 - pg_user: str = "capstone_app" + pg_user: str = "datamesh_app" pg_password: str = "changeme" - pg_database: str = "capstone" + pg_database: str = "datamesh" # Server host: str = "0.0.0.0" @@ -283,7 +283,7 @@ EOF # ─── services//app/main.py (health surface only) ───────────────────── cat > "${SVC_DIR}/app/main.py" <<'EOF' -"""__SERVICE__ — a §17 capstone data product (r22 skeleton). +"""__SERVICE__ — a §17 final project data product (r22 skeleton). r22 scope: the service stands up, connects to its Postgres schema (`__SCHEMA__`), and serves health probes. Its domain surface (REST/gRPC/ @@ -317,7 +317,7 @@ async def lifespan(app: FastAPI): app = FastAPI( title="__SERVICE__", version="0.1.0", - description="__SERVICE__ data product for the §17 capstone data mesh (skeleton).", + description="__SERVICE__ data product for the §17 final project data mesh (skeleton).", lifespan=lifespan, ) @@ -369,17 +369,17 @@ async def test_health_ok(): assert body["service"] == "__SERVICE__" EOF -# ─── charts/capstone/charts//Chart.yaml ────────────────────────────── +# ─── charts/datamesh/charts//Chart.yaml ────────────────────────────── cat > "${CHART_DIR}/Chart.yaml" <<'EOF' apiVersion: v2 name: __SERVICE__ -description: __SERVICE__ data product — FastAPI service backed by the capstone Postgres (__SCHEMA__ schema). r22 ships the health skeleton; domain surface added later. +description: __SERVICE__ data product — FastAPI service backed by the datamesh Postgres (__SCHEMA__ schema). r22 ships the health skeleton; domain surface added later. type: application version: 0.1.0 appVersion: "0.1.0" EOF -# ─── charts/capstone/charts//values.yaml ───────────────────────────── +# ─── charts/datamesh/charts//values.yaml ───────────────────────────── cat > "${CHART_DIR}/values.yaml" <<'EOF' # __SERVICE__ subchart values. @@ -387,7 +387,7 @@ replicas: 1 image: # Image is loaded into the node by build-image.sh (minikube image load); no registry. - repository: capstone/__SERVICE__ + repository: datamesh/__SERVICE__ tag: v1 # Never: images are loaded into the node by build-image.sh (minikube image load) and never pulled; build-image.sh restarts the Deployment so a rebuilt :v1 is used. pullPolicy: Never @@ -399,8 +399,8 @@ service: # Postgres connection. The CloudNativePG operator generates a Secret named # "-app" holding the app user's credentials; we reference it by key. postgres: - clusterName: capstone-postgres - appSecret: capstone-postgres-app + clusterName: datamesh-postgres + appSecret: datamesh-postgres-app schema: __SCHEMA__ resources: @@ -422,7 +422,7 @@ probes: periodSeconds: 5 EOF -# ─── charts/capstone/charts//templates/deployment.yaml ─────────────── +# ─── charts/datamesh/charts//templates/deployment.yaml ─────────────── cat > "${CHART_DIR}/templates/deployment.yaml" <<'EOF' apiVersion: apps/v1 kind: Deployment @@ -431,7 +431,7 @@ metadata: namespace: {{ .Release.Namespace }} labels: app.kubernetes.io/name: __SERVICE__ - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh app.kubernetes.io/component: data-product spec: replicas: {{ .Values.replicas }} @@ -442,7 +442,7 @@ spec: metadata: labels: app.kubernetes.io/name: __SERVICE__ - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh spec: containers: - name: __SERVICE__ @@ -495,7 +495,7 @@ spec: periodSeconds: {{ .Values.probes.readiness.periodSeconds }} EOF -# ─── charts/capstone/charts//templates/service.yaml ────────────────── +# ─── charts/datamesh/charts//templates/service.yaml ────────────────── cat > "${CHART_DIR}/templates/service.yaml" <<'EOF' apiVersion: v1 kind: Service @@ -504,7 +504,7 @@ metadata: namespace: {{ .Release.Namespace }} labels: app.kubernetes.io/name: __SERVICE__ - app.kubernetes.io/part-of: capstone + app.kubernetes.io/part-of: datamesh spec: type: ClusterIP selector: @@ -540,7 +540,7 @@ fi cat <&2 + printf 'ERROR: the datamesh scripts are supported on Fedora and RHEL hosts (bare metal or VM).\n' >&2 exit 1 fi host_id="$( . /etc/os-release 2>/dev/null && printf '%s %s' "${ID:-}" "${ID_LIKE:-}" )" || host_id="" case " $host_id " in *" fedora "*|*" rhel "*) ;; - *) printf 'WARNING: the capstone scripts are supported on Fedora and RHEL hosts (bare metal or VM); continuing anyway.\n' >&2 ;; + *) printf 'WARNING: the datamesh scripts are supported on Fedora and RHEL hosts (bare metal or VM); continuing anyway.\n' >&2 ;; esac # 1. Validate EXTRA_NODE_PORTS up front, before anything is deleted or started. @@ -149,7 +149,7 @@ if (( VM_ENGINE )); then printf ' for the node and expect inotify limits to be checked inside the node.\n' fi -# 7. Host inotify limits (§1's tweak). Capstone runs many controllers; the +# 7. Host inotify limits (§1's tweak). Datamesh runs many controllers; the # Fedora default fs.inotify.max_user_instances=128 is insufficient. Only # meaningful when the node shares the host kernel. if (( VM_ENGINE == 0 )); then @@ -197,13 +197,13 @@ except Exception: pass ' "$PROFILE_NAME" "$KUBE_VERSION" 2>/dev/null || true)" if [[ -n "$prof_mismatch" ]]; then - printf 'ERROR: profile %s was created with %s (want docker/containerd/%s); recreate it: ./scripts/setup-capstone-profile.sh --replace (or minikube delete -p %s)\n' \ + printf 'ERROR: profile %s was created with %s (want docker/containerd/%s); recreate it: ./scripts/setup-datamesh-profile.sh --replace (or minikube delete -p %s)\n' \ "$PROFILE_NAME" "$prof_mismatch" "$KUBE_VERSION" "$PROFILE_NAME" >&2 exit 1 fi fi -# 10. Warn (don't fail) if other minikube profiles are running. Capstone wants +# 10. Warn (don't fail) if other minikube profiles are running. Datamesh wants # the headroom. running_profiles=$(minikube profile list -o json 2>/dev/null \ | python3 -c ' @@ -236,7 +236,7 @@ if profile_container_exists && (( ! REPLACE )); then # Existing profile kept as-is: its published ports must already be right. check_published_ports || exit 1 if profile_container_running; then - printf '==> Profile %s already exists and is running. Pass --replace to recreate (deletes the cluster; re-run ./scripts/bootstrap-capstone.sh afterwards).\n' "$PROFILE_NAME" + printf '==> Profile %s already exists and is running. Pass --replace to recreate (deletes the cluster; re-run ./scripts/bootstrap-datamesh.sh afterwards).\n' "$PROFILE_NAME" else printf '==> Profile %s exists but is stopped. Starting it.\n' "$PROFILE_NAME" # A stopped profile holds no listeners: every host port must be free. @@ -264,7 +264,7 @@ assert_host_ports_free "$own_ports" || exit 1 if (( REPLACE )); then # Idempotent: also clears minikube's own record when the container is gone. - printf '==> Deleting existing %s profile (--replace specified; run ./scripts/bootstrap-capstone.sh afterwards)\n' "$PROFILE_NAME" + printf '==> Deleting existing %s profile (--replace specified; run ./scripts/bootstrap-datamesh.sh afterwards)\n' "$PROFILE_NAME" minikube delete -p "$PROFILE_NAME" fi @@ -292,7 +292,7 @@ printf '==> Checking node pod networking\n' ensure_node_forwarding # The node container's PID cap bounds TOTAL processes across all pods. The full -# meshed capstone runs ~2000+ tasks; a low cap makes the kubelet fail to fork +# meshed datamesh runs ~2000+ tasks; a low cap makes the kubelet fail to fork # (EAGAIN, "resource temporarily unavailable"). Warn only: the fix is an engine # setting, applied before the node is created. pids_limit="$(docker inspect -f '{{.HostConfig.PidsLimit}}' "$PROFILE_NAME" 2>/dev/null || true)" @@ -318,19 +318,19 @@ fi printf '==> Switching kubectl context to %s\n' "$PROFILE_NAME" kubectl config use-context "$PROFILE_NAME" -printf '==> Creating capstone namespace\n' -kubectl create namespace capstone --dry-run=client -o yaml | kubectl apply -f - +printf '==> Creating datamesh namespace\n' +kubectl create namespace datamesh --dry-run=client -o yaml | kubectl apply -f - printf '==> Verifying cluster health\n' kubectl get nodes kubectl get pods -n kube-system printf '\n' -printf '==> Capstone profile is ready.\n' +printf '==> Datamesh profile is ready.\n' printf '\n' printf 'Next steps:\n' printf ' 1. Service images: ./scripts/build-image.sh services/ v1\n' -printf ' (docker build + minikube image load); ./scripts/bootstrap-capstone.sh\n' +printf ' (docker build + minikube image load); ./scripts/bootstrap-datamesh.sh\n' printf ' does this for you.\n' printf ' 2. To free the profile when done with §17:\n' printf ' ./scripts/teardown.sh\n' diff --git a/examples/lgtm-datamesh/scripts/setup-istio.sh b/examples/lgtm-datamesh/scripts/setup-istio.sh index f5e821a..47e784b 100755 --- a/examples/lgtm-datamesh/scripts/setup-istio.sh +++ b/examples/lgtm-datamesh/scripts/setup-istio.sh @@ -1,10 +1,10 @@ #!/usr/bin/env bash # -# setup-istio.sh — install the Istio control plane into the capstone cluster and +# setup-istio.sh — install the Istio control plane into the datamesh cluster and # enable sidecar injection, in preparation for the order-service v1→v2 canary # (r26, CAP-024). # -# Like the other capstone platform installs (Postgres/Kafka operators, +# Like the other datamesh platform installs (Postgres/Kafka operators, # OpenMetadata), this is a run-once-per-cluster step, separate from the app # releases. Idempotent. # @@ -15,7 +15,7 @@ # the istio-ingressgateway the canary routes through. (Not `demo`, which # adds addons we don't need; not `minimal`, which omits the ingress # gateway.) -# 3. Labels the `capstone` namespace for sidecar injection. +# 3. Labels the `datamesh` namespace for sidecar injection. # # SCOPE NOTE (CAP-024): r26 meshes order-service for the canary, not the whole # mesh. Labeling the namespace enables injection, but only pods CREATED or @@ -31,13 +31,13 @@ # ./scripts/setup-istio.sh # # Then enable the canary (selector immutability means v1 must be recreated once): -# kubectl delete deployment order-service -n capstone --ignore-not-found -# helm upgrade --install capstone ./charts/capstone -n capstone +# kubectl delete deployment order-service -n datamesh --ignore-not-found +# helm upgrade --install datamesh ./charts/datamesh -n datamesh # ./demos/demo-canary-verify.sh set -euo pipefail -NS="capstone" +NS="datamesh" ISTIO_PROFILE="default" # ─── Pre-flight ────────────────────────────────────────────────────────────── @@ -69,9 +69,9 @@ fi printf '==> istioctl %s matches the pinned version\n' "$ISTIOCTL_VERSION" current_context="$(kubectl config current-context 2>/dev/null || echo "")" -if [[ "$current_context" != "capstone" ]]; then - printf 'WARNING: current kubectl context is "%s", not "capstone".\n' "$current_context" >&2 - printf 'Switch with: kubectl config use-context capstone\n' >&2 +if [[ "$current_context" != "datamesh" ]]; then + printf 'WARNING: current kubectl context is "%s", not "datamesh".\n' "$current_context" >&2 + printf 'Switch with: kubectl config use-context datamesh\n' >&2 printf 'Continue anyway? [y/N] ' >&2 read -r answer [[ "$answer" =~ ^[Yy] ]] || exit 1 @@ -79,7 +79,7 @@ fi # ─── 1. Install Istio (control plane + ingress gateway) ────────────────────── -printf '==> Installing Istio (profile=%s) into the capstone cluster\n' "$ISTIO_PROFILE" +printf '==> Installing Istio (profile=%s) into the datamesh cluster\n' "$ISTIO_PROFILE" istioctl install --set profile="$ISTIO_PROFILE" -y printf '==> Waiting for istiod and the ingress gateway to be ready\n' @@ -94,7 +94,7 @@ kubectl patch svc istio-ingressgateway -n istio-system --type='json' \ -p '[{"op":"replace","path":"/spec/ports/1/nodePort","value":30088}]' \ 2>/dev/null || true -# ─── 2. Enable injection on the capstone namespace ─────────────────────────── +# ─── 2. Enable injection on the datamesh namespace ─────────────────────────── printf '==> Labeling namespace %s for sidecar injection\n' "$NS" kubectl label namespace "$NS" istio-injection=enabled --overwrite @@ -106,7 +106,7 @@ printf 'Enable the order-service canary (one-time delete: the v1 selector now\n' printf 'includes version=v1, and selectors are immutable, so the old Deployment\n' printf 'must be recreated):\n' printf ' kubectl delete deployment order-service -n %s --ignore-not-found\n' "$NS" -printf ' helm upgrade --install capstone ./charts/capstone -n %s\n' "$NS" +printf ' helm upgrade --install datamesh ./charts/datamesh -n %s\n' "$NS" printf '\nThen run the canary demo + verification:\n' printf ' ./demos/demo-canary-verify.sh\n' printf '\nReminder (CAP-024 scope): do not restart the operator-managed infra pods\n' diff --git a/examples/lgtm-datamesh/scripts/setup-kafka-operator.sh b/examples/lgtm-datamesh/scripts/setup-kafka-operator.sh index 7164fb7..185b9ca 100755 --- a/examples/lgtm-datamesh/scripts/setup-kafka-operator.sh +++ b/examples/lgtm-datamesh/scripts/setup-kafka-operator.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # # setup-kafka-operator.sh — install the Strimzi Kafka operator into the -# capstone namespace via Helm (the operator pattern, same as CloudNativePG +# datamesh namespace via Helm (the operator pattern, same as CloudNativePG # in CAP-002). Pinned to a specific Strimzi version for reproducibility. # # Strimzi runs Kafka in KRaft mode (no ZooKeeper) since 0.46; the cluster CR @@ -12,7 +12,7 @@ set -euo pipefail -NS="capstone" +NS="datamesh" STRIMZI_VERSION="1.2.0" step() { printf '\n==> %s\n' "$1"; } diff --git a/examples/lgtm-datamesh/scripts/setup-keda.sh b/examples/lgtm-datamesh/scripts/setup-keda.sh index c9c8cd3..8a40dfc 100755 --- a/examples/lgtm-datamesh/scripts/setup-keda.sh +++ b/examples/lgtm-datamesh/scripts/setup-keda.sh @@ -1,11 +1,11 @@ #!/usr/bin/env bash # -# setup-keda.sh — install KEDA (core + HTTP add-on) into the capstone cluster, +# setup-keda.sh — install KEDA (core + HTTP add-on) into the datamesh cluster, # in preparation for the dual autoscalers (r26b, CAP-025): # * Kafka consumer-lag scaling for notification-service (core KEDA) # * HTTP request scaling for graphql-gateway (the HTTP add-on) # -# Like the other capstone platform installs, this is run-once-per-cluster, +# Like the other datamesh platform installs, this is run-once-per-cluster, # separate from the app releases. Idempotent. Versions match §12. # # Usage (from examples/lgtm-datamesh/): @@ -27,9 +27,9 @@ command -v kubectl >/dev/null 2>&1 || { printf 'ERROR: kubectl not in PATH.\n' > command -v helm >/dev/null 2>&1 || { printf 'ERROR: helm not in PATH — see §2.\n' >&2; exit 1; } current_context="$(kubectl config current-context 2>/dev/null || echo "")" -if [[ "$current_context" != "capstone" ]]; then - printf 'WARNING: current kubectl context is "%s", not "capstone".\n' "$current_context" >&2 - printf 'Switch with: kubectl config use-context capstone\n' >&2 +if [[ "$current_context" != "datamesh" ]]; then + printf 'WARNING: current kubectl context is "%s", not "datamesh".\n' "$current_context" >&2 + printf 'Switch with: kubectl config use-context datamesh\n' >&2 printf 'Continue anyway? [y/N] ' >&2 read -r answer [[ "$answer" =~ ^[Yy] ]] || exit 1 @@ -70,7 +70,7 @@ helm upgrade --install keda-add-ons-http kedacore/keda-add-ons-http \ # ─── 4. Pin the HTTP interceptor proxy to a fixed NodePort ─────────────────── # The demos wake graphql-gateway the real way — by driving a request through -# this interceptor (Host: graphql-gateway.capstone) — reached on NodePort +# this interceptor (Host: graphql-gateway.datamesh) — reached on NodePort # 30081, published on 127.0.0.1:8081 at profile creation (map: demos/lib/endpoints.sh). printf '==> Pinning KEDA HTTP interceptor proxy nodePort to 30081\n' kubectl patch svc keda-add-ons-http-interceptor-proxy -n "$NAMESPACE" \ diff --git a/examples/lgtm-datamesh/scripts/setup-kiali.sh b/examples/lgtm-datamesh/scripts/setup-kiali.sh index 260f2b8..0f0a3cf 100755 --- a/examples/lgtm-datamesh/scripts/setup-kiali.sh +++ b/examples/lgtm-datamesh/scripts/setup-kiali.sh @@ -1,10 +1,10 @@ #!/usr/bin/env bash # -# setup-kiali.sh — add Kiali (the mesh-visualization console) to the capstone -# cluster, wired to the EXISTING capstone observability stack rather than +# setup-kiali.sh — add Kiali (the mesh-visualization console) to the datamesh +# cluster, wired to the EXISTING datamesh observability stack rather than # standing up its own (CAP-0NN). Run-once-per-cluster, idempotent. # -# Why this exists: the capstone observability stack (setup-observability.sh) is +# Why this exists: the datamesh observability stack (setup-observability.sh) is # Prometheus + Tempo + Grafana in the `observability` namespace. Kiali gives the # one thing that stack doesn't: a live mesh-topology graph — the products and the # traffic between them, the canary split included. The demo walkthrough's final @@ -15,14 +15,14 @@ # http://prometheus.istio-system:9090. We do NOT want a second Prometheus. So # this script applies ONLY the Kiali addon (not the full samples/addons/ bundle, # which would also install Prometheus, Grafana, Jaeger, and Loki), then patches -# Kiali's ConfigMap so external_services points at the capstone's existing +# Kiali's ConfigMap so external_services points at the datamesh's existing # Prometheus, Grafana, and Tempo in the `observability` namespace. # # What it does: -# 1. Verifies the Istio dir (samples/addons/kiali.yaml) and the capstone +# 1. Verifies the Istio dir (samples/addons/kiali.yaml) and the datamesh # observability stack are present. # 2. Applies ONLY samples/addons/kiali.yaml into istio-system. -# 3. Patches the kiali ConfigMap external_services → capstone Prometheus / +# 3. Patches the kiali ConfigMap external_services → datamesh Prometheus / # Grafana / Tempo, and restarts Kiali to pick it up. # 4. Waits for the Kiali deployment to be Ready. # @@ -35,7 +35,7 @@ # # Then verify + view: # ./demos/demo-kiali.sh -# open http://127.0.0.1:20001/kiali (Graph → namespace: capstone) +# open http://127.0.0.1:20001/kiali (Graph → namespace: datamesh) set -euo pipefail @@ -47,7 +47,7 @@ ISTIO_DIR="${ISTIO_DIR:-${HOME}/.local/share/istio-current}" # picks up a different Kiali. KIALI_IMAGE="${KIALI_IMAGE:-quay.io/kiali/kiali:v2.31.0}" -# capstone observability service endpoints (single-stack wiring targets) +# datamesh observability service endpoints (single-stack wiring targets) PROM_URL="http://prometheus-server.${OBS_NS}:80" GRAFANA_IN_URL="http://grafana.${OBS_NS}:80" GRAFANA_EXT_URL="http://127.0.0.1:3000" # what a browser uses (published NodePort 30300) @@ -60,9 +60,9 @@ step() { printf '\n==> %s\n' "$1"; } command -v kubectl >/dev/null 2>&1 || { printf 'ERROR: kubectl not in PATH.\n' >&2; exit 1; } current_context="$(kubectl config current-context 2>/dev/null || echo "")" -if [[ "$current_context" != "capstone" ]]; then - printf 'WARNING: current kubectl context is "%s", not "capstone".\n' "$current_context" >&2 - printf 'Switch with: kubectl config use-context capstone\n' >&2 +if [[ "$current_context" != "datamesh" ]]; then + printf 'WARNING: current kubectl context is "%s", not "datamesh".\n' "$current_context" >&2 + printf 'Switch with: kubectl config use-context datamesh\n' >&2 printf 'Continue anyway? [y/N] ' >&2 read -r answer [[ "$answer" =~ ^[Yy] ]] || exit 1 @@ -93,12 +93,12 @@ step "Applying ONLY the Kiali addon (not the full samples/addons bundle)" printf ' source: %s\n' "$KIALI_MANIFEST" kubectl apply -f "$KIALI_MANIFEST" -# ─── 2. Wire Kiali to the existing capstone observability stack ────────────── +# ─── 2. Wire Kiali to the existing datamesh observability stack ────────────── # The addon ships a ConfigMap `kiali` whose key config.yaml contains the -# external_services block. We overwrite that block to point at the capstone +# external_services block. We overwrite that block to point at the datamesh # Prometheus / Grafana / Tempo instead of Kiali's bundled defaults. -step "Wiring Kiali external_services → the capstone observability stack" +step "Wiring Kiali external_services → the datamesh observability stack" printf ' prometheus: %s\n' "$PROM_URL" printf ' grafana: %s (in-cluster) / %s (browser)\n' "$GRAFANA_IN_URL" "$GRAFANA_EXT_URL" printf ' tracing: %s (Tempo)\n' "$TEMPO_URL" @@ -159,9 +159,9 @@ kubectl rollout status deployment/kiali -n "$ISTIO_SYSTEM" --timeout=5m # ─── Done ──────────────────────────────────────────────────────────────────── -step "Kiali is installed and wired to the capstone observability stack." +step "Kiali is installed and wired to the datamesh observability stack." printf '\nView the mesh topology (NodePort published on 127.0.0.1):\n' -printf ' open http://127.0.0.1:20001/kiali (Graph → namespace: capstone)\n' +printf ' open http://127.0.0.1:20001/kiali (Graph → namespace: datamesh)\n' printf '\nVerify:\n' printf ' ./demos/demo-kiali.sh\n' printf '\nNote: the live traffic graph only shows edges while traffic is flowing —\n' diff --git a/examples/lgtm-datamesh/scripts/setup-observability.sh b/examples/lgtm-datamesh/scripts/setup-observability.sh index ec26d3b..272c61b 100755 --- a/examples/lgtm-datamesh/scripts/setup-observability.sh +++ b/examples/lgtm-datamesh/scripts/setup-observability.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # -# setup-observability.sh — install the capstone observability stack into the +# setup-observability.sh — install the datamesh observability stack into the # cluster (CAP-027 metrics, CAP-028 traces): Prometheus (+ kube-state-metrics), # Tempo (trace backend), and Grafana, all in the 'observability' namespace. # @@ -13,7 +13,7 @@ # OTLP). Nothing emits traces yet; instrumenting a service to send them is the # next step (see §17 and the tracing demo). # -# Like the other capstone platform installs, this is run-once-per-cluster, +# Like the other datamesh platform installs, this is run-once-per-cluster, # separate from the app releases, and idempotent. # # Usage (from examples/lgtm-datamesh/): @@ -36,9 +36,9 @@ command -v kubectl >/dev/null 2>&1 || { printf 'ERROR: kubectl not in PATH.\n' > command -v helm >/dev/null 2>&1 || { printf 'ERROR: helm not in PATH — see §2.\n' >&2; exit 1; } current_context="$(kubectl config current-context 2>/dev/null || echo "")" -if [[ "$current_context" != "capstone" ]]; then - printf 'WARNING: current kubectl context is "%s", not "capstone".\n' "$current_context" >&2 - printf 'Switch with: kubectl config use-context capstone\n' >&2 +if [[ "$current_context" != "datamesh" ]]; then + printf 'WARNING: current kubectl context is "%s", not "datamesh".\n' "$current_context" >&2 + printf 'Switch with: kubectl config use-context datamesh\n' >&2 printf 'Continue anyway? [y/N] ' >&2 read -r answer [[ "$answer" =~ ^[Yy] ]] || exit 1 @@ -93,7 +93,7 @@ helm upgrade --install grafana grafana-community/grafana \ printf '\n==> Prometheus + Grafana installed in the %s namespace.\n\n' "$NAMESPACE" printf 'Services are exposed as NodePorts published on 127.0.0.1 (list them with):\n' printf ' ./scripts/show-endpoints.sh\n\n' -printf 'Then open Grafana and find the "Capstone — Scaling & Traffic" dashboard:\n' +printf 'Then open Grafana and find the "Datamesh — Scaling & Traffic" dashboard:\n' printf ' http://127.0.0.1:3000\n\n' printf 'Login (read the real credentials from the secret — the chart keeps an existing\n' printf 'password on upgrade, so do not assume it is the values default):\n' diff --git a/examples/lgtm-datamesh/scripts/setup-openmetadata.sh b/examples/lgtm-datamesh/scripts/setup-openmetadata.sh index 2c7aac2..4b3fa1b 100755 --- a/examples/lgtm-datamesh/scripts/setup-openmetadata.sh +++ b/examples/lgtm-datamesh/scripts/setup-openmetadata.sh @@ -1,11 +1,11 @@ #!/usr/bin/env bash # # setup-openmetadata.sh — deploy OpenMetadata (the data catalog) into the -# capstone cluster, lean single-node shape (CAP-022). +# datamesh cluster, lean single-node shape (CAP-022). # # What this does, in order: # 1. Provisions a dedicated `openmetadata` database + login role inside the -# EXISTING capstone-postgres (CloudNativePG) cluster — OpenMetadata reuses +# EXISTING datamesh-postgres (CloudNativePG) cluster — OpenMetadata reuses # our Postgres as its backend rather than standing up a separate MySQL. # 2. Creates the Kubernetes Secret holding that role's password, which the # OpenMetadata server chart reads. @@ -17,9 +17,9 @@ # releases. Idempotent — re-running upgrades in place and re-provisions safely. # # Prerequisites: -# * capstone profile running, kubectl context = capstone +# * datamesh profile running, kubectl context = datamesh # * CloudNativePG operator installed (./setup-postgres-operator.sh) AND the -# capstone-postgres Cluster already bootstrapped (the postgres subchart; +# datamesh-postgres Cluster already bootstrapped (the postgres subchart; # e.g. after a smoke that deploys Postgres). This script provisions INTO # that running cluster. # @@ -34,9 +34,9 @@ set -euo pipefail # ─── Configuration ─────────────────────────────────────────────────────────── -NS="capstone" +NS="datamesh" OM_CHART_VERSION="2.0.5" # pin both deps and server to this release -PG_CLUSTER="capstone-postgres" # the CloudNativePG Cluster name (postgres subchart) +PG_CLUSTER="datamesh-postgres" # the CloudNativePG Cluster name (postgres subchart) OM_DB="openmetadata" # dedicated database for OpenMetadata's own store OM_ROLE="openmetadata" # login role that owns it @@ -69,9 +69,9 @@ for f in "$DEPS_VALUES" "$APP_VALUES"; do done current_context=$(kubectl config current-context 2>/dev/null || echo "") -if [[ "$current_context" != "capstone" ]]; then - printf 'WARNING: current kubectl context is "%s", not "capstone".\n' "$current_context" >&2 - printf 'Switch with: kubectl config use-context capstone\n' >&2 +if [[ "$current_context" != "datamesh" ]]; then + printf 'WARNING: current kubectl context is "%s", not "datamesh".\n' "$current_context" >&2 + printf 'Switch with: kubectl config use-context datamesh\n' >&2 printf 'Continue anyway? [y/N] ' >&2 read -r answer [[ "$answer" =~ ^[Yy] ]] || exit 1 @@ -79,7 +79,7 @@ fi # Confirm the Postgres cluster is present and has a primary, since we provision # into it. The CNPG operator labels the primary pod cnpg.io/instanceRole=primary. -printf '==> Locating the capstone-postgres primary\n' +printf '==> Locating the datamesh-postgres primary\n' PG_PRIMARY="$(kubectl get pods -n "$NS" \ -l "cnpg.io/cluster=${PG_CLUSTER},cnpg.io/instanceRole=primary" \ -o jsonpath='{.items[0].metadata.name}' 2>/dev/null || echo "")" @@ -87,7 +87,7 @@ if [[ -z "$PG_PRIMARY" ]]; then printf 'ERROR: no primary pod for CloudNativePG cluster "%s" in namespace "%s".\n' \ "$PG_CLUSTER" "$NS" >&2 printf 'Install the operator (./setup-postgres-operator.sh) and bring up the\n' >&2 - printf 'capstone-postgres Cluster (e.g. run a smoke that deploys Postgres) first.\n' >&2 + printf 'datamesh-postgres Cluster (e.g. run a smoke that deploys Postgres) first.\n' >&2 exit 1 fi printf ' primary: %s\n' "$PG_PRIMARY" @@ -147,7 +147,7 @@ helm upgrade --install openmetadata-dependencies open-metadata/openmetadata-depe --values "$DEPS_VALUES" \ --wait --timeout 10m -printf '==> Installing the OpenMetadata server (backend = capstone Postgres)\n' +printf '==> Installing the OpenMetadata server (backend = datamesh Postgres)\n' helm upgrade --install openmetadata open-metadata/openmetadata \ --namespace "$NS" \ --version "$OM_CHART_VERSION" \ diff --git a/examples/lgtm-datamesh/scripts/setup-postgres-operator.sh b/examples/lgtm-datamesh/scripts/setup-postgres-operator.sh index 2517e8b..a713b3b 100755 --- a/examples/lgtm-datamesh/scripts/setup-postgres-operator.sh +++ b/examples/lgtm-datamesh/scripts/setup-postgres-operator.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # # setup-postgres-operator.sh — install the CloudNativePG operator into the -# capstone cluster. +# datamesh cluster. # # IMPORTANT: installing an operator is a CLUSTER-WIDE action. It: # - registers Custom Resource Definitions (CRDs are always cluster-scoped: @@ -43,10 +43,10 @@ if ! command -v kubectl >/dev/null 2>&1; then fi current_context=$(kubectl config current-context 2>/dev/null || echo "") -if [[ "$current_context" != "capstone" ]]; then - printf 'WARNING: current kubectl context is "%s", not "capstone".\n' "$current_context" >&2 +if [[ "$current_context" != "datamesh" ]]; then + printf 'WARNING: current kubectl context is "%s", not "datamesh".\n' "$current_context" >&2 printf 'The operator will be installed cluster-wide on THAT cluster.\n' >&2 - printf 'Switch with: kubectl config use-context capstone\n' >&2 + printf 'Switch with: kubectl config use-context datamesh\n' >&2 printf 'Continue anyway? [y/N] ' >&2 read -r answer [[ "$answer" =~ ^[Yy] ]] || exit 1 @@ -89,6 +89,6 @@ printf ' (these now exist in every namespace on this cluster)\n' printf ' - Controller running in namespace %s, reconciling Cluster CRs\n' "$OPERATOR_NS" printf ' in any namespace\n' printf '\n' -printf 'Next: the capstone umbrella chart ships a Cluster CR in the\n' -printf 'capstone namespace (charts/capstone/charts/postgres/). The operator\n' +printf 'Next: the datamesh umbrella chart ships a Cluster CR in the\n' +printf 'datamesh namespace (charts/datamesh/charts/postgres/). The operator\n' printf 'will see it and provision the actual Postgres pods + services.\n' diff --git a/examples/lgtm-datamesh/scripts/show-endpoints.sh b/examples/lgtm-datamesh/scripts/show-endpoints.sh index 490d18c..466a85f 100755 --- a/examples/lgtm-datamesh/scripts/show-endpoints.sh +++ b/examples/lgtm-datamesh/scripts/show-endpoints.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # -# show-endpoints.sh — read-only report of host access to the capstone cluster. +# show-endpoints.sh — read-only report of host access to the datamesh cluster. # # For each endpoint: URL, whether the profile publishes its port on 127.0.0.1, # whether the Service nodePort matches, and whether something answers. @@ -42,7 +42,7 @@ docker_engine_ok || exit 1 if ! { profile_container_exists && profile_container_running; }; then printf '%sERROR:%s cluster "%s" is not running.\n' "$RED" "$RST" "$EP_PROFILE" - printf 'Start it with: minikube start -p %s (or ./scripts/setup-capstone-profile.sh)\n' "$EP_PROFILE" + printf 'Start it with: minikube start -p %s (or ./scripts/setup-datamesh-profile.sh)\n' "$EP_PROFILE" exit 1 fi @@ -105,14 +105,14 @@ fi printf '\n' if (( fail )); then if (( missing_port )); then - printf '%sFAIL:%s ports are fixed at profile creation. Recreate with: ./scripts/setup-capstone-profile.sh --replace\n' "$RED" "$RST" - printf '(--replace deletes and recreates the cluster; run ./scripts/bootstrap-capstone.sh again afterwards.)\n' + printf '%sFAIL:%s ports are fixed at profile creation. Recreate with: ./scripts/setup-datamesh-profile.sh --replace\n' "$RED" "$RST" + printf '(--replace deletes and recreates the cluster; run ./scripts/bootstrap-datamesh.sh again afterwards.)\n' fi if (( apierr )); then printf '%sFAIL:%s cannot query the API server for some Services (see the SVC NODEPORT column).\n' "$RED" "$RST" fi if (( drift )); then - printf '%sFAIL:%s a Service nodePort drifted from the map in demos/lib/endpoints.sh; re-run the relevant setup script or ./scripts/bootstrap-capstone.sh.\n' "$RED" "$RST" + printf '%sFAIL:%s a Service nodePort drifted from the map in demos/lib/endpoints.sh; re-run the relevant setup script or ./scripts/bootstrap-datamesh.sh.\n' "$RED" "$RST" fi exit 1 fi diff --git a/examples/lgtm-datamesh/scripts/teardown.sh b/examples/lgtm-datamesh/scripts/teardown.sh index 852c36e..d88657c 100755 --- a/examples/lgtm-datamesh/scripts/teardown.sh +++ b/examples/lgtm-datamesh/scripts/teardown.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # -# teardown.sh — stop the capstone minikube profile (and optionally delete it). +# teardown.sh — stop the datamesh minikube profile (and optionally delete it). # # Usage: # ./teardown.sh # stop only (preserves state) @@ -8,7 +8,7 @@ set -euo pipefail -PROFILE_NAME="${MINIKUBE_PROFILE:-capstone}" +PROFILE_NAME="${MINIKUBE_PROFILE:-datamesh}" REMOVE=0 if [[ "${1:-}" == "--remove-profile" ]]; then @@ -26,7 +26,7 @@ minikube stop -p "$PROFILE_NAME" if (( REMOVE )); then printf '==> Deleting %s profile (--remove-profile specified)\n' "$PROFILE_NAME" minikube delete -p "$PROFILE_NAME" - printf '==> Profile deleted. To recreate: ./setup-capstone-profile.sh\n' + printf '==> Profile deleted. To recreate: ./setup-datamesh-profile.sh\n' else printf '==> Profile stopped. To restart: minikube start -p %s\n' "$PROFILE_NAME" printf '==> To delete entirely: ./teardown.sh --remove-profile\n' diff --git a/examples/lgtm-datamesh/services/graphql-gateway/Containerfile b/examples/lgtm-datamesh/services/graphql-gateway/Containerfile index 2488026..2911123 100644 --- a/examples/lgtm-datamesh/services/graphql-gateway/Containerfile +++ b/examples/lgtm-datamesh/services/graphql-gateway/Containerfile @@ -31,7 +31,7 @@ FROM registry.access.redhat.com/ubi10/python-314-minimal:10.2-1791464217 AS runt WORKDIR /opt/app-root/src COPY --from=builder --chown=1001:0 /opt/venv /opt/venv COPY --chown=1001:0 app/ ./app/ -# Committed gRPC client stubs (capstone.inventory.v1). app/ adds gen/ to sys.path. +# Committed gRPC client stubs (datamesh.inventory.v1). app/ adds gen/ to sys.path. COPY --chown=1001:0 gen/ ./gen/ ENV PATH="/opt/venv/bin:$PATH" \ PYTHONUNBUFFERED=1 \ diff --git a/examples/lgtm-datamesh/services/graphql-gateway/README.md b/examples/lgtm-datamesh/services/graphql-gateway/README.md index 06b450b..6f42250 100644 --- a/examples/lgtm-datamesh/services/graphql-gateway/README.md +++ b/examples/lgtm-datamesh/services/graphql-gateway/README.md @@ -1,6 +1,6 @@ # graphql-gateway -A §17 capstone data product (read layer). Stateless — owns no data; it +A §17 final project data product (read layer). Stateless — owns no data; it federates reads across services by calling them: - `order(id)` → order-service over **REST** @@ -17,7 +17,7 @@ production-scale pattern — see the §17 prose (CAP-016). # from examples/lgtm-datamesh/ ./scripts/gen-protos.sh # if stubs not generated yet ./scripts/build-image.sh services/graphql-gateway graphql-gateway v1 -helm upgrade --install graphql-gateway charts/capstone/charts/graphql-gateway -n capstone +helm upgrade --install graphql-gateway charts/datamesh/charts/graphql-gateway -n datamesh ``` Then open `/graphql` in a browser for the GraphiQL UI, or run diff --git a/examples/lgtm-datamesh/services/graphql-gateway/app/clients.py b/examples/lgtm-datamesh/services/graphql-gateway/app/clients.py index 07cfac4..feca2ea 100644 --- a/examples/lgtm-datamesh/services/graphql-gateway/app/clients.py +++ b/examples/lgtm-datamesh/services/graphql-gateway/app/clients.py @@ -2,10 +2,10 @@ The gateway federates by *calling* the services it composes: - order-service over REST (httpx) - - inventory-service over gRPC (the committed capstone.inventory.v1 stubs) + - inventory-service over gRPC (the committed datamesh.inventory.v1 stubs) The gRPC stubs live in the gateway's committed `gen/` tree (option b, -CAP-013); we add it to sys.path so `capstone.inventory.v1` imports in the +CAP-013); we add it to sys.path so `datamesh.inventory.v1` imports in the container and locally. This is exactly where the protocol comparison (CAP-012) becomes concrete: @@ -24,7 +24,7 @@ import grpc # noqa: E402 import httpx # noqa: E402 -from capstone.inventory.v1 import ( # noqa: E402 +from datamesh.inventory.v1 import ( # noqa: E402 inventory_pb2, inventory_pb2_grpc, ) diff --git a/examples/lgtm-datamesh/services/graphql-gateway/app/main.py b/examples/lgtm-datamesh/services/graphql-gateway/app/main.py index 6c9f11f..85a8f81 100644 --- a/examples/lgtm-datamesh/services/graphql-gateway/app/main.py +++ b/examples/lgtm-datamesh/services/graphql-gateway/app/main.py @@ -1,4 +1,4 @@ -"""graphql-gateway — the §17 capstone's federated read layer. +"""graphql-gateway — the §17 final project's federated read layer. r24 scope: a single Strawberry GraphQL endpoint that composes reads across services — order-service (REST) and inventory-service (gRPC) — into one @@ -28,7 +28,7 @@ app = FastAPI( title="graphql-gateway", version="0.1.0", - description="Federated GraphQL read layer for the §17 capstone (gateway orchestration).", + description="Federated GraphQL read layer for the §17 final project (gateway orchestration).", ) graphql_app = GraphQLRouter(schema) diff --git a/examples/lgtm-datamesh/services/graphql-gateway/gen/capstone/inventory/v1/inventory_pb2.py b/examples/lgtm-datamesh/services/graphql-gateway/gen/capstone/inventory/v1/inventory_pb2.py deleted file mode 100644 index 475bbe1..0000000 --- a/examples/lgtm-datamesh/services/graphql-gateway/gen/capstone/inventory/v1/inventory_pb2.py +++ /dev/null @@ -1,40 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# NO CHECKED-IN PROTOBUF GENCODE -# source: capstone/inventory/v1/inventory.proto -# Protobuf Python Version: 5.29.0 -"""Generated protocol buffer code.""" -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import runtime_version as _runtime_version -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder -_runtime_version.ValidateProtobufRuntimeVersion( - _runtime_version.Domain.PUBLIC, - 5, - 29, - 0, - '', - 'capstone/inventory/v1/inventory.proto' -) -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n%capstone/inventory/v1/inventory.proto\x12\x15\x63\x61pstone.inventory.v1\"2\n\x11\x43heckStockRequest\x12\x0b\n\x03sku\x18\x01 \x01(\t\x12\x10\n\x08quantity\x18\x02 \x01(\x05\"A\n\x12\x43heckStockResponse\x12\x11\n\tavailable\x18\x01 \x01(\x08\x12\x18\n\x10quantity_on_hand\x18\x02 \x01(\x05\x32u\n\x10InventoryService\x12\x61\n\nCheckStock\x12(.capstone.inventory.v1.CheckStockRequest\x1a).capstone.inventory.v1.CheckStockResponseb\x06proto3') - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'capstone.inventory.v1.inventory_pb2', _globals) -if not _descriptor._USE_C_DESCRIPTORS: - DESCRIPTOR._loaded_options = None - _globals['_CHECKSTOCKREQUEST']._serialized_start=64 - _globals['_CHECKSTOCKREQUEST']._serialized_end=114 - _globals['_CHECKSTOCKRESPONSE']._serialized_start=116 - _globals['_CHECKSTOCKRESPONSE']._serialized_end=181 - _globals['_INVENTORYSERVICE']._serialized_start=183 - _globals['_INVENTORYSERVICE']._serialized_end=300 -# @@protoc_insertion_point(module_scope) diff --git a/examples/lgtm-datamesh/services/graphql-gateway/gen/capstone/__init__.py b/examples/lgtm-datamesh/services/graphql-gateway/gen/datamesh/__init__.py similarity index 100% rename from examples/lgtm-datamesh/services/graphql-gateway/gen/capstone/__init__.py rename to examples/lgtm-datamesh/services/graphql-gateway/gen/datamesh/__init__.py diff --git a/examples/lgtm-datamesh/services/graphql-gateway/gen/capstone/inventory/__init__.py b/examples/lgtm-datamesh/services/graphql-gateway/gen/datamesh/inventory/__init__.py similarity index 100% rename from examples/lgtm-datamesh/services/graphql-gateway/gen/capstone/inventory/__init__.py rename to examples/lgtm-datamesh/services/graphql-gateway/gen/datamesh/inventory/__init__.py diff --git a/examples/lgtm-datamesh/services/graphql-gateway/gen/capstone/inventory/v1/__init__.py b/examples/lgtm-datamesh/services/graphql-gateway/gen/datamesh/inventory/v1/__init__.py similarity index 100% rename from examples/lgtm-datamesh/services/graphql-gateway/gen/capstone/inventory/v1/__init__.py rename to examples/lgtm-datamesh/services/graphql-gateway/gen/datamesh/inventory/v1/__init__.py diff --git a/examples/lgtm-datamesh/services/graphql-gateway/gen/datamesh/inventory/v1/inventory_pb2.py b/examples/lgtm-datamesh/services/graphql-gateway/gen/datamesh/inventory/v1/inventory_pb2.py new file mode 100644 index 0000000..ba2ea89 --- /dev/null +++ b/examples/lgtm-datamesh/services/graphql-gateway/gen/datamesh/inventory/v1/inventory_pb2.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: datamesh/inventory/v1/inventory.proto +# Protobuf Python Version: 7.36.2 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 7, + 36, + 2, + '', + 'datamesh/inventory/v1/inventory.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n%datamesh/inventory/v1/inventory.proto\x12\x15\x64\x61tamesh.inventory.v1\"A\n\x11\x43heckStockRequest\x12\x10\n\x03sku\x18\x01 \x01(\tR\x03sku\x12\x1a\n\x08quantity\x18\x02 \x01(\x05R\x08quantity\"\\\n\x12\x43heckStockResponse\x12\x1c\n\tavailable\x18\x01 \x01(\x08R\tavailable\x12(\n\x10quantity_on_hand\x18\x02 \x01(\x05R\x0equantityOnHand2u\n\x10InventoryService\x12\x61\n\nCheckStock\x12(.datamesh.inventory.v1.CheckStockRequest\x1a).datamesh.inventory.v1.CheckStockResponseb\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'datamesh.inventory.v1.inventory_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_CHECKSTOCKREQUEST']._serialized_start=64 + _globals['_CHECKSTOCKREQUEST']._serialized_end=129 + _globals['_CHECKSTOCKRESPONSE']._serialized_start=131 + _globals['_CHECKSTOCKRESPONSE']._serialized_end=223 + _globals['_INVENTORYSERVICE']._serialized_start=225 + _globals['_INVENTORYSERVICE']._serialized_end=342 +# @@protoc_insertion_point(module_scope) diff --git a/examples/lgtm-datamesh/services/inventory-service/gen/capstone/inventory/v1/inventory_pb2_grpc.py b/examples/lgtm-datamesh/services/graphql-gateway/gen/datamesh/inventory/v1/inventory_pb2_grpc.py similarity index 64% rename from examples/lgtm-datamesh/services/inventory-service/gen/capstone/inventory/v1/inventory_pb2_grpc.py rename to examples/lgtm-datamesh/services/graphql-gateway/gen/datamesh/inventory/v1/inventory_pb2_grpc.py index b6e3425..99b115c 100644 --- a/examples/lgtm-datamesh/services/inventory-service/gen/capstone/inventory/v1/inventory_pb2_grpc.py +++ b/examples/lgtm-datamesh/services/graphql-gateway/gen/datamesh/inventory/v1/inventory_pb2_grpc.py @@ -1,31 +1,11 @@ # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! """Client and server classes corresponding to protobuf-defined services.""" import grpc -import warnings -from capstone.inventory.v1 import inventory_pb2 as capstone_dot_inventory_dot_v1_dot_inventory__pb2 +from datamesh.inventory.v1 import inventory_pb2 as datamesh_dot_inventory_dot_v1_dot_inventory__pb2 -GRPC_GENERATED_VERSION = '1.71.2' -GRPC_VERSION = grpc.__version__ -_version_not_supported = False -try: - from grpc._utilities import first_version_is_lower - _version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION) -except ImportError: - _version_not_supported = True - -if _version_not_supported: - raise RuntimeError( - f'The grpc package installed is at version {GRPC_VERSION},' - + f' but the generated code in capstone/inventory/v1/inventory_pb2_grpc.py depends on' - + f' grpcio>={GRPC_GENERATED_VERSION}.' - + f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}' - + f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.' - ) - - -class InventoryServiceStub(object): +class InventoryServiceStub: """InventoryService answers stock questions for the order flow. r23 ships the single synchronous call order-service needs when placing an order; more RPCs are added as the inventory domain grows. @@ -38,13 +18,13 @@ def __init__(self, channel): channel: A grpc.Channel. """ self.CheckStock = channel.unary_unary( - '/capstone.inventory.v1.InventoryService/CheckStock', - request_serializer=capstone_dot_inventory_dot_v1_dot_inventory__pb2.CheckStockRequest.SerializeToString, - response_deserializer=capstone_dot_inventory_dot_v1_dot_inventory__pb2.CheckStockResponse.FromString, + '/datamesh.inventory.v1.InventoryService/CheckStock', + request_serializer=datamesh_dot_inventory_dot_v1_dot_inventory__pb2.CheckStockRequest.SerializeToString, + response_deserializer=datamesh_dot_inventory_dot_v1_dot_inventory__pb2.CheckStockResponse.FromString, _registered_method=True) -class InventoryServiceServicer(object): +class InventoryServiceServicer: """InventoryService answers stock questions for the order flow. r23 ships the single synchronous call order-service needs when placing an order; more RPCs are added as the inventory domain grows. @@ -63,18 +43,18 @@ def add_InventoryServiceServicer_to_server(servicer, server): rpc_method_handlers = { 'CheckStock': grpc.unary_unary_rpc_method_handler( servicer.CheckStock, - request_deserializer=capstone_dot_inventory_dot_v1_dot_inventory__pb2.CheckStockRequest.FromString, - response_serializer=capstone_dot_inventory_dot_v1_dot_inventory__pb2.CheckStockResponse.SerializeToString, + request_deserializer=datamesh_dot_inventory_dot_v1_dot_inventory__pb2.CheckStockRequest.FromString, + response_serializer=datamesh_dot_inventory_dot_v1_dot_inventory__pb2.CheckStockResponse.SerializeToString, ), } generic_handler = grpc.method_handlers_generic_handler( - 'capstone.inventory.v1.InventoryService', rpc_method_handlers) + 'datamesh.inventory.v1.InventoryService', rpc_method_handlers) server.add_generic_rpc_handlers((generic_handler,)) - server.add_registered_method_handlers('capstone.inventory.v1.InventoryService', rpc_method_handlers) + server.add_registered_method_handlers('datamesh.inventory.v1.InventoryService', rpc_method_handlers) # This class is part of an EXPERIMENTAL API. -class InventoryService(object): +class InventoryService: """InventoryService answers stock questions for the order flow. r23 ships the single synchronous call order-service needs when placing an order; more RPCs are added as the inventory domain grows. @@ -94,9 +74,9 @@ def CheckStock(request, return grpc.experimental.unary_unary( request, target, - '/capstone.inventory.v1.InventoryService/CheckStock', - capstone_dot_inventory_dot_v1_dot_inventory__pb2.CheckStockRequest.SerializeToString, - capstone_dot_inventory_dot_v1_dot_inventory__pb2.CheckStockResponse.FromString, + '/datamesh.inventory.v1.InventoryService/CheckStock', + datamesh_dot_inventory_dot_v1_dot_inventory__pb2.CheckStockRequest.SerializeToString, + datamesh_dot_inventory_dot_v1_dot_inventory__pb2.CheckStockResponse.FromString, options, channel_credentials, insecure, diff --git a/examples/lgtm-datamesh/services/graphql-gateway/pyproject.toml b/examples/lgtm-datamesh/services/graphql-gateway/pyproject.toml index d34012b..687a571 100644 --- a/examples/lgtm-datamesh/services/graphql-gateway/pyproject.toml +++ b/examples/lgtm-datamesh/services/graphql-gateway/pyproject.toml @@ -1,7 +1,7 @@ [tool.poetry] name = "graphql-gateway" version = "0.1.0" -description = "Federated GraphQL read layer for the §17 capstone — orchestrates order (REST) + inventory (gRPC)" +description = "Federated GraphQL read layer for the §17 final project — orchestrates order (REST) + inventory (gRPC)" authors = ["patterncatalyst"] readme = "README.md" package-mode = false diff --git a/examples/lgtm-datamesh/services/inventory-service/Containerfile b/examples/lgtm-datamesh/services/inventory-service/Containerfile index 77c27bd..1e9f37d 100644 --- a/examples/lgtm-datamesh/services/inventory-service/Containerfile +++ b/examples/lgtm-datamesh/services/inventory-service/Containerfile @@ -41,7 +41,7 @@ WORKDIR /opt/app-root/src COPY --from=builder --chown=1001:0 /opt/venv /opt/venv COPY --chown=1001:0 app/ ./app/ -# Committed gRPC stubs (capstone.inventory.v1). app/ adds this to sys.path. +# Committed gRPC stubs (datamesh.inventory.v1). app/ adds this to sys.path. COPY --chown=1001:0 gen/ ./gen/ ENV PATH="/opt/venv/bin:$PATH" \ diff --git a/examples/lgtm-datamesh/services/inventory-service/README.md b/examples/lgtm-datamesh/services/inventory-service/README.md index 02fd425..26de0bb 100644 --- a/examples/lgtm-datamesh/services/inventory-service/README.md +++ b/examples/lgtm-datamesh/services/inventory-service/README.md @@ -1,6 +1,6 @@ # inventory-service -A §17 capstone data product. Owns the `inventory` Postgres schema +A §17 final project data product. Owns the `inventory` Postgres schema (per-service ownership, CAP-003). **r22 scope (skeleton):** the service starts, ensures its schema exists, and @@ -17,8 +17,8 @@ appropriate to the service). ```bash # from examples/lgtm-datamesh/ ./scripts/build-image.sh services/inventory-service inventory-service v1 -helm upgrade --install inventory-service charts/capstone/charts/inventory-service -n capstone -kubectl rollout status deployment/inventory-service -n capstone --timeout=120s +helm upgrade --install inventory-service charts/datamesh/charts/inventory-service -n datamesh +kubectl rollout status deployment/inventory-service -n datamesh --timeout=120s ``` Or run the health smoke test, which does all of the above and asserts the diff --git a/examples/lgtm-datamesh/services/inventory-service/app/config.py b/examples/lgtm-datamesh/services/inventory-service/app/config.py index b935674..ac1f1fd 100644 --- a/examples/lgtm-datamesh/services/inventory-service/app/config.py +++ b/examples/lgtm-datamesh/services/inventory-service/app/config.py @@ -1,8 +1,8 @@ """Configuration for inventory-service, sourced from environment variables. In-cluster, the Postgres connection comes from the CloudNativePG-generated -Secret (`capstone-postgres-app`), surfaced as env vars by the helm subchart. -Locally, the defaults allow running against a local Postgres (e.g. `docker run --rm -p 127.0.0.1:5432:5432 -e POSTGRES_USER=capstone_app -e POSTGRES_PASSWORD=changeme -e POSTGRES_DB=capstone postgres:16`). +Secret (`datamesh-postgres-app`), surfaced as env vars by the helm subchart. +Locally, the defaults allow running against a local Postgres (e.g. `docker run --rm -p 127.0.0.1:5432:5432 -e POSTGRES_USER=datamesh_app -e POSTGRES_PASSWORD=changeme -e POSTGRES_DB=datamesh postgres:16`). """ from pydantic_settings import BaseSettings, SettingsConfigDict @@ -18,9 +18,9 @@ class Settings(BaseSettings): # Postgres connection. In-cluster these come from the CNPG app Secret. pg_host: str = "127.0.0.1" pg_port: int = 5432 - pg_user: str = "capstone_app" + pg_user: str = "datamesh_app" pg_password: str = "changeme" - pg_database: str = "capstone" + pg_database: str = "datamesh" # Server host: str = "0.0.0.0" diff --git a/examples/lgtm-datamesh/services/inventory-service/app/grpc_server.py b/examples/lgtm-datamesh/services/inventory-service/app/grpc_server.py index 1e29825..44488d3 100644 --- a/examples/lgtm-datamesh/services/inventory-service/app/grpc_server.py +++ b/examples/lgtm-datamesh/services/inventory-service/app/grpc_server.py @@ -2,7 +2,7 @@ The generated stubs live in the service's `gen/` tree (committed by scripts/gen-protos.sh, option b). We add that tree to sys.path so the -package `capstone.inventory.v1` is importable both in the container +package `datamesh.inventory.v1` is importable both in the container (/opt/app-root/src/gen) and locally (services/inventory-service/gen). The server runs in the same asyncio event loop as the FastAPI app, started @@ -21,7 +21,7 @@ sys.path.insert(0, _GEN) import grpc # noqa: E402 -from capstone.inventory.v1 import ( # noqa: E402 +from datamesh.inventory.v1 import ( # noqa: E402 inventory_pb2, inventory_pb2_grpc, ) diff --git a/examples/lgtm-datamesh/services/inventory-service/app/main.py b/examples/lgtm-datamesh/services/inventory-service/app/main.py index 6267f63..6d1e8b5 100644 --- a/examples/lgtm-datamesh/services/inventory-service/app/main.py +++ b/examples/lgtm-datamesh/services/inventory-service/app/main.py @@ -1,4 +1,4 @@ -"""inventory-service — a §17 capstone data product. +"""inventory-service — a §17 final project data product. r23 scope: REST health surface + a gRPC server implementing InventoryService.CheckStock, backed by the `stock` table in the service's @@ -42,7 +42,7 @@ async def lifespan(app: FastAPI): app = FastAPI( title="inventory-service", version="0.2.0", - description="inventory-service data product for the §17 capstone — REST health + gRPC CheckStock.", + description="inventory-service data product for the §17 final project — REST health + gRPC CheckStock.", lifespan=lifespan, ) diff --git a/examples/lgtm-datamesh/services/inventory-service/gen/capstone/inventory/v1/inventory_pb2.py b/examples/lgtm-datamesh/services/inventory-service/gen/capstone/inventory/v1/inventory_pb2.py deleted file mode 100644 index 475bbe1..0000000 --- a/examples/lgtm-datamesh/services/inventory-service/gen/capstone/inventory/v1/inventory_pb2.py +++ /dev/null @@ -1,40 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# NO CHECKED-IN PROTOBUF GENCODE -# source: capstone/inventory/v1/inventory.proto -# Protobuf Python Version: 5.29.0 -"""Generated protocol buffer code.""" -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import runtime_version as _runtime_version -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder -_runtime_version.ValidateProtobufRuntimeVersion( - _runtime_version.Domain.PUBLIC, - 5, - 29, - 0, - '', - 'capstone/inventory/v1/inventory.proto' -) -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n%capstone/inventory/v1/inventory.proto\x12\x15\x63\x61pstone.inventory.v1\"2\n\x11\x43heckStockRequest\x12\x0b\n\x03sku\x18\x01 \x01(\t\x12\x10\n\x08quantity\x18\x02 \x01(\x05\"A\n\x12\x43heckStockResponse\x12\x11\n\tavailable\x18\x01 \x01(\x08\x12\x18\n\x10quantity_on_hand\x18\x02 \x01(\x05\x32u\n\x10InventoryService\x12\x61\n\nCheckStock\x12(.capstone.inventory.v1.CheckStockRequest\x1a).capstone.inventory.v1.CheckStockResponseb\x06proto3') - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'capstone.inventory.v1.inventory_pb2', _globals) -if not _descriptor._USE_C_DESCRIPTORS: - DESCRIPTOR._loaded_options = None - _globals['_CHECKSTOCKREQUEST']._serialized_start=64 - _globals['_CHECKSTOCKREQUEST']._serialized_end=114 - _globals['_CHECKSTOCKRESPONSE']._serialized_start=116 - _globals['_CHECKSTOCKRESPONSE']._serialized_end=181 - _globals['_INVENTORYSERVICE']._serialized_start=183 - _globals['_INVENTORYSERVICE']._serialized_end=300 -# @@protoc_insertion_point(module_scope) diff --git a/examples/lgtm-datamesh/services/inventory-service/gen/capstone/__init__.py b/examples/lgtm-datamesh/services/inventory-service/gen/datamesh/__init__.py similarity index 100% rename from examples/lgtm-datamesh/services/inventory-service/gen/capstone/__init__.py rename to examples/lgtm-datamesh/services/inventory-service/gen/datamesh/__init__.py diff --git a/examples/lgtm-datamesh/services/inventory-service/gen/capstone/inventory/__init__.py b/examples/lgtm-datamesh/services/inventory-service/gen/datamesh/inventory/__init__.py similarity index 100% rename from examples/lgtm-datamesh/services/inventory-service/gen/capstone/inventory/__init__.py rename to examples/lgtm-datamesh/services/inventory-service/gen/datamesh/inventory/__init__.py diff --git a/examples/lgtm-datamesh/services/inventory-service/gen/capstone/inventory/v1/__init__.py b/examples/lgtm-datamesh/services/inventory-service/gen/datamesh/inventory/v1/__init__.py similarity index 100% rename from examples/lgtm-datamesh/services/inventory-service/gen/capstone/inventory/v1/__init__.py rename to examples/lgtm-datamesh/services/inventory-service/gen/datamesh/inventory/v1/__init__.py diff --git a/examples/lgtm-datamesh/services/inventory-service/gen/datamesh/inventory/v1/inventory_pb2.py b/examples/lgtm-datamesh/services/inventory-service/gen/datamesh/inventory/v1/inventory_pb2.py new file mode 100644 index 0000000..ba2ea89 --- /dev/null +++ b/examples/lgtm-datamesh/services/inventory-service/gen/datamesh/inventory/v1/inventory_pb2.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: datamesh/inventory/v1/inventory.proto +# Protobuf Python Version: 7.36.2 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 7, + 36, + 2, + '', + 'datamesh/inventory/v1/inventory.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n%datamesh/inventory/v1/inventory.proto\x12\x15\x64\x61tamesh.inventory.v1\"A\n\x11\x43heckStockRequest\x12\x10\n\x03sku\x18\x01 \x01(\tR\x03sku\x12\x1a\n\x08quantity\x18\x02 \x01(\x05R\x08quantity\"\\\n\x12\x43heckStockResponse\x12\x1c\n\tavailable\x18\x01 \x01(\x08R\tavailable\x12(\n\x10quantity_on_hand\x18\x02 \x01(\x05R\x0equantityOnHand2u\n\x10InventoryService\x12\x61\n\nCheckStock\x12(.datamesh.inventory.v1.CheckStockRequest\x1a).datamesh.inventory.v1.CheckStockResponseb\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'datamesh.inventory.v1.inventory_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_CHECKSTOCKREQUEST']._serialized_start=64 + _globals['_CHECKSTOCKREQUEST']._serialized_end=129 + _globals['_CHECKSTOCKRESPONSE']._serialized_start=131 + _globals['_CHECKSTOCKRESPONSE']._serialized_end=223 + _globals['_INVENTORYSERVICE']._serialized_start=225 + _globals['_INVENTORYSERVICE']._serialized_end=342 +# @@protoc_insertion_point(module_scope) diff --git a/examples/lgtm-datamesh/services/order-service/gen/capstone/inventory/v1/inventory_pb2_grpc.py b/examples/lgtm-datamesh/services/inventory-service/gen/datamesh/inventory/v1/inventory_pb2_grpc.py similarity index 64% rename from examples/lgtm-datamesh/services/order-service/gen/capstone/inventory/v1/inventory_pb2_grpc.py rename to examples/lgtm-datamesh/services/inventory-service/gen/datamesh/inventory/v1/inventory_pb2_grpc.py index b6e3425..99b115c 100644 --- a/examples/lgtm-datamesh/services/order-service/gen/capstone/inventory/v1/inventory_pb2_grpc.py +++ b/examples/lgtm-datamesh/services/inventory-service/gen/datamesh/inventory/v1/inventory_pb2_grpc.py @@ -1,31 +1,11 @@ # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! """Client and server classes corresponding to protobuf-defined services.""" import grpc -import warnings -from capstone.inventory.v1 import inventory_pb2 as capstone_dot_inventory_dot_v1_dot_inventory__pb2 +from datamesh.inventory.v1 import inventory_pb2 as datamesh_dot_inventory_dot_v1_dot_inventory__pb2 -GRPC_GENERATED_VERSION = '1.71.2' -GRPC_VERSION = grpc.__version__ -_version_not_supported = False -try: - from grpc._utilities import first_version_is_lower - _version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION) -except ImportError: - _version_not_supported = True - -if _version_not_supported: - raise RuntimeError( - f'The grpc package installed is at version {GRPC_VERSION},' - + f' but the generated code in capstone/inventory/v1/inventory_pb2_grpc.py depends on' - + f' grpcio>={GRPC_GENERATED_VERSION}.' - + f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}' - + f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.' - ) - - -class InventoryServiceStub(object): +class InventoryServiceStub: """InventoryService answers stock questions for the order flow. r23 ships the single synchronous call order-service needs when placing an order; more RPCs are added as the inventory domain grows. @@ -38,13 +18,13 @@ def __init__(self, channel): channel: A grpc.Channel. """ self.CheckStock = channel.unary_unary( - '/capstone.inventory.v1.InventoryService/CheckStock', - request_serializer=capstone_dot_inventory_dot_v1_dot_inventory__pb2.CheckStockRequest.SerializeToString, - response_deserializer=capstone_dot_inventory_dot_v1_dot_inventory__pb2.CheckStockResponse.FromString, + '/datamesh.inventory.v1.InventoryService/CheckStock', + request_serializer=datamesh_dot_inventory_dot_v1_dot_inventory__pb2.CheckStockRequest.SerializeToString, + response_deserializer=datamesh_dot_inventory_dot_v1_dot_inventory__pb2.CheckStockResponse.FromString, _registered_method=True) -class InventoryServiceServicer(object): +class InventoryServiceServicer: """InventoryService answers stock questions for the order flow. r23 ships the single synchronous call order-service needs when placing an order; more RPCs are added as the inventory domain grows. @@ -63,18 +43,18 @@ def add_InventoryServiceServicer_to_server(servicer, server): rpc_method_handlers = { 'CheckStock': grpc.unary_unary_rpc_method_handler( servicer.CheckStock, - request_deserializer=capstone_dot_inventory_dot_v1_dot_inventory__pb2.CheckStockRequest.FromString, - response_serializer=capstone_dot_inventory_dot_v1_dot_inventory__pb2.CheckStockResponse.SerializeToString, + request_deserializer=datamesh_dot_inventory_dot_v1_dot_inventory__pb2.CheckStockRequest.FromString, + response_serializer=datamesh_dot_inventory_dot_v1_dot_inventory__pb2.CheckStockResponse.SerializeToString, ), } generic_handler = grpc.method_handlers_generic_handler( - 'capstone.inventory.v1.InventoryService', rpc_method_handlers) + 'datamesh.inventory.v1.InventoryService', rpc_method_handlers) server.add_generic_rpc_handlers((generic_handler,)) - server.add_registered_method_handlers('capstone.inventory.v1.InventoryService', rpc_method_handlers) + server.add_registered_method_handlers('datamesh.inventory.v1.InventoryService', rpc_method_handlers) # This class is part of an EXPERIMENTAL API. -class InventoryService(object): +class InventoryService: """InventoryService answers stock questions for the order flow. r23 ships the single synchronous call order-service needs when placing an order; more RPCs are added as the inventory domain grows. @@ -94,9 +74,9 @@ def CheckStock(request, return grpc.experimental.unary_unary( request, target, - '/capstone.inventory.v1.InventoryService/CheckStock', - capstone_dot_inventory_dot_v1_dot_inventory__pb2.CheckStockRequest.SerializeToString, - capstone_dot_inventory_dot_v1_dot_inventory__pb2.CheckStockResponse.FromString, + '/datamesh.inventory.v1.InventoryService/CheckStock', + datamesh_dot_inventory_dot_v1_dot_inventory__pb2.CheckStockRequest.SerializeToString, + datamesh_dot_inventory_dot_v1_dot_inventory__pb2.CheckStockResponse.FromString, options, channel_credentials, insecure, diff --git a/examples/lgtm-datamesh/services/inventory-service/pyproject.toml b/examples/lgtm-datamesh/services/inventory-service/pyproject.toml index 1e935ec..1a90c0b 100644 --- a/examples/lgtm-datamesh/services/inventory-service/pyproject.toml +++ b/examples/lgtm-datamesh/services/inventory-service/pyproject.toml @@ -1,7 +1,7 @@ [tool.poetry] name = "inventory-service" version = "0.2.0" -description = "inventory-service data product for the §17 capstone — REST health + gRPC CheckStock" +description = "inventory-service data product for the §17 final project — REST health + gRPC CheckStock" authors = ["patterncatalyst"] readme = "README.md" package-mode = false diff --git a/examples/lgtm-datamesh/services/notification-service/README.md b/examples/lgtm-datamesh/services/notification-service/README.md index 96759c5..c59ccc2 100644 --- a/examples/lgtm-datamesh/services/notification-service/README.md +++ b/examples/lgtm-datamesh/services/notification-service/README.md @@ -1,6 +1,6 @@ # notification-service -A §17 capstone data product. Owns the `notifications` Postgres schema +A §17 final project data product. Owns the `notifications` Postgres schema (per-service ownership, CAP-003). **r22 scope (skeleton):** the service starts, ensures its schema exists, and @@ -17,8 +17,8 @@ appropriate to the service). ```bash # from examples/lgtm-datamesh/ ./scripts/build-image.sh services/notification-service notification-service v1 -helm upgrade --install notification-service charts/capstone/charts/notification-service -n capstone -kubectl rollout status deployment/notification-service -n capstone --timeout=120s +helm upgrade --install notification-service charts/datamesh/charts/notification-service -n datamesh +kubectl rollout status deployment/notification-service -n datamesh --timeout=120s ``` Or run the health smoke test, which does all of the above and asserts the diff --git a/examples/lgtm-datamesh/services/notification-service/app/config.py b/examples/lgtm-datamesh/services/notification-service/app/config.py index 41fcc0e..dee255d 100644 --- a/examples/lgtm-datamesh/services/notification-service/app/config.py +++ b/examples/lgtm-datamesh/services/notification-service/app/config.py @@ -11,15 +11,15 @@ class Settings(BaseSettings): pg_host: str = "127.0.0.1" pg_port: int = 5432 - pg_user: str = "capstone_app" + pg_user: str = "datamesh_app" pg_password: str = "changeme" - pg_database: str = "capstone" + pg_database: str = "datamesh" host: str = "0.0.0.0" port: int = 8080 # Kafka (r25). Consumes order.placed events. - kafka_bootstrap: str = "capstone-kafka-kafka-bootstrap:9092" + kafka_bootstrap: str = "datamesh-kafka-kafka-bootstrap:9092" kafka_order_topic: str = "order-placed" kafka_group: str = "notification-service" diff --git a/examples/lgtm-datamesh/services/notification-service/app/main.py b/examples/lgtm-datamesh/services/notification-service/app/main.py index 9a241af..b245c52 100644 --- a/examples/lgtm-datamesh/services/notification-service/app/main.py +++ b/examples/lgtm-datamesh/services/notification-service/app/main.py @@ -1,4 +1,4 @@ -"""notification-service — a §17 capstone data product (Kafka consumer). +"""notification-service — a §17 final project data product (Kafka consumer). Consumes `order.placed` events from Kafka (its designed role — a consumer-only data product) and persists them to its `notifications` table. @@ -37,7 +37,7 @@ async def lifespan(app: FastAPI): app = FastAPI( title="notification-service", version="0.3.0", - description="notification-service data product for the §17 capstone — consumes and persists order events.", + description="notification-service data product for the §17 final project — consumes and persists order events.", lifespan=lifespan, ) diff --git a/examples/lgtm-datamesh/services/notification-service/pyproject.toml b/examples/lgtm-datamesh/services/notification-service/pyproject.toml index 44a65cd..c8dace1 100644 --- a/examples/lgtm-datamesh/services/notification-service/pyproject.toml +++ b/examples/lgtm-datamesh/services/notification-service/pyproject.toml @@ -1,7 +1,7 @@ [tool.poetry] name = "notification-service" version = "0.4.0" -description = "notification-service data product for the §17 capstone — health skeleton (domain surface added in later iterations)" +description = "notification-service data product for the §17 final project — health skeleton (domain surface added in later iterations)" authors = ["patterncatalyst"] readme = "README.md" package-mode = false diff --git a/examples/lgtm-datamesh/services/order-service/Containerfile b/examples/lgtm-datamesh/services/order-service/Containerfile index 76a4630..83b3d59 100644 --- a/examples/lgtm-datamesh/services/order-service/Containerfile +++ b/examples/lgtm-datamesh/services/order-service/Containerfile @@ -51,7 +51,7 @@ WORKDIR /opt/app-root/src # unambiguous. Then the application code. COPY --from=builder --chown=1001:0 /opt/venv /opt/venv COPY --chown=1001:0 app/ ./app/ -# Committed gRPC stubs (capstone.inventory.v1). app/ adds this to sys.path. +# Committed gRPC stubs (datamesh.inventory.v1). app/ adds this to sys.path. COPY --chown=1001:0 gen/ ./gen/ # Canonical Avro schema this service owns and registers (r25b). app/events.py # loads it from ../schemas/order-placed.avsc relative to the app package. diff --git a/examples/lgtm-datamesh/services/order-service/README.md b/examples/lgtm-datamesh/services/order-service/README.md index 8338528..e2a4ade 100644 --- a/examples/lgtm-datamesh/services/order-service/README.md +++ b/examples/lgtm-datamesh/services/order-service/README.md @@ -1,13 +1,13 @@ # order-service -The first data product of the §17 capstone, and the **template +The first data product of the §17 final project, and the **template every other service follows**. r21 scope: REST + Postgres only. gRPC (r23), GraphQL (r24), and Kafka event publication (r25) are added in later iterations. ## What it owns -The `orders` schema in the shared capstone Postgres database +The `orders` schema in the shared datamesh Postgres database (CAP-003). order-service is the only service that writes this schema — that's the per-service data-ownership boundary. @@ -37,7 +37,7 @@ To run the service locally against a local Postgres container ```bash # In one terminal: a throwaway Postgres on 127.0.0.1:5432 docker run --rm -p 127.0.0.1:5432:5432 \ - -e POSTGRES_USER=capstone_app -e POSTGRES_PASSWORD=changeme -e POSTGRES_DB=capstone \ + -e POSTGRES_USER=datamesh_app -e POSTGRES_PASSWORD=changeme -e POSTGRES_DB=datamesh \ postgres:16 # In another: run with the default connection settings (127.0.0.1:5432) @@ -47,10 +47,10 @@ poetry run uvicorn app.main:app --port 8080 ## Build The Containerfile is a UBI 10 Python 3.14 (`python-314-minimal`) multi-stage build -(CAP-005). Build it into the capstone minikube profile: +(CAP-005). Build it into the datamesh minikube profile: ```bash -minikube image build -p capstone -t order-service:v1 services/order-service +minikube image build -p datamesh -t order-service:v1 services/order-service ``` **Recommended:** commit `poetry.lock` for reproducible builds. @@ -85,7 +85,7 @@ follows this same shape: - UBI 10 multi-stage `Containerfile` - `app/{config,db,models,schemas,main}.py` - own schema in the shared Postgres -- helm subchart under `charts/capstone/charts//` +- helm subchart under `charts/datamesh/charts//` - `/health` + `/healthz` probes r22 parallelizes this across the remaining four services. diff --git a/examples/lgtm-datamesh/services/order-service/app/config.py b/examples/lgtm-datamesh/services/order-service/app/config.py index a0f673a..ec56c31 100644 --- a/examples/lgtm-datamesh/services/order-service/app/config.py +++ b/examples/lgtm-datamesh/services/order-service/app/config.py @@ -20,9 +20,9 @@ class Settings(BaseSettings): pg_host: str = "127.0.0.1" pg_port: int = 5432 - pg_user: str = "capstone_app" + pg_user: str = "datamesh_app" pg_password: str = "changeme" - pg_database: str = "capstone" + pg_database: str = "datamesh" host: str = "0.0.0.0" port: int = 8080 @@ -30,7 +30,7 @@ class Settings(BaseSettings): inventory_grpc_addr: str = "inventory-service:50051" # Kafka (r25). order-service publishes order.placed events here. - kafka_bootstrap: str = "capstone-kafka-kafka-bootstrap:9092" + kafka_bootstrap: str = "datamesh-kafka-kafka-bootstrap:9092" kafka_order_topic: str = "order-placed" # Apicurio schema registry (r25b). order.placed is registered + serialized diff --git a/examples/lgtm-datamesh/services/order-service/app/inventory_client.py b/examples/lgtm-datamesh/services/order-service/app/inventory_client.py index 3a6e247..22e7f70 100644 --- a/examples/lgtm-datamesh/services/order-service/app/inventory_client.py +++ b/examples/lgtm-datamesh/services/order-service/app/inventory_client.py @@ -2,7 +2,7 @@ Wraps the InventoryService.CheckStock call. The generated stubs live in the service's committed `gen/` tree (option b); we add it to sys.path so -`capstone.inventory.v1` is importable in the container and locally. +`datamesh.inventory.v1` is importable in the container and locally. This is the order flow's one synchronous cross-service dependency: before an order is persisted, order-service asks inventory-service whether the SKU is @@ -20,7 +20,7 @@ sys.path.insert(0, _GEN) import grpc # noqa: E402 -from capstone.inventory.v1 import ( # noqa: E402 +from datamesh.inventory.v1 import ( # noqa: E402 inventory_pb2, inventory_pb2_grpc, ) diff --git a/examples/lgtm-datamesh/services/order-service/app/main.py b/examples/lgtm-datamesh/services/order-service/app/main.py index 04e5edd..df55a68 100644 --- a/examples/lgtm-datamesh/services/order-service/app/main.py +++ b/examples/lgtm-datamesh/services/order-service/app/main.py @@ -1,4 +1,4 @@ -"""order-service — the §17 capstone's first data product. +"""order-service — the §17 final project's first data product. r21: REST + Postgres. r23: gRPC stock check against inventory before persisting. r25: publishes an `order.placed` event to Kafka after persisting, @@ -49,7 +49,7 @@ async def lifespan(app: FastAPI): app = FastAPI( title="order-service", version="0.3.0", - description="Order data product for the §17 capstone data mesh.", + description="Order data product for the §17 final project data mesh.", lifespan=lifespan, ) diff --git a/examples/lgtm-datamesh/services/order-service/gen/capstone/inventory/v1/inventory_pb2.py b/examples/lgtm-datamesh/services/order-service/gen/capstone/inventory/v1/inventory_pb2.py deleted file mode 100644 index 475bbe1..0000000 --- a/examples/lgtm-datamesh/services/order-service/gen/capstone/inventory/v1/inventory_pb2.py +++ /dev/null @@ -1,40 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# NO CHECKED-IN PROTOBUF GENCODE -# source: capstone/inventory/v1/inventory.proto -# Protobuf Python Version: 5.29.0 -"""Generated protocol buffer code.""" -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import runtime_version as _runtime_version -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder -_runtime_version.ValidateProtobufRuntimeVersion( - _runtime_version.Domain.PUBLIC, - 5, - 29, - 0, - '', - 'capstone/inventory/v1/inventory.proto' -) -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n%capstone/inventory/v1/inventory.proto\x12\x15\x63\x61pstone.inventory.v1\"2\n\x11\x43heckStockRequest\x12\x0b\n\x03sku\x18\x01 \x01(\t\x12\x10\n\x08quantity\x18\x02 \x01(\x05\"A\n\x12\x43heckStockResponse\x12\x11\n\tavailable\x18\x01 \x01(\x08\x12\x18\n\x10quantity_on_hand\x18\x02 \x01(\x05\x32u\n\x10InventoryService\x12\x61\n\nCheckStock\x12(.capstone.inventory.v1.CheckStockRequest\x1a).capstone.inventory.v1.CheckStockResponseb\x06proto3') - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'capstone.inventory.v1.inventory_pb2', _globals) -if not _descriptor._USE_C_DESCRIPTORS: - DESCRIPTOR._loaded_options = None - _globals['_CHECKSTOCKREQUEST']._serialized_start=64 - _globals['_CHECKSTOCKREQUEST']._serialized_end=114 - _globals['_CHECKSTOCKRESPONSE']._serialized_start=116 - _globals['_CHECKSTOCKRESPONSE']._serialized_end=181 - _globals['_INVENTORYSERVICE']._serialized_start=183 - _globals['_INVENTORYSERVICE']._serialized_end=300 -# @@protoc_insertion_point(module_scope) diff --git a/examples/lgtm-datamesh/services/order-service/gen/capstone/__init__.py b/examples/lgtm-datamesh/services/order-service/gen/datamesh/__init__.py similarity index 100% rename from examples/lgtm-datamesh/services/order-service/gen/capstone/__init__.py rename to examples/lgtm-datamesh/services/order-service/gen/datamesh/__init__.py diff --git a/examples/lgtm-datamesh/services/order-service/gen/capstone/inventory/__init__.py b/examples/lgtm-datamesh/services/order-service/gen/datamesh/inventory/__init__.py similarity index 100% rename from examples/lgtm-datamesh/services/order-service/gen/capstone/inventory/__init__.py rename to examples/lgtm-datamesh/services/order-service/gen/datamesh/inventory/__init__.py diff --git a/examples/lgtm-datamesh/services/order-service/gen/capstone/inventory/v1/__init__.py b/examples/lgtm-datamesh/services/order-service/gen/datamesh/inventory/v1/__init__.py similarity index 100% rename from examples/lgtm-datamesh/services/order-service/gen/capstone/inventory/v1/__init__.py rename to examples/lgtm-datamesh/services/order-service/gen/datamesh/inventory/v1/__init__.py diff --git a/examples/lgtm-datamesh/services/order-service/gen/datamesh/inventory/v1/inventory_pb2.py b/examples/lgtm-datamesh/services/order-service/gen/datamesh/inventory/v1/inventory_pb2.py new file mode 100644 index 0000000..ba2ea89 --- /dev/null +++ b/examples/lgtm-datamesh/services/order-service/gen/datamesh/inventory/v1/inventory_pb2.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: datamesh/inventory/v1/inventory.proto +# Protobuf Python Version: 7.36.2 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 7, + 36, + 2, + '', + 'datamesh/inventory/v1/inventory.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n%datamesh/inventory/v1/inventory.proto\x12\x15\x64\x61tamesh.inventory.v1\"A\n\x11\x43heckStockRequest\x12\x10\n\x03sku\x18\x01 \x01(\tR\x03sku\x12\x1a\n\x08quantity\x18\x02 \x01(\x05R\x08quantity\"\\\n\x12\x43heckStockResponse\x12\x1c\n\tavailable\x18\x01 \x01(\x08R\tavailable\x12(\n\x10quantity_on_hand\x18\x02 \x01(\x05R\x0equantityOnHand2u\n\x10InventoryService\x12\x61\n\nCheckStock\x12(.datamesh.inventory.v1.CheckStockRequest\x1a).datamesh.inventory.v1.CheckStockResponseb\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'datamesh.inventory.v1.inventory_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_CHECKSTOCKREQUEST']._serialized_start=64 + _globals['_CHECKSTOCKREQUEST']._serialized_end=129 + _globals['_CHECKSTOCKRESPONSE']._serialized_start=131 + _globals['_CHECKSTOCKRESPONSE']._serialized_end=223 + _globals['_INVENTORYSERVICE']._serialized_start=225 + _globals['_INVENTORYSERVICE']._serialized_end=342 +# @@protoc_insertion_point(module_scope) diff --git a/examples/lgtm-datamesh/services/graphql-gateway/gen/capstone/inventory/v1/inventory_pb2_grpc.py b/examples/lgtm-datamesh/services/order-service/gen/datamesh/inventory/v1/inventory_pb2_grpc.py similarity index 64% rename from examples/lgtm-datamesh/services/graphql-gateway/gen/capstone/inventory/v1/inventory_pb2_grpc.py rename to examples/lgtm-datamesh/services/order-service/gen/datamesh/inventory/v1/inventory_pb2_grpc.py index b6e3425..99b115c 100644 --- a/examples/lgtm-datamesh/services/graphql-gateway/gen/capstone/inventory/v1/inventory_pb2_grpc.py +++ b/examples/lgtm-datamesh/services/order-service/gen/datamesh/inventory/v1/inventory_pb2_grpc.py @@ -1,31 +1,11 @@ # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! """Client and server classes corresponding to protobuf-defined services.""" import grpc -import warnings -from capstone.inventory.v1 import inventory_pb2 as capstone_dot_inventory_dot_v1_dot_inventory__pb2 +from datamesh.inventory.v1 import inventory_pb2 as datamesh_dot_inventory_dot_v1_dot_inventory__pb2 -GRPC_GENERATED_VERSION = '1.71.2' -GRPC_VERSION = grpc.__version__ -_version_not_supported = False -try: - from grpc._utilities import first_version_is_lower - _version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION) -except ImportError: - _version_not_supported = True - -if _version_not_supported: - raise RuntimeError( - f'The grpc package installed is at version {GRPC_VERSION},' - + f' but the generated code in capstone/inventory/v1/inventory_pb2_grpc.py depends on' - + f' grpcio>={GRPC_GENERATED_VERSION}.' - + f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}' - + f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.' - ) - - -class InventoryServiceStub(object): +class InventoryServiceStub: """InventoryService answers stock questions for the order flow. r23 ships the single synchronous call order-service needs when placing an order; more RPCs are added as the inventory domain grows. @@ -38,13 +18,13 @@ def __init__(self, channel): channel: A grpc.Channel. """ self.CheckStock = channel.unary_unary( - '/capstone.inventory.v1.InventoryService/CheckStock', - request_serializer=capstone_dot_inventory_dot_v1_dot_inventory__pb2.CheckStockRequest.SerializeToString, - response_deserializer=capstone_dot_inventory_dot_v1_dot_inventory__pb2.CheckStockResponse.FromString, + '/datamesh.inventory.v1.InventoryService/CheckStock', + request_serializer=datamesh_dot_inventory_dot_v1_dot_inventory__pb2.CheckStockRequest.SerializeToString, + response_deserializer=datamesh_dot_inventory_dot_v1_dot_inventory__pb2.CheckStockResponse.FromString, _registered_method=True) -class InventoryServiceServicer(object): +class InventoryServiceServicer: """InventoryService answers stock questions for the order flow. r23 ships the single synchronous call order-service needs when placing an order; more RPCs are added as the inventory domain grows. @@ -63,18 +43,18 @@ def add_InventoryServiceServicer_to_server(servicer, server): rpc_method_handlers = { 'CheckStock': grpc.unary_unary_rpc_method_handler( servicer.CheckStock, - request_deserializer=capstone_dot_inventory_dot_v1_dot_inventory__pb2.CheckStockRequest.FromString, - response_serializer=capstone_dot_inventory_dot_v1_dot_inventory__pb2.CheckStockResponse.SerializeToString, + request_deserializer=datamesh_dot_inventory_dot_v1_dot_inventory__pb2.CheckStockRequest.FromString, + response_serializer=datamesh_dot_inventory_dot_v1_dot_inventory__pb2.CheckStockResponse.SerializeToString, ), } generic_handler = grpc.method_handlers_generic_handler( - 'capstone.inventory.v1.InventoryService', rpc_method_handlers) + 'datamesh.inventory.v1.InventoryService', rpc_method_handlers) server.add_generic_rpc_handlers((generic_handler,)) - server.add_registered_method_handlers('capstone.inventory.v1.InventoryService', rpc_method_handlers) + server.add_registered_method_handlers('datamesh.inventory.v1.InventoryService', rpc_method_handlers) # This class is part of an EXPERIMENTAL API. -class InventoryService(object): +class InventoryService: """InventoryService answers stock questions for the order flow. r23 ships the single synchronous call order-service needs when placing an order; more RPCs are added as the inventory domain grows. @@ -94,9 +74,9 @@ def CheckStock(request, return grpc.experimental.unary_unary( request, target, - '/capstone.inventory.v1.InventoryService/CheckStock', - capstone_dot_inventory_dot_v1_dot_inventory__pb2.CheckStockRequest.SerializeToString, - capstone_dot_inventory_dot_v1_dot_inventory__pb2.CheckStockResponse.FromString, + '/datamesh.inventory.v1.InventoryService/CheckStock', + datamesh_dot_inventory_dot_v1_dot_inventory__pb2.CheckStockRequest.SerializeToString, + datamesh_dot_inventory_dot_v1_dot_inventory__pb2.CheckStockResponse.FromString, options, channel_credentials, insecure, diff --git a/examples/lgtm-datamesh/services/order-service/pyproject.toml b/examples/lgtm-datamesh/services/order-service/pyproject.toml index b246f94..6b70750 100644 --- a/examples/lgtm-datamesh/services/order-service/pyproject.toml +++ b/examples/lgtm-datamesh/services/order-service/pyproject.toml @@ -1,7 +1,7 @@ [tool.poetry] name = "order-service" version = "0.4.0" -description = "Order-service data product for the §17 capstone — REST + Postgres + gRPC client to inventory (GraphQL, Kafka added later)" +description = "Order-service data product for the §17 final project — REST + Postgres + gRPC client to inventory (GraphQL, Kafka added later)" authors = ["patterncatalyst"] readme = "README.md" package-mode = false diff --git a/examples/lgtm-datamesh/services/order-service/schemas/order-placed.avsc b/examples/lgtm-datamesh/services/order-service/schemas/order-placed.avsc index 62d83f5..5fa160f 100644 --- a/examples/lgtm-datamesh/services/order-service/schemas/order-placed.avsc +++ b/examples/lgtm-datamesh/services/order-service/schemas/order-placed.avsc @@ -1,7 +1,7 @@ { "type": "record", "name": "OrderPlaced", - "namespace": "capstone.order.v1", + "namespace": "datamesh.order.v1", "doc": "Emitted by order-service after an order is durably persisted. The runtime contract for the order-placed Kafka topic (CAP-018, CAP-019).", "fields": [ { "name": "event_type", "type": "string", "doc": "Always 'order.placed'." }, diff --git a/examples/lgtm-datamesh/services/payment-service/README.md b/examples/lgtm-datamesh/services/payment-service/README.md index 12e3fad..c62bc42 100644 --- a/examples/lgtm-datamesh/services/payment-service/README.md +++ b/examples/lgtm-datamesh/services/payment-service/README.md @@ -1,6 +1,6 @@ # payment-service -A §17 capstone data product. Owns the `payments` Postgres schema +A §17 final project data product. Owns the `payments` Postgres schema (per-service ownership, CAP-003). **r22 scope (skeleton):** the service starts, ensures its schema exists, and @@ -17,8 +17,8 @@ appropriate to the service). ```bash # from examples/lgtm-datamesh/ ./scripts/build-image.sh services/payment-service payment-service v1 -helm upgrade --install payment-service charts/capstone/charts/payment-service -n capstone -kubectl rollout status deployment/payment-service -n capstone --timeout=120s +helm upgrade --install payment-service charts/datamesh/charts/payment-service -n datamesh +kubectl rollout status deployment/payment-service -n datamesh --timeout=120s ``` Or run the health smoke test, which does all of the above and asserts the diff --git a/examples/lgtm-datamesh/services/payment-service/app/config.py b/examples/lgtm-datamesh/services/payment-service/app/config.py index 3f1adc5..eee2f37 100644 --- a/examples/lgtm-datamesh/services/payment-service/app/config.py +++ b/examples/lgtm-datamesh/services/payment-service/app/config.py @@ -1,8 +1,8 @@ """Configuration for payment-service, sourced from environment variables. In-cluster, the Postgres connection comes from the CloudNativePG-generated -Secret (`capstone-postgres-app`), surfaced as env vars by the helm subchart. -Locally, the defaults allow running against a local Postgres (e.g. `docker run --rm -p 127.0.0.1:5432:5432 -e POSTGRES_USER=capstone_app -e POSTGRES_PASSWORD=changeme -e POSTGRES_DB=capstone postgres:16`). +Secret (`datamesh-postgres-app`), surfaced as env vars by the helm subchart. +Locally, the defaults allow running against a local Postgres (e.g. `docker run --rm -p 127.0.0.1:5432:5432 -e POSTGRES_USER=datamesh_app -e POSTGRES_PASSWORD=changeme -e POSTGRES_DB=datamesh postgres:16`). """ from pydantic_settings import BaseSettings, SettingsConfigDict @@ -18,9 +18,9 @@ class Settings(BaseSettings): # Postgres connection. In-cluster these come from the CNPG app Secret. pg_host: str = "127.0.0.1" pg_port: int = 5432 - pg_user: str = "capstone_app" + pg_user: str = "datamesh_app" pg_password: str = "changeme" - pg_database: str = "capstone" + pg_database: str = "datamesh" # Server host: str = "0.0.0.0" diff --git a/examples/lgtm-datamesh/services/payment-service/app/main.py b/examples/lgtm-datamesh/services/payment-service/app/main.py index 5c14cd7..3153e31 100644 --- a/examples/lgtm-datamesh/services/payment-service/app/main.py +++ b/examples/lgtm-datamesh/services/payment-service/app/main.py @@ -1,4 +1,4 @@ -"""payment-service — a §17 capstone data product (r22 skeleton). +"""payment-service — a §17 final project data product (r22 skeleton). r22 scope: the service stands up, connects to its Postgres schema (`payments`), and serves health probes. Its domain surface (REST/gRPC/ @@ -32,7 +32,7 @@ async def lifespan(app: FastAPI): app = FastAPI( title="payment-service", version="0.1.0", - description="payment-service data product for the §17 capstone data mesh (skeleton).", + description="payment-service data product for the §17 final project data mesh (skeleton).", lifespan=lifespan, ) diff --git a/examples/lgtm-datamesh/services/payment-service/pyproject.toml b/examples/lgtm-datamesh/services/payment-service/pyproject.toml index f805084..9885d98 100644 --- a/examples/lgtm-datamesh/services/payment-service/pyproject.toml +++ b/examples/lgtm-datamesh/services/payment-service/pyproject.toml @@ -1,7 +1,7 @@ [tool.poetry] name = "payment-service" version = "0.1.0" -description = "payment-service data product for the §17 capstone — health skeleton (domain surface added in later iterations)" +description = "payment-service data product for the §17 final project — health skeleton (domain surface added in later iterations)" authors = ["patterncatalyst"] readme = "README.md" package-mode = false diff --git a/examples/lgtm-datamesh/services/review-service/README.md b/examples/lgtm-datamesh/services/review-service/README.md index 0cba996..dc30637 100644 --- a/examples/lgtm-datamesh/services/review-service/README.md +++ b/examples/lgtm-datamesh/services/review-service/README.md @@ -1,6 +1,6 @@ # review-service -A §17 capstone data product. Owns the `reviews` Postgres schema +A §17 final project data product. Owns the `reviews` Postgres schema (per-service ownership, CAP-003). **r22 scope (skeleton):** the service starts, ensures its schema exists, and @@ -17,8 +17,8 @@ appropriate to the service). ```bash # from examples/lgtm-datamesh/ ./scripts/build-image.sh services/review-service review-service v1 -helm upgrade --install review-service charts/capstone/charts/review-service -n capstone -kubectl rollout status deployment/review-service -n capstone --timeout=120s +helm upgrade --install review-service charts/datamesh/charts/review-service -n datamesh +kubectl rollout status deployment/review-service -n datamesh --timeout=120s ``` Or run the health smoke test, which does all of the above and asserts the diff --git a/examples/lgtm-datamesh/services/review-service/app/config.py b/examples/lgtm-datamesh/services/review-service/app/config.py index 741fb29..05cd901 100644 --- a/examples/lgtm-datamesh/services/review-service/app/config.py +++ b/examples/lgtm-datamesh/services/review-service/app/config.py @@ -1,8 +1,8 @@ """Configuration for review-service, sourced from environment variables. In-cluster, the Postgres connection comes from the CloudNativePG-generated -Secret (`capstone-postgres-app`), surfaced as env vars by the helm subchart. -Locally, the defaults allow running against a local Postgres (e.g. `docker run --rm -p 127.0.0.1:5432:5432 -e POSTGRES_USER=capstone_app -e POSTGRES_PASSWORD=changeme -e POSTGRES_DB=capstone postgres:16`). +Secret (`datamesh-postgres-app`), surfaced as env vars by the helm subchart. +Locally, the defaults allow running against a local Postgres (e.g. `docker run --rm -p 127.0.0.1:5432:5432 -e POSTGRES_USER=datamesh_app -e POSTGRES_PASSWORD=changeme -e POSTGRES_DB=datamesh postgres:16`). """ from pydantic_settings import BaseSettings, SettingsConfigDict @@ -18,9 +18,9 @@ class Settings(BaseSettings): # Postgres connection. In-cluster these come from the CNPG app Secret. pg_host: str = "127.0.0.1" pg_port: int = 5432 - pg_user: str = "capstone_app" + pg_user: str = "datamesh_app" pg_password: str = "changeme" - pg_database: str = "capstone" + pg_database: str = "datamesh" # Server host: str = "0.0.0.0" diff --git a/examples/lgtm-datamesh/services/review-service/app/main.py b/examples/lgtm-datamesh/services/review-service/app/main.py index adfbf69..f723fed 100644 --- a/examples/lgtm-datamesh/services/review-service/app/main.py +++ b/examples/lgtm-datamesh/services/review-service/app/main.py @@ -1,4 +1,4 @@ -"""review-service — a §17 capstone data product: product reviews/ratings. +"""review-service — a §17 final project data product: product reviews/ratings. A minimal REST data product, added (and backed out) as a Phase A demonstration of the add-a-data-product-to-the-mesh workflow: stand up the product, publish @@ -46,7 +46,7 @@ async def lifespan(app: FastAPI): app = FastAPI( title="review-service", version="1.0.0", - description="review-service data product for the §17 capstone data mesh: product reviews/ratings.", + description="review-service data product for the §17 final project data mesh: product reviews/ratings.", lifespan=lifespan, ) diff --git a/examples/lgtm-datamesh/services/review-service/pyproject.toml b/examples/lgtm-datamesh/services/review-service/pyproject.toml index 554d388..b26e600 100644 --- a/examples/lgtm-datamesh/services/review-service/pyproject.toml +++ b/examples/lgtm-datamesh/services/review-service/pyproject.toml @@ -1,7 +1,7 @@ [tool.poetry] name = "review-service" version = "0.1.0" -description = "review-service data product for the §17 capstone — health skeleton (domain surface added in later iterations)" +description = "review-service data product for the §17 final project — health skeleton (domain surface added in later iterations)" authors = ["patterncatalyst"] readme = "README.md" package-mode = false diff --git a/examples/lgtm-datamesh/services/shipping-service/README.md b/examples/lgtm-datamesh/services/shipping-service/README.md index 58e1419..8a710c9 100644 --- a/examples/lgtm-datamesh/services/shipping-service/README.md +++ b/examples/lgtm-datamesh/services/shipping-service/README.md @@ -1,6 +1,6 @@ # shipping-service -A §17 capstone data product. Owns the `shipping` Postgres schema +A §17 final project data product. Owns the `shipping` Postgres schema (per-service ownership, CAP-003). **r22 scope (skeleton):** the service starts, ensures its schema exists, and @@ -17,8 +17,8 @@ appropriate to the service). ```bash # from examples/lgtm-datamesh/ ./scripts/build-image.sh services/shipping-service shipping-service v1 -helm upgrade --install shipping-service charts/capstone/charts/shipping-service -n capstone -kubectl rollout status deployment/shipping-service -n capstone --timeout=120s +helm upgrade --install shipping-service charts/datamesh/charts/shipping-service -n datamesh +kubectl rollout status deployment/shipping-service -n datamesh --timeout=120s ``` Or run the health smoke test, which does all of the above and asserts the diff --git a/examples/lgtm-datamesh/services/shipping-service/app/config.py b/examples/lgtm-datamesh/services/shipping-service/app/config.py index 1893e82..284e93e 100644 --- a/examples/lgtm-datamesh/services/shipping-service/app/config.py +++ b/examples/lgtm-datamesh/services/shipping-service/app/config.py @@ -1,8 +1,8 @@ """Configuration for shipping-service, sourced from environment variables. In-cluster, the Postgres connection comes from the CloudNativePG-generated -Secret (`capstone-postgres-app`), surfaced as env vars by the helm subchart. -Locally, the defaults allow running against a local Postgres (e.g. `docker run --rm -p 127.0.0.1:5432:5432 -e POSTGRES_USER=capstone_app -e POSTGRES_PASSWORD=changeme -e POSTGRES_DB=capstone postgres:16`). +Secret (`datamesh-postgres-app`), surfaced as env vars by the helm subchart. +Locally, the defaults allow running against a local Postgres (e.g. `docker run --rm -p 127.0.0.1:5432:5432 -e POSTGRES_USER=datamesh_app -e POSTGRES_PASSWORD=changeme -e POSTGRES_DB=datamesh postgres:16`). """ from pydantic_settings import BaseSettings, SettingsConfigDict @@ -18,9 +18,9 @@ class Settings(BaseSettings): # Postgres connection. In-cluster these come from the CNPG app Secret. pg_host: str = "127.0.0.1" pg_port: int = 5432 - pg_user: str = "capstone_app" + pg_user: str = "datamesh_app" pg_password: str = "changeme" - pg_database: str = "capstone" + pg_database: str = "datamesh" # Server host: str = "0.0.0.0" diff --git a/examples/lgtm-datamesh/services/shipping-service/app/main.py b/examples/lgtm-datamesh/services/shipping-service/app/main.py index a68c943..c03577a 100644 --- a/examples/lgtm-datamesh/services/shipping-service/app/main.py +++ b/examples/lgtm-datamesh/services/shipping-service/app/main.py @@ -1,4 +1,4 @@ -"""shipping-service — a §17 capstone data product (r22 skeleton). +"""shipping-service — a §17 final project data product (r22 skeleton). r22 scope: the service stands up, connects to its Postgres schema (`shipping`), and serves health probes. Its domain surface (REST/gRPC/ @@ -32,7 +32,7 @@ async def lifespan(app: FastAPI): app = FastAPI( title="shipping-service", version="0.1.0", - description="shipping-service data product for the §17 capstone data mesh (skeleton).", + description="shipping-service data product for the §17 final project data mesh (skeleton).", lifespan=lifespan, ) diff --git a/examples/lgtm-datamesh/services/shipping-service/pyproject.toml b/examples/lgtm-datamesh/services/shipping-service/pyproject.toml index ff58784..b9b7531 100644 --- a/examples/lgtm-datamesh/services/shipping-service/pyproject.toml +++ b/examples/lgtm-datamesh/services/shipping-service/pyproject.toml @@ -1,7 +1,7 @@ [tool.poetry] name = "shipping-service" version = "0.1.0" -description = "shipping-service data product for the §17 capstone — health skeleton (domain surface added in later iterations)" +description = "shipping-service data product for the §17 final project — health skeleton (domain surface added in later iterations)" authors = ["patterncatalyst"] readme = "README.md" package-mode = false diff --git a/onboarding/GETTING-STARTED.md b/onboarding/GETTING-STARTED.md index 168c886..158145f 100644 --- a/onboarding/GETTING-STARTED.md +++ b/onboarding/GETTING-STARTED.md @@ -79,7 +79,7 @@ the workload. What's verified to work end to end: - **Host:** Fedora 44 with native Docker Engine (docker-ce) as the container runtime -- **Memory:** 64 GB RAM (the `capstone` minikube profile uses 24 GB; the +- **Memory:** 64 GB RAM (the `datamesh` minikube profile uses 24 GB; the rest is host headroom for IDEs, browsers, and host services) - **Disk:** 1 TB total, with about 100 GB free under the Docker data root (/var/lib/docker) for image cache and persistent volumes @@ -106,7 +106,7 @@ or an engine that cannot be given that much memory. ```bash cd examples/lgtm-datamesh -./scripts/bootstrap-capstone.sh +./scripts/bootstrap-datamesh.sh ``` Ten steps; ~25 minutes on a warm cache, longer on the first run while @@ -147,7 +147,7 @@ The high-level map of the repo: document the current demo state including any deferred upstream issues. - **`_plans/`** is decision-log and reconciliation tracking. Active decisions live in `_plans/decisions.md` (DRA-001 forward); historical - decisions from when this lived as the §17 capstone of + decisions from when this lived as the §17 final project of `minikube-on-fedora` are preserved at `_plans/archive/` for the audit trail. @@ -163,6 +163,6 @@ runnable examples that match existing patterns are welcome as direct PRs. If you're proposing a non-minikube runtime (e.g. EKS or OpenShift local), the most useful contribution is a sibling to -`examples/lgtm-datamesh/scripts/bootstrap-capstone.sh` that does the +`examples/lgtm-datamesh/scripts/bootstrap-datamesh.sh` that does the runtime-specific setup, plus a `README.md` documenting any deltas. The existing bootstrap can serve as the template. diff --git a/onboarding/LESSONS-LEARNED.md b/onboarding/LESSONS-LEARNED.md index 6e0d86c..7d21c10 100644 --- a/onboarding/LESSONS-LEARNED.md +++ b/onboarding/LESSONS-LEARNED.md @@ -1,7 +1,7 @@ # Lessons learned This document distills the hard-won lessons from building this reference, -drawn from the decisions in `_plans/archive/capstone-decisions.md` +drawn from the decisions in `_plans/archive/final-project-decisions.md` (CAP-001 through CAP-047) and from the July 2026 smoke-test campaign that brought the full stack up from nothing on a fresh Fedora 44 host and ran every demo script to green (commits `5403d06`–`e22b318`). It's organised @@ -275,7 +275,7 @@ long-lived dev machine would surface: registry addon pinned a `kube-registry-proxy` digest that no longer existed on gcr.io, so the addon could never come up on that minikube version regardless of configuration. The fix then was upgrading minikube, not - debugging the cluster. The capstone no longer uses the registry addon (images + debugging the cluster. The final project no longer uses the registry addon (images are loaded with `minikube image load`), but the lesson stands for any addon that pins an image by digest. @@ -290,7 +290,7 @@ same machine can't expose. On the Docker-driver profile, every `POST /orders` failed with `503 inventory-service unreachable ... DEADLINE_EXCEEDED`, although inventory answered its own `CheckStock` in 10 ms. Timing the call from the order pod isolated it: `inventory-service:50051` took -3.01 s, while the fully qualified `inventory-service.capstone.svc.cluster.local:50051` +3.01 s, while the fully qualified `inventory-service.datamesh.svc.cluster.local:50051` took 0.01 s, and `getaddrinfo` resolved the short name instantly. gRPC Python resolves names with its bundled c-ares resolver, which walks the search list itself and waited about 3 s on one lookup, exactly the client's 3 s deadline. `GRPC_DNS_RESOLVER=native` @@ -316,15 +316,15 @@ does to the components that talk to it, not only to the component itself. ### Pushing to a loopback registry only works on a native engine -A push to a registry on the host's loopback port is made by the container engine's daemon, so the address is resolved from the daemon's network namespace. On a native Docker Engine that is the host. On a VM-based engine (Docker Desktop) the daemon runs inside a VM whose `127.0.0.1` is not the host's, and the push fails with `dial tcp [::1]:5000: i/o timeout`. `minikube image load` hands the image to the profile directly and works with any engine, which is why the capstone uses it and runs no registry. +A push to a registry on the host's loopback port is made by the container engine's daemon, so the address is resolved from the daemon's network namespace. On a native Docker Engine that is the host. On a VM-based engine (Docker Desktop) the daemon runs inside a VM whose `127.0.0.1` is not the host's, and the push fails with `dial tcp [::1]:5000: i/o timeout`. `minikube image load` hands the image to the profile directly and works with any engine, which is why the final project uses it and runs no registry. ### Local images: `imagePullPolicy: Never` plus a restart on rebuild -Images loaded with `minikube image load` are tagged `capstone/:v1`, and the charts set `imagePullPolicy: Never`. A missing image then fails fast with `ErrImageNeverPull` instead of falling through to a Docker Hub lookup that can never succeed. The other half of the rule: a mutable `:v1` tag means running pods keep the old image after a rebuild, so `scripts/build-image.sh` restarts the Deployments that use the image it just loaded. +Images loaded with `minikube image load` are tagged `datamesh/:v1`, and the charts set `imagePullPolicy: Never`. A missing image then fails fast with `ErrImageNeverPull` instead of falling through to a Docker Hub lookup that can never succeed. The other half of the rule: a mutable `:v1` tag means running pods keep the old image after a rebuild, so `scripts/build-image.sh` restarts the Deployments that use the image it just loaded. ### A fresh node can drop all pod traffic: reset the `FORWARD` policy -On minikube v1.38.1, a new capstone profile came up Ready, yet CoreDNS timed out +On minikube v1.38.1, a new datamesh profile came up Ready, yet CoreDNS timed out and the Istio ingress gateway never passed its readiness probe. A busybox pod could not ping, TCP-connect, or send UDP to any other pod. The cause was inside the node: the node image starts Docker once at first boot, and Docker 29 sets the @@ -347,7 +347,7 @@ These describe the earlier rootless-podman setup. They are kept for the reasonin ### Why minikube moved off rootless podman (historical) -The capstone ran minikube with the rootless podman driver from r20 to October 2026. +The final project ran minikube with the rootless podman driver from r20 to October 2026. On 2026-10-08, recreating the profile on minikube v1.38.1 (Fedora 44, podman 5.8.7) surfaced a run of problems, each needing its own workaround, while the sibling Quarkus reference ran the same platform on the docker driver with none of them: @@ -362,7 +362,7 @@ Quarkus reference ran the same platform on the docker driver with none of them: | Rootless plumbing | `sudo podman` prompts without `MINIKUBE_ROOTLESS=true`; hostPort pods failing without host iptables modules; PID exhaustion at the default `pids_limit` | Env var on every script, host kernel-module and pids pre-flights | Each workaround worked, but together they made the minikube path fragile and -unlike what learners run elsewhere. DRA-019 moved the minikube capstone to Docker +unlike what learners run elsewhere. DRA-019 moved the final project's minikube setup to Docker Engine with containerd and runc, and kept podman only for the optional OpenShift Local (CRC) appendix, where it is the native Red Hat tool. The entries below record each problem in detail. @@ -381,13 +381,13 @@ at node creation, not after. The podman driver runs the node container with crun. Pairing it with `--container-runtime=containerd` puts runc under the pods, so the stack used two -OCI runtimes. For a short time the capstone switched to CRI-O, whose minikube default is crun (DRA-018, since superseded by DRA-019). +OCI runtimes. For a short time the final project switched to CRI-O, whose minikube default is crun (DRA-018, since superseded by DRA-019). One side effect: `minikube addons enable` fails under CRI-O + crun because its paused-container check calls `runc list`; enable addons in `minikube start --addons=` instead. Another: minikube's hostpath provisioner creates volume directories `0755 root`, so non-root pods cannot write to them (CloudNativePG's `initdb`, running as uid 26, failed -with `Permission denied`). The capstone made the local-path provisioner, which +with `Permission denied`). The final project made the local-path provisioner, which creates them `0777`, the default StorageClass. ### Rootless-podman minikube has its own image-distribution model (historical) diff --git a/presentation/README.md b/presentation/README.md index ea38b11..6d102bf 100644 --- a/presentation/README.md +++ b/presentation/README.md @@ -1,6 +1,6 @@ # Presentation assets -This directory holds the presentation materials for the capstone: the existing +This directory holds the presentation materials for the final project: the existing **Data Mesh 101** deck (the conceptual intro) and, in time, a new implementation-focused deck that walks the §17 reference architecture and demos it step by step. @@ -107,7 +107,7 @@ Phase D (which slide uses which); refine as the sections are written. | `contract-flow` | Contracts, registry, catalog | runtime vs discovery path | | `contracts-registry-catalog` | Apicurio + OpenMetadata | contract → registry → catalog | | `ingestion-streaming-sourcing` | The async spine (Kafka) | ingestion/streaming | -| `reference-data-mesh-architecture` | The capstone as reference architecture | centerpiece / Phase E | +| `reference-data-mesh-architecture` | The final project as reference architecture | centerpiece / Phase E | When a Phase C section adopts a diagram, copy it into `assets/diagrams/` under the tutorial's `NN-name.svg` + `.excalidraw` convention (so the doc can embed it diff --git a/presentation/data-mesh-101/diagrams/contracts-registry-catalog.excalidraw b/presentation/data-mesh-101/diagrams/contracts-registry-catalog.excalidraw index 3c65a13..685f174 100644 --- a/presentation/data-mesh-101/diagrams/contracts-registry-catalog.excalidraw +++ b/presentation/data-mesh-101/diagrams/contracts-registry-catalog.excalidraw @@ -431,11 +431,11 @@ "locked": false, "fontSize": 9.5, "fontFamily": 3, - "text": "capstone.inventory.v1", + "text": "datamesh.inventory.v1", "textAlign": "middle", "verticalAlign": "top", "containerId": null, - "originalText": "capstone.inventory.v1", + "originalText": "datamesh.inventory.v1", "lineHeight": 1.25 }, { diff --git a/presentation/data-mesh-101/diagrams/contracts-registry-catalog.svg b/presentation/data-mesh-101/diagrams/contracts-registry-catalog.svg index a95cf7e..8bc6f9c 100644 --- a/presentation/data-mesh-101/diagrams/contracts-registry-catalog.svg +++ b/presentation/data-mesh-101/diagrams/contracts-registry-catalog.svg @@ -1 +1 @@ -Contracts, the registry, and the catalogevery protocol's contract lives in Apicurio; OpenMetadata builds lineage from itPROTOCOL SURFACES — EACH SERVICE'S CONTRACTREST (order-service)contract = OpenAPI document/openapi.json○ discovery contractgRPC (inventory-service)contract = Protobuf (.proto)capstone.inventory.v1○ discovery contractGraphQL (graphql-gateway)contract = GraphQL SDLschema.graphql○ discovery contractKafka events (order→notification)contract = Avro schemaorder.placed● RUNTIME contractApicurio Registry — the contract metadata (one home, many formats)OpenAPI artifactsREST surfaces○ discoveryProtobuf artifactsgRPC service defs○ discoveryGraphQL SDLgateway schema○ discoveryAvro schemasevent payloads● RUNTIMEpublish (discovery) / register (runtime)OpenMetadata — lineage & discovery metadataingests contracts + data sources, assembles the “who produces / who consumes” graphlineage graphorder-service—[ order.placed ]→ notification-servicePostgres schemasper service (CNPG)Kafka topics(Strimzi)ingest contractsingest data sources alongside the contracts → lineage \ No newline at end of file +Contracts, the registry, and the catalogevery protocol's contract lives in Apicurio; OpenMetadata builds lineage from itPROTOCOL SURFACES — EACH SERVICE'S CONTRACTREST (order-service)contract = OpenAPI document/openapi.json○ discovery contractgRPC (inventory-service)contract = Protobuf (.proto)datamesh.inventory.v1○ discovery contractGraphQL (graphql-gateway)contract = GraphQL SDLschema.graphql○ discovery contractKafka events (order→notification)contract = Avro schemaorder.placed● RUNTIME contractApicurio Registry — the contract metadata (one home, many formats)OpenAPI artifactsREST surfaces○ discoveryProtobuf artifactsgRPC service defs○ discoveryGraphQL SDLgateway schema○ discoveryAvro schemasevent payloads● RUNTIMEpublish (discovery) / register (runtime)OpenMetadata — lineage & discovery metadataingests contracts + data sources, assembles the “who produces / who consumes” graphlineage graphorder-service—[ order.placed ]→ notification-servicePostgres schemasper service (CNPG)Kafka topics(Strimzi)ingest contractsingest data sources alongside the contracts → lineage \ No newline at end of file diff --git a/presentation/data-mesh-openshift/build-deck.js b/presentation/data-mesh-openshift/build-deck.js index 4d40521..dac9ba6 100644 --- a/presentation/data-mesh-openshift/build-deck.js +++ b/presentation/data-mesh-openshift/build-deck.js @@ -522,7 +522,7 @@ contentSlide({ eyebrow: "Anti-patterns", title: "The architecture diagram is the trap: "Adopting a mesh because it's fashionable. It earns its complexity in large orgs with many domains, many consumers, and the maturity to operate products and standards across teams — for a small org, the overhead can cost more than the bottleneck it removes.", tell: "Chasing more data products as an end in itself; months of planning the perfect mesh instead of shipping one real product; adopting the whole paradigm when one principle would do.", fix: "Weigh data size, organizational complexity, existing tooling, and culture. Be willing to conclude a full mesh — or only some of its principles — is the right fit.", - n: "Less about HOW you build a mesh and more about WHETHER you should. This is the honest slide — and it builds credibility. A mesh is not for every organization. Sometimes a single principle, usually the self-serve platform, delivers most of the value without the full paradigm. Telling people when NOT to do this makes them trust you on when to. In our build, the capstone is deliberately a learning implementation — sized to teach the shape, not to argue everyone should run a mesh in production." }, + n: "Less about HOW you build a mesh and more about WHETHER you should. This is the honest slide — and it builds credibility. A mesh is not for every organization. Sometimes a single principle, usually the self-serve platform, delivers most of the value without the full paradigm. Telling people when NOT to do this makes them trust you on when to. In our build, the final project is deliberately a learning implementation — sized to teach the shape, not to argue everyone should run a mesh in production." }, ]; items.forEach((it) => { const s = pres.addSlide(); diff --git a/presentation/data-mesh-openshift/dimg/contracts-registry-catalog.svg b/presentation/data-mesh-openshift/dimg/contracts-registry-catalog.svg index a95cf7e..8bc6f9c 100644 --- a/presentation/data-mesh-openshift/dimg/contracts-registry-catalog.svg +++ b/presentation/data-mesh-openshift/dimg/contracts-registry-catalog.svg @@ -1 +1 @@ -Contracts, the registry, and the catalogevery protocol's contract lives in Apicurio; OpenMetadata builds lineage from itPROTOCOL SURFACES — EACH SERVICE'S CONTRACTREST (order-service)contract = OpenAPI document/openapi.json○ discovery contractgRPC (inventory-service)contract = Protobuf (.proto)capstone.inventory.v1○ discovery contractGraphQL (graphql-gateway)contract = GraphQL SDLschema.graphql○ discovery contractKafka events (order→notification)contract = Avro schemaorder.placed● RUNTIME contractApicurio Registry — the contract metadata (one home, many formats)OpenAPI artifactsREST surfaces○ discoveryProtobuf artifactsgRPC service defs○ discoveryGraphQL SDLgateway schema○ discoveryAvro schemasevent payloads● RUNTIMEpublish (discovery) / register (runtime)OpenMetadata — lineage & discovery metadataingests contracts + data sources, assembles the “who produces / who consumes” graphlineage graphorder-service—[ order.placed ]→ notification-servicePostgres schemasper service (CNPG)Kafka topics(Strimzi)ingest contractsingest data sources alongside the contracts → lineage \ No newline at end of file +Contracts, the registry, and the catalogevery protocol's contract lives in Apicurio; OpenMetadata builds lineage from itPROTOCOL SURFACES — EACH SERVICE'S CONTRACTREST (order-service)contract = OpenAPI document/openapi.json○ discovery contractgRPC (inventory-service)contract = Protobuf (.proto)datamesh.inventory.v1○ discovery contractGraphQL (graphql-gateway)contract = GraphQL SDLschema.graphql○ discovery contractKafka events (order→notification)contract = Avro schemaorder.placed● RUNTIME contractApicurio Registry — the contract metadata (one home, many formats)OpenAPI artifactsREST surfaces○ discoveryProtobuf artifactsgRPC service defs○ discoveryGraphQL SDLgateway schema○ discoveryAvro schemasevent payloads● RUNTIMEpublish (discovery) / register (runtime)OpenMetadata — lineage & discovery metadataingests contracts + data sources, assembles the “who produces / who consumes” graphlineage graphorder-service—[ order.placed ]→ notification-servicePostgres schemasper service (CNPG)Kafka topics(Strimzi)ingest contractsingest data sources alongside the contracts → lineage \ No newline at end of file diff --git a/scripts/audit-fedora-prereqs.sh b/scripts/audit-fedora-prereqs.sh index 55b7b0d..626d141 100755 --- a/scripts/audit-fedora-prereqs.sh +++ b/scripts/audit-fedora-prereqs.sh @@ -56,7 +56,7 @@ if command -v docker >/dev/null 2>&1; then echo " (sudo usermod -aG docker \$USER, then log in again)" fi else - echo " STATUS: ⚠ docker not installed — required for the minikube capstone" + echo " STATUS: ⚠ docker not installed — required for the minikube final project" fi section "Red Hat appendix (CRC) tools — optional" @@ -120,7 +120,7 @@ for m in ip_tables iptable_nat ip6_tables br_netfilter overlay; do fi done -section "docker default-pids-limit (capstone node runs ~2000+ tasks — CAP-040)" +section "docker default-pids-limit (final-project node runs ~2000+ tasks — CAP-040)" DAEMON_JSON=/etc/docker/daemon.json PIDS_LIMIT="" if [[ -r "$DAEMON_JSON" ]]; then @@ -129,11 +129,11 @@ if [[ -r "$DAEMON_JSON" ]]; then fi if [[ -z "$PIDS_LIMIT" ]]; then echo " default-pids-limit not set in ${DAEMON_JSON} (Docker default applies: unlimited)" - echo " STATUS: ✓ OK for the full meshed capstone" + echo " STATUS: ✓ OK for the full meshed final project" else echo " default-pids-limit = ${PIDS_LIMIT} (0 or -1 = unlimited)" if (( PIDS_LIMIT <= 0 || PIDS_LIMIT >= 8192 )); then - echo " STATUS: ✓ OK for the full meshed capstone" + echo " STATUS: ✓ OK for the full meshed final project" else echo " STATUS: ⚠ the node would cap TOTAL processes across all pods at ${PIDS_LIMIT}." echo " Raise it in ${DAEMON_JSON} (\"default-pids-limit\": -1) and" @@ -161,7 +161,7 @@ if command -v minikube >/dev/null 2>&1; then if [[ "$(printf '%s\n' "v1.39.0" "$MK_VERSION" | sort -V | head -1)" == "v1.39.0" ]]; then echo " STATUS: ✓ OK (>= 1.39.0)" else - echo " STATUS: ⚠ older than 1.39.0 — setup-capstone-profile.sh refuses it (Kubernetes v1.36.5 needs 1.39.0)." + echo " STATUS: ⚠ older than 1.39.0 — setup-datamesh-profile.sh refuses it (Kubernetes v1.36.5 needs 1.39.0)." echo " Install a current minikube (e.g. to ~/.local/bin, which" echo " precedes /usr/local/bin on PATH)." fi diff --git a/scripts/setup-strimzi.sh b/scripts/setup-strimzi.sh index 40b1f0a..19d2da4 100755 --- a/scripts/setup-strimzi.sh +++ b/scripts/setup-strimzi.sh @@ -15,8 +15,8 @@ # Known issues: # - Strimzi 1.x accepts ONLY the kafka.strimzi.io/v1 API; v1beta2 # custom resources are rejected. Kafka 3.x and ZooKeeper are gone, so -# Kafka CRs pin a 4.x version (the capstone uses 4.3.1, KRaft + KafkaNodePool) -# - Strimzi 1.2 needs a recent Kubernetes; the capstone profile pins +# Kafka CRs pin a 4.x version (the final project uses 4.3.1, KRaft + KafkaNodePool) +# - Strimzi 1.2 needs a recent Kubernetes; the datamesh profile pins # v1.36.5, so we're fine # - The Cluster Operator can occasionally get stuck in a NotReady state # on first install — if `helm install --wait` times out, check diff --git a/setup.html b/setup.html index 2899a43..9dce738 100644 --- a/setup.html +++ b/setup.html @@ -66,7 +66,7 @@

    Kernel tuning

    inotify limits

    - The capstone runs many controllers; Fedora's default 128 + The final project runs many controllers; Fedora's default 128 instances is not enough.

    sudo sh -c 'printf "fs.inotify.max_user_instances = 512\nfs.inotify.max_user_watches = 524288\n" \
    @@ -81,7 +81,7 @@ 

    inotify limits

    Container engine

    - The capstone runs on Docker Engine: native docker-ce on Linux, + The final project runs on Docker Engine: native docker-ce on Linux, with the daemon running and your user in the docker group. Install it from docs.docker.com/engine/install, @@ -97,21 +97,21 @@

    Container engine

    VM-based engines

    - The capstone scripts are supported on Fedora and RHEL hosts (bare metal + The final-project scripts are supported on Fedora and RHEL hosts (bare metal or VM). A VM-based engine such as Docker Desktop can provide the engine instead. It is an option, not a requirement. Its VM must be sized to at least 28 GB of memory; set MINIKUBE_CPUS and MINIKUBE_MEMORY to fit it, as described below.

    -

    Upgrading from an earlier (rootless podman) capstone profile

    +

    Upgrading from an earlier (rootless podman) datamesh profile

    An earlier release created the profile with rootless podman. Delete that profile first, then clear the setting, then run setup:

    -
    MINIKUBE_ROOTLESS=true minikube delete -p capstone 
    +
    MINIKUBE_ROOTLESS=true minikube delete -p datamesh 
     minikube config unset rootless 
    -./scripts/setup-capstone-profile.sh
    +./scripts/setup-datamesh-profile.sh

    Fitting minikube to the engine

    @@ -168,7 +168,7 @@

    Bootstrap

    Bring the whole system up

    cd examples/lgtm-datamesh
    -./scripts/bootstrap-capstone.sh
    +./scripts/bootstrap-datamesh.sh

    Images are built with Docker Engine and loaded into the node with minikube image load; there is no registry. Bootstrap runs 10 tiers: minikube profile, Istio, @@ -223,13 +223,13 @@

    Accessing the tools

    The tools run inside the cluster and are exposed as NodePort services published on 127.0.0.1 when the - capstone minikube profile is created. Nothing runs in + datamesh minikube profile is created. Nothing runs in the background and nothing needs starting per demo. Ports are fixed at creation; an older profile without them is refused by - setup-capstone-profile.sh and recreated with - ./scripts/setup-capstone-profile.sh --replace. + setup-datamesh-profile.sh and recreated with + ./scripts/setup-datamesh-profile.sh --replace. --replace deletes and recreates the cluster, so run - ./scripts/bootstrap-capstone.sh again afterwards. + ./scripts/bootstrap-datamesh.sh again afterwards. Run the workshop in isolation: shut down CRC, other minikube profiles, and other workloads first so the host ports are free. To see which endpoints are published and reachable: @@ -260,7 +260,7 @@

    Accessing the tools

    Grafana default credentials are admin / the value from - kubectl get secret grafana -n capstone -o jsonpath='{.data.admin-password}' | base64 -d. + kubectl get secret grafana -n datamesh -o jsonpath='{.data.admin-password}' | base64 -d.