Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into main-2440-global-in…
Browse files Browse the repository at this point in the history
…structions
  • Loading branch information
itisallgood committed Dec 18, 2024
2 parents dd01a9e + 2cde05c commit f516931
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 18 deletions.
10 changes: 8 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ ENV PATH="$VIRTUAL_ENV/bin:$PATH"
RUN curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.29/deb/Release.key -o Release.key

# Set the architecture-specific kube lineage URLs
ARG ARM_URL=https://github.com/Avi-Robusta/kube-lineage/releases/download/v2.1/kube-lineage-macos-latest-v2.1
ARG AMD_URL=https://github.com/Avi-Robusta/kube-lineage/releases/download/v2.1/kube-lineage-ubuntu-latest-v2.1
ARG ARM_URL=https://github.com/Avi-Robusta/kube-lineage/releases/download/v2.2.1/kube-lineage-macos-latest-v2.2.1
ARG AMD_URL=https://github.com/Avi-Robusta/kube-lineage/releases/download/v2.2.1/kube-lineage-ubuntu-latest-v2.2.1
# Define a build argument to identify the platform
ARG TARGETPLATFORM
# Conditional download based on the platform
Expand All @@ -41,6 +41,8 @@ RUN if [ "$TARGETPLATFORM" = "linux/arm64" ]; then \
RUN chmod 777 kube-lineage
RUN ./kube-lineage --version

RUN curl -sSL -o argocd-linux-amd64 https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-amd64

# Set up poetry
ARG PRIVATE_PACKAGE_REGISTRY="none"
RUN if [ "${PRIVATE_PACKAGE_REGISTRY}" != "none" ]; then \
Expand Down Expand Up @@ -90,6 +92,10 @@ RUN apt-get install -y kubectl
COPY --from=builder /app/kube-lineage /usr/local/bin
RUN kube-lineage --version

COPY --from=builder /app/argocd-linux-amd64 /usr/local/bin/argocd
RUN chmod 555 /usr/local/bin/argocd
RUN argocd --help

ARG AWS_DEFAULT_PROFILE
ARG AWS_DEFAULT_REGION
ARG AWS_PROFILE
Expand Down
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,15 @@ HolmesGPT can consult webpages containing runbooks or other relevant information
HolmesGPT uses playwright to scrape webpages and requires playwright to be installed and working through `playwright install`.
</details>

<details>
<summary>
ArgoCD
</summary>

