ocmo-cli 0.8.19__py3-none-any.whl

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 (81) hide show
  1. LICENSE +201 -0
  2. NOTICE +16 -0
  3. ocmo_cli/__init__.py +3 -0
  4. ocmo_cli/__main__.py +4 -0
  5. ocmo_cli/_address.py +182 -0
  6. ocmo_cli/_audit_item.py +33 -0
  7. ocmo_cli/_auth_resolve.py +66 -0
  8. ocmo_cli/_body_payload.py +203 -0
  9. ocmo_cli/_click_groups.py +227 -0
  10. ocmo_cli/_client.py +351 -0
  11. ocmo_cli/_client_commands.py +35 -0
  12. ocmo_cli/_command_registry.py +29 -0
  13. ocmo_cli/_commands_map.py +65 -0
  14. ocmo_cli/_config.py +183 -0
  15. ocmo_cli/_config_content.py +43 -0
  16. ocmo_cli/_delete_item_output.py +129 -0
  17. ocmo_cli/_diff_input.py +144 -0
  18. ocmo_cli/_dry_run.py +292 -0
  19. ocmo_cli/_errors.py +151 -0
  20. ocmo_cli/_exit.py +13 -0
  21. ocmo_cli/_export_metadata.py +47 -0
  22. ocmo_cli/_generated_registry.py +45 -0
  23. ocmo_cli/_get_cast_output.py +52 -0
  24. ocmo_cli/_get_item_list.py +23 -0
  25. ocmo_cli/_globalpermission_output.py +98 -0
  26. ocmo_cli/_import_metadata.py +140 -0
  27. ocmo_cli/_import_plan.py +221 -0
  28. ocmo_cli/_item_output.py +223 -0
  29. ocmo_cli/_lazy_mixin.py +29 -0
  30. ocmo_cli/_ls_wide.py +286 -0
  31. ocmo_cli/_mutating.py +39 -0
  32. ocmo_cli/_notice.py +17 -0
  33. ocmo_cli/_options.py +77 -0
  34. ocmo_cli/_output.py +424 -0
  35. ocmo_cli/_output_manifest.py +332 -0
  36. ocmo_cli/_resolve_draft.py +50 -0
  37. ocmo_cli/_resolve_options.py +143 -0
  38. ocmo_cli/_resolve_output.py +228 -0
  39. ocmo_cli/_resolve_parameters_output.py +72 -0
  40. ocmo_cli/_resolve_series.py +89 -0
  41. ocmo_cli/_resolve_series_chart.py +409 -0
  42. ocmo_cli/_resolve_write.py +185 -0
  43. ocmo_cli/_resolver_output.py +34 -0
  44. ocmo_cli/_resource_aliases.py +22 -0
  45. ocmo_cli/_sdk_dispatch.py +310 -0
  46. ocmo_cli/_typing.py +27 -0
  47. ocmo_cli/_version_output.py +39 -0
  48. ocmo_cli/_whoami_output.py +43 -0
  49. ocmo_cli/commands/__init__.py +1 -0
  50. ocmo_cli/commands/api.py +125 -0
  51. ocmo_cli/commands/api_health.py +12 -0
  52. ocmo_cli/commands/apply.py +153 -0
  53. ocmo_cli/commands/auth.py +786 -0
  54. ocmo_cli/commands/can_i.py +51 -0
  55. ocmo_cli/commands/completion.py +59 -0
  56. ocmo_cli/commands/config_cmd.py +235 -0
  57. ocmo_cli/commands/describe.py +109 -0
  58. ocmo_cli/commands/diff.py +86 -0
  59. ocmo_cli/commands/edit.py +200 -0
  60. ocmo_cli/commands/export.py +242 -0
  61. ocmo_cli/commands/generated.py +907 -0
  62. ocmo_cli/commands/gp_move.py +108 -0
  63. ocmo_cli/commands/import_.py +595 -0
  64. ocmo_cli/commands/item_relocate.py +187 -0
  65. ocmo_cli/commands/ls.py +481 -0
  66. ocmo_cli/commands/resolve.py +658 -0
  67. ocmo_cli/commands/resolve_draft.py +102 -0
  68. ocmo_cli/commands/resolve_parameters.py +65 -0
  69. ocmo_cli/commands/resolve_series.py +109 -0
  70. ocmo_cli/commands/schema.py +112 -0
  71. ocmo_cli/commands/timeline.py +135 -0
  72. ocmo_cli/commands/version_cmd.py +102 -0
  73. ocmo_cli/commands/whoami.py +12 -0
  74. ocmo_cli/main.py +241 -0
  75. ocmo_cli/output_formats.yaml +295 -0
  76. ocmo_cli-0.8.19.dist-info/METADATA +169 -0
  77. ocmo_cli-0.8.19.dist-info/RECORD +81 -0
  78. ocmo_cli-0.8.19.dist-info/WHEEL +4 -0
  79. ocmo_cli-0.8.19.dist-info/entry_points.txt +2 -0
  80. ocmo_cli-0.8.19.dist-info/licenses/LICENSE +201 -0
  81. ocmo_cli-0.8.19.dist-info/licenses/NOTICE +16 -0
