devlift-cli 0.1.3__tar.gz → 0.1.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/PKG-INFO +1 -1
  2. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/MANUAL.md +27 -13
  3. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/__init__.py +1 -1
  4. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/commands/clusters.py +25 -10
  5. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/commands/eks.py +37 -5
  6. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/skill/SKILL.md +18 -0
  7. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/skill/reference/commands.md +1 -1
  8. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/skill/reference/workflows.md +3 -1
  9. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli.egg-info/PKG-INFO +1 -1
  10. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/README.md +0 -0
  11. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/__main__.py +0 -0
  12. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/api/__init__.py +0 -0
  13. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/api/approvals.py +0 -0
  14. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/api/catalog.py +0 -0
  15. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/api/client.py +0 -0
  16. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/api/context.py +0 -0
  17. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/api/deployments.py +0 -0
  18. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/api/infra.py +0 -0
  19. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/api/infra_list.py +0 -0
  20. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/api/kong.py +0 -0
  21. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/api/services.py +0 -0
  22. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/api/vpc.py +0 -0
  23. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/app.py +0 -0
  24. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/auth/__init__.py +0 -0
  25. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/auth/oauth.py +0 -0
  26. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/auth/session.py +0 -0
  27. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/auth/storage.py +0 -0
  28. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/commands/__init__.py +0 -0
  29. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/commands/approval.py +0 -0
  30. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/commands/auth.py +0 -0
  31. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/commands/catalog.py +0 -0
  32. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/commands/deployment.py +0 -0
  33. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/commands/dynamodb.py +0 -0
  34. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/commands/kong.py +0 -0
  35. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/commands/languages.py +0 -0
  36. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/commands/manual.py +0 -0
  37. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/commands/repositories.py +0 -0
  38. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/commands/request.py +0 -0
  39. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/commands/s3.py +0 -0
  40. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/commands/skill.py +0 -0
  41. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/commands/sqs.py +0 -0
  42. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/config.py +0 -0
  43. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/context.py +0 -0
  44. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/data/placement/vance.json +0 -0
  45. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/errors.py +0 -0
  46. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/ops/__init__.py +0 -0
  47. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/ops/approvals.py +0 -0
  48. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/ops/eks.py +0 -0
  49. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/ops/kong.py +0 -0
  50. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/ops/placement.py +0 -0
  51. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/ops/resources.py +0 -0
  52. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/ops/status.py +0 -0
  53. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/ops/wait.py +0 -0
  54. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/render/__init__.py +0 -0
  55. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/render/output.py +0 -0
  56. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/resolve/__init__.py +0 -0
  57. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/resolve/allowlist.py +0 -0
  58. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/resolve/names.py +0 -0
  59. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli/skill/reference/exit-codes.md +0 -0
  60. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli.egg-info/SOURCES.txt +0 -0
  61. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli.egg-info/dependency_links.txt +0 -0
  62. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli.egg-info/entry_points.txt +0 -0
  63. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli.egg-info/requires.txt +0 -0
  64. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/devlift_cli.egg-info/top_level.txt +0 -0
  65. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/pyproject.toml +0 -0
  66. {devlift_cli-0.1.3 → devlift_cli-0.1.5}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devlift-cli
3
- Version: 0.1.3
3
+ Version: 0.1.5
4
4
  Summary: DevLift command-line tool: create, change, review and deploy DevLift resources from the terminal.
5
5
  License: Proprietary
6
6
  Keywords: devlift,devops,deployment,infrastructure,cli