Holmes can use the `argocd` CLI to get details about the ArgoCD setup like the apps configuration and status, clusters and projects within ArgoCD.
To enable ArgoCD, set the `ARGOCD_AUTH_TOKEN` environment variable as described in the [argocd documentation](https://argo-cd.readthedocs.io/en/latest/user-guide/commands/argocd_account_generate-token/).
</details>

## More Use Cases

HolmesGPT was designed for incident response, but it is a general DevOps assistant too. Here are some examples:
Expand Down
43 changes: 43 additions & 0 deletions holmes/plugins/toolsets/argocd.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
toolsets:
argocd/core:
description: "Set of tools to get argocd metadata like list of apps, repositories, projects, etc."
docs_url: "https://argo-cd.readthedocs.io/en/stable/user-guide/commands/argocd/"
icon_url: "https://argo-cd.readthedocs.io/en/stable/assets/logo.png"
tags:
- core
prerequisites:
- command: "argocd version"
- env:
- ARGOCD_AUTH_TOKEN
tools:
- name: "argocd_app_get"
description: "Retrieve information about an existing application, such as its status and configuration"
command: "argocd app get {{ app_name }} --show-operation -o yaml"

- name: "argocd_app_diff"
description: "Display the differences between the current state of an application and the desired state specified in its Git repository"
command: "argocd app diff {{ app_name }}"

- name: "argocd_app_list"
description: "List the applications in Argocd"
command: "argocd app list"

- name: "argocd_app_history"
description: "List the deployment history of an application in ArgoCD"
command: "argocd app history {{app_name}} --app-namespace {{namespace}}"

- name: "argocd_repo_list"
description: "List all the Git repositories that ArgoCD is currently managing"
command: "argocd repo list"

- name: "argocd_proj_list"
description: "List all available projects"
command: "argocd proj list"

- name: "argocd_proj_get"
description: "Retrieves information about an existing project, such as its applications and policies"
command: "argocd proj get {{ project_name }}"

- name: "argocd_cluster_list"
description: "List all known clusters"
command: "argocd cluster list"
5 changes: 5 additions & 0 deletions holmes/utils/holmes_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@

def update_holmes_status_in_db(dal: SupabaseDal, config: Config):
logging.info("Updating status of holmes")

if not config.cluster_name:
raise Exception("Cluster name is missing in the configuration. Please ensure 'CLUSTER_NAME' is defined in the environment variables, "
"or verify that a cluster name is provided in the Robusta configuration file.")

dal.upsert_holmes_status(
{
"cluster_id": config.cluster_name,
Expand Down
17 changes: 13 additions & 4 deletions holmes/utils/holmes_sync_toolsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from holmes.plugins.prompts import load_and_render_prompt
from holmes.utils.definitions import CUSTOM_TOOLSET_LOCATION
import logging
from datetime import datetime
from datetime import datetime


def load_custom_toolsets_config() -> list[ToolsetYamlFromConfig]:
Expand Down Expand Up @@ -96,11 +96,21 @@ def holmes_sync_toolsets_status(dal: SupabaseDal, config) -> None:
toolsets_loaded_from_config, default_toolsets_by_name
)

db_toolsets = []
updated_at = datetime.now().isoformat()
# we check every toolset and save to local config toolsets which have passed the checks
# before we try to upsert anything to db
for toolset in toolsets_for_sync_by_name.values():
if toolset.enabled:
toolset.check_prerequisites()

config.enabled_toolsets_names = [toolset.name for toolset in toolsets_for_sync_by_name.values() if toolset.get_status() == ToolsetStatusEnum.ENABLED]

if not config.cluster_name:
raise Exception("Cluster name is missing in the configuration. Please ensure 'CLUSTER_NAME' is defined in the environment variables, "
"or verify that a cluster name is provided in the Robusta configuration file.")

db_toolsets = []
updated_at = datetime.now().isoformat()
for toolset in toolsets_for_sync_by_name.values():
if not toolset.installation_instructions:
is_default_toolset = bool(toolset.name in default_toolsets_by_name.keys())
instructions = render_default_installation_instructions_for_toolset(
Expand All @@ -118,7 +128,6 @@ def holmes_sync_toolsets_status(dal: SupabaseDal, config) -> None:
updated_at=updated_at
).model_dump(exclude_none=True)
)
config.enabled_toolsets_names = [toolset.name for toolset in toolsets_for_sync_by_name.values() if toolset.get_status() == ToolsetStatusEnum.ENABLED]
dal.sync_toolsets(db_toolsets, config.cluster_name)


Expand Down
18 changes: 6 additions & 12 deletions server.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
import os
from holmes.core import investigation
from holmes.utils.cert_utils import add_custom_certificate
from contextlib import asynccontextmanager
from holmes.utils.holmes_status import update_holmes_status_in_db

ADDITIONAL_CERTIFICATE: str = os.environ.get("CERTIFICATE", "")
if add_custom_certificate(ADDITIONAL_CERTIFICATE):
print("added custom certificate")

# DO NOT ADD ANY IMPORTS OR CODE ABOVE THIS LINE
# IMPORTING ABOVE MIGHT INITIALIZE AN HTTPS CLIENT THAT DOESN'T TRUST THE CUSTOM CERTIFICATE


from holmes.core import investigation
from contextlib import asynccontextmanager
from holmes.utils.holmes_status import update_holmes_status_in_db
import jinja2
import logging
import uvicorn
Expand Down Expand Up @@ -128,16 +126,12 @@ def workload_health_check(request: WorkloadHealthRequest):
request.ask = f"{request.ask}\n My instructions for the investigation '''{nl.join(instructions)}'''"

global_instructions = dal.get_global_instructions_for_account()
print("GLOBAL INSTRUCTIONS")
print(global_instructions)
if global_instructions and global_instructions.instructions and len(global_instructions.instructions[0]) > 0:
request.ask += f"\n\nGlobal Instructions (use only if relevant): {global_instructions.instructions[0]}\n"

print(request.ask)
system_prompt = load_and_render_prompt(request.prompt_template)
system_prompt = jinja2.Environment().from_string(system_prompt)
system_prompt = system_prompt.render(alerts=workload_alerts)
print(system_prompt)
system_prompt = load_and_render_prompt(request.prompt_template, context={'alerts': workload_alerts})


ai = config.create_toolcalling_llm(console, dal=dal)

structured_output = {"type": "json_object"}
Expand Down

0 comments on commit f516931

Please sign in to comment.