@@ -0,0 +1,153 @@
1
+ """ocmo apply — upload a local file as a named OCMO item.
2
+
3
+ Replaces the manifest-based approach with a direct file-to-tree-path mapping:
4
+
5
+ ocmo -n prod apply -f nginx.conf app/nginx/site -t template
6
+ ocmo -n prod apply -f config.yaml app/web/main # -t inferred as config
7
+ ocmo -n prod apply -f - app/web/inline -t config # read from stdin
8
+
9
+ The type is inferred from the file extension when -t is omitted:
10
+ *.yaml / *.yml / *.json → config
11
+ everything else → template
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import sys
17
+ from collections.abc import Callable
18
+ from typing import TYPE_CHECKING, Any
19
+
20
+ import click
21
+
22
+ from .._address import parse_address_or_exit
23
+ from .._client import OcmoCtx
24
+ from .._config_content import prepare_config_apply_content
25
+ from .._errors import sdk_command
26
+ from .._exit import USAGE_ERROR
27
+ from .._options import dry_run_option, namespace_option
28
+ from .._output import err, status
29
+ from .._resolver_output import print_resolver_token
30
+
31
+ if TYPE_CHECKING:
32
+ from ocmo import NamespaceView
33
+
34
+ _VALID_TYPES = ("config", "template", "secret", "resolver")
35
+ _VALID_TYPES_DISPLAY = " | ".join(_VALID_TYPES)
36
+
37
+ _HELP = """\
38
+ Create or update a tree item from a local file.
39
+
40
+ When -t is omitted, type is inferred from the file extension:
41
+ *.yaml / *.yml / *.json become config; all other extensions become template.
42
+
43
+ \b
44
+ Examples:
45
+ ocmo -n prod apply -f config.yaml app/web/main
46
+ ocmo -n prod apply -f nginx.conf app/nginx/site -t template
47
+ cat resolver.yaml | ocmo -n prod apply -f - app/resolvers/default -t resolver
48
+ """
49
+
50
+
51
+ @click.command("apply", help=_HELP)
52
+ @click.argument("tree_path")
53
+ @click.option(
54
+ "-f",
55
+ "--file",
56
+ "file_path",
57
+ required=True,
58
+ metavar="FILE|-",
59
+ help="Source file to upload. Use '-' to read from stdin.",
60
+ )
61
+ @click.option(
62
+ "-t",
63
+ "--type",
64
+ "item_type",
65
+ type=click.Choice(list(_VALID_TYPES)),
66
+ default=None,
67
+ help=f"Item type: {_VALID_TYPES_DISPLAY}. Inferred from extension when omitted.",
68
+ )
69
+ @namespace_option()
70
+ @dry_run_option(help="Print plan without uploading.")
71
+ @click.pass_obj
72
+ @sdk_command
73
+ def apply_cmd(
74
+ ctx: OcmoCtx,
75
+ tree_path: str,
76
+ file_path: str,
77
+ item_type: str | None,
78
+ namespace: str | None,
79
+ dry_run: bool,
80
+ ) -> None:
81
+ path, _version = parse_address_or_exit(tree_path)
82
+
83
+ # Read content
84
+ if file_path == "-":
85
+ content = sys.stdin.read()
86
+ source_name = "<stdin>"
87
+ else:
88
+ with open(file_path) as f:
89
+ content = f.read()
90
+ source_name = file_path
91
+
92
+ # Infer type from extension when not given
93
+ kind = item_type or _infer_type(file_path)
94
+ if kind == "config":
95
+ content = prepare_config_apply_content(content, source_name=source_name)
96
+
97
+ if dry_run or ctx.dry_run:
98
+ from .._dry_run import emit_dry_run_plan, format_apply_dry_run # deferred
99
+
100
+ ns = namespace or ctx.namespace
101
+ emit_dry_run_plan(
102
+ format_apply_dry_run(
103
+ kind=kind,
104
+ path=path,
105
+ source_name=source_name,
106
+ namespace=ns if isinstance(ns, str) else None,
107
+ )
108
+ )
109
+ return
110
+
111
+ view = ctx.namespace_view(namespace)
112
+
113
+ created, result = _upload(view, path, content, kind)
114
+ verb = "Created" if created else "Updated"
115
+ status(f"{verb} {kind} {path!r}.")
116
+ if kind == "resolver" and created:
117
+ print_resolver_token(result)
118
+
119
+
120
+ def _infer_type(file_path: str) -> str:
121
+ if file_path == "-":
122
+ return "config"
123
+ import os
124
+
125
+ ext = os.path.splitext(file_path)[1].lower()
126
+ return "config" if ext in (".yaml", ".yml", ".json") else "template"
127
+
128
+
129
+ def _upload(view: NamespaceView, path: str, content: str, kind: str) -> tuple[bool, Any]:
130
+ """Upload content; returns (created, api_result)."""
131
+ _update, _create = _get_methods(view, kind)
132
+ try:
133
+ result = _update(path=path, content=content)
134
+ return False, result
135
+ except Exception:
136
+ result = _create(path=path, content=content)
137
+ return True, result
138
+
139
+
140
+ def _get_methods(
141
+ view: NamespaceView,
142
+ kind: str,
143
+ ) -> tuple[Callable[..., Any], Callable[..., Any]]:
144
+ methods = {
145
+ "config": (view.update_config, view.create_config),
146
+ "template": (view.update_template, view.create_template),
147
+ "secret": (view.update_secret, view.create_secret),
148
+ "resolver": (view.update_resolver, view.create_resolver),
149
+ }
150
+ if kind not in methods:
151
+ err(f"Unknown type {kind!r}. Valid: {_VALID_TYPES_DISPLAY}")
152
+ raise SystemExit(USAGE_ERROR)
153
+ return methods[kind]