@@ -227,11 +227,13 @@ devlift clusters list [--app NAME] [--env ENV] [--region REGION] [--type eks|ecs
227
227
  ```
228
228
 
229
229
  The clusters services run on, and the `--cluster` values for `eks create`.
230
- Narrowed to placements you could really create in: the backend reports only
231
- the environments this deployment serves, and the placement allowlist
232
- (section 5) says which of those offer EKS or ECS. Clusters outside both are
233
- real but unusable from here, so they are hidden and counted; `--all` shows
234
- everything the backend reports.
230
+ Narrowed by three filters, the same ones a create goes through: the backend
231
+ reports only the environments this deployment serves, the placement allowlist
232
+ (section 5) says which of those offer EKS or ECS, and only a **registered**
233
+ cluster may take a new service. Anything outside those is real but can never
234
+ be chosen, so it is hidden and counted. `--all` drops all three and shows
235
+ everything the backend reports, for checking what exists rather than for
236
+ choosing.
235
237
 
236
238
  ```
237
239
  devlift clusters list --type eks --app core --env stage
@@ -239,16 +241,20 @@ devlift clusters list --type eks --app core --env stage
239
241
 
240
242
  ```
241
243
  22 of 25 hidden: not a placement this deployment offers; --all shows everything.
244
+ 2 more hidden: not registered, so no service can be created on them.
242
245
 
243
- Cluster Type Environment Region Application Registered
246
+ Cluster Type Environment Region Application Registered
244
247
  acme-core-stage-mumbai-01-application-cluster EKS stage Mumbai core yes
245
- …two more in the same placement, not registered
246
248
  ```
247
249
 
248
- Within that, **Registered** is the flag that matters: only a registered
249
- cluster may take a new service, and `eks create` will not offer the others.
250
- A row whose Application reads "tenant-level" belongs to no single product
251
- and is the fallback for products with no cluster of their own.
250
+ Everything listed is a cluster `eks create` would accept. A row whose
251
+ Application reads "tenant-level" belongs to no single product and is the
252
+ fallback for products with no cluster of their own.
253
+
254
+ **Name and code are two labels for one cluster.** The Cluster column and
255
+ `eks create` both show the name; the Code column and `eks show`'s
256
+ `cluster_code` show the backend's identifier. They look nothing alike, so do
257
+ not read a difference between them as two different clusters.
252
258
 
253
259
  With exactly one registered cluster in a placement, `eks create` fills it in
254
260
  silently. With several it asks, or wants `--cluster` under `--no-input`.
@@ -503,7 +509,7 @@ devlift eks create --name NAME --app APP --env ENV --region REGION --type api|wo
503
509
  [--set key=value ...] [--public] [-y]
504
510
  devlift eks settings Every key --set accepts, and when each applies.
505
511
  devlift eks settings <service> Only the keys that apply to it, with its current values.
506
- devlift eks show <service> --env ENV The configuration as it stands, with pending values marked.
512
+ devlift eks show <service> --env ENV The configuration, with any pending draft over it; pending rows name the deployed value too.
507
513
  devlift eks diff <service> --env ENV Preview the pending change: Field | Deployed | Requested.
508
514
  devlift eks diff <service> --deployed The live configuration versus the last deployment.
509
515
  devlift eks edit <service> --env ENV [--set key=value ...]
@@ -746,7 +752,15 @@ last deployed. That one ignores drafts entirely, so on a service whose
746
752
  change is still a draft it shows the live row and its defaults, not what the
747
753
  draft proposes.
748
754
 
749
- `eks show` marks each value that a pending request would change.
755
+ **`eks show` is not "what is deployed" while a request is open.** Its
756
+ Configuration table is the live configuration with the open draft laid over
757
+ it, so a pending row shows the value the draft *proposes*. Each such row is
758
+ marked `pending (<status>) — deployed <value>`, so both numbers are visible.
759
+
760
+ In `-o json` the same thing is spelled out: `settings` is the merged view,
761
+ `deployed_settings` is what is actually running, and `pending` gives
762
+ `{deployed, requested}` for each changed key. When `pending_request` is null
763
+ there is no draft and `settings` is simply the deployed configuration.
750
764
 
751
765
  ### kong
752
766
 
@@ -1,3 +1,3 @@
1
1
  """DevLift command-line tool."""
2
2
 
3
- __version__ = "0.1.3"
3
+ __version__ = "0.1.5"
@@ -66,14 +66,17 @@ def clusters_list(
66
66
  ):
67
67
  """List the clusters a service can run on.
68
68
 
69
- Narrowed to placements this deployment serves and the placement allowlist
70
- permits, so a cluster listed here is one a service could actually be
71
- created on. `--all` shows everything the backend reports.
72
-
73
- "Registered" is the flag that matters within that: only a registered
74
- cluster may take a new service, and `eks create` will not offer the
75
- others. A cluster with no application is tenant-level and is the fallback
76
- for every product that has none of its own.
69
+ Three filters, the same ones every create goes through: placements this
70
+ deployment serves, placements the allowlist permits, and registration.
71
+ Only a registered cluster may take a new service, so an unregistered one
72
+ is never a candidate and is not listed. Everything shown here is a cluster
73
+ `eks create` would actually accept.
74
+
75
+ `--all` drops all three and shows everything the backend reports, which is
76
+ for checking what exists rather than for choosing.
77
+
78
+ A cluster with no application is tenant-level and is the fallback for
79
+ every product that has none of its own.
77
80
  """
78
81
  inv: Invocation = ctx.obj
79
82
  res = Resolver(inv.api, inv.profile.name)
@@ -95,8 +98,20 @@ def clusters_list(
95
98
  if not show_all:
96
99
  before = len(rows)
97
100
  rows = _placeable(res, rows)
98
- if before > len(rows):
99
- output.info(f"{before - len(rows)} of {before} hidden: not a placement this deployment offers; --all shows everything.")
101
+ placement_hidden = before - len(rows)
102
+
103
+ # Unregistered clusters are not offerable, so listing them is worse than
104
+ # useless: a service cannot be created on one, and naming it invites a
105
+ # comparison against the registered cluster that reads as a discrepancy.
106
+ # `--all` still shows them, for someone checking what exists.
107
+ registered = [r for r in rows if r.get("is_registered")]
108
+ unregistered_hidden = len(rows) - len(registered)
109
+ rows = registered
110
+
111
+ if placement_hidden:
112
+ output.info(f"{placement_hidden} of {before} hidden: not a placement this deployment offers; --all shows everything.")
113
+ if unregistered_hidden:
114
+ output.info(f"{unregistered_hidden} more hidden: not registered, so no service can be created on them.")
100
115
  inv.emit(rows, lambda d: rows_table(
101
116
  ["Cluster", "Type", "Environment", "Region", "Application", "Registered", "Status", "Code"],
102
117
  [(r.get("cluster_name") or r.get("name"), r.get("cluster_type"), r.get("environment"),
@@ -110,35 +110,67 @@ def eks_show(
110
110
  region: str | None = typer.Option(None, "--region", help="Region, when the service runs in several."),
111
111
  ):
112
112
  """Show a service's configuration as it stands, marking values pending in an open request."""
113
- from devlift_cli.ops.eks import LABELS, load_effective, _show
113
+ from devlift_cli.ops.eks import LABELS, load_effective, settings_from_config, _show
114
114
  from devlift_cli.render import output
115
115
 
116
116
  inv: Invocation = ctx.obj
117
117
  eff = load_effective(inv, Resolver(inv.api, inv.profile.name), service, env, region, for_edit=False)
118
118
  live = eff.live
119
119
  request = eff.draft
120
+ # `eff.settings` is the live config with the open draft laid OVER it, so for
121
+ # any pending key its value is what the draft proposes, not what is running.
122
+ # Reading it as "the current configuration" is the obvious mistake, and one
123
+ # that has been made, so the deployed values are published beside it rather
124
+ # than left to be inferred from pending_keys.
125
+ deployed_settings = settings_from_config(dict(live.get("config") or {}))
120
126
  data = {
121
127
  "service": eff.target.service_name, "service_config_code": eff.target.config_code,
122
- "environment": live.get("environment"), "region": eff.target.region_name, "cluster": live.get("infrastructure_mst_code"),
128
+ "environment": live.get("environment"), "region": eff.target.region_name,
129
+ # The NAME, the same identifier `eks create` and `clusters list` print.
130
+ # This used to report infrastructure_mst_code, so the two commands named
131
+ # one cluster two different ways and anyone comparing them concluded the
132
+ # service had moved. The code is still here, under its own key.
133
+ "cluster": eff.config.get("cluster_name") or live.get("infrastructure_mst_code"),
134
+ "cluster_code": live.get("infrastructure_mst_code"),
123
135
  "type": eff.service.get("service_type"), "repository": eff.config.get("repository"),
124
136
  "branches": eff.config.get("branches") or eff.config.get("selected_branches"),
125
137
  "language": f"{eff.language_label or ''} {eff.language_version or ''}".strip() or None,
126
- "settings": eff.settings, "pending_request": {"code": request["code"], "status": request["status"]} if request else None,
138
+ # effective = deployed, with the pending draft laid over it.
139
+ "settings": eff.settings,
140
+ # what is actually running right now, whatever is pending.
141
+ "deployed_settings": deployed_settings,
142
+ "pending_request": {"code": request["code"], "status": request["status"]} if request else None,
127
143
  "pending_keys": sorted(eff.pending_keys),
144
+ # Both sides per changed setting, so "what is deployed" needs no
145
+ # cross-referencing of two dicts against a list of keys.
146
+ "pending": {
147
+ k: {"deployed": deployed_settings.get(k), "requested": eff.settings.get(k)}
148
+ for k in sorted(eff.settings)
149
+ if k in eff.pending_keys or (k in ("hpa_enabled", "min_replicas", "max_replicas") and "hpa" in eff.pending_keys)
150
+ } if request else {},
128
151
  }
129
152
 
130
153
  def table(d):
131
154
  output.err_console.print(kv_table([
132
155
  ("Service", d["service"]), ("Type", d["type"]), ("Environment", f"{d['environment']} / {d['region']}"),
133
156
  ("Cluster", d["cluster"]), ("Repository", d["repository"] or "–"),
157
+ # Kept out of the table: the code adds nothing a reader can act on,
158
+ # and showing both invites exactly the comparison this fixes.
134
159
  ("Branches", ", ".join(d["branches"] or []) or "–"), ("Language", d["language"] or "–"),
135
160
  ("Pending request", f"{d['pending_request']['code']} ({d['pending_request']['status']})" if d["pending_request"] else "none"),
136
161
  ], title=d["service"]))
137
162
  pend = set(d["pending_keys"])
138
163
  def mark(k):
139
164
  hit = k in pend or (k in ("hpa_enabled", "min_replicas", "max_replicas") and "hpa" in pend)
140
- return f"pending ({d['pending_request']['status']})" if hit and d["pending_request"] else ""
141
- return rows_table(["Setting", "Value", ""], [(LABELS.get(k, k), _show(v), mark(k)) for k, v in d["settings"].items()], title="Configuration")
165
+ if not (hit and d["pending_request"]):
166
+ return ""
167
+ # Name the value that is actually running. Marking the row "pending"
168
+ # while showing only the draft's number tells the reader the setting
169
+ # is changing but not what it is changing FROM, which is the half
170
+ # they need to judge it.
171
+ return f"pending ({d['pending_request']['status']}) — deployed {_show(d['deployed_settings'].get(k))}"
172
+ header = "Value (deployed)" if not d["pending_request"] else "Value (with pending draft)"
173
+ return rows_table(["Setting", header, ""], [(LABELS.get(k, k), _show(v), mark(k)) for k, v in d["settings"].items()], title="Configuration")
142
174
  inv.emit(data, table)
143
175
 
144
176
 
@@ -239,6 +239,24 @@ the approved rows. The summary is printed on every dry run, in json mode too.
239
239
  finished, and `eks status <service> --env <env>` also asks ArgoCD whether the
240
240
  pod is actually serving, which is the real "is it up" question. A finished
241
241
  pipeline is not a running application.
242
+ - **`eks show` is not "what is deployed" when a request is open.** Its
243
+ `settings` are the live configuration with the open draft laid OVER it, so
244
+ for any pending key the value shown is what the draft PROPOSES. Quoting one
245
+ as the running value is wrong and has misled a user.
246
+ Check `pending_request` first. If it is null, `settings` is the deployed
247
+ configuration and you can quote it freely. If it is set, use
248
+ `deployed_settings` for what is running, or `pending` which gives
249
+ `{deployed, requested}` per changed key, or run `devlift eks diff <service>
250
+ --env <env>`. Never describe a value as current, running or deployed on the
251
+ strength of `settings` alone while something is pending.
252
+ - **Never compare a cluster code with a cluster name.** `eks show` returns both
253
+ `cluster` (the name, e.g. `acme-core-stage-mumbai-01-application-cluster`)
254
+ and `cluster_code` (e.g. `infra-acme-eks-staging-mumbai-app-01`). They are
255
+ two labels for the SAME cluster. Use `cluster` when you talk about it, and
256
+ never tell a user their services are on different clusters because the
257
+ strings differ — check with `devlift clusters list` before claiming any such
258
+ thing. That list is already narrowed to registered clusters a service can
259
+ actually be created on, so it is the authority.
242
260
  - Resources behave differently. `s3`, `sqs` and `dynamodb` create and update
243
261
  deploy straight away, so there report the resource name and the workflow id,
244
262
  which is what `deployment status` needs.
@@ -63,7 +63,7 @@ devlift eks create --name NAME --app APP --env ENV --region REGION --type api|wo
63
63
  --repository owner/name --branch main [--branch ...]
64
64
  --language Go|Python|Node.js|"Java Maven"|"Java Gradle" --version 1.24
65
65
  [--set key=value ...] [--public] [-y]
66
- devlift eks show <service> --env ENV configuration as it stands; pending values marked
66
+ devlift eks show <service> --env ENV live config WITH any open draft over it; deployed_settings + pending{} give the real deployed values
67
67
  devlift eks diff <service> --env ENV preview the pending request: Field | Deployed | Requested
68
68
  devlift eks diff <service> --deployed instead: live config vs the last deployment
69
69
  devlift eks settings <service> --env ENV the --set keys that apply to it, with current values
@@ -59,7 +59,9 @@ the user it is a draft, nothing is deployed, and continue with workflow 6.
59
59
  ## 4. Change a running service's settings
60
60
 
61
61
  ```
62
- devlift eks show orders --env stage --no-input -o json # current values; pending_request + pending_keys if a draft exists
62
+ devlift eks show orders --env stage --no-input -o json # settings = live WITH the open draft over it.
63
+ # pending_request null -> settings IS the deployed config
64
+ # pending_request set -> use deployed_settings, or pending{key:{deployed,requested}}, or `eks diff`
63
65
  devlift eks edit orders --env stage --set memory_limit=1 --no-input # Current | New, exit 5
64
66
  devlift eks edit orders --env stage --set memory_limit=1 --no-input -y -o json
65
67
  # → {changed, changes{field:{from,to}}, queue_code, queue_status}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devlift-cli
3
- Version: 0.1.3
3
+ Version: 0.1.5
4
4
  Summary: DevLift command-line tool: create, change, review and deploy DevLift resources from the terminal.
5
5
  License: Proprietary
6
6
  Keywords: devlift,devops,deployment,infrastructure,cli
File without changes
File without changes
File without changes