Pick the builds. Get a live environment
Environment Manager gives you your own Kubernetes namespace with the services you pick: a Harbor tag or your branch. ArgoCD deploys it, and it deletes itself when its time runs out.
New environment
Name, parent, services, how long
DEV-3150Committed
Helm values and an ArgoCD app in ft-deployments
PUSHEDSynced
Creates the namespace and rolls the services out
SYNCEDLive
URLs, ports and database logins ready to copy
HEALTHYDeleted on time
Unless you extend it
AFTER 1 DAYFrom asking for a namespace to one form
Before by hand, through DevOps
- Ask someone for a namespace
- Edit Helm values and ArgoCD files by hand
- Hunt for URLs, ports and database passwords
- Forget to delete it; the cluster fills up
Now two steps in Environment Manager
You pick a parent, the services and how long it lives.
Environment Manager commits it; ArgoCD deploys it.
Then, with no clicks:
- Your branch built
- URLs grouped, one click to copy
- JDBC URL, user and password
- Deleted when its time runs out
How it works
- 1
Sign in
With your @friendly-tech.com e-mail and a 6-digit code.
You - 2
Create
A name, a parent to share, the services you run yourself, how long it lives.
You - 3
Build and deploy
Branches are built in GitHub Actions; ArgoCD rolls everything out.
Automatic - 4
Use
Open the URLs, connect to the database, read pods and logs, change services.
You and QA - 5
Delete on time
Every hour expired environments are removed, unless you extend yours.
Automatic
Sign in with a code, not a password
Open env.rd.friendly-tech.com. Only @friendly-tech.com addresses can sign in. A sign-in lasts 3 days.
Get a live environment.
A Kubernetes namespace with the services you tick, synced by ArgoCD and deleted automatically when its time runs out.
- The code lives 15 minutesThe mail is “Environment Manager - Your sign-in code”. A new code can be sent after 60 seconds.
- Or the link in the mailIt opens a card with a Sign In button. Opening the link alone signs nobody in.
- Five wrong codesThe code is destroyed. Ask for a new one.
Your environments, and everyone else's
The first tab shows yours. Show all environments adds the rest of the team and the static ones. The list refreshes every 30 seconds.
My environmentsAll environments
Show all environments · 5Show only mine · 2 New environment| Environment | State | CPU, cores | Memory | Owner | Expires | |
|---|---|---|---|---|---|---|
| dev-3150partial of dev-mysql · MySQL · 1 service | Starting | 220m | 1.1 Gi | anna.k | in 1 day | Logs⋯ |
| dev-3144full · MySQL | Healthy | 380m | 2.7 Gi | anna.k | in 5 days | Logs⋯ |
| dev-samlpartial of dev-oracle · Oracle · 2 services | Degraded | 140m | 0.9 Gi | oleg.s | in 18 h | Logs⋯ |
| qa-regressfull · Oracle | Stopped | 0m | 0 Mi | maria.v | in 3 days | Logs⋯ |
| Static · 2 — shared, never deleted | ||||||
| dev-mysqlstatic · MySQL | Healthy | 1.20 | 4.5 Gi | — | no auto-delete | Logs⋯ |
What the state means
- Healthy
- Every resource ArgoCD tracks is healthy.
- Starting
- ArgoCD is still rolling it out. If it stays here, open Pods for the pod that is not ready.
- Out of sync
- The cluster differs from git. Self-heal usually clears it; Sync applies git now.
- Degraded
- A resource is failing or missing. Open Pods for the reason, then Logs.
- Stopped
- Scaled to zero. Resume brings the same images back.
- The bars on topPods, CPU, memory and storage of the whole cluster. The dark part is yours, the light part is everyone else.
- Logs on every rowOpens the environment straight on its Logs tab. ⋯ holds Sync with ArgoCD, Stop or Resume, and Delete.
- Static environmentsdev-mysql, dev-oracle, latest-mysql, latest-oracle are shared and never deleted. They are the parents of partial environments.
Create an environment for your branch
Tab New environment. The usual case is a partial environment: you run only what you changed, everything else comes from a parent such as dev-mysql.
New environment
A Kubernetes namespace with the services you tick. It appears in your list as soon as you create it.
Services
Every service starts from dev-mysql. Pick Harbor tag or Branch to run your own version of it here.
| Service | Source | Version | |
|---|---|---|---|
| ACS | dev-mysqlHarbor tagBranch | v7.1.2feat/login | builds on Create |
| UI Backend | dev-mysqlHarbor tagBranch | v7.1.2 | |
| UI Portals | dev-mysqlHarbor tagBranch | v7.1.2 | |
| Optional, Helm-managed · 1 — never shared; runs here or not at all | |||
| Grafana | ☐ Run in this environment | ||
dev-3150 is created
ArgoCD is deploying it. 1 service builds from a branch first and starts once its image is ready. You can leave this page.
- NameLowercase letters, digits and hyphens, up to 63. It becomes the namespace and part of every URL:
ftacs.dev-3150.rd.friendly-tech.com. - Delete automaticallyAfter 1 day by default; 3, 7, 14 or 30 days, or Never. You can extend it later.
- BranchBuilt by the service's GitHub Actions workflow. The Harbor tag is the branch name made safe:
feat/loginbecomesfeat-login. - Enable ArgoCD Image UpdaterRedeploys when the tag you picked is pushed again. It never moves to another tag.
Type: Partial or Full
The one choice that decides where the database, the infrastructure and every service you do not touch come from.
Your services on a parent’s base
- What runs in yours
- Only the services you switch to Harbor tag or Branch. Every other row stays on the parent’s name.
- Where the rest comes from
- The parent: its database and infrastructure (MySQL or Oracle, Hazelcast, ClickHouse) and every service you did not pick. Your services reach them inside the cluster at
<service>.dev-mysql.svc.cluster.local. - Which parent
- A running full or static environment:
dev-mysqlby default,dev-oraclefor Oracle, or a teammate’s full one.
- The data is shared. You write into the parent’s database; everyone on that parent sees it.
- The parent must run. If it is stopped or deleted, your environment stops working.
- Nothing is added for you. If your change needs a new version of another service too, switch that one as well.
- Parent URLs lead to the parent. Overview lists them under “From dev-mysql”.
Everything of its own
- What makes it full
- Its own database (you choose MySQL or Oracle) and its own infrastructure in its own namespace. It depends on no other environment.
- What runs
- Nothing until you pick it. What a service needs is switched on with it, at Harbor tag
latest, marked needed by; its Off option is locked while something needs it. - What pulls in what
- ACS → FT Configs Service and Hazelcast · UI Backend → ACS and FT Device Network · UI Portals → UI Backend · UI AI Agent → AI Agent Sandbox.
- Heavier. It takes more CPU, memory and storage from the cluster (the bars on the list) and longer to start.
- Its data is its own. Nothing from dev-mysql is in it, and nobody else writes to it.
- It can be a parent. Teammates can run partial environments on it while it runs.
You change one or two services and test them against the usual data. Most branches.
You need clean or private data, a database migration, Oracle on your own, or a base for others.
QA: everything about one environment in one window
Click its row. Four tabs: Overview, Pods, Services, Logs. Nothing to look up elsewhere.
| Pod | Status | Age | Restarts | |
|---|---|---|---|---|
| ftacs-5f9f9b9d66-fwbtvapp ftacs · 1 container | CrashLoopBackOff | 12 min | ⚠ 7 | Logs ⋯ |
| hazelcast-0app hazelcast · 1 container | Running | 2 d | 0 | Logs ⋯ |
- Service URLsGrouped (Core, APIs, Portals…). Base copies the host, Swagger / UI / Metrics the full link. URLs from the parent are listed apart: those requests go to the parent.
- DatabasePick a database (ftacs, admin, configs…) and copy JDBC, User or Password. Ports list the NodePorts for MySQL, MQTT, USP and JDWP debug.
- PodsStatus shows the reason, e.g. CrashLoopBackOff. ⋯ → Restart pod… or Restart deployment… (same tag, rolling).
- LogsOpens on the pod that needs attention most. Search with Enter / Shift+Enter, Previous container (after a crash), Follow · every 5 s. Stack traces are folded.
What the Overview tab gives you
Everything you need to connect to the environment: links, device ports, debug ports and the database. Each copy button puts the value on your clipboard.
IllustrationNumbers and names are sample data. Ports differ per environment.
- 1Service URLs — this environmentLinks to the services that run in your namespace, grouped Core, APIs, Portals, Testing… Base copies
http://host; Swagger / UI / Metrics copy the full link. - 2From the parent partial onlyServices you left on the parent. Requests to these links go to the parent, not to your environment — test your change on the links in block 1.
- 3Device connectionPorts for real devices and emulators: MQTT, USP (CoAP, DTLS, MQTT, STOMP, WebSocket, Bulk) and more. Left: the NodePort to connect to from outside the cluster; right: the port inside. Point the device at
dev-2358-2.rd.friendly-tech.com:31709(the same host the JDBC URL uses). Every environment has its own numbers: base + its port offset (Details). - 4Debug (JDWP)Every dynamic environment runs with debug on. In IntelliJ: Run → Edit Configurations → Remote JVM Debug, host = the environment host, port = the number next to the service, e.g. FT Configs Service
31509. Breakpoints then stop the running pod. - 5DatabasePick a database (ftacs, admin, configs…) and copy JDBC, User or Password into your SQL client. shared means it is the parent’s: writes reach every environment on it.
Developer: change what runs, without a new environment
Tab Services. Switch a service to another tag or your branch, take it back to the parent, or turn it off. Nothing changes until Apply changes.
| Service | Running now | Source | Version |
|---|---|---|---|
| ACSchanged | feat-loginv7.1.3 | dev-mysqlHarbor tagBranch | feat/loginv7.1.3 |
| UI Backend | from dev-mysql | dev-mysqlHarbor tagBranch | v7.1.2 |
Apply commits to git, then ArgoCD syncs; changed services roll out.DiscardApply changes
Reading the Services tab
| Service | Running now 1 | Source 2 | Version 3 | Build 4 |
|---|---|---|---|---|
| Services · 18 | ||||
| ACS | latestsha256:20be7847fbc1 | dev-mysqlHarbor tagBranch | latest | pick a branch first |
| UI Backend | feature/dev-2358sha256:b90b106ecb15 | dev-mysqlHarbor tagBranch | feature/dev-2358 | Build |
| UI Portals | from dev-mysql | dev-mysqlHarbor tagBranch | dev | |
| AI Agent Sandbox | from dev-mysql | dev-mysqlHarbor tag | latest | |
- 1Running nowWhat the pod runs at this moment: the tag and its image digest, or from dev-mysql when the parent serves it. Compare it with Version to see whether your change has rolled out.
- 2Sourcedev-mysql (the parent’s name; Off on a full environment) — not yours. Harbor tag — a ready image. Branch — your git branch, built for you. Highlighted rows are the ones you run yourself. A service without a git repository has no Branch, e.g. AI Agent Sandbox.
- 3VersionThe tag or branch to run. The list comes from Harbor (tags) or GitHub (branches).
- 4BuildOnly for Branch. Builds the branch into a Harbor tag: Dispatched → Building → Built. Until a branch is picked it says pick a branch first.
- Source → Branch, pick your branch in Version.
- Press Build and wait for Built.
- Press Apply changes at the bottom. ArgoCD rolls the service out; Running now shows your branch.
- Source → dev-mysql, then Apply changes. Your pod stops; requests go to the parent again.
- New commits on your branchPress Build again in the row, then Apply if the tag changed. With Image Updater on, a rebuilt tag is redeployed by itself.
- ApplyCommits the change to git and ArgoCD rolls the service out. If it fails, your changes stay and Retry apply is offered.
- Static environments are read-onlydev-mysql and the others change through GitOps, not here. Their Services tab only shows what runs.
Every environment has a delete-by time
So the cluster does not fill up with forgotten namespaces. Extend it from the environment when you need it longer.
Created
Expires in 1 dayThe time starts with Create.
Extend
+1 · +3 · +7 · +14 daysAdded to the current expiry. Never-expiring ones get Set expiry… instead.
Stop
Scaled to 0Volumes and the database are kept. The time keeps running.
Resume
Same images backSame replica counts, ArgoCD auto-sync on again.
Expired
Under 24 h: ⚠The list warns on the last day.
Deleted
Hourly cleanupNamespace, ArgoCD app and volumes. Stopped ones too.
IllustrationDelete can also be pressed by hand: ⋯ → Delete environment…. It cannot be undone.
When something goes wrong
The state tells you where to look. The messages say what to do.
Build failedYour branch did not build
- That service does not start
- Fix the branch and press Build again in Services
- Or pick a Harbor tag for it instead
DegradedA pod is failing
- Pods shows the reason (CrashLoopBackOff, OOMKilled…)
- Logs opens on that pod; tick Previous container after a crash
- On a partial: is the parent running? A stopped parent breaks its partials
Couldn’t …env-manager did not answer
- Check your connection (VPN) and try again
- “Kubernetes or ArgoCD isn’t reachable”: wait a minute and retry
CarefulAnyone can delete a dynamic environment
- There is no owner check on Delete
- Look at the Owner column before you press it
Questions we get
I pushed again to my branch. How do I get it?
Services → Build in that row. With Image Updater on, ArgoCD redeploys by itself when the tag is pushed again.
Does Restart deployment pull my new image?
Only for :latest or imagePullPolicy Always. To run another tag, change it in Services.
Why can’t I change dev-mysql?
Static environments are the shared base for partial ones. They change through GitOps, and only admins can stop or resume them.
My test data showed up in someone else’s environment.
A partial environment uses its parent’s database. Create a Full one when you need your own data.
Who sees my environment?
Everyone, under Show all environments, with you as the owner.
It stays in Starting.
A branch build may still be running, or a pod is not ready. Open Pods for the one that is not ready, then its Logs.
Questions?
Create one for your next branch. Tell us what was unclear, what was missing or what broke.