lazyops-cli 1.0.0__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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mridul Tiwari
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,247 @@
1
+ Metadata-Version: 2.4
2
+ Name: lazyops-cli
3
+ Version: 1.0.0
4
+ Summary: CLI to discover, fetch, and run reusable automation workflows from remote plugin packs.
5
+ Author: Mridul Tiwari
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/MridulTi/LazyOps
8
+ Project-URL: Repository, https://github.com/MridulTi/LazyOps
9
+ Project-URL: Issues, https://github.com/MridulTi/LazyOps/issues
10
+ Project-URL: Documentation, https://github.com/MridulTi/LazyOps#readme
11
+ Keywords: cli,automation,workflows,devops,ops
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: System Administrators
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
22
+ Classifier: Topic :: System :: Systems Administration
23
+ Requires-Python: >=3.10
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: typer>=0.12.0
27
+ Requires-Dist: PyYAML>=6.0
28
+ Dynamic: license-file
29
+
30
+ # LazyOps
31
+
32
+ > Turn your scattered scripts into reusable, searchable, and shareable workflows.
33
+
34
+ ## Why LazyOps?
35
+
36
+ Every engineer has a folder full of scripts:
37
+
38
+ ```text
39
+ cleanup.sh
40
+ restart-pods.py
41
+ rotate_logs.sh
42
+ debug-nginx.sh
43
+ fix-permissions.sh
44
+ ```
45
+
46
+ After a few months:
47
+
48
+ * You forget they exist.
49
+ * You can't remember their arguments.
50
+ * They're undocumented.
51
+ * They only work on your machine.
52
+ * Your teammates rewrite the same automation.
53
+
54
+ LazyOps solves this by adding a lightweight workflow layer on top of existing scripts.
55
+
56
+ No rewrites. No proprietary language. Just structure.
57
+
58
+ ## Features
59
+
60
+ * 🚀 Run scripts as named workflows (`lazyops run pack/plugin`)
61
+ * 📦 Install workflow **packs** (aws, kubernetes, security, …) from a remote catalog
62
+ * 🔍 Search and list workflows across installed packs
63
+ * 🐍 Support multiple runtimes (Bash, Python, Node.js, executables)
64
+ * 📝 Interactive picker when you run `lazyops run` with no arguments
65
+ * ✅ Manifest validation before execution
66
+ * 🔖 Pin catalog version by git branch or tag (`source.ref`)
67
+ * 🤝 Workflows live in a separate repo — share and version them independently
68
+
69
+ ## Architecture
70
+
71
+ LazyOps is a **CLI-only installer**. Workflows are fetched at runtime from a separate plugins repo:
72
+
73
+ | Repo | Role |
74
+ |------|------|
75
+ | [LazyOps](https://github.com/MridulTi/LazyOps) | CLI, config, fetch & run |
76
+ | [lazyops-plugins](https://github.com/MridulTi/lazyops-plugins) | Workflow catalog (packs + plugins) |
77
+
78
+ Each **pack** is a bundle (e.g. `aws`, `kubernetes`). Each **plugin** is one workflow folder under that pack. The git **branch or tag** on the plugins repo is the catalog **version**.
79
+
80
+ ```text
81
+ lazyops-plugins/
82
+ └── plugins/
83
+ └── aws/
84
+ ├── pack.yaml
85
+ └── addpatchclasstag/
86
+ ├── workflow.yaml
87
+ ├── script.sh
88
+ └── README.md
89
+ ```
90
+
91
+ Run a workflow:
92
+
93
+ ```bash
94
+ lazyops run aws/addpatchclasstag
95
+ ```
96
+
97
+ LazyOps fetches the plugin at your configured `source.ref`, validates the manifest, and executes the script.
98
+
99
+ ## Installation
100
+
101
+ ### From PyPI (recommended)
102
+
103
+ The PyPI package is **`lazyops-cli`** (the name `lazyops` is taken by another project). The command is still `lazyops`:
104
+
105
+ ```bash
106
+ pipx install lazyops-cli
107
+ lazyops --help
108
+ ```
109
+
110
+ Requires Python 3.10+ and `git` (used to fetch workflows at runtime).
111
+
112
+ ### From source (development)
113
+
114
+ LazyOps runs from a project-local virtual environment (`.venv`). Do not install with system `pip`.
115
+
116
+ ```bash
117
+ git clone https://github.com/MridulTi/LazyOps.git
118
+ cd LazyOps
119
+ bash setup.sh
120
+ source ~/.zshrc # or ~/.bashrc — loads the lazyops alias
121
+ lazyops --help # works from any directory
122
+ ```
123
+
124
+ `setup.sh` adds a global shell alias pointing at the repo wrapper (which always uses `.venv`):
125
+
126
+ ```bash
127
+ alias lazyops='/path/to/LazyOps/lazyops'
128
+ export LAZYOPS_ROOT='/path/to/LazyOps'
129
+ ```
130
+
131
+ You can also run from the repo without the alias:
132
+
133
+ ```bash
134
+ ./lazyops --help
135
+ source .venv/bin/activate
136
+ ```
137
+
138
+ ## Quick start
139
+
140
+ Point LazyOps at the plugins catalog, enable packs, and run workflows:
141
+
142
+ ```bash
143
+ # 1. Configure the plugins source (branch = version)
144
+ lazyops source init https://github.com/MridulTi/lazyops-plugins.git --ref v1.0.0
145
+
146
+ # 2. Enable packs you need
147
+ lazyops pack add aws
148
+ lazyops pack add kubernetes
149
+
150
+ # 3. Discover and run
151
+ lazyops list
152
+ lazyops search patch
153
+ lazyops run aws/addpatchclasstag
154
+ lazyops run # interactive: pick pack → pick plugin → confirm
155
+
156
+ # 4. Upgrade catalog version
157
+ lazyops source update --ref v1.2.0
158
+ ```
159
+
160
+ For local development against a checkout of lazyops-plugins:
161
+
162
+ ```bash
163
+ lazyops source init file:///path/to/lazyops-plugins --ref main
164
+ ```
165
+
166
+ Config is stored at `~/.lazyops/config.yaml`:
167
+
168
+ ```yaml
169
+ source:
170
+ url: https://github.com/MridulTi/lazyops-plugins.git
171
+ ref: v1.0.0
172
+ path_prefix: plugins
173
+ packs:
174
+ - aws
175
+ - kubernetes
176
+ ```
177
+
178
+ ## Commands
179
+
180
+ | Command | Purpose |
181
+ |---------|---------|
182
+ | `lazyops source init <url> [--ref]` | Set plugins repo URL and version |
183
+ | `lazyops source show` | Show current source config |
184
+ | `lazyops source update --ref <ref>` | Bump catalog version |
185
+ | `lazyops pack add <pack>` | Enable a pack |
186
+ | `lazyops pack list` | List installed packs |
187
+ | `lazyops pack list <pack>` | List plugins in a pack |
188
+ | `lazyops pack remove <pack>` | Disable a pack |
189
+ | `lazyops run <pack>/<plugin> [args...]` | Fetch and run a workflow |
190
+ | `lazyops run` | Interactive workflow picker |
191
+ | `lazyops list` | List workflows in installed packs |
192
+ | `lazyops search <query>` | Search by name, id, or description |
193
+
194
+ ## Example manifest
195
+
196
+ ```yaml
197
+ id: addpatchclasstag
198
+
199
+ name: "Add Patch Class Tag"
200
+
201
+ description: "Add patch class tags to instances. Required env: AWS_REGION or REGION."
202
+
203
+ runtime: bash
204
+
205
+ entrypoint: script.sh
206
+
207
+ pack: aws
208
+
209
+ version: 1.0.0
210
+
211
+ inputs:
212
+ - name: instance_id
213
+ required: true
214
+ ```
215
+
216
+ ## Philosophy
217
+
218
+ Scripts should remain scripts.
219
+
220
+ LazyOps does not replace your automation. It makes it easier to organize, discover, document, and reuse — with a shared catalog your whole team can install and pin to a version.
221
+
222
+ ## Roadmap
223
+
224
+ * [x] Workflow specification
225
+ * [x] Remote plugin catalog (source + packs)
226
+ * [x] Fetch and run workflows from git
227
+ * [x] Interactive CLI
228
+ * [x] Search and list
229
+ * [ ] Input validation
230
+ * [ ] Plugin runtimes
231
+ * [ ] Optional web dashboard
232
+
233
+ ## Contributing
234
+
235
+ Contributions are welcome.
236
+
237
+ You can help by:
238
+
239
+ * Adding workflows to [lazyops-plugins](https://github.com/MridulTi/lazyops-plugins)
240
+ * Improving CLI documentation
241
+ * Supporting additional runtimes
242
+ * Reporting bugs
243
+ * Suggesting new features
244
+
245
+ ## License
246
+
247
+ MIT License
@@ -0,0 +1,218 @@
1
+ # LazyOps
2
+
3
+ > Turn your scattered scripts into reusable, searchable, and shareable workflows.
4
+
5
+ ## Why LazyOps?
6
+
7
+ Every engineer has a folder full of scripts:
8
+
9
+ ```text
10
+ cleanup.sh
11
+ restart-pods.py
12
+ rotate_logs.sh
13
+ debug-nginx.sh
14
+ fix-permissions.sh
15
+ ```
16
+
17
+ After a few months:
18
+
19
+ * You forget they exist.
20
+ * You can't remember their arguments.
21
+ * They're undocumented.
22
+ * They only work on your machine.
23
+ * Your teammates rewrite the same automation.
24
+
25
+ LazyOps solves this by adding a lightweight workflow layer on top of existing scripts.
26
+
27
+ No rewrites. No proprietary language. Just structure.
28
+
29
+ ## Features
30
+
31
+ * 🚀 Run scripts as named workflows (`lazyops run pack/plugin`)
32
+ * 📦 Install workflow **packs** (aws, kubernetes, security, …) from a remote catalog
33
+ * 🔍 Search and list workflows across installed packs
34
+ * 🐍 Support multiple runtimes (Bash, Python, Node.js, executables)
35
+ * 📝 Interactive picker when you run `lazyops run` with no arguments
36
+ * ✅ Manifest validation before execution
37
+ * 🔖 Pin catalog version by git branch or tag (`source.ref`)
38
+ * 🤝 Workflows live in a separate repo — share and version them independently
39
+
40
+ ## Architecture
41
+
42
+ LazyOps is a **CLI-only installer**. Workflows are fetched at runtime from a separate plugins repo:
43
+
44
+ | Repo | Role |
45
+ |------|------|
46
+ | [LazyOps](https://github.com/MridulTi/LazyOps) | CLI, config, fetch & run |
47
+ | [lazyops-plugins](https://github.com/MridulTi/lazyops-plugins) | Workflow catalog (packs + plugins) |
48
+
49
+ Each **pack** is a bundle (e.g. `aws`, `kubernetes`). Each **plugin** is one workflow folder under that pack. The git **branch or tag** on the plugins repo is the catalog **version**.
50
+
51
+ ```text
52
+ lazyops-plugins/
53
+ └── plugins/
54
+ └── aws/
55
+ ├── pack.yaml
56
+ └── addpatchclasstag/
57
+ ├── workflow.yaml
58
+ ├── script.sh
59
+ └── README.md
60
+ ```
61
+
62
+ Run a workflow:
63
+
64
+ ```bash
65
+ lazyops run aws/addpatchclasstag
66
+ ```
67
+
68
+ LazyOps fetches the plugin at your configured `source.ref`, validates the manifest, and executes the script.
69
+
70
+ ## Installation
71
+
72
+ ### From PyPI (recommended)
73
+
74
+ The PyPI package is **`lazyops-cli`** (the name `lazyops` is taken by another project). The command is still `lazyops`:
75
+
76
+ ```bash
77
+ pipx install lazyops-cli
78
+ lazyops --help
79
+ ```
80
+
81
+ Requires Python 3.10+ and `git` (used to fetch workflows at runtime).
82
+
83
+ ### From source (development)
84
+
85
+ LazyOps runs from a project-local virtual environment (`.venv`). Do not install with system `pip`.
86
+
87
+ ```bash
88
+ git clone https://github.com/MridulTi/LazyOps.git
89
+ cd LazyOps
90
+ bash setup.sh
91
+ source ~/.zshrc # or ~/.bashrc — loads the lazyops alias
92
+ lazyops --help # works from any directory
93
+ ```
94
+
95
+ `setup.sh` adds a global shell alias pointing at the repo wrapper (which always uses `.venv`):
96
+
97
+ ```bash
98
+ alias lazyops='/path/to/LazyOps/lazyops'
99
+ export LAZYOPS_ROOT='/path/to/LazyOps'
100
+ ```
101
+
102
+ You can also run from the repo without the alias:
103
+
104
+ ```bash
105
+ ./lazyops --help
106
+ source .venv/bin/activate
107
+ ```
108
+
109
+ ## Quick start
110
+
111
+ Point LazyOps at the plugins catalog, enable packs, and run workflows:
112
+
113
+ ```bash
114
+ # 1. Configure the plugins source (branch = version)
115
+ lazyops source init https://github.com/MridulTi/lazyops-plugins.git --ref v1.0.0
116
+
117
+ # 2. Enable packs you need
118
+ lazyops pack add aws
119
+ lazyops pack add kubernetes
120
+
121
+ # 3. Discover and run
122
+ lazyops list
123
+ lazyops search patch
124
+ lazyops run aws/addpatchclasstag
125
+ lazyops run # interactive: pick pack → pick plugin → confirm
126
+
127
+ # 4. Upgrade catalog version
128
+ lazyops source update --ref v1.2.0
129
+ ```
130
+
131
+ For local development against a checkout of lazyops-plugins:
132
+
133
+ ```bash
134
+ lazyops source init file:///path/to/lazyops-plugins --ref main
135
+ ```
136
+
137
+ Config is stored at `~/.lazyops/config.yaml`:
138
+
139
+ ```yaml
140
+ source:
141
+ url: https://github.com/MridulTi/lazyops-plugins.git
142
+ ref: v1.0.0
143
+ path_prefix: plugins
144
+ packs:
145
+ - aws
146
+ - kubernetes
147
+ ```
148
+
149
+ ## Commands
150
+
151
+ | Command | Purpose |
152
+ |---------|---------|
153
+ | `lazyops source init <url> [--ref]` | Set plugins repo URL and version |
154
+ | `lazyops source show` | Show current source config |
155
+ | `lazyops source update --ref <ref>` | Bump catalog version |
156
+ | `lazyops pack add <pack>` | Enable a pack |
157
+ | `lazyops pack list` | List installed packs |
158
+ | `lazyops pack list <pack>` | List plugins in a pack |
159
+ | `lazyops pack remove <pack>` | Disable a pack |
160
+ | `lazyops run <pack>/<plugin> [args...]` | Fetch and run a workflow |
161
+ | `lazyops run` | Interactive workflow picker |
162
+ | `lazyops list` | List workflows in installed packs |
163
+ | `lazyops search <query>` | Search by name, id, or description |
164
+
165
+ ## Example manifest
166
+
167
+ ```yaml
168
+ id: addpatchclasstag
169
+
170
+ name: "Add Patch Class Tag"
171
+
172
+ description: "Add patch class tags to instances. Required env: AWS_REGION or REGION."
173
+
174
+ runtime: bash
175
+
176
+ entrypoint: script.sh
177
+
178
+ pack: aws
179
+
180
+ version: 1.0.0
181
+
182
+ inputs:
183
+ - name: instance_id
184
+ required: true
185
+ ```
186
+
187
+ ## Philosophy
188
+
189
+ Scripts should remain scripts.
190
+
191
+ LazyOps does not replace your automation. It makes it easier to organize, discover, document, and reuse — with a shared catalog your whole team can install and pin to a version.
192
+
193
+ ## Roadmap
194
+
195
+ * [x] Workflow specification
196
+ * [x] Remote plugin catalog (source + packs)
197
+ * [x] Fetch and run workflows from git
198
+ * [x] Interactive CLI
199
+ * [x] Search and list
200
+ * [ ] Input validation
201
+ * [ ] Plugin runtimes
202
+ * [ ] Optional web dashboard
203
+
204
+ ## Contributing
205
+
206
+ Contributions are welcome.
207
+
208
+ You can help by:
209
+
210
+ * Adding workflows to [lazyops-plugins](https://github.com/MridulTi/lazyops-plugins)
211
+ * Improving CLI documentation
212
+ * Supporting additional runtimes
213
+ * Reporting bugs
214
+ * Suggesting new features
215
+
216
+ ## License
217
+
218
+ MIT License
File without changes
@@ -0,0 +1,22 @@
1
+ import typer
2
+
3
+ from registry.catalog import CatalogError, iter_installed_workflows
4
+
5
+
6
+ def register(app:typer.Typer):
7
+
8
+ @app.command("list",help="List all commands")
9
+ def list_workflows():
10
+ try:
11
+ items = iter_installed_workflows()
12
+ except CatalogError as exc:
13
+ typer.secho(str(exc), fg=typer.colors.RED, err=True)
14
+ raise typer.Exit(1)
15
+ if not items:
16
+ typer.echo("No workflows found.")
17
+ typer.echo("Install packs: lazyops pack add aws")
18
+ return
19
+ for i, item in enumerate(items, start=1):
20
+ wf = item["workflow"]
21
+ name = wf.get("name", item["plugin"])
22
+ typer.echo(f"{i}. {item['pack']}/{item['plugin']} — {name}")
@@ -0,0 +1,75 @@
1
+ import typer
2
+
3
+ from registry import packs as pack_registry
4
+ from registry.fetch import FetchError, list_pack_plugins
5
+ from registry.source import SourceError, get_source
6
+
7
+ pack_app = typer.Typer(help="Manage installed workflow packs (aws,kubernetes,...)")
8
+
9
+ def register(app: typer.Typer):
10
+ app.add_typer(pack_app,name="pack")
11
+
12
+ @pack_app.command("add")
13
+ def pack_add(name:str=typer.Argument(...,help="Pack id eg. aws")):
14
+ try:
15
+ pack_registry.add_pack(name)
16
+ except pack_registry.PackError as exc:
17
+ typer.secho(str(exc),fg=typer.colors.RED, err=True)
18
+ raise typer.Exit(1)
19
+
20
+ typer.secho(f"Installed pack: {name}", fg=typer.colors.GREEN)
21
+ typer.secho("Run workflow with: lazyops run <pack>/<plugin>")
22
+
23
+ @pack_app.command("list")
24
+ def pack_list(pack: str | None = typer.Argument(None, help="Optional pack id to list plugins")):
25
+ if pack is None:
26
+ items = pack_registry.list_packs()
27
+ if not items:
28
+ typer.echo("No packs installed.")
29
+ typer.echo("Install one: lazyops pack add aws")
30
+ return
31
+ try:
32
+ source = get_source()
33
+ except SourceError as exc:
34
+ typer.secho(str(exc), fg=typer.colors.RED, err=True)
35
+ raise typer.Exit(1)
36
+ for name in items:
37
+ try:
38
+ plugins = list_pack_plugins(
39
+ source["url"],
40
+ source["ref"],
41
+ source.get("path_prefix", "plugins"),
42
+ name,
43
+ )
44
+ typer.echo(f"{name} ({len(plugins)} plugins)")
45
+ except FetchError as exc:
46
+ typer.echo(f"{name} (failed to list: {exc})")
47
+ else:
48
+ try:
49
+ source = get_source()
50
+ plugins = list_pack_plugins(
51
+ source["url"],
52
+ source["ref"],
53
+ source.get("path_prefix", "plugins"),
54
+ pack,
55
+ )
56
+ except SourceError as exc:
57
+ typer.secho(str(exc), fg=typer.colors.RED, err=True)
58
+ raise typer.Exit(1)
59
+ except FetchError as exc:
60
+ typer.secho(str(exc), fg=typer.colors.RED, err=True)
61
+ raise typer.Exit(1)
62
+ if not plugins:
63
+ typer.echo(f"No plugins found in pack: {pack}")
64
+ return
65
+ for plugin in plugins:
66
+ typer.echo(f"{pack}/{plugin}")
67
+
68
+ @pack_app.command("remove")
69
+ def pack_remove(name: str = typer.Argument(..., help="Pack id to remove")):
70
+ try:
71
+ pack_registry.remove_pack(name)
72
+ except pack_registry.PackError as exc:
73
+ typer.secho(str(exc), fg=typer.colors.RED, err=True)
74
+ raise typer.Exit(1)
75
+ typer.secho(f"Removed pack: {name}", fg=typer.colors.GREEN)