opsmith-cli 0.3.1b0__tar.gz → 0.4.1b0__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.
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/.gitignore +2 -1
- opsmith_cli-0.4.1b0/CONVENTIONS.md +35 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/PKG-INFO +2 -2
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/agent.py +4 -4
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/cloud_providers/aws.py +54 -22
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/cloud_providers/base.py +3 -9
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/cloud_providers/gcp.py +58 -22
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/deployment_strategies/base.py +74 -61
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/deployment_strategies/monolithic.py +375 -104
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/infra_provisioners/ansible_provisioner.py +6 -3
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/main.py +96 -88
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/models.py +61 -3
- opsmith_cli-0.4.1b0/opsmith/templates/container_registry/aws/main.tf +22 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/templates/container_registry/aws/variables.tf +6 -0
- opsmith_cli-0.4.1b0/opsmith/templates/container_registry/gcp/main.tf +26 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/templates/container_registry/gcp/variables.tf +6 -0
- opsmith_cli-0.4.1b0/opsmith/templates/docker_build_push/aws/main.yml +73 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/templates/docker_build_push/gcp/main.yml +24 -12
- opsmith_cli-0.4.1b0/opsmith/templates/docker_compose_deploy/aws/inventory.yml +15 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/templates/docker_compose_deploy/aws/main.yml +26 -14
- opsmith_cli-0.4.1b0/opsmith/templates/docker_compose_deploy/gcp/inventory.yml +8 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/templates/docker_compose_deploy/gcp/main.yml +24 -14
- opsmith_cli-0.4.1b0/opsmith/templates/docker_compose_run/aws/inventory.yml +15 -0
- {opsmith_cli-0.3.1b0/opsmith/templates/docker_compose_run/common → opsmith_cli-0.4.1b0/opsmith/templates/docker_compose_run/aws}/main.yml +10 -3
- opsmith_cli-0.4.1b0/opsmith/templates/docker_compose_run/gcp/inventory.yml +8 -0
- opsmith_cli-0.4.1b0/opsmith/templates/docker_compose_run/gcp/main.yml +26 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/templates/docker_compose_snippets/base.yml +8 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/templates/docker_compose_snippets/services/backend_api.yml +1 -0
- opsmith_cli-0.4.1b0/opsmith/templates/docker_compose_snippets/services/backend_worker.yml +4 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/templates/docker_compose_snippets/services/full_stack.yml +1 -0
- opsmith_cli-0.4.1b0/opsmith/templates/fetch_remote_files/aws/inventory.yml +15 -0
- opsmith_cli-0.4.1b0/opsmith/templates/fetch_remote_files/gcp/inventory.yml +8 -0
- opsmith_cli-0.4.1b0/opsmith/templates/fetch_remote_files/gcp/main.yml +22 -0
- opsmith_cli-0.4.1b0/opsmith/templates/virtual_machine/aws/main.tf +270 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/templates/virtual_machine/aws/outputs.tf +7 -2
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/templates/virtual_machine/aws/variables.tf +10 -0
- opsmith_cli-0.4.1b0/opsmith/templates/virtual_machine/gcp/main.tf +205 -0
- opsmith_cli-0.4.1b0/opsmith/templates/virtual_machine/gcp/outputs.tf +19 -0
- opsmith_cli-0.4.1b0/opsmith/templates/virtual_machine/gcp/variables.tf +51 -0
- opsmith_cli-0.4.1b0/opsmith/templates/virtual_machine_setup/aws/inventory.yml +15 -0
- opsmith_cli-0.4.1b0/opsmith/templates/virtual_machine_setup/aws/main.yml +236 -0
- opsmith_cli-0.4.1b0/opsmith/templates/virtual_machine_setup/gcp/inventory.yml +8 -0
- opsmith_cli-0.4.1b0/opsmith/templates/virtual_machine_setup/gcp/main.yml +90 -0
- opsmith_cli-0.4.1b0/opsmith/tests/__init__.py +0 -0
- opsmith_cli-0.4.1b0/opsmith/tests/test_service_detector.py +133 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/types.py +21 -3
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/pyproject.toml +7 -2
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/uv.lock +1577 -100
- opsmith_cli-0.3.1b0/CONVENTIONS.md +0 -16
- opsmith_cli-0.3.1b0/opsmith/templates/container_registry/aws/main.tf +0 -12
- opsmith_cli-0.3.1b0/opsmith/templates/container_registry/gcp/main.tf +0 -11
- opsmith_cli-0.3.1b0/opsmith/templates/docker_build_push/aws/main.yml +0 -51
- opsmith_cli-0.3.1b0/opsmith/templates/docker_compose_snippets/services/backend_worker.yml +0 -3
- opsmith_cli-0.3.1b0/opsmith/templates/docker_setup/aws/main.yml +0 -36
- opsmith_cli-0.3.1b0/opsmith/templates/docker_setup/gcp/main.yml +0 -38
- opsmith_cli-0.3.1b0/opsmith/templates/virtual_machine/aws/main.tf +0 -136
- opsmith_cli-0.3.1b0/opsmith/templates/virtual_machine/gcp/main.tf +0 -74
- opsmith_cli-0.3.1b0/opsmith/templates/virtual_machine/gcp/outputs.tf +0 -14
- opsmith_cli-0.3.1b0/opsmith/templates/virtual_machine/gcp/variables.tf +0 -24
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/.flake8 +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/.github/workflows/python-publish.yml +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/.pre-commit-config.yaml +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/LICENSE.txt +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/README.md +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/__init__.py +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/cloud_providers/__init__.py +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/constants.py +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/deployment_strategies/__init__.py +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/exceptions.py +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/git_repo.py +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/infra_provisioners/__init__.py +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/infra_provisioners/base_provisioner.py +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/infra_provisioners/terraform_provisioner.py +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/prompts.py +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/queries/tree-sitter-languages/README.md +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/queries/tree-sitter-languages/arduino-tags.scm +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/queries/tree-sitter-languages/c-tags.scm +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/queries/tree-sitter-languages/c_sharp-tags.scm +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/queries/tree-sitter-languages/chatito-tags.scm +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/queries/tree-sitter-languages/commonlisp-tags.scm +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/queries/tree-sitter-languages/cpp-tags.scm +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/queries/tree-sitter-languages/csharp-tags.scm +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/queries/tree-sitter-languages/d-tags.scm +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/queries/tree-sitter-languages/dart-tags.scm +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/queries/tree-sitter-languages/elisp-tags.scm +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/queries/tree-sitter-languages/elixir-tags.scm +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/queries/tree-sitter-languages/elm-tags.scm +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/queries/tree-sitter-languages/gleam-tags.scm +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/queries/tree-sitter-languages/go-tags.scm +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/queries/tree-sitter-languages/hcl-tags.scm +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/queries/tree-sitter-languages/java-tags.scm +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/queries/tree-sitter-languages/javascript-tags.scm +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/queries/tree-sitter-languages/kotlin-tags.scm +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/queries/tree-sitter-languages/lua-tags.scm +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/queries/tree-sitter-languages/ocaml-tags.scm +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/queries/tree-sitter-languages/ocaml_interface-tags.scm +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/queries/tree-sitter-languages/php-tags.scm +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/queries/tree-sitter-languages/pony-tags.scm +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/queries/tree-sitter-languages/properties-tags.scm +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/queries/tree-sitter-languages/python-tags.scm +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/queries/tree-sitter-languages/ql-tags.scm +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/queries/tree-sitter-languages/r-tags.scm +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/queries/tree-sitter-languages/racket-tags.scm +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/queries/tree-sitter-languages/ruby-tags.scm +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/queries/tree-sitter-languages/rust-tags.scm +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/queries/tree-sitter-languages/scala-tags.scm +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/queries/tree-sitter-languages/solidity-tags.scm +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/queries/tree-sitter-languages/swift-tags.scm +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/queries/tree-sitter-languages/typescript-tags.scm +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/queries/tree-sitter-languages/udev-tags.scm +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/repo_map.py +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/service_detector.py +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/settings.py +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/templates/cloud_storage_cleanup/aws/main.yml +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/templates/cloud_storage_cleanup/gcp/main.yml +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/templates/container_registry/aws/outputs.tf +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/templates/container_registry/gcp/outputs.tf +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/templates/docker_compose_snippets/elasticsearch.yml +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/templates/docker_compose_snippets/kafka.yml +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/templates/docker_compose_snippets/mongodb.yml +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/templates/docker_compose_snippets/mysql.yml +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/templates/docker_compose_snippets/postgresql.yml +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/templates/docker_compose_snippets/rabbitmq.yml +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/templates/docker_compose_snippets/redis.yml +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/templates/docker_compose_snippets/traefik.yml +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/templates/docker_compose_snippets/weaviate.yml +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/templates/dockerfiles/python_backend_api +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/templates/dockerfiles/python_backend_worker +0 -0
- {opsmith_cli-0.3.1b0/opsmith/templates/fetch_remote_files/common → opsmith_cli-0.4.1b0/opsmith/templates/fetch_remote_files/aws}/main.yml +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/templates/frontend_bucket_cert/aws/main.tf +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/templates/frontend_bucket_cert/aws/outputs.tf +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/templates/frontend_bucket_cert/aws/variables.tf +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/templates/frontend_bucket_cert/gcp/main.tf +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/templates/frontend_bucket_cert/gcp/outputs.tf +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/templates/frontend_bucket_cert/gcp/variables.tf +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/templates/frontend_cdn/aws/main.tf +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/templates/frontend_cdn/aws/outputs.tf +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/templates/frontend_cdn/aws/variables.tf +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/templates/frontend_cdn/gcp/main.tf +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/templates/frontend_cdn/gcp/outputs.tf +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/templates/frontend_cdn/gcp/variables.tf +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/templates/frontend_deploy/aws/main.yml +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/templates/frontend_deploy/gcp/main.yml +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/opsmith/utils.py +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/resources/deploy_demo.gif +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/resources/deploy_demo.svg +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/resources/setup_demo.gif +0 -0
- {opsmith_cli-0.3.1b0 → opsmith_cli-0.4.1b0}/resources/setup_demo.svg +0 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Engineering Conventions
|
|
2
|
+
|
|
3
|
+
## Conventions
|
|
4
|
+
> When writing code follow these conventions
|
|
5
|
+
|
|
6
|
+
- Write simple verbose code over terse, compact, dense code
|
|
7
|
+
- Use types everywhere possible.
|
|
8
|
+
- Add logs where applicable so that debugging becomes easy
|
|
9
|
+
- Add docstring to functions that describe its use
|
|
10
|
+
- Add try/except blocks sparingly, only where it is essential
|
|
11
|
+
- Use pytest to write tests
|
|
12
|
+
- Add docstring to each test case that describes its flow clearly
|
|
13
|
+
- Tests should mock out external calls and command calls
|
|
14
|
+
- Do not assert on logs in tests as that is not a best practice
|
|
15
|
+
|
|
16
|
+
## Project Structure
|
|
17
|
+
|
|
18
|
+
- `opsmith/` - Source code for this CLI tool
|
|
19
|
+
- `cloud_providers/` - Cloud provider implementations (e.g., AWS, GCP).
|
|
20
|
+
- `deployment_strategies/` - Application deployment strategies (e.g., monolithic).
|
|
21
|
+
- `infra_provisioners/` - Wrappers for infrastructure tools (e.g., Terraform, Ansible).
|
|
22
|
+
- `templates/` - Infrastructure-as-code templates (e.g., Terraform modules, Ansible Playbooks).
|
|
23
|
+
- `tests/` - Tests for all the components
|
|
24
|
+
- `agent.py` - AI agent logic.
|
|
25
|
+
- `exceptions.py` - Custom exceptions used by Opsmith
|
|
26
|
+
- `git_repo.py` - Connector for a git repo
|
|
27
|
+
- `main.py` - CLI command definitions (Typer).
|
|
28
|
+
- `models.py` - List of available LLMs
|
|
29
|
+
- `prompts.py` - Prompts used to interact with the LLM
|
|
30
|
+
- `repo_map.py` - Generates a ,ap of the files in the repository
|
|
31
|
+
- `service_detector.py` - Logic to detect services in a repository.
|
|
32
|
+
- `settings.py` - Configurations for Opsmith
|
|
33
|
+
- `types.py` - Core Pydantic data models for configuration and state.
|
|
34
|
+
- `utils.py` - Shared utility functions.
|
|
35
|
+
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: opsmith-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.1b0
|
|
4
4
|
Summary: Opsmith is an AI devops engineer in your terminal
|
|
5
5
|
License-Expression: GPL-3.0-only
|
|
6
6
|
License-File: LICENSE.txt
|
|
@@ -28,7 +28,7 @@ Requires-Dist: inquirer>=3.4.0
|
|
|
28
28
|
Requires-Dist: jinja2>=3.1.6
|
|
29
29
|
Requires-Dist: networkx>=3.4.2
|
|
30
30
|
Requires-Dist: pick>=2.4.0
|
|
31
|
-
Requires-Dist: pydantic-ai[logfire]==
|
|
31
|
+
Requires-Dist: pydantic-ai[logfire]==1.27.0
|
|
32
32
|
Requires-Dist: pydantic>=2.11.5
|
|
33
33
|
Requires-Dist: python-dotenv>=1.1.0
|
|
34
34
|
Requires-Dist: pyyaml>=6.0.2
|
|
@@ -45,9 +45,9 @@ def build_agent(model_config: Type[BaseAiModel], instrument: bool = False) -> Ag
|
|
|
45
45
|
)
|
|
46
46
|
|
|
47
47
|
@agent.tool(retries=5)
|
|
48
|
-
def
|
|
48
|
+
def read_repo_files(ctx: RunContext[AgentDeps], filenames: List[str]) -> List[str]:
|
|
49
49
|
"""
|
|
50
|
-
Reads and returns the content of specified files from the
|
|
50
|
+
Reads and returns the content of specified files from the repo.
|
|
51
51
|
Use this to understand file structures, dependencies, or specific configurations.
|
|
52
52
|
Provide the relative file paths from the repository root.
|
|
53
53
|
|
|
@@ -59,9 +59,9 @@ def build_agent(model_config: Type[BaseAiModel], instrument: bool = False) -> Ag
|
|
|
59
59
|
A list of strings, where each string is the content of the corresponding file.
|
|
60
60
|
The order of contents in the list matches the order of filenames in the input.
|
|
61
61
|
"""
|
|
62
|
-
if is_duplicate_tool_call(ctx, "
|
|
62
|
+
if is_duplicate_tool_call(ctx, "read_repo_files"):
|
|
63
63
|
raise ModelRetry(
|
|
64
|
-
"The tool '
|
|
64
|
+
"The tool 'read_repo_files' has already been called with the exact same list of "
|
|
65
65
|
"files in this conversation."
|
|
66
66
|
)
|
|
67
67
|
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import shutil
|
|
1
2
|
from typing import Literal, Type
|
|
2
3
|
|
|
3
4
|
import boto3
|
|
4
5
|
import botocore.session
|
|
6
|
+
import inquirer
|
|
5
7
|
from botocore.exceptions import ClientError, NoCredentialsError
|
|
6
8
|
from pydantic import Field
|
|
7
9
|
|
|
@@ -13,11 +15,13 @@ from opsmith.cloud_providers.base import (
|
|
|
13
15
|
MachineType,
|
|
14
16
|
MachineTypeList,
|
|
15
17
|
)
|
|
18
|
+
from opsmith.utils import WaitingSpinner
|
|
16
19
|
|
|
17
20
|
|
|
18
21
|
class AWSCloudDetail(BaseCloudProviderDetail):
|
|
19
22
|
name: Literal["AWS"] = Field(default="AWS", description="Provider name, 'AWS'")
|
|
20
23
|
account_id: str = Field(..., description="AWS Account ID.")
|
|
24
|
+
ssm_plugin: str = Field(..., description="Path to session-manager-plugin executable.")
|
|
21
25
|
|
|
22
26
|
|
|
23
27
|
class AWSProvider(BaseCloudProvider):
|
|
@@ -38,33 +42,35 @@ class AWSProvider(BaseCloudProvider):
|
|
|
38
42
|
"""The cloud provider detail model."""
|
|
39
43
|
return AWSCloudDetail
|
|
40
44
|
|
|
41
|
-
|
|
45
|
+
@staticmethod
|
|
46
|
+
def get_regions() -> list[tuple[str, str]]:
|
|
42
47
|
"""
|
|
43
48
|
Retrieves a list of available AWS regions with their display names.
|
|
44
49
|
"""
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
50
|
+
with WaitingSpinner(text="Fetching available regions from AWS Cloud Provider..."):
|
|
51
|
+
# Get available region codes from EC2
|
|
52
|
+
ec2_client = boto3.client("ec2", region_name="us-east-1")
|
|
53
|
+
response = ec2_client.describe_regions()
|
|
54
|
+
available_region_codes = {region["RegionName"] for region in response["Regions"]}
|
|
55
|
+
|
|
56
|
+
# Get region descriptions from botocore's packaged data
|
|
57
|
+
session = botocore.session.get_session()
|
|
58
|
+
# The first partition is 'aws' which contains all standard regions
|
|
59
|
+
region_data = session.get_data("endpoints")["partitions"][0]["regions"]
|
|
60
|
+
|
|
61
|
+
regions = []
|
|
62
|
+
for code in available_region_codes:
|
|
63
|
+
data = region_data[code]
|
|
64
|
+
description = data.get("description", code.replace("-", " ").title())
|
|
65
|
+
regions.append((f"{description} ({code})", code))
|
|
66
|
+
|
|
67
|
+
return sorted(regions, key=lambda x: x[1])
|
|
68
|
+
|
|
69
|
+
def get_instance_types(self) -> MachineTypeList:
|
|
64
70
|
"""
|
|
65
71
|
Retrieves a list of available instance types for the given region using heuristics.
|
|
66
72
|
"""
|
|
67
|
-
ec2_client = boto3.client("ec2", region_name=region)
|
|
73
|
+
ec2_client = boto3.client("ec2", region_name=self.provider_detail.region)
|
|
68
74
|
|
|
69
75
|
# Prioritize newer generation, general-purpose and compute-optimized instance families
|
|
70
76
|
instance_families = [
|
|
@@ -129,6 +135,16 @@ class AWSProvider(BaseCloudProvider):
|
|
|
129
135
|
Retrieves structured AWS account details.
|
|
130
136
|
"""
|
|
131
137
|
try:
|
|
138
|
+
ssm_plugin_path = shutil.which("session-manager-plugin")
|
|
139
|
+
if not ssm_plugin_path:
|
|
140
|
+
raise CloudCredentialsError(
|
|
141
|
+
message=(
|
|
142
|
+
"'session-manager-plugin' not found. Please install the AWS Session Manager"
|
|
143
|
+
" plugin."
|
|
144
|
+
),
|
|
145
|
+
help_url="https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html",
|
|
146
|
+
)
|
|
147
|
+
|
|
132
148
|
sts_client = boto3.client("sts")
|
|
133
149
|
identity = sts_client.get_caller_identity()
|
|
134
150
|
account_id = identity.get("Account")
|
|
@@ -140,7 +156,23 @@ class AWSProvider(BaseCloudProvider):
|
|
|
140
156
|
),
|
|
141
157
|
help_url="https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html",
|
|
142
158
|
)
|
|
143
|
-
|
|
159
|
+
|
|
160
|
+
regions = AWSProvider.get_regions()
|
|
161
|
+
questions = [
|
|
162
|
+
inquirer.List(
|
|
163
|
+
"region",
|
|
164
|
+
message="Select an AWS region",
|
|
165
|
+
choices=regions,
|
|
166
|
+
),
|
|
167
|
+
]
|
|
168
|
+
answers = inquirer.prompt(questions)
|
|
169
|
+
if not answers or not answers.get("region"):
|
|
170
|
+
raise ValueError("AWS region selection is required. Aborting.")
|
|
171
|
+
selected_region = answers["region"]
|
|
172
|
+
|
|
173
|
+
return AWSCloudDetail(
|
|
174
|
+
account_id=account_id, ssm_plugin=ssm_plugin_path, region=selected_region
|
|
175
|
+
)
|
|
144
176
|
except (NoCredentialsError, ClientError) as e:
|
|
145
177
|
raise CloudCredentialsError(
|
|
146
178
|
message=f"AWS credentials error: {e}",
|
|
@@ -57,6 +57,7 @@ class MachineTypeList(BaseModel):
|
|
|
57
57
|
|
|
58
58
|
class BaseCloudProviderDetail(BaseModel):
|
|
59
59
|
name: str = Field(..., description="Provider name")
|
|
60
|
+
region: str = Field(..., description="The cloud provider region for this environment.")
|
|
60
61
|
|
|
61
62
|
|
|
62
63
|
class CloudProviderRegistry:
|
|
@@ -160,7 +161,7 @@ class BaseCloudProvider(abc.ABC):
|
|
|
160
161
|
raise NotImplementedError
|
|
161
162
|
|
|
162
163
|
@abc.abstractmethod
|
|
163
|
-
def get_instance_types(self
|
|
164
|
+
def get_instance_types(self) -> "MachineTypeList":
|
|
164
165
|
"""
|
|
165
166
|
Retrieves a list of available instance types for the given region.
|
|
166
167
|
"""
|
|
@@ -172,11 +173,4 @@ class BaseCloudProvider(abc.ABC):
|
|
|
172
173
|
Subclasses should implement specific authentication and setup.
|
|
173
174
|
"""
|
|
174
175
|
self.provider_detail = TypeAdapter(self.get_detail_model()).validate_python(provider_detail)
|
|
175
|
-
|
|
176
|
-
@abc.abstractmethod
|
|
177
|
-
def get_regions(self) -> List[Tuple[str, str]]:
|
|
178
|
-
"""
|
|
179
|
-
Retrieves a list of available regions for the cloud provider.
|
|
180
|
-
Returns a list of tuples, where each tuple contains the display name and the region code.
|
|
181
|
-
"""
|
|
182
|
-
raise NotImplementedError
|
|
176
|
+
self.provider_detail_dump = self.provider_detail.model_dump(mode="json", exclude={"name"})
|
|
@@ -15,6 +15,7 @@ from opsmith.cloud_providers.base import (
|
|
|
15
15
|
MachineType,
|
|
16
16
|
MachineTypeList,
|
|
17
17
|
)
|
|
18
|
+
from opsmith.utils import WaitingSpinner
|
|
18
19
|
|
|
19
20
|
GCP_REGION_DESCRIPTIONS = {
|
|
20
21
|
"africa-south1": "Johannesburg, South Africa",
|
|
@@ -62,6 +63,7 @@ GCP_REGION_DESCRIPTIONS = {
|
|
|
62
63
|
class GCPCloudDetail(BaseCloudProviderDetail):
|
|
63
64
|
name: Literal["GCP"] = Field(default="GCP", description="Provider name, 'GCP'")
|
|
64
65
|
project_id: str = Field(..., description="GCP Project ID.")
|
|
66
|
+
zone: str = Field(..., description="The GCP zone for this environment.")
|
|
65
67
|
|
|
66
68
|
|
|
67
69
|
class GCPProvider(BaseCloudProvider):
|
|
@@ -101,37 +103,47 @@ class GCPProvider(BaseCloudProvider):
|
|
|
101
103
|
self._credentials, _ = google.auth.default()
|
|
102
104
|
return self._credentials
|
|
103
105
|
|
|
104
|
-
|
|
106
|
+
@staticmethod
|
|
107
|
+
def get_regions(project_id: str, credentials: Credentials) -> list[tuple[str, str]]:
|
|
105
108
|
"""
|
|
106
109
|
Retrieves a list of available GCP regions using the GCP API.
|
|
107
110
|
"""
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
111
|
+
with WaitingSpinner(text="Fetching available regions from GCP Cloud Provider..."):
|
|
112
|
+
client = compute_v1.RegionsClient(credentials=credentials)
|
|
113
|
+
|
|
114
|
+
request = compute_v1.ListRegionsRequest(project=project_id)
|
|
115
|
+
pager = client.list(request=request)
|
|
116
|
+
|
|
117
|
+
regions = []
|
|
118
|
+
for region in pager:
|
|
119
|
+
code = region.name
|
|
120
|
+
name = (
|
|
121
|
+
GCP_REGION_DESCRIPTIONS.get(code)
|
|
122
|
+
or region.description
|
|
123
|
+
or code.replace("-", " ").title()
|
|
124
|
+
)
|
|
125
|
+
regions.append((f"{name} ({code})", code))
|
|
113
126
|
|
|
114
|
-
|
|
115
|
-
for region in pager:
|
|
116
|
-
code = region.name
|
|
117
|
-
name = (
|
|
118
|
-
GCP_REGION_DESCRIPTIONS.get(code)
|
|
119
|
-
or region.description
|
|
120
|
-
or code.replace("-", " ").title()
|
|
121
|
-
)
|
|
122
|
-
regions.append((f"{name} ({code})", code))
|
|
127
|
+
return sorted(regions, key=lambda x: x[1])
|
|
123
128
|
|
|
124
|
-
|
|
129
|
+
@staticmethod
|
|
130
|
+
def get_zones(project_id: str, region_name: str, credentials: Credentials) -> list[str]:
|
|
131
|
+
"""
|
|
132
|
+
Retrieves a list of available GCP zones for a given region.
|
|
133
|
+
"""
|
|
134
|
+
client = compute_v1.RegionsClient(credentials=credentials)
|
|
135
|
+
request = compute_v1.GetRegionRequest(project=project_id, region=region_name)
|
|
136
|
+
region_details = client.get(request=request)
|
|
137
|
+
zones = [zone.split("/")[-1] for zone in region_details.zones]
|
|
138
|
+
return sorted(zones)
|
|
125
139
|
|
|
126
|
-
def get_instance_types(self
|
|
140
|
+
def get_instance_types(self) -> MachineTypeList:
|
|
127
141
|
"""
|
|
128
|
-
Retrieves a list of available instance types for the given
|
|
142
|
+
Retrieves a list of available instance types for the given zone using the GCP API.
|
|
129
143
|
"""
|
|
130
144
|
client = compute_v1.MachineTypesClient(credentials=self.get_credentials())
|
|
131
145
|
project_id = self.provider_detail.project_id
|
|
132
|
-
|
|
133
|
-
# We need a zone to list machine types. We'll pick a zone in the region, assuming standard naming.
|
|
134
|
-
zone = f"{region}-a"
|
|
146
|
+
zone = self.provider_detail.zone
|
|
135
147
|
|
|
136
148
|
request = compute_v1.ListMachineTypesRequest(project=project_id, zone=zone)
|
|
137
149
|
pager = client.list(request=request)
|
|
@@ -183,7 +195,31 @@ class GCPProvider(BaseCloudProvider):
|
|
|
183
195
|
raise ValueError("GCP project selection is required. Aborting.")
|
|
184
196
|
|
|
185
197
|
selected_project_id = answers["project_id"]
|
|
186
|
-
|
|
198
|
+
|
|
199
|
+
regions = cls.get_regions(selected_project_id, credentials)
|
|
200
|
+
region_questions = [
|
|
201
|
+
inquirer.List(
|
|
202
|
+
"region",
|
|
203
|
+
message="Select a GCP region",
|
|
204
|
+
choices=regions,
|
|
205
|
+
),
|
|
206
|
+
]
|
|
207
|
+
answers = inquirer.prompt(region_questions)
|
|
208
|
+
if not answers or not answers.get("region"):
|
|
209
|
+
raise ValueError("GCP region selection is required. Aborting.")
|
|
210
|
+
|
|
211
|
+
selected_region = answers["region"]
|
|
212
|
+
|
|
213
|
+
zones = cls.get_zones(selected_project_id, selected_region, credentials)
|
|
214
|
+
if not zones:
|
|
215
|
+
raise ValueError(f"No zones found for region '{selected_region}'.")
|
|
216
|
+
|
|
217
|
+
# For now, just use the first zone.
|
|
218
|
+
selected_zone = zones[0]
|
|
219
|
+
|
|
220
|
+
return GCPCloudDetail(
|
|
221
|
+
project_id=selected_project_id, region=selected_region, zone=selected_zone
|
|
222
|
+
)
|
|
187
223
|
|
|
188
224
|
except DefaultCredentialsError as e:
|
|
189
225
|
raise CloudCredentialsError(
|
|
@@ -9,16 +9,20 @@ from importlib.metadata import entry_points
|
|
|
9
9
|
from pathlib import Path
|
|
10
10
|
from typing import Dict, List, Optional, Tuple, Type
|
|
11
11
|
|
|
12
|
-
import yaml
|
|
13
12
|
from pydantic_ai import Agent
|
|
14
13
|
from rich import print
|
|
15
14
|
|
|
16
15
|
from opsmith.agent import AgentDeps
|
|
17
|
-
from opsmith.cloud_providers.base import BaseCloudProvider
|
|
16
|
+
from opsmith.cloud_providers.base import BaseCloudProvider, MachineType
|
|
18
17
|
from opsmith.infra_provisioners.ansible_provisioner import AnsibleProvisioner
|
|
19
18
|
from opsmith.infra_provisioners.terraform_provisioner import TerraformProvisioner
|
|
20
19
|
from opsmith.settings import settings
|
|
21
|
-
from opsmith.types import
|
|
20
|
+
from opsmith.types import (
|
|
21
|
+
DeploymentConfig,
|
|
22
|
+
DeploymentEnvironment,
|
|
23
|
+
ServiceTypeEnum,
|
|
24
|
+
VirtualMachineState,
|
|
25
|
+
)
|
|
22
26
|
from opsmith.utils import slugify
|
|
23
27
|
|
|
24
28
|
|
|
@@ -97,9 +101,9 @@ class BaseDeploymentStrategy(abc.ABC):
|
|
|
97
101
|
|
|
98
102
|
def __init__(self, agent: Agent, src_dir: Path):
|
|
99
103
|
self.agent = agent
|
|
100
|
-
self.agent_deps = AgentDeps(src_dir=
|
|
104
|
+
self.agent_deps = AgentDeps(src_dir=src_dir)
|
|
101
105
|
self.src_dir = src_dir
|
|
102
|
-
self.deployments_path =
|
|
106
|
+
self.deployments_path = src_dir.joinpath(settings.deployments_dir)
|
|
103
107
|
self.templates_dir = Path(__file__).parent.parent / "templates"
|
|
104
108
|
|
|
105
109
|
def _get_env_state_path(self, environment_name: str) -> Path:
|
|
@@ -111,7 +115,7 @@ class BaseDeploymentStrategy(abc.ABC):
|
|
|
111
115
|
"""Sets up a container registry for the given region."""
|
|
112
116
|
app_name = deployment_config.app_name_slug
|
|
113
117
|
# Registry name should probably be unique per region for the app
|
|
114
|
-
registry_name = slugify(f"{app_name}-{environment.region}")
|
|
118
|
+
registry_name = slugify(f"{app_name}-{environment.cloud_provider_detail.region}")
|
|
115
119
|
|
|
116
120
|
cloud_provider_instance = environment.cloud_provider_instance
|
|
117
121
|
provider_name = cloud_provider_instance.name()
|
|
@@ -120,7 +124,7 @@ class BaseDeploymentStrategy(abc.ABC):
|
|
|
120
124
|
self.deployments_path
|
|
121
125
|
/ "environments"
|
|
122
126
|
/ "global"
|
|
123
|
-
/ f"{cloud_provider_instance.name()}-{environment.region}"
|
|
127
|
+
/ f"{cloud_provider_instance.name()}-{environment.cloud_provider_detail.region}"
|
|
124
128
|
/ "container_registry"
|
|
125
129
|
)
|
|
126
130
|
tf = TerraformProvisioner(working_dir=registry_infra_path)
|
|
@@ -128,7 +132,7 @@ class BaseDeploymentStrategy(abc.ABC):
|
|
|
128
132
|
variables = {
|
|
129
133
|
"app_name": app_name,
|
|
130
134
|
"registry_name": registry_name,
|
|
131
|
-
"
|
|
135
|
+
"force_delete": "true",
|
|
132
136
|
}
|
|
133
137
|
env_vars = cloud_provider_instance.provider_detail.model_dump(mode="json")
|
|
134
138
|
|
|
@@ -201,17 +205,16 @@ class BaseDeploymentStrategy(abc.ABC):
|
|
|
201
205
|
|
|
202
206
|
ansible_runner = AnsibleProvisioner(working_dir=build_infra_path)
|
|
203
207
|
|
|
204
|
-
provider_name = environment.
|
|
208
|
+
provider_name = environment.cloud_provider_detail.name.lower()
|
|
205
209
|
|
|
206
210
|
extra_vars = {
|
|
207
211
|
"docker_path": str(self.agent_deps.src_dir),
|
|
208
|
-
"
|
|
212
|
+
"dockerfile_path": str(dockerfile_path_abs),
|
|
209
213
|
"image_name_slug": image_name_slug,
|
|
210
214
|
"image_tag_name": "latest",
|
|
211
|
-
"region": environment.region,
|
|
212
215
|
"registry_url": registry_url,
|
|
213
216
|
}
|
|
214
|
-
|
|
217
|
+
extra_vars.update(environment.cloud_provider_instance.provider_detail_dump)
|
|
215
218
|
ansible_runner.copy_template("docker_build_push", provider_name)
|
|
216
219
|
outputs = ansible_runner.run_playbook("main.yml", extra_vars)
|
|
217
220
|
|
|
@@ -303,9 +306,9 @@ class BaseDeploymentStrategy(abc.ABC):
|
|
|
303
306
|
self,
|
|
304
307
|
deployment_config: DeploymentConfig,
|
|
305
308
|
environment: DeploymentEnvironment,
|
|
306
|
-
|
|
309
|
+
machine_type: MachineType,
|
|
307
310
|
cloud_provider: BaseCloudProvider,
|
|
308
|
-
) ->
|
|
311
|
+
) -> VirtualMachineState:
|
|
309
312
|
"""Creates a new virtual machine for the deployment."""
|
|
310
313
|
provider_name = cloud_provider.name().lower()
|
|
311
314
|
infra_path = self.deployments_path / "environments" / environment.name / "virtual_machine"
|
|
@@ -313,63 +316,61 @@ class BaseDeploymentStrategy(abc.ABC):
|
|
|
313
316
|
|
|
314
317
|
variables = {
|
|
315
318
|
"app_name": deployment_config.app_name_slug,
|
|
316
|
-
"
|
|
317
|
-
"
|
|
319
|
+
"environment": environment.name,
|
|
320
|
+
"instance_type": machine_type.name,
|
|
321
|
+
"instance_arch": machine_type.architecture.value,
|
|
318
322
|
"ssh_pub_key": self._get_ssh_public_key(),
|
|
319
323
|
}
|
|
320
|
-
env_vars = cloud_provider.
|
|
324
|
+
env_vars = cloud_provider.provider_detail_dump
|
|
321
325
|
|
|
322
|
-
|
|
323
|
-
tf.copy_template("virtual_machine", provider_name)
|
|
326
|
+
tf.copy_template("virtual_machine", provider_name)
|
|
324
327
|
|
|
325
|
-
|
|
328
|
+
tf.init_and_apply(variables, env_vars=env_vars)
|
|
326
329
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
if outputs:
|
|
330
|
-
print("[bold green]Outputs:[/bold green]")
|
|
331
|
-
print(yaml.dump(outputs))
|
|
330
|
+
outputs = tf.get_output()
|
|
331
|
+
print("[bold green]Monolithic infrastructure provisioned successfully.[/bold green]")
|
|
332
332
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
333
|
+
virtual_machine_state = VirtualMachineState(
|
|
334
|
+
ram_gb=machine_type.ram_gb,
|
|
335
|
+
cpu=machine_type.cpu,
|
|
336
|
+
instance_type=machine_type.name,
|
|
337
|
+
architecture=machine_type.architecture,
|
|
338
|
+
**outputs,
|
|
339
|
+
)
|
|
339
340
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
print("[bold red]Could not find 'ansible_user' in Terraform outputs.[/bold red]")
|
|
343
|
-
raise ValueError("Could not find 'ansible_user' in Terraform outputs.")
|
|
341
|
+
print("[bold blue]Waiting 15 seconds for instance to become ready...[/bold blue]")
|
|
342
|
+
time.sleep(15)
|
|
344
343
|
|
|
345
|
-
|
|
346
|
-
time.sleep(15)
|
|
344
|
+
print("\n[bold blue]Setting up Docker on the newly created VM[/bold blue]")
|
|
347
345
|
|
|
348
|
-
|
|
346
|
+
setup_docker_path = (
|
|
347
|
+
self.deployments_path / "environments" / environment.name / "virtual_machine_setup"
|
|
348
|
+
)
|
|
349
|
+
ansible_runner = AnsibleProvisioner(working_dir=setup_docker_path)
|
|
350
|
+
ansible_runner.copy_template("virtual_machine_setup", provider_name)
|
|
349
351
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
inventory=instance_public_ip,
|
|
359
|
-
user=ansible_user,
|
|
360
|
-
)
|
|
361
|
-
print("[bold green]Docker setup complete.[/bold green]")
|
|
352
|
+
extra_vars = {
|
|
353
|
+
"environment_name": environment.name,
|
|
354
|
+
"app_name": deployment_config.app_name_slug,
|
|
355
|
+
**cloud_provider.provider_detail_dump,
|
|
356
|
+
**virtual_machine_state.model_dump(mode="json"),
|
|
357
|
+
}
|
|
358
|
+
# extra_vars.update(virtual_machine_state.model_dump(mode="json"))
|
|
359
|
+
# extra_vars.update(cloud_provider.provider_detail_dump)
|
|
362
360
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
361
|
+
ansible_runner.run_playbook(
|
|
362
|
+
"main.yml",
|
|
363
|
+
extra_vars=extra_vars,
|
|
364
|
+
)
|
|
365
|
+
print("[bold green]Docker setup complete.[/bold green]")
|
|
366
|
+
|
|
367
|
+
return virtual_machine_state
|
|
367
368
|
|
|
368
369
|
def _fetch_remote_deployment_files(
|
|
369
370
|
self,
|
|
371
|
+
deployment_config: DeploymentConfig,
|
|
370
372
|
environment: DeploymentEnvironment,
|
|
371
|
-
|
|
372
|
-
ansible_user: str,
|
|
373
|
+
virtual_machine: VirtualMachineState,
|
|
373
374
|
remote_files: List[str],
|
|
374
375
|
) -> List[str]:
|
|
375
376
|
print("\n[bold blue]Fetching current deployment files from server...[/bold blue]")
|
|
@@ -378,17 +379,20 @@ class BaseDeploymentStrategy(abc.ABC):
|
|
|
378
379
|
)
|
|
379
380
|
|
|
380
381
|
ansible_runner = AnsibleProvisioner(working_dir=fetch_files_path)
|
|
381
|
-
|
|
382
|
-
|
|
382
|
+
ansible_runner.copy_template(
|
|
383
|
+
"fetch_remote_files", environment.cloud_provider_instance.name()
|
|
384
|
+
)
|
|
383
385
|
extra_vars = {
|
|
386
|
+
"app_name": deployment_config.app_name_slug,
|
|
387
|
+
"environment_name": environment.name,
|
|
384
388
|
"remote_files": remote_files,
|
|
389
|
+
**virtual_machine.model_dump(mode="json"),
|
|
390
|
+
**environment.cloud_provider_instance.provider_detail_dump,
|
|
385
391
|
}
|
|
386
392
|
|
|
387
393
|
outputs = ansible_runner.run_playbook(
|
|
388
394
|
"main.yml",
|
|
389
395
|
extra_vars=extra_vars,
|
|
390
|
-
inventory=instance_public_ip,
|
|
391
|
-
user=ansible_user,
|
|
392
396
|
)
|
|
393
397
|
|
|
394
398
|
fetched_files_b64 = outputs.get("fetched_files", "")
|
|
@@ -430,8 +434,8 @@ class BaseDeploymentStrategy(abc.ABC):
|
|
|
430
434
|
|
|
431
435
|
extra_vars = {
|
|
432
436
|
"bucket_name": bucket_name,
|
|
433
|
-
"region": environment.region,
|
|
434
437
|
}
|
|
438
|
+
extra_vars.update(environment.cloud_provider_instance.provider_detail_dump)
|
|
435
439
|
ansible_runner.run_playbook("main.yml", extra_vars=extra_vars, inventory="localhost")
|
|
436
440
|
print(f"[bold green]Bucket '{bucket_name}' emptied successfully.[/bold green]")
|
|
437
441
|
|
|
@@ -472,3 +476,12 @@ class BaseDeploymentStrategy(abc.ABC):
|
|
|
472
476
|
):
|
|
473
477
|
"""Runs a command on a specific service."""
|
|
474
478
|
raise NotImplementedError
|
|
479
|
+
|
|
480
|
+
@abc.abstractmethod
|
|
481
|
+
def update(
|
|
482
|
+
self,
|
|
483
|
+
deployment_config: DeploymentConfig,
|
|
484
|
+
environment: DeploymentEnvironment,
|
|
485
|
+
):
|
|
486
|
+
"""Updates service configuration for an existing deployment."""
|
|
487
|
+
raise NotImplementedError
|