commit 2b5d29ef67f04b2c4c1707fe6ec104951289d3fd Author: Sebastian Serfling Date: Fri Apr 24 09:06:07 2026 +0200 Initial commit: Windmill workspace sync Scripts, flows, apps, resources and resource types from the Windmill workspace. API token excluded via .gitignore (config/). diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f68ea2c --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +# Windmill CLI credentials (contains API token) +config/ + +# Claude Code internals +.claude/ +.config/ diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..ae6b3aa --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,68 @@ +# Windmill AI Agent Instructions + +You are a helpful assistant that can help with Windmill scripts, flows, apps, and resources management. + +## Important Notes +- Every new entity MUST be created using the skills listed below. +- Every modification of an entity MUST be done using the skills listed below. +- User MUST be asked where to create the entity. It can be in its user folder, under u/{user_name} folder, or in a new folder, /f/{folder_name}/. folder_name and user_name must be provided by the user. + +## Script Writing Guide + +You MUST use the `write-script-` skill to write or modify scripts in the language specified by the user. Use bun by default. + +## Flow Writing Guide + +You MUST use the `write-flow` skill to create or modify flows. + +## Raw App Development + +You MUST use the `raw-app` skill to create or modify raw apps. +Whenever a new app needs to be created you MUST ask the user to run `wmill app new` in its terminal first. + +## Triggers + +You MUST use the `triggers` skill to configure HTTP routes, WebSocket, Kafka, NATS, SQS, MQTT, GCP, or Postgres CDC triggers. + +## Schedules + +You MUST use the `schedules` skill to configure cron schedules. + +## Resources + +You MUST use the `resources` skill to manage resource types and credentials. + +## CLI Reference + +You MUST use the `cli-commands` skill to use the CLI. + +## Skills + +For specific guidance, ALWAYS use the skills listed below. + +- `.claude/skills/write-script-bash/SKILL.md` - MUST use when writing Bash scripts. +- `.claude/skills/write-script-bigquery/SKILL.md` - MUST use when writing BigQuery queries. +- `.claude/skills/write-script-bun/SKILL.md` - MUST use when writing Bun/TypeScript scripts. +- `.claude/skills/write-script-bunnative/SKILL.md` - MUST use when writing Bun Native scripts. +- `.claude/skills/write-script-csharp/SKILL.md` - MUST use when writing C# scripts. +- `.claude/skills/write-script-deno/SKILL.md` - MUST use when writing Deno/TypeScript scripts. +- `.claude/skills/write-script-duckdb/SKILL.md` - MUST use when writing DuckDB queries. +- `.claude/skills/write-script-go/SKILL.md` - MUST use when writing Go scripts. +- `.claude/skills/write-script-graphql/SKILL.md` - MUST use when writing GraphQL queries. +- `.claude/skills/write-script-java/SKILL.md` - MUST use when writing Java scripts. +- `.claude/skills/write-script-mssql/SKILL.md` - MUST use when writing MS SQL Server queries. +- `.claude/skills/write-script-mysql/SKILL.md` - MUST use when writing MySQL queries. +- `.claude/skills/write-script-nativets/SKILL.md` - MUST use when writing Native TypeScript scripts. +- `.claude/skills/write-script-php/SKILL.md` - MUST use when writing PHP scripts. +- `.claude/skills/write-script-postgresql/SKILL.md` - MUST use when writing PostgreSQL queries. +- `.claude/skills/write-script-powershell/SKILL.md` - MUST use when writing PowerShell scripts. +- `.claude/skills/write-script-python3/SKILL.md` - MUST use when writing Python scripts. +- `.claude/skills/write-script-rlang/SKILL.md` - MUST use when writing R scripts. +- `.claude/skills/write-script-rust/SKILL.md` - MUST use when writing Rust scripts. +- `.claude/skills/write-script-snowflake/SKILL.md` - MUST use when writing Snowflake queries. +- `.claude/skills/write-flow/SKILL.md` - MUST use when creating flows. +- `.claude/skills/raw-app/SKILL.md` - MUST use when creating raw apps. +- `.claude/skills/triggers/SKILL.md` - MUST use when configuring triggers. +- `.claude/skills/schedules/SKILL.md` - MUST use when configuring schedules. +- `.claude/skills/resources/SKILL.md` - MUST use when managing resources. +- `.claude/skills/cli-commands/SKILL.md` - MUST use when using the CLI. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..d799d07 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +Instructions are in @AGENTS.md diff --git a/ably.resource-type.yaml b/ably.resource-type.yaml new file mode 100644 index 0000000..a1c1d74 --- /dev/null +++ b/ably.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKye: + type: string + description: API key generated against an app on the dashboard. + required: + - apiKey diff --git a/abstractapi.resource-type.yaml b/abstractapi.resource-type.yaml new file mode 100644 index 0000000..1d89608 --- /dev/null +++ b/abstractapi.resource-type.yaml @@ -0,0 +1,16 @@ +description: >- + Abstract API has a bunch of standalone API products, each with their own + endpoints and API keys. + + Head to desired API page, and copy the `Primary Key`. +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: Key obtained from the dashboard page for each API product + required: + - apiKey diff --git a/accelo.resource-type.yaml b/accelo.resource-type.yaml new file mode 100644 index 0000000..70fa53c --- /dev/null +++ b/accelo.resource-type.yaml @@ -0,0 +1,21 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + clientId: + type: string + description: The client ID of your Accelo application. + clientSecret: + type: string + description: The client secret of your Accelo application. + deployment: + type: string + description: The deployment subdomain of your Accelo instance. For example, + 'mydeployement' for 'https://mydeployement.accelo.com'. + required: + - deployment + - clientId + - clientSecret diff --git a/actimo.resource-type.yaml b/actimo.resource-type.yaml new file mode 100644 index 0000000..8c70c9c --- /dev/null +++ b/actimo.resource-type.yaml @@ -0,0 +1,11 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + required: + - apiKey diff --git a/acumbamail.resource-type.yaml b/acumbamail.resource-type.yaml new file mode 100644 index 0000000..ab987cd --- /dev/null +++ b/acumbamail.resource-type.yaml @@ -0,0 +1,16 @@ +description: >- + 1. Visit https://acumbamail.com/en/apidoc/ upon successfully logging into the + Acumbamail account + + 2. Copy the `auth_token` under `customer identifier` +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + authToken: + type: string + description: Auth token found on the developer documentation of Acumbamail + required: + - authToken diff --git a/adhook.resource-type.yaml b/adhook.resource-type.yaml new file mode 100644 index 0000000..05833c6 --- /dev/null +++ b/adhook.resource-type.yaml @@ -0,0 +1,11 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + required: + - token diff --git a/adrapid.resource-type.yaml b/adrapid.resource-type.yaml new file mode 100644 index 0000000..06746a8 --- /dev/null +++ b/adrapid.resource-type.yaml @@ -0,0 +1,11 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiToken: + type: string + required: + - apiToken diff --git a/aero_workflow.resource-type.yaml b/aero_workflow.resource-type.yaml new file mode 100644 index 0000000..8c70c9c --- /dev/null +++ b/aero_workflow.resource-type.yaml @@ -0,0 +1,11 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + required: + - apiKey diff --git a/ai21.resource-type.yaml b/ai21.resource-type.yaml new file mode 100644 index 0000000..be72cc7 --- /dev/null +++ b/ai21.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: API key retrieved from the dashboard. + required: + - apiKey diff --git a/airtable.resource-type.yaml b/airtable.resource-type.yaml new file mode 100644 index 0000000..f2a5585 --- /dev/null +++ b/airtable.resource-type.yaml @@ -0,0 +1,12 @@ +description: The airtable OAuth token +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: '' + default: keyXXXXXXXXXXXXXX + required: [] diff --git a/airtable_table.resource-type.yaml b/airtable_table.resource-type.yaml new file mode 100644 index 0000000..a281f5c --- /dev/null +++ b/airtable_table.resource-type.yaml @@ -0,0 +1,14 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + baseId: + type: string + description: '' + tableName: + type: string + description: '' + required: [] diff --git a/ansible_inventory.resource-type.yaml b/ansible_inventory.resource-type.yaml new file mode 100644 index 0000000..07d9ee4 --- /dev/null +++ b/ansible_inventory.resource-type.yaml @@ -0,0 +1,13 @@ +description: An Ansible inventory +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - content + properties: + content: + type: string + description: Text contents of the file + required: [] diff --git a/anthropic.resource-type.yaml b/anthropic.resource-type.yaml new file mode 100644 index 0000000..d093cdf --- /dev/null +++ b/anthropic.resource-type.yaml @@ -0,0 +1,35 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - apiKey + - base_url + - platform + - enable_1M_context + properties: + apiKey: + type: string + description: '' + default: '' + base_url: + type: string + description: 'Optional. Only needed to overwrite the default base URL. For + google_vertex_ai: + https://{region}-aiplatform.googleapis.com/v1/projects/{project_id}/locations/{region}/publishers/anthropic/models/' + default: '' + enable_1M_context: + type: boolean + description: Enable beta header for 1M context on eligible models. + default: false + platform: + type: string + description: Platform to use for Anthropic API. + default: standard + enum: + - standard + - google_vertex_ai + required: + - apiKey diff --git a/api_key_auth.resource-type.yaml b/api_key_auth.resource-type.yaml new file mode 100644 index 0000000..540e3a0 --- /dev/null +++ b/api_key_auth.resource-type.yaml @@ -0,0 +1,23 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - api_key_header + - api_key_secret + properties: + api_key_header: + type: string + description: '' + default: '' + nullable: false + api_key_secret: + type: string + description: '' + default: '' + nullable: false + required: + - api_key_header + - api_key_secret diff --git a/apify.resource-type.yaml b/apify.resource-type.yaml new file mode 100644 index 0000000..b3bf480 --- /dev/null +++ b/apify.resource-type.yaml @@ -0,0 +1,17 @@ +description: Credentials for the Apify API using an OAuth token. +format_extension: null +is_fileset: false +schema: + type: object + order: + - token + properties: + token: + type: string + description: Apify OAuth token. Available only on Windmill Cloud. + default: '' + nullable: false + password: true + title: Apify OAuth Token + required: + - token diff --git a/apify_api_key.resource-type.yaml b/apify_api_key.resource-type.yaml new file mode 100644 index 0000000..2169caf --- /dev/null +++ b/apify_api_key.resource-type.yaml @@ -0,0 +1,17 @@ +description: Credentials for the Apify API using a personal API Key. +format_extension: null +is_fileset: false +schema: + type: object + order: + - api_key + properties: + api_key: + type: string + description: Your personal API token from your Apify account settings. + default: '' + nullable: false + password: true + title: Apify API Key + required: + - api_key diff --git a/apify_webhook_config.resource-type.yaml b/apify_webhook_config.resource-type.yaml new file mode 100644 index 0000000..d83dd1a --- /dev/null +++ b/apify_webhook_config.resource-type.yaml @@ -0,0 +1,27 @@ +description: Webhook config needed to create an Apify webhook with URL and token + from your Windmill flow. +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - url + - token + properties: + token: + type: string + description: Webhook-specific token from your Windmill flow. + default: '' + nullable: false + password: true + title: Token + url: + type: string + description: Webhook URL from your Windmill flow. + default: '' + nullable: false + title: URL + required: + - url + - token diff --git a/apollo.resource-type.yaml b/apollo.resource-type.yaml new file mode 100644 index 0000000..b68fc3a --- /dev/null +++ b/apollo.resource-type.yaml @@ -0,0 +1,14 @@ +description: |- + 1. Visit https://developer.apollo.io/ to generate an API key. + 2. Copy the API key +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: API Key generated inside the settings for Apollo. + required: + - apiKey diff --git a/appwrite.resource-type.yaml b/appwrite.resource-type.yaml new file mode 100644 index 0000000..5e9ef06 --- /dev/null +++ b/appwrite.resource-type.yaml @@ -0,0 +1,27 @@ +description: credentials to connect to an [appwrite](https://appwrite.io/docs) project +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + endpoint: + type: string + description: url of your appwrite server + default: https:// + key: + type: string + description: API key of your appwrite project + default: '' + project: + type: string + description: ID of your appwrite project + default: '' + self_signed: + type: boolean + description: use self signed certificates on server (only for development) + default: '' + required: + - endpoint + - project + - key diff --git a/arcgis_account.resource-type.yaml b/arcgis_account.resource-type.yaml new file mode 100644 index 0000000..3f6a2fd --- /dev/null +++ b/arcgis_account.resource-type.yaml @@ -0,0 +1,21 @@ +description: Username and password of an ArcGIS Account to be able to access + Feature Services. +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - username + - password + properties: + password: + type: string + description: '' + default: '' + password: true + username: + type: string + description: '' + default: '' + required: [] diff --git a/asana.resource-type.yaml b/asana.resource-type.yaml new file mode 100644 index 0000000..1b46413 --- /dev/null +++ b/asana.resource-type.yaml @@ -0,0 +1,13 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: '' + default: '' + required: + - token diff --git a/assemblyai.resource-type.yaml b/assemblyai.resource-type.yaml new file mode 100644 index 0000000..be72cc7 --- /dev/null +++ b/assemblyai.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: API key retrieved from the dashboard. + required: + - apiKey diff --git a/attio.resource-type.yaml b/attio.resource-type.yaml new file mode 100644 index 0000000..194c42e --- /dev/null +++ b/attio.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: Access token generated from the dashboard or the OAuth flow. + required: + - token diff --git a/aws.resource-type.yaml b/aws.resource-type.yaml new file mode 100644 index 0000000..240ada0 --- /dev/null +++ b/aws.resource-type.yaml @@ -0,0 +1,22 @@ +description: AWS credentials +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + awsAccessKeyId: + type: string + description: '' + default: '' + awsSecretAccessKey: + type: string + description: '' + default: '' + region: + type: string + description: '' + default: '' + required: + - awsAccessKeyId + - awsSecretAccessKey diff --git a/aws_bedrock.resource-type.yaml b/aws_bedrock.resource-type.yaml new file mode 100644 index 0000000..9144582 --- /dev/null +++ b/aws_bedrock.resource-type.yaml @@ -0,0 +1,43 @@ +description: AWS Bedrock resource type +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - region + - apiKey + properties: + apiKey: + type: string + description: AWS bedrock API key (simplest, no need for awsAccessKeyId and + awsSecretAccessKey) + default: '' + nullable: true + password: true + awsAccessKeyId: + type: string + description: AWS IAM access key ID (alternative to apiKey) + default: '' + nullable: true + password: true + awsSecretAccessKey: + type: string + description: AWS IAM secret access key (alternative to apiKey) + default: '' + nullable: true + password: true + awsSessionToken: + type: string + description: AWS IAM session token (alternative to apiKey). You will need to + refresh this token periodically. + default: '' + nullable: true + password: true + region: + type: string + description: AWS Bedrock region (e.g., us-east-1) + default: '' + nullable: false + required: + - region diff --git a/aws_oidc.resource-type.yaml b/aws_oidc.resource-type.yaml new file mode 100644 index 0000000..c93de86 --- /dev/null +++ b/aws_oidc.resource-type.yaml @@ -0,0 +1,20 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - roleArn + - region + properties: + region: + type: string + description: '' + roleArn: + type: string + description: '' + default: '' + nullable: false + required: + - roleArn diff --git a/azure.resource-type.yaml b/azure.resource-type.yaml new file mode 100644 index 0000000..f876bc1 --- /dev/null +++ b/azure.resource-type.yaml @@ -0,0 +1,23 @@ +description: Azure Service Principal Credentials +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + azureClientId: + type: string + description: Client ID of the Azure AD app registration + default: '' + azureClientSecret: + type: string + description: Client Secret of the Azure AD app registration + default: '' + azureTenantId: + type: string + description: Azure AD tenant ID + default: '' + required: + - azureTenantId + - azureClientId + - azureClientSecret diff --git a/azure_blob.resource-type.yaml b/azure_blob.resource-type.yaml new file mode 100644 index 0000000..c0c4891 --- /dev/null +++ b/azure_blob.resource-type.yaml @@ -0,0 +1,37 @@ +description: An Azure Blob Storage connection info +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - accountName + - containerName + - accessKey + - useSSL + - endpoint + properties: + accessKey: + type: string + description: '' + default: '' + accountName: + type: string + description: '' + default: '' + containerName: + type: string + description: '' + default: '' + endpoint: + type: string + description: '' + default: '' + useSSL: + type: boolean + description: '' + default: true + required: + - accountName + - containerName + - useSSL diff --git a/azure_oauth.resource-type.yaml b/azure_oauth.resource-type.yaml new file mode 100644 index 0000000..33f8df3 --- /dev/null +++ b/azure_oauth.resource-type.yaml @@ -0,0 +1,16 @@ +description: Azure OAuth token +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - token + properties: + token: + type: string + description: AAD token for authentication + default: '' + password: true + required: + - token diff --git a/azure_openai.resource-type.yaml b/azure_openai.resource-type.yaml new file mode 100644 index 0000000..dd7b7ab --- /dev/null +++ b/azure_openai.resource-type.yaml @@ -0,0 +1,24 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - apiKey + - baseUrl + properties: + apiKey: + type: string + description: '' + default: '' + nullable: false + password: true + baseUrl: + type: string + description: https://.openai.azure.com/openai + default: '' + nullable: false + required: + - apiKey + - baseUrl diff --git a/azure_workload_identity.resource-type.yaml b/azure_workload_identity.resource-type.yaml new file mode 100644 index 0000000..b386b7f --- /dev/null +++ b/azure_workload_identity.resource-type.yaml @@ -0,0 +1,33 @@ +description: | + Azure Blob Storage configuration which works with Azure Workload Identity. + + Assume the servers and workers are passed the following env variable: + AZURE_FEDERATED_TOKEN_FILE + AZURE_CLIENT_ID + AZURE_TENANT_ID +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - accountName + - containerName + - useSSL + properties: + accountName: + type: string + description: '' + default: '' + containerName: + type: string + description: '' + default: '' + useSSL: + type: boolean + description: '' + default: true + required: + - accountName + - containerName + - useSSL diff --git a/bamboo_hr.resource-type.yaml b/bamboo_hr.resource-type.yaml new file mode 100644 index 0000000..272f60c --- /dev/null +++ b/bamboo_hr.resource-type.yaml @@ -0,0 +1,16 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft-07/schema# + type: object + properties: + apiKey: + type: string + description: API key + companyDomain: + type: string + description: Company domain + required: + - companyDomain + - apiKey diff --git a/baremetrics.resource-type.yaml b/baremetrics.resource-type.yaml new file mode 100644 index 0000000..08e4852 --- /dev/null +++ b/baremetrics.resource-type.yaml @@ -0,0 +1,14 @@ +description: |- + 1. Once on the dashboard, open up `Settings`, and then `API` + 2. Copy `Live API Key` +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: Live API key obtained from the Baremetrics dashboard + required: + - apiKey diff --git a/baserow.resource-type.yaml b/baserow.resource-type.yaml new file mode 100644 index 0000000..3100a43 --- /dev/null +++ b/baserow.resource-type.yaml @@ -0,0 +1,24 @@ +description: Baserow is an open-source no-code database and an alternative to Airtable. +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - base_url + - token + properties: + base_url: + type: string + description: By default, the URL points to the official Baserow site, though it + can be modified for self-hosted setups. + default: https://baserow.io + nullable: false + token: + type: string + description: The Database token + default: '' + nullable: false + password: true + required: + - base_url diff --git a/baserow_table.resource-type.yaml b/baserow_table.resource-type.yaml new file mode 100644 index 0000000..e393933 --- /dev/null +++ b/baserow_table.resource-type.yaml @@ -0,0 +1,18 @@ +description: Specifies a particular Baserow table, to be used in conjunction + with the 'baserow' resource that contains the access token and URL. +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - database_id + - table_id + properties: + database_id: + type: integer + description: The numeric database id + table_id: + type: integer + description: The numeric table id + required: [] diff --git a/basic_http_auth.resource-type.yaml b/basic_http_auth.resource-type.yaml new file mode 100644 index 0000000..6f82944 --- /dev/null +++ b/basic_http_auth.resource-type.yaml @@ -0,0 +1,23 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - username + - password + properties: + password: + type: string + description: '' + default: '' + nullable: false + username: + type: string + description: '' + default: '' + nullable: false + required: + - username + - password diff --git a/basis_theory.resource-type.yaml b/basis_theory.resource-type.yaml new file mode 100644 index 0000000..27a6511 --- /dev/null +++ b/basis_theory.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: API key retrieved upon creating an application. + required: + - apiKey diff --git a/beamer.resource-type.yaml b/beamer.resource-type.yaml new file mode 100644 index 0000000..8c70c9c --- /dev/null +++ b/beamer.resource-type.yaml @@ -0,0 +1,11 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + required: + - apiKey diff --git a/bigquery.resource-type.yaml b/bigquery.resource-type.yaml new file mode 100644 index 0000000..41f9d35 --- /dev/null +++ b/bigquery.resource-type.yaml @@ -0,0 +1,43 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + type: + type: string + auth_provider_x509_cert_url: + type: string + format: url + auth_uri: + type: string + format: url + client_email: + type: string + format: email + client_id: + type: string + client_x509_cert_url: + type: string + format: url + private_key: + type: string + private_key_id: + type: string + project_id: + type: string + token_uri: + type: string + format: url + required: + - type + - auth_uri + - client_id + - token_uri + - project_id + - private_key + - client_email + - private_key_id + - client_x509_cert_url + - auth_provider_x509_cert_url diff --git a/bitbucket.resource-type.yaml b/bitbucket.resource-type.yaml new file mode 100644 index 0000000..01625a0 --- /dev/null +++ b/bitbucket.resource-type.yaml @@ -0,0 +1,18 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + password: + type: string + description: '' + default: '' + username: + type: string + description: '' + default: '' + required: + - username + - password diff --git a/bitly.resource-type.yaml b/bitly.resource-type.yaml new file mode 100644 index 0000000..bd78001 --- /dev/null +++ b/bitly.resource-type.yaml @@ -0,0 +1,13 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: 'Generic access token or OAuth access token: + https://dev.bitly.com/docs/getting-started/authentication/' + required: + - token diff --git a/bluesky.resource-type.yaml b/bluesky.resource-type.yaml new file mode 100644 index 0000000..1c271a6 --- /dev/null +++ b/bluesky.resource-type.yaml @@ -0,0 +1,23 @@ +description: Bluesky credentials +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - username + - password + properties: + password: + type: string + description: Create an App password in Settings -> Privacy and Security -> App + passwords + default: '' + password: true + username: + type: string + description: User handle without the @ + default: '' + placeholder: johnsmith.bsky.social + title: '' + required: [] diff --git a/botify.resource-type.yaml b/botify.resource-type.yaml new file mode 100644 index 0000000..05833c6 --- /dev/null +++ b/botify.resource-type.yaml @@ -0,0 +1,11 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + required: + - token diff --git a/box.resource-type.yaml b/box.resource-type.yaml new file mode 100644 index 0000000..45f678c --- /dev/null +++ b/box.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: Access token generated using the Client ID and the Client Secret. + required: + - token diff --git a/brevo.resource-type.yaml b/brevo.resource-type.yaml new file mode 100644 index 0000000..53e05d1 --- /dev/null +++ b/brevo.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: API key generated from the dashboard. + required: + - apiKey diff --git a/brex.resource-type.yaml b/brex.resource-type.yaml new file mode 100644 index 0000000..7e78765 --- /dev/null +++ b/brex.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: API token retrieved from the settings page. + required: + - token diff --git a/buttondown.resource-type.yaml b/buttondown.resource-type.yaml new file mode 100644 index 0000000..b7b6ea8 --- /dev/null +++ b/buttondown.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: API token generated from the dashboard. + required: + - token diff --git a/c_winrm.resource-type.yaml b/c_winrm.resource-type.yaml new file mode 100644 index 0000000..19122ff --- /dev/null +++ b/c_winrm.resource-type.yaml @@ -0,0 +1,34 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - host + - username + - password + - transport + - use_https + - server_cert_validation + properties: + host: + type: string + description: '' + default: '' + password: + type: string + description: '' + server_cert_validation: + type: string + description: '' + transport: + type: string + description: '' + use_https: + type: string + description: '' + username: + type: string + description: '' + required: [] diff --git a/cacertificate.resource-type.yaml b/cacertificate.resource-type.yaml new file mode 100644 index 0000000..93f1e8d --- /dev/null +++ b/cacertificate.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + certificate: + type: string + description: '' + default: '' + required: [] diff --git a/calendly.resource-type.yaml b/calendly.resource-type.yaml new file mode 100644 index 0000000..05833c6 --- /dev/null +++ b/calendly.resource-type.yaml @@ -0,0 +1,11 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + required: + - token diff --git a/campayn.resource-type.yaml b/campayn.resource-type.yaml new file mode 100644 index 0000000..3ceb6af --- /dev/null +++ b/campayn.resource-type.yaml @@ -0,0 +1,14 @@ +description: |- + 1. On the dashboard, open `Settings` and then navigate to `Account` + 2. Press `Show your campayn API key` to reveal the API key and copy it +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: API Key retrieved from the settings page for Campayn. + required: + - apiKey diff --git a/certopus.resource-type.yaml b/certopus.resource-type.yaml new file mode 100644 index 0000000..f3157e4 --- /dev/null +++ b/certopus.resource-type.yaml @@ -0,0 +1,16 @@ +description: >- + 1. After completing the onboarding, click the puzzle icon on the left + navigation bar to switch to the integrations tab. + + 2. Copy the `REST API KEY` under `Canva`. +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: API key obtained from the Certopus dashboard + required: + - apiKey diff --git a/chromadb.resource-type.yaml b/chromadb.resource-type.yaml new file mode 100644 index 0000000..89f2c71 --- /dev/null +++ b/chromadb.resource-type.yaml @@ -0,0 +1,40 @@ +description: Open-source vector database to store, manage, and query vector embeddings. +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - host + - port + - ssl + - tenant + - database + properties: + database: + type: string + description: "Optional: The database to use. Default is 'default_database'." + default: null + nullable: true + host: + type: string + description: The host of the remote server. Default is localhost. + default: localhost + nullable: false + port: + type: integer + description: The port of the remote server. Default is 8000. + ssl: + type: boolean + description: If True, the client will use HTTPS. If not specified, the default + is False. + default: false + tenant: + type: string + description: "Optional: The tenant to use (logical grouping for a set of + databases). Default is 'default_tenant'." + default: null + nullable: true + required: + - host + - port diff --git a/circleci.resource-type.yaml b/circleci.resource-type.yaml new file mode 100644 index 0000000..05833c6 --- /dev/null +++ b/circleci.resource-type.yaml @@ -0,0 +1,11 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + required: + - token diff --git a/clerk.resource-type.yaml b/clerk.resource-type.yaml new file mode 100644 index 0000000..8cb83b1 --- /dev/null +++ b/clerk.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: Secret Key found in configure tab of the instance. + required: + - apiKey diff --git a/clickhouse.resource-type.yaml b/clickhouse.resource-type.yaml new file mode 100644 index 0000000..4e619d0 --- /dev/null +++ b/clickhouse.resource-type.yaml @@ -0,0 +1,20 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + host: + type: string + description: Database host + default: '' + password: + type: string + description: Database password or API key secret (Cloud API) + default: '' + username: + type: string + description: Database username or API key id (Cloud API) + default: '' + required: [] diff --git a/clickup.resource-type.yaml b/clickup.resource-type.yaml new file mode 100644 index 0000000..37bee4f --- /dev/null +++ b/clickup.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: API token retrieved from the dashboard. + required: + - token diff --git a/cloudflare.resource-type.yaml b/cloudflare.resource-type.yaml new file mode 100644 index 0000000..973135d --- /dev/null +++ b/cloudflare.resource-type.yaml @@ -0,0 +1,23 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + email: + type: string + description: '' + default: '' + key: + type: string + description: '' + default: '' + token: + type: string + description: '' + default: '' + required: + - key + - token + - email diff --git a/cockroachdb.resource-type.yaml b/cockroachdb.resource-type.yaml new file mode 100644 index 0000000..db90854 --- /dev/null +++ b/cockroachdb.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: Access token retrieved from the dashboard. + required: + - token diff --git a/codat.resource-type.yaml b/codat.resource-type.yaml new file mode 100644 index 0000000..8d797d8 --- /dev/null +++ b/codat.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + encodedKey: + type: string + description: Encoded API key retrieved from the dashboard. + required: + - encodedKey diff --git a/cohere.resource-type.yaml b/cohere.resource-type.yaml new file mode 100644 index 0000000..cff5c6d --- /dev/null +++ b/cohere.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: API key generated from Cohere dashboard. + required: + - apiKey diff --git a/comapeo_server.resource-type.yaml b/comapeo_server.resource-type.yaml new file mode 100644 index 0000000..dc87d4b --- /dev/null +++ b/comapeo_server.resource-type.yaml @@ -0,0 +1,21 @@ +description: A server URL and access token pair to connect to a CoMapeo archive server. +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - server_url + - access_token + properties: + access_token: + type: string + description: Your access token for the CoMapeo archive server + default: '' + server_url: + type: string + description: The base URL of your CoMapeo archive server + default: '' + required: + - server_url + - access_token diff --git a/confluence.resource-type.yaml b/confluence.resource-type.yaml new file mode 100644 index 0000000..0e66367 --- /dev/null +++ b/confluence.resource-type.yaml @@ -0,0 +1,20 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiToken: + type: string + description: Token generated from Atlassian dashboard. + baseUrl: + type: string + description: Base URL of confluence account. + email: + type: string + description: Email used to register the Confluence account. + required: + - email + - apiToken + - baseUrl diff --git a/contentful.resource-type.yaml b/contentful.resource-type.yaml new file mode 100644 index 0000000..b93d88c --- /dev/null +++ b/contentful.resource-type.yaml @@ -0,0 +1,26 @@ +description: |- + 1. Open up the `Settings` dropdown and select `General Settings` + 2. Copy the `Space ID` + 3. Open up the `Settings` dropdown again and select `CMA tokens` + 4. Create a new personal access token, copy the access token + 5. Open up the `Settings` dropdown one last time and select `Environments` + 6. Copy any `Environment ID`. The value for this will most likely be `master` +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + accessToken: + type: string + description: Access token for Content Management API (CMA). + environment: + type: string + description: Environment (e.g. master). + spaceId: + type: string + description: Unique identifier of the space. + required: + - accessToken + - environment + - spaceId diff --git a/contiguity.resource-type.yaml b/contiguity.resource-type.yaml new file mode 100644 index 0000000..13588cb --- /dev/null +++ b/contiguity.resource-type.yaml @@ -0,0 +1,16 @@ +description: >- + 1. On the dashboard, click on `generate & use revokable tokens` under the + `authenticating with revokable tokens` section + + 2. Provide a name for the token and create it, then copy it +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: Revokable token generated from the dashboard + required: + - token diff --git a/convertkit.resource-type.yaml b/convertkit.resource-type.yaml new file mode 100644 index 0000000..1af9324 --- /dev/null +++ b/convertkit.resource-type.yaml @@ -0,0 +1,18 @@ +description: >- + 1. Open up `Settings` by clicking on the profile picture icon at the top-right + corner + + 2. Select `Advanced` from the left navigation bar. + + 3. View the `API Secret` and copy it +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiSecret: + type: string + description: The API Secret associated to the converkit account + required: + - apiSecret diff --git a/currencyapi.resource-type.yaml b/currencyapi.resource-type.yaml new file mode 100644 index 0000000..8bda9bc --- /dev/null +++ b/currencyapi.resource-type.yaml @@ -0,0 +1,13 @@ +description: Api key for currencyapi.com +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: the apikey for the currencyapi.com + default: '' + required: + - apiKey diff --git a/customai.resource-type.yaml b/customai.resource-type.yaml new file mode 100644 index 0000000..fbdb05c --- /dev/null +++ b/customai.resource-type.yaml @@ -0,0 +1,23 @@ +description: Any OpenAI API compatible provider +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - api_key + - base_url + properties: + api_key: + type: string + description: '' + default: '' + password: true + base_url: + type: string + description: e.g. https://my.custom.provider/v1 + default: '' + nullable: false + placeholder: '' + required: + - base_url diff --git a/datadog.resource-type.yaml b/datadog.resource-type.yaml new file mode 100644 index 0000000..cd98189 --- /dev/null +++ b/datadog.resource-type.yaml @@ -0,0 +1,18 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiBase: + type: string + description: '' + apiKey: + type: string + description: '' + appKey: + type: string + description: '' + required: + - apiKey diff --git a/datocms.resource-type.yaml b/datocms.resource-type.yaml new file mode 100644 index 0000000..494f9c5 --- /dev/null +++ b/datocms.resource-type.yaml @@ -0,0 +1,14 @@ +description: |- + 1. On a project page, select "project settings" from the top navigation bar. + 2. Switch to "api tokens" tab and copy the `full-access API token`. +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: API key obtained from the DatoCMS dashboard + required: + - apiKey diff --git a/deel.resource-type.yaml b/deel.resource-type.yaml new file mode 100644 index 0000000..bbb59a1 --- /dev/null +++ b/deel.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft-07/schema# + type: object + properties: + apiKey: + type: string + description: API key + required: + - apiKey diff --git a/deep_infra.resource-type.yaml b/deep_infra.resource-type.yaml new file mode 100644 index 0000000..fbc4fc4 --- /dev/null +++ b/deep_infra.resource-type.yaml @@ -0,0 +1,13 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: Some of the APIs are accessible using the API key on the dashboard, + others require the JWT token copied from the network tab. + required: + - token diff --git a/deepl.resource-type.yaml b/deepl.resource-type.yaml new file mode 100644 index 0000000..969bc0d --- /dev/null +++ b/deepl.resource-type.yaml @@ -0,0 +1,16 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: API key generated on the dashboard for DeepL API product. + baseUrl: + type: string + description: Base URL for your API plan - free and pro have different API base URLs. + required: + - apiKey + - baseUrl diff --git a/deepseek.resource-type.yaml b/deepseek.resource-type.yaml new file mode 100644 index 0000000..45aff6a --- /dev/null +++ b/deepseek.resource-type.yaml @@ -0,0 +1,22 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - api_key + - base_url + properties: + api_key: + type: string + description: '' + default: '' + nullable: false + password: true + base_url: + type: string + description: Optional. Only needed to overwrite the default base URL. + default: '' + required: + - api_key diff --git a/digitalocean.resource-type.yaml b/digitalocean.resource-type.yaml new file mode 100644 index 0000000..05833c6 --- /dev/null +++ b/digitalocean.resource-type.yaml @@ -0,0 +1,11 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + required: + - token diff --git a/discord_bot_configuration.resource-type.yaml b/discord_bot_configuration.resource-type.yaml new file mode 100644 index 0000000..911b085 --- /dev/null +++ b/discord_bot_configuration.resource-type.yaml @@ -0,0 +1,16 @@ +description: 'See: https://www.windmill.dev/blog/knowledge-base-discord-bot' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + application_id: + type: string + description: '' + default: '' + public_key: + type: string + description: '' + default: '' + required: [] diff --git a/discord_webhook.resource-type.yaml b/discord_webhook.resource-type.yaml new file mode 100644 index 0000000..23f7ea8 --- /dev/null +++ b/discord_webhook.resource-type.yaml @@ -0,0 +1,16 @@ +description: >- + Discord webhook url to send messages. + + + See: + +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + webhook_url: + type: string + description: The webhook url + required: [] diff --git a/discourse.resource-type.yaml b/discourse.resource-type.yaml new file mode 100644 index 0000000..4389893 --- /dev/null +++ b/discourse.resource-type.yaml @@ -0,0 +1,18 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: API key retrieved from Discourse. + apiUsername: + type: string + description: API username retrieved from Discourse. + defaultHost: + type: string + description: Base URL of the Discourse instance. + required: + - '{property1}' diff --git a/docspring.resource-type.yaml b/docspring.resource-type.yaml new file mode 100644 index 0000000..ce9c592 --- /dev/null +++ b/docspring.resource-type.yaml @@ -0,0 +1,14 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + tokenId: + type: string + tokenSecret: + type: string + required: + - tokenId + - tokenSecret diff --git a/dust.resource-type.yaml b/dust.resource-type.yaml new file mode 100644 index 0000000..644b35f --- /dev/null +++ b/dust.resource-type.yaml @@ -0,0 +1,22 @@ +description: >- + 1. On the workspace console, switch to the `Build` tab, open `Developer Tools` + -> `API Keys`, and create a new API key + + 2. Next, open up `Settings` -> `Workspace`. The URL of this page will look + something like the following: `https://dust.tt/w/{workspace_id}/workspace`. + Copy the `workspace_id` part +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: API Key generated from the dashboard + workspaceId: + type: string + description: Workspace id in the URL bar after w/ + required: + - apiKey + - workspaceId diff --git a/dynatrace.resource-type.yaml b/dynatrace.resource-type.yaml new file mode 100644 index 0000000..4452464 --- /dev/null +++ b/dynatrace.resource-type.yaml @@ -0,0 +1,24 @@ +description: Credentials for connecting to a Dynatrace tenant +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + accessToken: + type: string + description: 'Documentation: + https://www.dynatrace.com/support/help/manage/access-control/access-tokens' + default: '' + environmentId: + type: string + description: "In Dynatrace SaaS, your environment ID is the first part of your + Dynatrace environment's URL: {environmentId}.live.dynatrace.com" + default: '' + environmentUrl: + type: string + description: URL of your environment. Default is live.dynatrace.com + default: live.dynatrace.com + required: + - environmentId + - accessToken diff --git a/edgedb.resource-type.yaml b/edgedb.resource-type.yaml new file mode 100644 index 0000000..289666d --- /dev/null +++ b/edgedb.resource-type.yaml @@ -0,0 +1,49 @@ +description: Connection details for an EdgeDB database, either hosted on EdgeDB + Cloud or self-hosted +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + database: + type: string + description: Name of the database to connect to. (Required unless a DSN or an + EdgeDB Cloud instance are provided) + default: '' + dsn: + type: string + description: Overrides any other settings except password. (Required unless + host, port, user, and database, or an EdgeDB Cloud instance name are + provided) + default: '' + host: + type: string + description: Hostname of the EdgeDB instance. (Required unless a DSN or an + EdgeDB Cloud instance are provided) + default: '' + format: hostname + instanceName: + type: string + description: Only for use with EdgeDB Cloud instances. Format is + / (Required for EdgeDB Cloud instances + unless a DSN is provided) + default: '' + password: + type: string + description: (Required unless a secret key for an EdgeDB Cloud instance is provided) + default: '' + port: + type: number + description: (Required unless a DSN or an EdgeDB Cloud instance are provided) + secretKey: + type: string + description: Specifies the secret key to use for authentication with EdgeDB + Cloud instances. (Required for EdgeDB Cloud instance) + default: '' + user: + type: string + description: Username to use for connecting to the database. (Required unless a + DSN or an EdgeDB Cloud instance are provided) + default: '' + required: [] diff --git a/enode.resource-type.yaml b/enode.resource-type.yaml new file mode 100644 index 0000000..05833c6 --- /dev/null +++ b/enode.resource-type.yaml @@ -0,0 +1,11 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + required: + - token diff --git a/exa.resource-type.yaml b/exa.resource-type.yaml new file mode 100644 index 0000000..be72cc7 --- /dev/null +++ b/exa.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: API key retrieved from the dashboard. + required: + - apiKey diff --git a/f/Backup/backup_restore_orchestrator__flow/aktive_datastores_aus_db_holen.my.sql b/f/Backup/backup_restore_orchestrator__flow/aktive_datastores_aus_db_holen.my.sql new file mode 100644 index 0000000..764b48e --- /dev/null +++ b/f/Backup/backup_restore_orchestrator__flow/aktive_datastores_aus_db_holen.my.sql @@ -0,0 +1 @@ +SELECT datastore FROM Kunden.`bronze.backup.server.datastore` AS kbbsd WHERE kbbsd.restore = 1 diff --git a/f/Backup/backup_restore_orchestrator__flow/alle_freien_restore-server_holen.lock b/f/Backup/backup_restore_orchestrator__flow/alle_freien_restore-server_holen.lock new file mode 100644 index 0000000..48ff042 --- /dev/null +++ b/f/Backup/backup_restore_orchestrator__flow/alle_freien_restore-server_holen.lock @@ -0,0 +1,17 @@ +# py: 3.12 +anyio==4.12.1 +bcrypt==5.0.0 +certifi==2026.2.25 +cffi==2.0.0 +cryptography==46.0.5 +h11==0.16.0 +httpcore==1.0.9 +httpx==0.28.1 +idna==3.11 +invoke==2.2.1 +mysql-connector-python==9.6.0 +paramiko==4.0.0 +pycparser==3.0 +pynacl==1.6.2 +typing-extensions==4.15.0 +wmill==1.657.2 diff --git a/f/Backup/backup_restore_orchestrator__flow/alle_freien_restore-server_holen.py b/f/Backup/backup_restore_orchestrator__flow/alle_freien_restore-server_holen.py new file mode 100644 index 0000000..8ccb95f --- /dev/null +++ b/f/Backup/backup_restore_orchestrator__flow/alle_freien_restore-server_holen.py @@ -0,0 +1,40 @@ +import wmill, mysql.connector, json + +def main(prev: dict): + if prev.get("mode") == "webhook": + return prev + + db_cfg = json.loads(wmill.get_variable("f/Backup/mysql_config")) + conn = mysql.connector.connect(**db_cfg) + cur = conn.cursor(dictionary=True) + + # FIX: max_backup_size_gb hinzugefügt + cur.execute(""" + SELECT hostname, ip, free_space_gb, + script_deployed, script_version, + restore_mount, restore_path, + max_backup_size_gb, + min_backup_size_gb + FROM Kunden.`bronze.restore.server` + WHERE is_active = 1 AND current_job_uuid IS NULL + ORDER BY free_space_gb DESC + """) + servers = cur.fetchall() + cur.close(); conn.close() + + if not servers: + raise Exception("Kein freier Restore-Server verfuegbar!") + + for s in servers: + if not s.get("restore_mount"): + raise Exception( + f"restore_mount fuer '{s['hostname']}' nicht konfiguriert!" + ) + if not s.get("restore_path"): + raise Exception( + f"restore_path fuer '{s['hostname']}' nicht konfiguriert!" + ) + + print(f"{len(servers)} freie Restore-Server: " + f"{[s['hostname'] for s in servers]}") + return {**prev, "target_servers": servers} diff --git a/f/Backup/backup_restore_orchestrator__flow/alte_restore-ordner_auf_backup-server_loeschen.lock b/f/Backup/backup_restore_orchestrator__flow/alte_restore-ordner_auf_backup-server_loeschen.lock new file mode 100644 index 0000000..69e2713 --- /dev/null +++ b/f/Backup/backup_restore_orchestrator__flow/alte_restore-ordner_auf_backup-server_loeschen.lock @@ -0,0 +1,17 @@ +# py: 3.12 +anyio==4.13.0 +bcrypt==5.0.0 +certifi==2026.2.25 +cffi==2.0.0 +cryptography==46.0.6 +h11==0.16.0 +httpcore==1.0.9 +httpx==0.28.1 +idna==3.11 +invoke==2.2.1 +mysql-connector-python==9.6.0 +paramiko==4.0.0 +pycparser==3.0 +pynacl==1.6.2 +typing-extensions==4.15.0 +wmill==1.666.0 \ No newline at end of file diff --git a/f/Backup/backup_restore_orchestrator__flow/alte_restore-ordner_auf_backup-server_loeschen.py b/f/Backup/backup_restore_orchestrator__flow/alte_restore-ordner_auf_backup-server_loeschen.py new file mode 100644 index 0000000..eee54e3 --- /dev/null +++ b/f/Backup/backup_restore_orchestrator__flow/alte_restore-ordner_auf_backup-server_loeschen.py @@ -0,0 +1,83 @@ +import wmill, json, paramiko, mysql.connector, re, io + + +def main(prev: dict): + if prev.get("mode") == "webhook": + return prev + + db_cfg = json.loads(wmill.get_variable("f/Backup/mysql_config")) + conn = mysql.connector.connect(**db_cfg) + cur = conn.cursor(dictionary=True) + + cur.execute(""" + SELECT datastore, rsync_target, retention_days + FROM Kunden.`bronze.backup.datastore.config` + WHERE rsync_target IS NOT NULL AND rsync_target != '' + """) + configs = cur.fetchall() + cur.close(); conn.close() + + if not configs: + print("Keine Datastore-Configs - Cleanup uebersprungen.") + return prev + + backup_server = wmill.get_variable("f/Backup/backup_server_host") + ip_match = re.search(r'https?://([0-9.]+)', backup_server) + ip = ip_match.group(1) if ip_match else backup_server + bw_pass = wmill.get_variable("f/Backup/backup_server_ssh_password") + + ssh = paramiko.SSHClient() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + ssh.connect(ip, username="root", password=bw_pass) + + # Cleanup-Script aufbauen + # Datum-basierter Vergleich statt -mtime + script_lines = ["#!/bin/bash", "set -euo pipefail", ""] + + for cfg in configs: + datastore = cfg["datastore"] + target = cfg["rsync_target"] + retention_days = cfg.get("retention_days") or 7 + + script_lines.append( + f"echo '[{datastore}] Cleanup {target} (Ordner aelter als {retention_days} Tage)'" + ) + script_lines.append(f"if [ -d '{target}' ]; then") + script_lines.append(f" cutoff=$(date -d '{retention_days} days ago' +%Y-%m-%d)") + script_lines.append(f" find '{target}' -maxdepth 1 -type d -name '????-??-??' | while read dir; do") + script_lines.append(f" folder_date=$(basename \"$dir\")") + script_lines.append(f" if [[ \"$folder_date\" < \"$cutoff\" ]]; then") + script_lines.append(f" echo \" Loesche: $dir (Datum: $folder_date < Cutoff: $cutoff)\"") + script_lines.append(f" rm -rf \"$dir\"") + script_lines.append(f" else") + script_lines.append(f" echo \" Behalte: $dir\"") + script_lines.append(f" fi") + script_lines.append(f" done") + script_lines.append(f"else") + script_lines.append(f" echo ' WARNUNG: Verzeichnis nicht gefunden: {target}'") + script_lines.append(f"fi") + script_lines.append("") + + script_lines.append("echo 'Cleanup abgeschlossen.'") + cleanup_script = "\n".join(script_lines) + + # Script per SFTP hochladen statt Heredoc + sftp = ssh.open_sftp() + sftp.putfo( + io.BytesIO(cleanup_script.encode()), + "/tmp/cleanup_restore.sh" + ) + sftp.close() + + ssh.exec_command("chmod +x /tmp/cleanup_restore.sh") + + import time; time.sleep(1) + + ssh.exec_command( + "nohup /tmp/cleanup_restore.sh > /tmp/cleanup_restore.log 2>&1 &" + ) + + ssh.close() + print(f"Cleanup auf {ip} im Hintergrund gestartet.") + print(f"Log: /tmp/cleanup_restore.log") + return {**prev, "cleanup": "started_background"} \ No newline at end of file diff --git a/f/Backup/backup_restore_orchestrator__flow/ersten_restore_pro_server_starten.lock b/f/Backup/backup_restore_orchestrator__flow/ersten_restore_pro_server_starten.lock new file mode 100644 index 0000000..cdc21f2 --- /dev/null +++ b/f/Backup/backup_restore_orchestrator__flow/ersten_restore_pro_server_starten.lock @@ -0,0 +1,17 @@ +# py: 3.12 +anyio==4.13.0 +bcrypt==5.0.0 +certifi==2026.2.25 +cffi==2.0.0 +cryptography==46.0.5 +h11==0.16.0 +httpcore==1.0.9 +httpx==0.28.1 +idna==3.11 +invoke==2.2.1 +mysql-connector-python==9.6.0 +paramiko==4.0.0 +pycparser==3.0 +pynacl==1.6.2 +typing-extensions==4.15.0 +wmill==1.664.0 \ No newline at end of file diff --git a/f/Backup/backup_restore_orchestrator__flow/ersten_restore_pro_server_starten.py b/f/Backup/backup_restore_orchestrator__flow/ersten_restore_pro_server_starten.py new file mode 100644 index 0000000..988c6de --- /dev/null +++ b/f/Backup/backup_restore_orchestrator__flow/ersten_restore_pro_server_starten.py @@ -0,0 +1,158 @@ +import wmill, json, paramiko, mysql.connector + + +def start_restore(server, backup, job_uuid, webhook_url, webhook_tok): + """Startet restore.sh auf einem Server non-blocking.""" + ssh = paramiko.SSHClient() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + ssh.connect( + server["ip"], + username=server["ssh_creds"]["user"], + password=server["ssh_creds"]["password"] + ) + safe_client = backup["client_name"].replace("/", "_").replace(":", "_") + srv_hostname = server["hostname"] + bk_size = backup.get("backup_size_bytes") or 0 + cmd = ( + f"nohup /opt/windmill-restore/restore.sh" + f" --job-uuid '{job_uuid}'" + f" --backup-path '{backup['backup_path']}'" + f" --client '{backup['client_name']}'" + f" --restore-mount '{server['restore_mount']}'" + f" --restore-path '{server['restore_path']}'" + f" --rsync-target '{backup['rsync_target']}'" + f" --pbs-storage '{backup['pbs_storage_id']}'" + f" --webhook-url '{webhook_url}'" + f" --webhook-token '{webhook_tok}'" + f" --server-hostname '{srv_hostname}'" + f" --backup-size '{bk_size}'" + f" > /opt/windmill-restore/logs/{safe_client}.log 2>&1 &" + ) + ssh.exec_command(cmd) + ssh.close() + + +def find_backup_for_server(server, backups): + """ + Sucht das erste Backup aus der Liste das zur Server-Größenklasse passt. + max_backup_size_gb = NULL -> kein oberes Limit + min_backup_size_gb = NULL -> kein unteres Limit + Gibt (index, backup) zurueck oder (None, None) wenn nichts passt. + """ + max_gb = server.get("max_backup_size_gb") + min_gb = server.get("min_backup_size_gb") + max_bytes = max_gb * 1024 * 1024 * 1024 if max_gb is not None else None + min_bytes = min_gb * 1024 * 1024 * 1024 if min_gb is not None else None + + for i, backup in enumerate(backups): + size = backup.get("backup_size_bytes") or 0 + if max_bytes is not None and size > max_bytes: + continue + if min_bytes is not None and size < min_bytes: + continue + return i, backup + return None, None + + +def main(prev: dict): + if prev.get("mode") == "webhook": + return prev + + servers = prev.get("target_servers", []) + backups = list(prev.get("backups", [])) + job_uuid = prev["job_uuid"] + + if not backups: + return {**prev, "status": "no_backups"} + + db_cfg = json.loads(wmill.get_variable("f/Backup/mysql_config")) + conn = mysql.connector.connect(**db_cfg) + cur = conn.cursor() + + webhook_url = wmill.get_variable("f/Backup/windmill_webhook_url") + webhook_tok = wmill.get_variable("f/Backup/windmill_webhook_token") + + servers_sorted = sorted( + servers, + key=lambda s: s.get("max_backup_size_gb") or 999999, + reverse=True + ) + + started = [] + + for server in servers_sorted: + if not backups: + break + + idx, backup = find_backup_for_server(server, backups) + + if backup is None: + print(f"Kein passendes Backup fuer '{server['hostname']}' " + f"(max: {server.get('max_backup_size_gb')} GB)") + continue + + backups.pop(idx) + + def fail_backup(msg, bk=backup, sv=server): + cur.execute(""" + INSERT INTO Kunden.`bronze.restore.result` + (job_uuid, client_name, backup_path, + backup_size_bytes, restore_server, status, error_message) + VALUES (%s, %s, %s, %s, %s, 'failed', %s) + """, (job_uuid, bk["client_name"], bk["backup_path"], + bk.get("backup_size_bytes", 0), sv["hostname"], msg)) + cur.execute(""" + UPDATE Kunden.`bronze.restore.jobs` + SET failed_count=failed_count+1 WHERE job_uuid=%s + """, (job_uuid,)) + conn.commit() + + if not backup.get("rsync_target"): + fail_backup("rsync_target fehlt"); continue + if not backup.get("pbs_storage_id"): + fail_backup("pbs_storage_id fehlt"); continue + if not server.get("restore_mount"): + fail_backup("restore_mount fehlt"); continue + if not server.get("restore_path"): + fail_backup("restore_path fehlt"); continue + + client_like = f"{backup['client_name']}%" + + cur.execute(""" + INSERT INTO Kunden.`bronze.restore.result` + (job_uuid, client_name, backup_path, + backup_size_bytes, restore_server, status, started_at) + VALUES (%s, %s, %s, %s, %s, 'restoring', NOW()) + """, (job_uuid, backup["client_name"], backup["backup_path"], + backup.get("backup_size_bytes", 0), server["hostname"])) + + cur.execute(""" + UPDATE Kunden.`bronze.restore.server` + SET current_job_uuid=%s WHERE hostname=%s + """, (job_uuid, server["hostname"])) + + cur.execute(""" + UPDATE Kunden.`bronze.backup.queue` + SET status='assigned' + WHERE job_uuid=%s AND backup_path LIKE %s + """, (job_uuid, client_like)) + conn.commit() + + start_restore(server, backup, job_uuid, webhook_url, webhook_tok) + size_gb = (backup.get("backup_size_bytes") or 0) / 1024 / 1024 / 1024 + print(f"Restore gestartet: {backup['client_name']} " + f"({size_gb:.1f} GB) auf {server['hostname']} " + f"(max: {server.get('max_backup_size_gb')} GB)") + started.append({ + "client": backup["client_name"], + "server": server["hostname"], + }) + + cur.close(); conn.close() + + return { + **prev, + "status": "restore_started", + "started": started, + "backups": backups, + } \ No newline at end of file diff --git a/f/Backup/backup_restore_orchestrator__flow/flow.yaml b/f/Backup/backup_restore_orchestrator__flow/flow.yaml new file mode 100644 index 0000000..8d5cbc5 --- /dev/null +++ b/f/Backup/backup_restore_orchestrator__flow/flow.yaml @@ -0,0 +1,121 @@ +summary: Backup Restore Orchestrator +description: | + Startet täglich um 00:11 Uhr. Holt Backup-Liste direkt via + proxmox-backup-client, schreibt Queue nach Größe sortiert in DB, + registriert PBS-Datastores auf allen freien Restore-Servern, + startet Restores parallel auf mehreren Servern per Webhook-Chaining. +value: + modules: + - id: f + summary: Aktive Datastores aus DB holen + value: + type: rawscript + content: '!inline aktive_datastores_aus_db_holen.my.sql' + input_transforms: + database: + type: static + value: $res:u/sebastianserfling/fascinating_mysql + lock: '' + language: mysql + - id: a + summary: Job initialisieren & Backup-Queue aus PBS aufbauen + value: + type: rawscript + content: '!inline job_initialisieren_&_backup-queue_aus_pbs_aufbauen.py' + input_transforms: + datastores: + type: javascript + expr: results.f + trigger_type: + type: javascript + expr: "flow_input.job_uuid ? 'webhook' : 'schedule'" + webhook_data: + type: javascript + expr: 'flow_input.job_uuid ? flow_input : {}' + lock: '!inline job_initialisieren_&_backup-queue_aus_pbs_aufbauen.lock' + language: python3 + - id: b + summary: Alle freien Restore-Server holen + value: + type: rawscript + content: '!inline alle_freien_restore-server_holen.py' + input_transforms: + prev: + type: javascript + expr: results.a + lock: '!inline alle_freien_restore-server_holen.lock' + language: python3 + - id: g + summary: SSH-Credentials fuer alle Restore-Server aus Bitwarden + value: + type: rawscript + content: '!inline ssh-credentials_fuer_alle_restore-server_aus_bitwarden.py' + input_transforms: + bw_url: + type: static + value: https://bitwarden.stines.de + prev: + type: javascript + expr: results.b + lock: '!inline ssh-credentials_fuer_alle_restore-server_aus_bitwarden.lock' + language: python3 + - id: c + summary: Script deployen & PBS-Datastores auf allen Servern registrieren + value: + type: rawscript + content: '!inline + script_deployen_&_pbs-datastores_auf_allen_servern_registrieren.py' + input_transforms: + bw_result: + type: javascript + expr: results.g + datastores: + type: javascript + expr: results.f + prev: + type: javascript + expr: results.g + lock: '!inline + script_deployen_&_pbs-datastores_auf_allen_servern_registrieren.lock' + language: python3 + - id: h + summary: Alte Restore-Ordner auf Backup-Server loeschen + value: + type: rawscript + content: '!inline alte_restore-ordner_auf_backup-server_loeschen.py' + input_transforms: + prev: + type: javascript + expr: results.c + lock: '!inline alte_restore-ordner_auf_backup-server_loeschen.lock' + language: python3 + - id: d + summary: Ersten Restore pro Server starten + value: + type: rawscript + content: '!inline ersten_restore_pro_server_starten.py' + input_transforms: + prev: + type: javascript + expr: results.h + lock: '!inline ersten_restore_pro_server_starten.lock' + language: python3 + continue_on_error: false + - id: e + summary: Webhook verarbeiten & naechsten Restore auf demselben Server starten + value: + type: rawscript + content: '!inline + webhook_verarbeiten_&_naechsten_restore_auf_demselben_server_starten.py' + input_transforms: + from_init: + type: javascript + expr: results.a + lock: '!inline + webhook_verarbeiten_&_naechsten_restore_auf_demselben_server_starten.lock' + language: python3 +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: [] + properties: {} diff --git a/f/Backup/backup_restore_orchestrator__flow/job_initialisieren_&_backup-queue_aus_pbs_aufbauen.lock b/f/Backup/backup_restore_orchestrator__flow/job_initialisieren_&_backup-queue_aus_pbs_aufbauen.lock new file mode 100644 index 0000000..3cde8ea --- /dev/null +++ b/f/Backup/backup_restore_orchestrator__flow/job_initialisieren_&_backup-queue_aus_pbs_aufbauen.lock @@ -0,0 +1,10 @@ +# py: 3.12 +anyio==4.12.1 +certifi==2026.2.25 +h11==0.16.0 +httpcore==1.0.9 +httpx==0.28.1 +idna==3.11 +mysql-connector-python==9.6.0 +typing-extensions==4.15.0 +wmill==1.662.0 \ No newline at end of file diff --git a/f/Backup/backup_restore_orchestrator__flow/job_initialisieren_&_backup-queue_aus_pbs_aufbauen.py b/f/Backup/backup_restore_orchestrator__flow/job_initialisieren_&_backup-queue_aus_pbs_aufbauen.py new file mode 100644 index 0000000..7645302 --- /dev/null +++ b/f/Backup/backup_restore_orchestrator__flow/job_initialisieren_&_backup-queue_aus_pbs_aufbauen.py @@ -0,0 +1,161 @@ +import wmill, mysql.connector, json, uuid, subprocess, sys, os +from datetime import datetime + +def main( + trigger_type: str = "schedule", + webhook_data: dict = {}, + datastores: list = [], +): + # Webhook erkennen: kind=webhook ODER job_uuid im payload + if trigger_type == "webhook" or webhook_data.get("job_uuid"): + return {"mode": "webhook", "data": webhook_data} + + pbs = json.loads(wmill.get_variable("f/Backup/pbs_variable")) + port = pbs.get("port", 8007) + + env = os.environ.copy() + env["PBS_PASSWORD"] = pbs["password"] + if pbs.get("fingerprint"): + env["PBS_FINGERPRINT"] = pbs["fingerprint"] + + if subprocess.run(["which", "proxmox-backup-client"], + capture_output=True).returncode != 0: + print("Installiere proxmox-backup-client...", file=sys.stderr) + subprocess.run(["bash", "-c", ( + "echo 'deb http://download.proxmox.com/debian/pbs bookworm pbs-no-subscription'" + " > /etc/apt/sources.list.d/pbs-client.list && " + "wget -qO /etc/apt/trusted.gpg.d/proxmox-release-bookworm.gpg " + " https://enterprise.proxmox.com/debian/proxmox-release-bookworm.gpg && " + "apt-get update -qq && apt-get install -y proxmox-backup-client" + )], check=True) + + db_cfg = json.loads(wmill.get_variable("f/Backup/mysql_config")) + conn = mysql.connector.connect(**db_cfg) + cur = conn.cursor(dictionary=True) + + cur.execute(""" + SELECT datastore, rsync_target, pbs_storage_id + FROM Kunden.`bronze.backup.datastore.config` + """) + ds_config = {row["datastore"]: row for row in cur.fetchall()} + + all_snaps = [] + for row in datastores: + datastore = row["datastore"] + if port != 8007: + repo = f"{pbs['user']}@{pbs['host']}!{port}:{datastore}" + else: + repo = f"{pbs['user']}@{pbs['host']}:{datastore}" + + env["PBS_REPOSITORY"] = repo + print(f"Hole Snapshots: {datastore}...", file=sys.stderr) + + result = subprocess.run( + ["proxmox-backup-client", "snapshots", "--output-format", "json"], + capture_output=True, text=True, env=env, + ) + if result.returncode != 0: + print(f"WARNUNG: {datastore} fehlgeschlagen:\n{result.stderr}", + file=sys.stderr) + continue + + snaps = json.loads(result.stdout) + snaps = [s for s in snaps if s.get("backup-type") in ("vm", "ct")] + for s in snaps: + s["_datastore"] = datastore + all_snaps.extend(snaps) + print(f" -> {len(snaps)} Snapshots.", file=sys.stderr) + + if not all_snaps: + raise Exception("Keine Snapshots gefunden!") + + latest: dict = {} + for snap in all_snaps: + key = f"{snap['_datastore']}/{snap['backup-type']}/{snap['backup-id']}" + if key not in latest or snap["backup-time"] > latest[key]["backup-time"]: + latest[key] = snap + + sorted_snaps = sorted(latest.values(), key=lambda s: s.get("size", 0), reverse=True) + print(f"{len(sorted_snaps)} Gruppen -> Queue.", file=sys.stderr) + + job_uuid = str(uuid.uuid4()) + + cur.execute(""" + SELECT job_uuid FROM Kunden.`bronze.restore.jobs` + WHERE status = 'running' + LIMIT 1 + """) + existing = cur.fetchone() + if existing: + cur.close(); conn.close() + raise Exception( + f"Job bereits aktiv: {existing['job_uuid']} – " + f"kein neuer Job gestartet." + ) + + cur.execute("SET time_zone = 'Europe/Berlin'") + + cur.execute(""" + INSERT INTO Kunden.`bronze.restore.jobs` + (job_uuid, started_at, status, restore_server) + VALUES (%s, NOW(), 'running', '') + """, (job_uuid,)) + + cur.execute(""" + UPDATE Kunden.`bronze.backup.queue` + SET status='obsolete' WHERE status='queued' + """) + + for idx, snap in enumerate(sorted_snaps): + backup_type = snap["backup-type"] + backup_id = str(snap["backup-id"]) + datastore = snap["_datastore"] + size_bytes = snap.get("size", 0) + ts = snap["backup-time"] + client_name = f"{datastore}:{backup_type}/{backup_id}" + backup_time_str = datetime.utcfromtimestamp(ts).strftime("%Y-%m-%dT%H:%M:%SZ") + backup_path = f"{datastore}:{backup_type}/{backup_id}/{backup_time_str}" + cfg = ds_config.get(datastore, {}) + rsync_target = cfg.get("rsync_target") + pbs_storage_id = cfg.get("pbs_storage_id") + + cur.execute(""" + INSERT INTO Kunden.`bronze.backup.queue` + (job_uuid, client_name, backup_path, backup_size_bytes, + encrypt_key_ref, priority, rsync_target, + pbs_storage_id, status, last_seen_at) + VALUES (%s, %s, %s, %s, %s, %s, %s, %s, 'queued', NOW()) + """, ( + job_uuid, client_name, backup_path, size_bytes, + client_name, idx, rsync_target, pbs_storage_id, + )) + + cur.execute(""" + INSERT INTO Kunden.`bronze.restore.plan` + (job_uuid, client_name, vm_name) + VALUES (%s, %s, %s) + """, (job_uuid, client_name, f"{backup_type}/{backup_id}")) + + cur.execute(""" + UPDATE Kunden.`bronze.restore.jobs` + SET total_backups=%s WHERE job_uuid=%s + """, (len(sorted_snaps), job_uuid)) + conn.commit() + + cur.execute(""" + SELECT client_name, backup_path, backup_size_bytes, + encrypt_key_ref, priority, + rsync_target, pbs_storage_id + FROM Kunden.`bronze.backup.queue` + WHERE job_uuid = %s AND status = 'queued' + ORDER BY priority ASC + """, (job_uuid,)) + queued = cur.fetchall() + cur.close(); conn.close() + + print(f"Queue: {len(queued)} Backups.", file=sys.stderr) + return { + "mode": "schedule", + "job_uuid": job_uuid, + "backups": queued, + } \ No newline at end of file diff --git a/f/Backup/backup_restore_orchestrator__flow/script_deployen_&_pbs-datastores_auf_allen_servern_registrieren.lock b/f/Backup/backup_restore_orchestrator__flow/script_deployen_&_pbs-datastores_auf_allen_servern_registrieren.lock new file mode 100644 index 0000000..12fa61b --- /dev/null +++ b/f/Backup/backup_restore_orchestrator__flow/script_deployen_&_pbs-datastores_auf_allen_servern_registrieren.lock @@ -0,0 +1,17 @@ +# py: 3.12 +anyio==4.12.1 +bcrypt==5.0.0 +certifi==2026.2.25 +cffi==2.0.0 +cryptography==46.0.5 +h11==0.16.0 +httpcore==1.0.9 +httpx==0.28.1 +idna==3.11 +invoke==2.2.1 +mysql-connector-python==9.6.0 +paramiko==4.0.0 +pycparser==3.0 +pynacl==1.6.2 +typing-extensions==4.15.0 +wmill==1.659.1 \ No newline at end of file diff --git a/f/Backup/backup_restore_orchestrator__flow/script_deployen_&_pbs-datastores_auf_allen_servern_registrieren.py b/f/Backup/backup_restore_orchestrator__flow/script_deployen_&_pbs-datastores_auf_allen_servern_registrieren.py new file mode 100644 index 0000000..a5b88da --- /dev/null +++ b/f/Backup/backup_restore_orchestrator__flow/script_deployen_&_pbs-datastores_auf_allen_servern_registrieren.py @@ -0,0 +1,245 @@ +import wmill, json, paramiko, io, mysql.connector, re + +GITEA_REPO = "http://172.17.1.251:8080/sebastian.serfling/BackupScript.git" + + +def deploy_to_server(ssh, server, pbs, pbs_host, pbs_user, pbs_pass, + pbs_port, ds_config, datastores, gitea_token, + backup_server_host, job_uuid, ssh_creds, db_cfg, + script_version): + + hostname = server["hostname"] + + _, out, _ = ssh.exec_command( + "cat /opt/windmill-restore/version.txt 2>/dev/null || echo none" + ) + current_version = out.read().decode().strip() + needs_deploy = current_version != script_version \ + or not server.get("script_deployed") + + if needs_deploy: + print(f"[{hostname}] Deploye Script v{script_version}...") + ssh.exec_command("mkdir -p /opt/windmill-restore/logs") + ssh.exec_command("which git || apt-get install -y git 2>/dev/null") + repo_url = GITEA_REPO.replace("http://", f"http://{gitea_token}@") + + _, out, err = ssh.exec_command( + "cd /opt/windmill-restore && " + "if [ -d 'BackupScript/.git' ]; then " + " cd BackupScript && git pull; " + "else " + " rm -rf BackupScript && " + " git clone '" + repo_url + "' BackupScript; " + "fi" + ) + exit_code = out.channel.recv_exit_status() + stderr_out = err.read().decode().strip() + if exit_code != 0: + raise Exception(f"[{hostname}] Git fehlgeschlagen: {stderr_out}") + + _, out, err = ssh.exec_command( + "cp /opt/windmill-restore/BackupScript/restore.sh " + " /opt/windmill-restore/restore.sh && " + "chmod +x /opt/windmill-restore/restore.sh && " + "echo '" + script_version + "' > /opt/windmill-restore/version.txt" + ) + exit_code = out.channel.recv_exit_status() + stderr_out = err.read().decode().strip() + if exit_code != 0: + raise Exception(f"[{hostname}] Script kopieren fehlgeschlagen: {stderr_out}") + + print(f"[{hostname}] Script v{script_version} deployed.") + + pbs_conf = "\n".join([ + f"PBS_HOST={pbs_host}", + f"PBS_PORT={pbs_port}", + f"PBS_USER={pbs_user}", + f"PBS_PASSWORD={pbs_pass}", + ]) + "\n" + sftp = ssh.open_sftp() + sftp.putfo(io.BytesIO(pbs_conf.encode()), + "/opt/windmill-restore/pbs.conf") + sftp.putfo(io.BytesIO(backup_server_host.encode()), + "/opt/windmill-restore/backup_server_host") + sftp.close() + ssh.exec_command("chmod 600 /opt/windmill-restore/pbs.conf") + print(f"[{hostname}] backup_server_host: {backup_server_host}") + else: + print(f"[{hostname}] Script aktuell (v{current_version}).") + + ssh.exec_command( + "mkdir -p /opt/windmill-restore/keys && " + "chmod 700 /opt/windmill-restore/keys" + ) + + _, out, _ = ssh.exec_command( + "pvesm status 2>/dev/null | awk 'NR>1{print $1}'" + ) + existing_storages = out.read().decode().splitlines() + pbs_storages = [] + + for row in datastores: + datastore = row["datastore"] + storage_id = "pbs-" + datastore.lower() \ + .replace(" ", "-") \ + .replace("_", "-") + ds_cfg = ds_config.get(datastore, {}) + fingerprint = ds_cfg.get("fingerprint", "") or "" + keyfile_path = f"/opt/windmill-restore/keys/{datastore}.keyfile" + + rsync_src = f"root@{pbs_host}:/root/Scripte/{datastore}.keyfile" + _, out, err = ssh.exec_command( + "if [ -s '" + keyfile_path + "' ]; then " + " echo 'vorhanden'; " + "else " + " rsync -az -e 'ssh -o StrictHostKeyChecking=no' " + " '" + rsync_src + "' '" + keyfile_path + "' " + " && chmod 600 '" + keyfile_path + "' " + " && echo 'geholt'; " + "fi" + ) + exit_code = out.channel.recv_exit_status() + stderr_out = err.read().decode().strip() + if exit_code != 0: + raise Exception( + f"[{hostname}] Keyfile fehlgeschlagen fuer '{datastore}': {stderr_out}" + ) + + if storage_id in existing_storages: + print(f"[{hostname}] Storage '{storage_id}' vorhanden.") + else: + fp_part = f"--fingerprint '{fingerprint}'" if fingerprint else "" + cmd = ( + f"pvesm add pbs {storage_id} " + f"--server '{pbs_host}' " + f"--datastore '{datastore}' " + f"--username '{pbs_user}' " + f"--password '{pbs_pass}' " + f"--port {pbs_port} " + f"--encryption-key '{keyfile_path}' " + f"--content backup" + ) + _, out, err = ssh.exec_command(cmd) + exit_code = out.channel.recv_exit_status() + stderr = err.read().decode().strip() + if exit_code != 0: + raise Exception( + f"[{hostname}] pvesm add '{datastore}' fehlgeschlagen: {stderr}" + ) + print(f"[{hostname}] -> '{storage_id}' registriert") + + pbs_storages.append({"datastore": datastore, "storage_id": storage_id}) + + conn = mysql.connector.connect(**db_cfg) + cur = conn.cursor() + + if needs_deploy: + cur.execute(""" + UPDATE Kunden.`bronze.restore.server` + SET script_deployed=1, script_version=%s WHERE hostname=%s + """, (script_version, hostname)) + + for entry in pbs_storages: + cur.execute(""" + UPDATE Kunden.`bronze.backup.datastore.config` + SET pbs_storage_id=%s WHERE datastore=%s + """, (entry["storage_id"], entry["datastore"])) + + cur.execute(""" + INSERT INTO Kunden.`bronze.restore.session` + (job_uuid, hostname, ip, ssh_user, ssh_password) + VALUES (%s, %s, %s, %s, %s) + ON DUPLICATE KEY UPDATE + ip=VALUES(ip), ssh_user=VALUES(ssh_user), + ssh_password=VALUES(ssh_password) + """, ( + job_uuid, hostname, + ssh_creds["ip"], ssh_creds["user"], ssh_creds["password"], + )) + + conn.commit(); cur.close(); conn.close() + print(f"[{hostname}] Session-Creds gespeichert.") + + return pbs_storages + + +def main(prev: dict, bw_result: dict = {}, datastores: list = []): + if prev.get("mode") == "webhook": + return prev + + servers = prev["target_servers"] + server_creds = prev.get("server_creds", {}) + job_uuid = prev["job_uuid"] + + script_version = wmill.get_variable("f/Backup/restore_version").strip() + print(f"Script-Version aus Variable: {script_version}") + + pbs = json.loads(wmill.get_variable("f/Backup/pbs_variable")) + pbs_host = pbs["host"] + pbs_user = pbs["user"] + pbs_pass = pbs["password"] + pbs_port = str(pbs.get("port", 8007)) + + db_cfg = json.loads(wmill.get_variable("f/Backup/mysql_config")) + conn = mysql.connector.connect(**db_cfg) + cur = conn.cursor(dictionary=True) + cur.execute(""" + SELECT datastore, rsync_target, pbs_storage_id, fingerprint + FROM Kunden.`bronze.backup.datastore.config` + """) + ds_config = {row["datastore"]: row for row in cur.fetchall()} + cur.close(); conn.close() + + gitea_token = wmill.get_variable("f/Backup/gitea_token") + backup_server_host = wmill.get_variable("f/Backup/backup_server_host") + + target_servers_out = [] + + for server in servers: + hostname = server["hostname"] + creds = server_creds.get(hostname, {}) + + url = creds.get("url", "") + ip_match = re.search(r'https?://([0-9.]+)', url) + ip = ip_match.group(1) if ip_match else server.get("ip", "") + + if not ip: + print(f"WARNUNG: Keine IP fuer '{hostname}' – uebersprungen.") + continue + + ssh_creds_dict = { + "ip": ip, + "user": creds.get("username", "root"), + "password": creds.get("password", ""), + } + + ssh = paramiko.SSHClient() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + ssh.connect(ip, username=ssh_creds_dict["user"], + password=ssh_creds_dict["password"]) + + try: + pbs_storages = deploy_to_server( + ssh, server, pbs, pbs_host, pbs_user, pbs_pass, + pbs_port, ds_config, datastores, gitea_token, + backup_server_host, job_uuid, ssh_creds_dict, db_cfg, + script_version + ) + finally: + ssh.close() + + target_servers_out.append({ + **server, + "ip": ip, + "ssh_creds": ssh_creds_dict, + "pbs_storages": pbs_storages, + }) + + if not target_servers_out: + raise Exception("Kein Server konnte vorbereitet werden!") + + return { + **prev, + "target_servers": target_servers_out, + "script_version": script_version, + } \ No newline at end of file diff --git a/f/Backup/backup_restore_orchestrator__flow/ssh-credentials_fuer_alle_restore-server_aus_bitwarden.lock b/f/Backup/backup_restore_orchestrator__flow/ssh-credentials_fuer_alle_restore-server_aus_bitwarden.lock new file mode 100644 index 0000000..8f80405 --- /dev/null +++ b/f/Backup/backup_restore_orchestrator__flow/ssh-credentials_fuer_alle_restore-server_aus_bitwarden.lock @@ -0,0 +1,9 @@ +# py: 3.12 +anyio==4.12.1 +certifi==2026.2.25 +h11==0.16.0 +httpcore==1.0.9 +httpx==0.28.1 +idna==3.11 +typing-extensions==4.15.0 +wmill==1.657.2 diff --git a/f/Backup/backup_restore_orchestrator__flow/ssh-credentials_fuer_alle_restore-server_aus_bitwarden.py b/f/Backup/backup_restore_orchestrator__flow/ssh-credentials_fuer_alle_restore-server_aus_bitwarden.py new file mode 100644 index 0000000..a50350c --- /dev/null +++ b/f/Backup/backup_restore_orchestrator__flow/ssh-credentials_fuer_alle_restore-server_aus_bitwarden.py @@ -0,0 +1,82 @@ +import subprocess, sys, json, os, wmill + +def bw_lookup(search_term, env, run): + run(["bw", "sync", "--session", env["BW_SESSION"]], check=False) + for attempt in range(3): + result = run( + ["bw", "list", "items", "--search", search_term, + "--session", env["BW_SESSION"]] + ) + items = json.loads(result.stdout) + if items: + break + import time; time.sleep(3) + if not items: + raise Exception(f"Kein Bitwarden-Eintrag fuer: '{search_term}'") + exact = next( + (i for i in items + if i.get("name","").strip().lower() == search_term.strip().lower()), + None, + ) + item = exact if exact else items[0] + url = ((item.get("login",{}).get("uris") or [{}])[0].get("uri","")) \ + if item.get("login") else "" + return { + "username": item.get("login",{}).get("username","") if item.get("login") else "", + "password": item.get("login",{}).get("password","") if item.get("login") else "", + "url": url, + } + +def main( + prev: dict, + bw_url: str = "https://bitwarden.stines.de", +): + if prev.get("mode") == "webhook": + return prev + + servers = prev.get("target_servers", []) + + bw_creds = json.loads(wmill.get_variable("f/Backup/bitwarden_api_login")) + env = os.environ.copy() + env["BW_CLIENTID"] = bw_creds["bw_clientid"] + env["BW_CLIENTSECRET"] = bw_creds["bw_clientsecret"] + env["BW_PASSWORD"] = bw_creds["bw_masterpassword"] + + def run(cmd, check=True): + return subprocess.run(cmd, env=env, text=True, capture_output=True, check=check) + + if subprocess.run(["which", "bw"], capture_output=True).returncode != 0: + run(["wget", + "https://github.com/bitwarden/cli/releases/download/v1.22.1/bw-linux-1.22.1.zip", + "-O", "bw.zip"]) + run(["unzip", "bw.zip"]) + run(["chmod", "+x", "bw"]) + run(["mv", "bw", "/usr/local/bin/bw"]) + + with open("/etc/hosts", "a") as f: + f.write("172.17.1.3 bitwarden.stines.de\n") + + run(["bw", "config", "server", bw_url]) + run(["bw", "logout"], check=False) + + result = run(["bw", "login", "--apikey"], check=False) + if result.returncode != 0: + raise Exception(f"Bitwarden Login fehlgeschlagen: {result.stderr}") + + unlock = run(["bw", "unlock", bw_creds["bw_masterpassword"], "--raw"]) + bw_session = unlock.stdout.strip() + if not bw_session: + raise Exception("Vault konnte nicht entsperrt werden") + env["BW_SESSION"] = bw_session + + server_creds = {} + for server in servers: + hostname = server["hostname"] + print(f"Hole Creds fuer: {hostname}") + creds = bw_lookup(hostname, env, run) + server_creds[hostname] = creds + print(f" -> OK: {creds['username']}@{hostname}") + + run(["bw", "logout"], check=False) + + return {**prev, "server_creds": server_creds} diff --git a/f/Backup/backup_restore_orchestrator__flow/webhook_verarbeiten_&_naechsten_restore_auf_demselben_server_starten.lock b/f/Backup/backup_restore_orchestrator__flow/webhook_verarbeiten_&_naechsten_restore_auf_demselben_server_starten.lock new file mode 100644 index 0000000..442e082 --- /dev/null +++ b/f/Backup/backup_restore_orchestrator__flow/webhook_verarbeiten_&_naechsten_restore_auf_demselben_server_starten.lock @@ -0,0 +1,17 @@ +# py: 3.12 +anyio==4.13.0 +bcrypt==5.0.0 +certifi==2026.2.25 +cffi==2.0.0 +cryptography==46.0.7 +h11==0.16.0 +httpcore==1.0.9 +httpx==0.28.1 +idna==3.11 +invoke==3.0.3 +mysql-connector-python==9.6.0 +paramiko==4.0.0 +pycparser==3.0 +pynacl==1.6.2 +typing-extensions==4.15.0 +wmill==1.680.0 \ No newline at end of file diff --git a/f/Backup/backup_restore_orchestrator__flow/webhook_verarbeiten_&_naechsten_restore_auf_demselben_server_starten.py b/f/Backup/backup_restore_orchestrator__flow/webhook_verarbeiten_&_naechsten_restore_auf_demselben_server_starten.py new file mode 100644 index 0000000..f416e5c --- /dev/null +++ b/f/Backup/backup_restore_orchestrator__flow/webhook_verarbeiten_&_naechsten_restore_auf_demselben_server_starten.py @@ -0,0 +1,404 @@ +import wmill, json, mysql.connector, paramiko, re, base64 + +from datetime import datetime + +import httpx + + + +def send_nextcloud_message(message: str): + """Sendet eine Nachricht an Nextcloud Talk.""" + try: + nc_url = wmill.get_variable("f/Backup/nextcloud_talk_url").rstrip("/") + nc_room = wmill.get_variable("f/Backup/nextcloud_talk_room") + nc_user = wmill.get_variable("f/Backup/nextcloud_talk_user") + nc_password = wmill.get_variable("f/Backup/nextcloud_talk_password") + + credentials = base64.b64encode( + f"{nc_user}:{nc_password}".encode() + ).decode() + + url = f"{nc_url}/ocs/v2.php/apps/spreed/api/v1/chat/{nc_room}" + headers = { + "Authorization": f"Basic {credentials}", + "OCS-APIREQUEST": "true", + "Content-Type": "application/json", + "Accept": "application/json", + } + + response = httpx.post( + url, + headers=headers, + json={"message": message}, + timeout=15, + verify=False, + ) + print(f"Nextcloud Talk: HTTP {response.status_code}") + except Exception as e: + print(f"Nextcloud Talk Fehler (nicht kritisch): {e}") + + +def find_next_backup_for_server(cur, job_uuid, server_hostname, max_backup_size_gb): + if max_backup_size_gb is not None: + max_bytes = max_backup_size_gb * 1024 * 1024 * 1024 + cur.execute(""" + SELECT q.client_name, q.backup_path, q.backup_size_bytes, + q.rsync_target, q.pbs_storage_id, + r.hostname AS server_hostname, + r.ip AS server_ip, + r.restore_mount, + r.restore_path AS restore_path, + r.free_space_gb, + r.max_backup_size_gb, + r.min_backup_size_gb + FROM Kunden.`bronze.backup.queue` q + JOIN Kunden.`bronze.restore.server` r + ON r.hostname = %s + WHERE q.job_uuid = %s AND q.status = 'queued' + AND r.current_job_uuid = %s + AND (q.backup_size_bytes IS NULL OR q.backup_size_bytes <= %s) + AND (r.min_backup_size_gb IS NULL OR q.backup_size_bytes >= r.min_backup_size_gb * 1024 * 1024 * 1024) + ORDER BY q.priority ASC + LIMIT 1 + """, (server_hostname, job_uuid, job_uuid, max_bytes)) + else: + cur.execute(""" + SELECT q.client_name, q.backup_path, q.backup_size_bytes, + q.rsync_target, q.pbs_storage_id, + r.hostname AS server_hostname, + r.ip AS server_ip, + r.restore_mount, + r.restore_path AS restore_path, + r.free_space_gb, + r.max_backup_size_gb, + r.min_backup_size_gb + FROM Kunden.`bronze.backup.queue` q + JOIN Kunden.`bronze.restore.server` r + ON r.hostname = %s + WHERE q.job_uuid = %s AND q.status = 'queued' + AND r.current_job_uuid = %s + AND (r.min_backup_size_gb IS NULL OR q.backup_size_bytes >= r.min_backup_size_gb * 1024 * 1024 * 1024) + ORDER BY q.priority ASC + LIMIT 1 + """, (server_hostname, job_uuid, job_uuid)) + return cur.fetchone() + + +def release_server_and_check_done(cur, conn, job_uuid, server_hostname): + """Server freigeben und prüfen ob alle Jobs fertig sind.""" + cur.execute(""" + UPDATE Kunden.`bronze.restore.server` + SET current_job_uuid=NULL + WHERE hostname=%s + """, (server_hostname,)) + conn.commit() + print(f"Server '{server_hostname}' fertig.") + + cur.execute(""" + SELECT COUNT(*) AS cnt FROM Kunden.`bronze.restore.server` + WHERE current_job_uuid = %s + """, (job_uuid,)) + still_active = cur.fetchone()["cnt"] + + if still_active == 0: + cur.execute(""" + UPDATE Kunden.`bronze.restore.jobs` + SET status='completed', finished_at=NOW() + WHERE job_uuid=%s + """, (job_uuid,)) + cur.execute(""" + DELETE FROM Kunden.`bronze.restore.session` + WHERE job_uuid=%s + """, (job_uuid,)) + # Statistik für Abschluss-Nachricht + cur.execute(""" + SELECT total_backups, restored_count, failed_count, + TIMESTAMPDIFF(MINUTE, started_at, NOW()) AS duration_min + FROM Kunden.`bronze.restore.jobs` + WHERE job_uuid=%s + """, (job_uuid,)) + job_stats = cur.fetchone() + conn.commit() + print(f"Job {job_uuid} vollstaendig abgeschlossen.") + if job_stats: + total = job_stats["total_backups"] or 0 + restored = job_stats["restored_count"] or 0 + failed = job_stats["failed_count"] or 0 + dur_min = job_stats["duration_min"] or 0 + dur_str = f"{dur_min//60}h {dur_min%60}m" if dur_min >= 60 else f"{dur_min}m" + if failed == 0: + msg = ( + f"✅ **Backup-Job abgeschlossen**\n" + f"Alle {total} Backups erfolgreich | Dauer: {dur_str}" + ) + else: + msg = ( + f"⚠️ **Backup-Job abgeschlossen mit Fehlern**\n" + f"✅ {restored}/{total} erfolgreich | ❌ {failed} fehlgeschlagen | Dauer: {dur_str}" + ) + send_nextcloud_message(msg) + return "all_done" + else: + conn.commit() + print(f"Noch {still_active} Server aktiv.") + return "server_done" + + +def main(from_init: dict): + + if from_init.get("mode") == "schedule": + print("Restores gestartet - Flow wartet auf Webhooks.") + return {"status": "waiting_for_webhook", + "job_uuid": from_init.get("job_uuid")} + + data = from_init.get("data", {}) + job_uuid = data.get("job_uuid") + client = data.get("client_name") + status = data.get("status", "unknown") + server_hostname = data.get("server_hostname", "") + + if not job_uuid or not client: + raise Exception(f"Ungueltiger Webhook-Payload: {data}") + + print(f"Webhook: {client} -> {status} (Server: {server_hostname})") + + client_like = f"{client}%" + + db_cfg = json.loads(wmill.get_variable("f/Backup/mysql_config")) + conn = mysql.connector.connect(**db_cfg) + cur = conn.cursor(dictionary=True) + + cur.execute(""" + UPDATE Kunden.`bronze.restore.result` SET + vm_name = %s, + vm_id_original = %s, + vm_id_restored = %s, + restore_duration_sec = %s, + actual_disk_used_bytes = %s, + zip_size_bytes = %s, + zip_duration_sec = %s, + rsync_size_bytes = %s, + rsync_ok = %s, + rsync_retries = %s, + qm_agent_ok = %s, + status = %s, + error_message = %s, + webhook_received_at = %s + WHERE job_uuid = %s AND backup_path LIKE %s + """, ( + data.get("vm_name", ""), + data.get("vm_id_original"), + data.get("vm_id_restored"), + data.get("restore_duration_sec"), + data.get("actual_disk_used_bytes"), + data.get("zip_size_bytes"), + data.get("zip_duration_sec"), + data.get("rsync_size_bytes"), + 1 if data.get("rsync_ok") else 0, + data.get("rsync_retries", 0), + 1 if data.get("qm_agent_ok") in (True, "true", "skipped") else 0, + "done" if status == "success" else "failed", + data.get("error_message", ""), + datetime.now(), + job_uuid, client_like, + )) + + cur.execute(""" + UPDATE Kunden.`bronze.backup.queue` SET status=%s + WHERE job_uuid=%s AND backup_path LIKE %s + """, ("done" if status == "success" else "failed", job_uuid, client_like)) + + field = "restored_count" if status == "success" else "failed_count" + cur.execute( + f"UPDATE Kunden.`bronze.restore.jobs` " + f"SET {field}={field}+1 WHERE job_uuid=%s", + (job_uuid,) + ) + + if data.get("free_space_gb") is not None and server_hostname: + cur.execute(""" + UPDATE Kunden.`bronze.restore.server` + SET free_space_gb = %s WHERE hostname = %s + """, (data.get("free_space_gb"), server_hostname)) + + conn.commit() + + vm_name = data.get("vm_name") or client + dur_sec = data.get("restore_duration_sec") or 0 + dur_str = f"{dur_sec//60}m {dur_sec%60}s" if dur_sec >= 60 else f"{dur_sec}s" + zip_mb = (data.get("zip_size_bytes") or 0) // 1024 // 1024 + icon = "✅" if status == "success" else "❌" + + if status != "success": + err = data.get("error_message", "")[:100] + nc_msg = ( + f"{icon} **{vm_name}** ({client})\n" + f"Server: {server_hostname} | Fehler: {err}" + ) + send_nextcloud_message(nc_msg) + + cur.execute(""" + SELECT max_backup_size_gb, min_backup_size_gb, free_space_gb + FROM Kunden.`bronze.restore.server` + WHERE hostname = %s + """, (server_hostname,)) + srv_cfg = cur.fetchone() + max_backup_size_gb = srv_cfg["max_backup_size_gb"] if srv_cfg else None + min_backup_size_gb = srv_cfg["min_backup_size_gb"] if srv_cfg else None + max_bytes = max_backup_size_gb * 1024 * 1024 * 1024 if max_backup_size_gb is not None else None + min_bytes = min_backup_size_gb * 1024 * 1024 * 1024 if min_backup_size_gb is not None else None + + nxt = find_next_backup_for_server(cur, job_uuid, server_hostname, max_backup_size_gb) + conn.commit() + + if not nxt: + if max_backup_size_gb is not None and min_backup_size_gb is not None: + cur.execute(""" + SELECT client_name, backup_path, backup_size_bytes, + rsync_target, pbs_storage_id + FROM Kunden.`bronze.backup.queue` + WHERE job_uuid = %s AND status = 'queued' + AND (backup_size_bytes IS NULL OR backup_size_bytes <= %s) + AND backup_size_bytes >= %s + ORDER BY priority ASC + LIMIT 1 + """, (job_uuid, max_bytes, min_bytes)) + elif max_backup_size_gb is not None: + cur.execute(""" + SELECT client_name, backup_path, backup_size_bytes, + rsync_target, pbs_storage_id + FROM Kunden.`bronze.backup.queue` + WHERE job_uuid = %s AND status = 'queued' + AND (backup_size_bytes IS NULL OR backup_size_bytes <= %s) + ORDER BY priority ASC + LIMIT 1 + """, (job_uuid, max_bytes)) + elif min_backup_size_gb is not None: + cur.execute(""" + SELECT client_name, backup_path, backup_size_bytes, + rsync_target, pbs_storage_id + FROM Kunden.`bronze.backup.queue` + WHERE job_uuid = %s AND status = 'queued' + AND backup_size_bytes >= %s + ORDER BY priority ASC + LIMIT 1 + """, (job_uuid, min_bytes)) + else: + cur.execute(""" + SELECT client_name, backup_path, backup_size_bytes, + rsync_target, pbs_storage_id + FROM Kunden.`bronze.backup.queue` + WHERE job_uuid = %s AND status = 'queued' + ORDER BY priority ASC + LIMIT 1 + """, (job_uuid,)) + next_queued = cur.fetchone() + + if next_queued: + print(f"Server '{server_hostname}' nimmt naechstes passendes Backup: " + f"{next_queued['client_name']}") + + cur.execute(""" + SELECT hostname, ip, restore_mount, restore_path, + free_space_gb, max_backup_size_gb, min_backup_size_gb + FROM Kunden.`bronze.restore.server` + WHERE hostname = %s + """, (server_hostname,)) + srv = cur.fetchone() + + nxt = { + **next_queued, + "server_hostname": server_hostname, + "server_ip": srv["ip"] if srv else "", + "restore_mount": srv["restore_mount"] if srv else "", + "restore_path": srv["restore_path"] if srv else "", + "free_space_gb": srv["free_space_gb"] if srv else 0, + "max_backup_size_gb": srv["max_backup_size_gb"] if srv else None, + "min_backup_size_gb": srv["min_backup_size_gb"] if srv else None, + } + else: + result = release_server_and_check_done(cur, conn, job_uuid, server_hostname) + cur.close(); conn.close() + if result == "all_done": + return {"status": "all_done", "job_uuid": job_uuid} + else: + return {"status": "server_done", + "server": server_hostname, + "job_uuid": job_uuid} + + cur.close(); conn.close() + + # FIX: started_at hinzugefügt + conn2 = mysql.connector.connect(**db_cfg) + cur2 = conn2.cursor() + cur2.execute(""" + INSERT INTO Kunden.`bronze.restore.result` + (job_uuid, client_name, backup_path, + backup_size_bytes, restore_server, status, started_at) + VALUES (%s, %s, %s, %s, %s, 'restoring', NOW()) + """, ( + job_uuid, nxt["client_name"], nxt["backup_path"], + nxt.get("backup_size_bytes", 0), nxt["server_hostname"], + )) + cur2.execute(""" + UPDATE Kunden.`bronze.backup.queue` SET status='assigned' + WHERE job_uuid=%s AND backup_path LIKE %s + """, (job_uuid, f"{nxt['client_name']}%")) + conn2.commit(); cur2.close(); conn2.close() + + conn3 = mysql.connector.connect(**db_cfg) + cur3 = conn3.cursor(dictionary=True) + cur3.execute(""" + SELECT ip, ssh_user, ssh_password + FROM Kunden.`bronze.restore.session` + WHERE job_uuid = %s AND hostname = %s + LIMIT 1 + """, (job_uuid, server_hostname)) + session = cur3.fetchone() + cur3.close(); conn3.close() + + if not session: + raise Exception( + f"Keine Session-Creds fuer '{server_hostname}'. " + f"Job-UUID: {job_uuid}" + ) + + webhook_url = wmill.get_variable("f/Backup/windmill_webhook_url") + webhook_tok = wmill.get_variable("f/Backup/windmill_webhook_token") + + ssh = paramiko.SSHClient() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + ssh.connect( + session["ip"], + username=session["ssh_user"], + password=session["ssh_password"] + ) + + safe_client = nxt["client_name"].replace("/", "_").replace(":", "_") + nxt_size = nxt.get("backup_size_bytes") or 0 + cmd = ( + f"nohup /opt/windmill-restore/restore.sh" + f" --job-uuid '{job_uuid}'" + f" --backup-path '{nxt['backup_path']}'" + f" --client '{nxt['client_name']}'" + f" --restore-mount '{nxt['restore_mount']}'" + f" --restore-path '{nxt['restore_path']}'" + f" --rsync-target '{nxt['rsync_target']}'" + f" --pbs-storage '{nxt['pbs_storage_id']}'" + f" --webhook-url '{webhook_url}'" + f" --webhook-token '{webhook_tok}'" + f" --server-hostname '{server_hostname}'" + f" --backup-size '{nxt_size}'" + f" > /opt/windmill-restore/logs/{safe_client}.log 2>&1 &" + ) + ssh.exec_command(cmd) + ssh.close() + + size_gb = nxt_size / 1024 / 1024 / 1024 + print(f"Naechster Restore: {nxt['client_name']} ({size_gb:.1f} GB) auf {server_hostname}") + return { + "status": "next_restore_started", + "client": nxt["client_name"], + "server": server_hostname, + "job_uuid": job_uuid, + } \ No newline at end of file diff --git a/f/Backup/backup_restore_report___nextcloud_talk__flow/flow.yaml b/f/Backup/backup_restore_report___nextcloud_talk__flow/flow.yaml new file mode 100644 index 0000000..a3fa79c --- /dev/null +++ b/f/Backup/backup_restore_report___nextcloud_talk__flow/flow.yaml @@ -0,0 +1,31 @@ +summary: Backup Restore Report - Nextcloud Talk +description: | + Läuft täglich um 08:00 Uhr. Holt das Ergebnis des letzten + Backup-Restore-Jobs aus der DB und sendet eine Zusammenfassung + per Nextcloud Talk (Webhook/Bot). +value: + modules: + - id: a + summary: Letzten Job aus DB holen & Report zusammenbauen + value: + type: rawscript + content: '!inline letzten_job_aus_db_holen_&_report_zusammenbauen.py' + input_transforms: {} + lock: '!inline letzten_job_aus_db_holen_&_report_zusammenbauen.lock' + language: python3 + - id: b + summary: Nachricht an Nextcloud Talk senden + value: + type: rawscript + content: '!inline nachricht_an_nextcloud_talk_senden.py' + input_transforms: + report: + type: javascript + expr: results.a + lock: '!inline nachricht_an_nextcloud_talk_senden.lock' + language: python3 +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: [] + properties: {} diff --git a/f/Backup/backup_restore_report___nextcloud_talk__flow/letzten_job_aus_db_holen_&_report_zusammenbauen.lock b/f/Backup/backup_restore_report___nextcloud_talk__flow/letzten_job_aus_db_holen_&_report_zusammenbauen.lock new file mode 100644 index 0000000..f773d7a --- /dev/null +++ b/f/Backup/backup_restore_report___nextcloud_talk__flow/letzten_job_aus_db_holen_&_report_zusammenbauen.lock @@ -0,0 +1,10 @@ +# py: 3.12 +anyio==4.12.1 +certifi==2026.2.25 +h11==0.16.0 +httpcore==1.0.9 +httpx==0.28.1 +idna==3.11 +mysql-connector-python==9.6.0 +typing-extensions==4.15.0 +wmill==1.659.1 \ No newline at end of file diff --git a/f/Backup/backup_restore_report___nextcloud_talk__flow/letzten_job_aus_db_holen_&_report_zusammenbauen.py b/f/Backup/backup_restore_report___nextcloud_talk__flow/letzten_job_aus_db_holen_&_report_zusammenbauen.py new file mode 100644 index 0000000..5a0e8af --- /dev/null +++ b/f/Backup/backup_restore_report___nextcloud_talk__flow/letzten_job_aus_db_holen_&_report_zusammenbauen.py @@ -0,0 +1,129 @@ +import wmill, mysql.connector, json +from datetime import datetime + +def fmt_bytes(b): + if not b: return "—" + b = int(b) + for unit in ["B","KB","MB","GB","TB"]: + if b < 1024: return f"{b:.1f} {unit}" + b /= 1024 + return f"{b:.1f} PB" + +def fmt_dur(sec): + if not sec: return "—" + sec = int(sec) + if sec < 60: return f"{sec}s" + if sec < 3600: return f"{sec//60}m {sec%60}s" + return f"{sec//3600}h {(sec%3600)//60}m" + +def main(): + db_cfg = json.loads(wmill.get_variable("f/Backup/mysql_config")) + conn = mysql.connector.connect(**db_cfg) + cur = conn.cursor(dictionary=True) + + cur.execute(""" + SELECT job_uuid, started_at, finished_at, status, + total_backups, restored_count, failed_count + FROM Kunden.`bronze.restore.jobs` + WHERE status IN ('completed', 'failed') + ORDER BY started_at DESC + LIMIT 1 + """) + job = cur.fetchone() + + if not job: + cur.close(); conn.close() + return {"message": "⚠️ Kein abgeschlossener Backup-Job gefunden."} + + job_uuid = job["job_uuid"] + + duration = "" + if job["started_at"] and job["finished_at"]: + secs = (job["finished_at"] - job["started_at"]).seconds + duration = fmt_dur(secs) + + cur.execute(""" + SELECT client_name, vm_name, restore_server, status, + restore_duration_sec, zip_size_bytes, + rsync_ok, qm_agent_ok, error_message + FROM Kunden.`bronze.restore.result` + WHERE job_uuid = %s + ORDER BY status ASC, client_name ASC + """, (job_uuid,)) + results = cur.fetchall() + + # Nicht gelaufene VMs + cur.execute(""" + SELECT p.client_name, p.vm_name + FROM Kunden.`bronze.restore.plan` p + LEFT JOIN Kunden.`bronze.restore.result` r + ON r.job_uuid = p.job_uuid + AND r.client_name = p.client_name + WHERE p.job_uuid = %s + AND r.id IS NULL + ORDER BY p.client_name ASC + """, (job_uuid,)) + not_run = cur.fetchall() + + cur.close(); conn.close() + + total = job["total_backups"] or 0 + done = job["restored_count"] or 0 + failed = job["failed_count"] or 0 + skipped = len(not_run) + date_str = job["started_at"].strftime("%d.%m.%Y") if job["started_at"] else "?" + time_str = job["started_at"].strftime("%H:%M") if job["started_at"] else "?" + + if failed == 0 and skipped == 0: + status_icon = "✅" + elif done == 0: + status_icon = "❌" + else: + status_icon = "⚠️" + + lines = [ + f"{status_icon} **Backup Restore Report – {date_str}**", + f"", + f"🕐 Start: {time_str} | Dauer: {duration}", + f"📊 Gesamt: {total} | ✅ OK: {done} | ❌ Fehler: {failed} | ⏭️ Nicht gestartet: {skipped}", + f"", + ] + + # Fehlgeschlagene + failed_results = [r for r in results if r["status"] == "failed"] + if failed_results: + lines.append("**❌ Fehlgeschlagen:**") + for r in failed_results: + name = r["vm_name"] or r["client_name"] + err = r["error_message"] or "unbekannt" + if len(err) > 80: + err = err[:80] + "..." + lines.append(f" • {name} ({r['restore_server']}): {err}") + lines.append("") + + # Nicht gestartet + if not_run: + lines.append("**⏭️ Nicht gestartet:**") + for r in not_run: + name = r["vm_name"] or r["client_name"] + lines.append(f" • {name}") + lines.append("") + + # Erfolgreich + done_results = [r for r in results if r["status"] == "done"] + if done_results: + lines.append("**✅ Erfolgreich:**") + for r in done_results: + name = r["vm_name"] or r["client_name"] + dauer = fmt_dur(r["restore_duration_sec"]) + zipsize = fmt_bytes(r["zip_size_bytes"]) + agent = "✓" if r["qm_agent_ok"] else "✗" + rsync = "✓" if r["rsync_ok"] else "✗" + lines.append( + f" • {name} | {r['restore_server']} | " + f"⏱ {dauer} | 📦 {zipsize} | Agent: {agent} | Rsync: {rsync}" + ) + + message = "\n".join(lines) + print(message) + return {"message": message, "job_uuid": job_uuid, "failed": failed, "skipped": skipped} \ No newline at end of file diff --git a/f/Backup/backup_restore_report___nextcloud_talk__flow/nachricht_an_nextcloud_talk_senden.lock b/f/Backup/backup_restore_report___nextcloud_talk__flow/nachricht_an_nextcloud_talk_senden.lock new file mode 100644 index 0000000..8f80405 --- /dev/null +++ b/f/Backup/backup_restore_report___nextcloud_talk__flow/nachricht_an_nextcloud_talk_senden.lock @@ -0,0 +1,9 @@ +# py: 3.12 +anyio==4.12.1 +certifi==2026.2.25 +h11==0.16.0 +httpcore==1.0.9 +httpx==0.28.1 +idna==3.11 +typing-extensions==4.15.0 +wmill==1.657.2 diff --git a/f/Backup/backup_restore_report___nextcloud_talk__flow/nachricht_an_nextcloud_talk_senden.py b/f/Backup/backup_restore_report___nextcloud_talk__flow/nachricht_an_nextcloud_talk_senden.py new file mode 100644 index 0000000..b15d123 --- /dev/null +++ b/f/Backup/backup_restore_report___nextcloud_talk__flow/nachricht_an_nextcloud_talk_senden.py @@ -0,0 +1,44 @@ +import wmill, json +import httpx + +def main(report: dict): + import base64 + message = report.get("message", "Kein Bericht verfuegbar.") + + nc_url = wmill.get_variable("f/Backup/nextcloud_talk_url").rstrip("/") + nc_room = wmill.get_variable("f/Backup/nextcloud_talk_room") + nc_user = wmill.get_variable("f/Backup/nextcloud_talk_user") + nc_password = wmill.get_variable("f/Backup/nextcloud_talk_password") + + credentials = base64.b64encode( + f"{nc_user}:{nc_password}".encode() + ).decode() + + url = f"{nc_url}/ocs/v2.php/apps/spreed/api/v1/chat/{nc_room}" + + headers = { + "Authorization": f"Basic {credentials}", + "OCS-APIREQUEST": "true", + "Content-Type": "application/json", + "Accept": "application/json", + } + + payload = {"message": message} + + response = httpx.post( + url, + headers=headers, + json=payload, + timeout=30, + verify=False, # falls self-signed cert + ) + + print(f"HTTP: {response.status_code}") + print(f"URL: {url}") + if response.status_code not in (200, 201): + raise Exception( + f"Nextcloud Talk Fehler: {response.status_code} – {response.text}" + ) + + print("Nachricht gesendet ✓") + return {"status": "sent", "http": response.status_code} diff --git a/f/Backup/folder.meta.yaml b/f/Backup/folder.meta.yaml new file mode 100644 index 0000000..ec1e3f0 --- /dev/null +++ b/f/Backup/folder.meta.yaml @@ -0,0 +1,6 @@ +summary: '' +display_name: Backup +extra_perms: + sebastianserfling@stines.de: true +owners: + - sebastianserfling@stines.de diff --git a/f/Backup/nextcloud_talk_room.variable.yaml b/f/Backup/nextcloud_talk_room.variable.yaml new file mode 100644 index 0000000..68dc66f --- /dev/null +++ b/f/Backup/nextcloud_talk_room.variable.yaml @@ -0,0 +1,3 @@ +description: '' +value: btrv2jb9 +is_secret: false diff --git a/f/Backup/nextcloud_talk_url.variable.yaml b/f/Backup/nextcloud_talk_url.variable.yaml new file mode 100644 index 0000000..49bf18d --- /dev/null +++ b/f/Backup/nextcloud_talk_url.variable.yaml @@ -0,0 +1,3 @@ +description: '' +value: https://cloudstorage.stines.de +is_secret: false diff --git a/f/Backup/restore_version.variable.yaml b/f/Backup/restore_version.variable.yaml new file mode 100644 index 0000000..92b8a39 --- /dev/null +++ b/f/Backup/restore_version.variable.yaml @@ -0,0 +1,3 @@ +description: '' +value: 1.0.28 +is_secret: false diff --git a/f/Nextcloud/folder.meta.yaml b/f/Nextcloud/folder.meta.yaml new file mode 100644 index 0000000..2029457 --- /dev/null +++ b/f/Nextcloud/folder.meta.yaml @@ -0,0 +1,6 @@ +summary: null +display_name: Nextcloud +extra_perms: + sebastianserfling@stines.de: true +owners: + - sebastianserfling@stines.de diff --git a/f/Proxmox/folder.meta.yaml b/f/Proxmox/folder.meta.yaml new file mode 100644 index 0000000..5582833 --- /dev/null +++ b/f/Proxmox/folder.meta.yaml @@ -0,0 +1,2 @@ +summary: Proxmox +description: '' diff --git a/f/Proxmox/proxmox_backup_webhook__flow/flow.yaml b/f/Proxmox/proxmox_backup_webhook__flow/flow.yaml new file mode 100644 index 0000000..78e8784 --- /dev/null +++ b/f/Proxmox/proxmox_backup_webhook__flow/flow.yaml @@ -0,0 +1,87 @@ +summary: Proxmox Backup Webhook +description: | + Empfängt Backup-Benachrichtigungen von Proxmox via Webhook, + speichert alle VM-Backups in MySQL und sendet eine Zusammenfassung + an Nextcloud Talk. +value: + modules: + - id: a + summary: Payload parsen & aufbereiten + value: + type: rawscript + content: '!inline payload_parsen_&_aufbereiten.py' + input_transforms: + message: + type: javascript + expr: flow_input.message || '' + severity: + type: javascript + expr: flow_input.severity || '' + title: + type: javascript + expr: flow_input.title || '' + debug_mode: + type: javascript + expr: flow_input.debug_mode || false + lock: '!inline payload_parsen_&_aufbereiten.lock' + language: python3 + - id: b + summary: In MySQL speichern + value: + type: rawscript + content: '!inline in_mysql_speichern.py' + input_transforms: + backups: + type: javascript + expr: results.a.backups + batch_id: + type: javascript + expr: results.a.batch_id + raw_payload: + type: javascript + expr: results.a.raw_payload + total_size: + type: javascript + expr: results.a.total_size + total_time: + type: javascript + expr: results.a.total_time + debug_mode: + type: javascript + expr: flow_input.debug_mode || false + lock: '!inline in_mysql_speichern.lock' + language: python3 + - id: c + summary: Nachricht an Nextcloud Talk + value: + type: rawscript + content: '!inline nachricht_an_nextcloud_talk.py' + input_transforms: + talk_message: + type: javascript + expr: results.a.talk_message + debug_mode: + type: javascript + expr: flow_input.debug_mode || false + lock: '!inline nachricht_an_nextcloud_talk.lock' + language: python3 +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + message: + type: string + description: Vollständige Nachricht mit Summary und Logs + default: "Details\n=======\nVMID Name Status Time Size Filename\n127 OLV-CLOUD01-IP17.2 ok 4s 50 GiB vm/127/2026-04-22T19:43:13Z\n131 OLV-WORDP01-IP17.3 ok 3s 50 GiB vm/131/2026-04-22T19:43:17Z\n132 OLV-SMTP01-IP17.1 ok 5s 50 GiB vm/132/2026-04-22T19:43:20Z\n\nTotal running time: 12s\nTotal size: 150 GiB\n\nLogs\n====\nvzdump 127 131 132 --prune-backups 'keep-all=1' --mode snapshot\n\n127: 2026-04-22 21:43:13 INFO: Starting Backup of VM 127 (qemu)\n127: 2026-04-22 21:43:17 INFO: Finished Backup of VM 127 (00:00:04)\n\n131: 2026-04-22 21:43:17 INFO: Starting Backup of VM 131 (qemu)\n131: 2026-04-22 21:43:20 INFO: Finished Backup of VM 131 (00:00:03)\n\n132: 2026-04-22 21:43:20 INFO: Starting Backup of VM 132 (qemu)\n132: 2026-04-22 21:43:25 INFO: Finished Backup of VM 132 (00:00:05)" + severity: + type: string + description: Severity-Level (info, warning, error) + default: "info" + title: + type: string + description: Titel der Proxmox-Notification + default: "vzdump backup status (proxmox.netbird.stines.de): backup successful" + debug_mode: + type: boolean + description: "Debug-Modus: überspringt DB-Insert und Nextcloud-Nachricht" + default: false diff --git a/f/Proxmox/proxmox_backup_webhook__flow/in_mysql_speichern.lock b/f/Proxmox/proxmox_backup_webhook__flow/in_mysql_speichern.lock new file mode 100644 index 0000000..e13b7ab --- /dev/null +++ b/f/Proxmox/proxmox_backup_webhook__flow/in_mysql_speichern.lock @@ -0,0 +1,10 @@ +# py: 3.12 +anyio==4.13.0 +certifi==2026.2.25 +h11==0.16.0 +httpcore==1.0.9 +httpx==0.28.1 +idna==3.11 +mysql-connector-python==9.6.0 +typing-extensions==4.15.0 +wmill==1.688.0 \ No newline at end of file diff --git a/f/Proxmox/proxmox_backup_webhook__flow/in_mysql_speichern.py b/f/Proxmox/proxmox_backup_webhook__flow/in_mysql_speichern.py new file mode 100644 index 0000000..5a3d2e1 --- /dev/null +++ b/f/Proxmox/proxmox_backup_webhook__flow/in_mysql_speichern.py @@ -0,0 +1,51 @@ +import wmill +import json +import mysql.connector + +def main(backups: list, batch_id: str, total_time: str, total_size: str, raw_payload: dict, debug_mode: bool = False): + if not backups: + print("Keine Backups zum Speichern.") + return {"inserted": 0} + + if debug_mode: + print(f"[DEBUG] DB-Insert übersprungen (debug_mode=True)") + print(f"[DEBUG] batch_id={batch_id} | {len(backups)} VMs | total_time={total_time!r} | total_size={total_size!r}") + for b in backups: + print(f"[DEBUG] VM {b['vmid']} ({b['vm_name']}): status={b['status']}, size={b['size']}, duration={b['duration_sec']}s") + return {"inserted": 0, "batch_id": batch_id, "debug": True} + + db_cfg = json.loads(wmill.get_variable("f/Backup/mysql_config")) + conn = mysql.connector.connect(**db_cfg) + cur = conn.cursor() + + inserted = 0 + + for b in backups: + try: + cur.execute(""" + INSERT INTO Kunden.`bronze.proxmox_backup_log` + (batch_id, vmid, vm_name, status, duration_sec, size, filename, log_text, total_time, total_size, raw_payload) + VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) + """, ( + batch_id, + b['vmid'], + b['vm_name'], + b['status'], + b['duration_sec'], + b['size'], + b['filename'], + b['log_text'], + total_time, + total_size, + json.dumps(raw_payload) + )) + inserted += 1 + except Exception as e: + print(f"Fehler beim Insert für VM {b['vmid']}: {e}") + + conn.commit() + cur.close() + conn.close() + + print(f"{inserted} Backup-Einträge in DB gespeichert (batch_id: {batch_id})") + return {"inserted": inserted, "batch_id": batch_id} diff --git a/f/Proxmox/proxmox_backup_webhook__flow/nachricht_an_nextcloud_talk.lock b/f/Proxmox/proxmox_backup_webhook__flow/nachricht_an_nextcloud_talk.lock new file mode 100644 index 0000000..069aced --- /dev/null +++ b/f/Proxmox/proxmox_backup_webhook__flow/nachricht_an_nextcloud_talk.lock @@ -0,0 +1,9 @@ +# py: 3.12 +anyio==4.13.0 +certifi==2026.2.25 +h11==0.16.0 +httpcore==1.0.9 +httpx==0.28.1 +idna==3.11 +typing-extensions==4.15.0 +wmill==1.688.0 \ No newline at end of file diff --git a/f/Proxmox/proxmox_backup_webhook__flow/nachricht_an_nextcloud_talk.py b/f/Proxmox/proxmox_backup_webhook__flow/nachricht_an_nextcloud_talk.py new file mode 100644 index 0000000..eda0716 --- /dev/null +++ b/f/Proxmox/proxmox_backup_webhook__flow/nachricht_an_nextcloud_talk.py @@ -0,0 +1,46 @@ +import wmill +import httpx +import base64 + +def main(talk_message: str, debug_mode: bool = False): + if debug_mode: + print(f"[DEBUG] Nextcloud Talk übersprungen (debug_mode=True)") + print(f"[DEBUG] Nachricht die gesendet worden wäre:\n{talk_message}") + return {"status": "skipped", "debug": True} + + nc_url = wmill.get_variable("f/Backup/nextcloud_talk_url").rstrip("/") + nc_room = wmill.get_variable("f/Backup/nextcloud_talk_room") + nc_user = wmill.get_variable("f/Backup/nextcloud_talk_user") + nc_password = wmill.get_variable("f/Backup/nextcloud_talk_password") + + credentials = base64.b64encode( + f"{nc_user}:{nc_password}".encode() + ).decode() + + url = f"{nc_url}/ocs/v2.php/apps/spreed/api/v1/chat/{nc_room}" + + headers = { + "Authorization": f"Basic {credentials}", + "OCS-APIREQUEST": "true", + "Content-Type": "application/json", + "Accept": "application/json", + } + + payload = {"message": talk_message} + + response = httpx.post( + url, + headers=headers, + json=payload, + timeout=30, + verify=False + ) + + print(f"HTTP: {response.status_code}") + if response.status_code not in (200, 201): + raise Exception( + f"Nextcloud Talk Fehler: {response.status_code} – {response.text}" + ) + + print("Nachricht gesendet ✓") + return {"status": "sent", "http": response.status_code} diff --git a/f/Proxmox/proxmox_backup_webhook__flow/payload_parsen_&_aufbereiten.lock b/f/Proxmox/proxmox_backup_webhook__flow/payload_parsen_&_aufbereiten.lock new file mode 100644 index 0000000..3aacf1d --- /dev/null +++ b/f/Proxmox/proxmox_backup_webhook__flow/payload_parsen_&_aufbereiten.lock @@ -0,0 +1 @@ +# py: 3.12 diff --git a/f/Proxmox/proxmox_backup_webhook__flow/payload_parsen_&_aufbereiten.py b/f/Proxmox/proxmox_backup_webhook__flow/payload_parsen_&_aufbereiten.py new file mode 100644 index 0000000..644a273 --- /dev/null +++ b/f/Proxmox/proxmox_backup_webhook__flow/payload_parsen_&_aufbereiten.py @@ -0,0 +1,174 @@ +import re +import uuid +from datetime import datetime + + +def parse_duration(duration_str): + """Parse '1m 21s', '48s', '4s', '1h 58s' to seconds.""" + if not duration_str: + return None + total = 0 + for match in re.finditer(r'(\d+)\s*(h|m|s)', duration_str): + val, unit = int(match.group(1)), match.group(2) + if unit == 'h': + total += val * 3600 + elif unit == 'm': + total += val * 60 + elif unit == 's': + total += val + return total if total > 0 else None + + +def main(title: str = "", message: str = "", severity: str = "", debug_mode: bool = False): + batch_id = str(uuid.uuid4())[:8] + + if debug_mode: + print(f"[DEBUG] title={title!r} | severity={severity!r}") + print(f"[DEBUG] message ({len(message)} Zeichen):\n{message[:2000]}") + + lines = message.split('\n') + + backups = [] + total_time = None + total_size = None + + in_details = False + in_logs = False + vm_logs = {} + current_vmid = None + + for line in lines: + stripped = line.strip() + + if stripped.startswith('Total running time:'): + total_time = stripped.replace('Total running time:', '').strip() + in_details = False + elif stripped.startswith('Total size:'): + total_size = stripped.replace('Total size:', '').strip() + elif stripped == 'Details': + in_details = True + continue + elif stripped == 'Logs': + in_details = False + in_logs = True + continue + elif re.match(r'^=+$', stripped): + continue + elif in_details: + # Skip header row and empty lines + if not stripped or stripped.upper().startswith('VMID'): + continue + # Split by 2+ spaces → works for both old and new Proxmox format + cols = re.split(r'\s{2,}', stripped) + if len(cols) >= 6 and cols[0].isdigit(): + vmid, name, status, time_str, size_str, filename = cols[:6] + backups.append({ + 'vmid': int(vmid), + 'vm_name': name, + 'status': status.lower(), + 'duration_sec': parse_duration(time_str), + 'size': size_str.strip(), + 'filename': filename.strip(), + 'log_text': '' + }) + elif in_logs: + vm_match = re.match(r'^(\d+):\s+\d{4}-\d{2}-\d{2}', line) + if vm_match: + current_vmid = vm_match.group(1) + if current_vmid not in vm_logs: + vm_logs[current_vmid] = [] + if current_vmid: + vm_logs[current_vmid].append(line) + else: + # Old format without "Details" header: try direct VM row parsing + if stripped and not stripped.upper().startswith('VMID'): + cols = re.split(r'\s{2,}', stripped) + if len(cols) >= 6 and cols[0].isdigit(): + vmid, name, status, time_str, size_str, filename = cols[:6] + backups.append({ + 'vmid': int(vmid), + 'vm_name': name, + 'status': status.lower(), + 'duration_sec': parse_duration(time_str), + 'size': size_str.strip(), + 'filename': filename.strip(), + 'log_text': '' + }) + + for backup in backups: + vmid_str = str(backup['vmid']) + if vmid_str in vm_logs: + backup['log_text'] = '\n'.join(vm_logs[vmid_str]) + + if debug_mode: + print(f"[DEBUG] {len(backups)} VMs geparst: {[b['vm_name'] for b in backups]}") + print(f"[DEBUG] total_time={total_time!r} | total_size={total_size!r}") + + if not backups: + return { + 'backups': [], + 'batch_id': batch_id, + 'total_time': total_time, + 'total_size': total_size, + 'talk_message': f"⚠️ Proxmox Webhook empfangen, aber keine VMs gefunden.\n\n```\n{message[:500]}\n```", + 'raw_payload': {'title': title, 'message': message, 'severity': severity} + } + + failed = [b for b in backups if b['status'] != 'ok'] + ok = [b for b in backups if b['status'] == 'ok'] + + if len(failed) == 0: + status_icon = "✅" + elif len(ok) == 0: + status_icon = "❌" + else: + status_icon = "⚠️" + + # --- Talk-Nachricht aufbauen --- + talk_lines = [] + + # Titel-Zeile mit Hostname und Status aus Proxmox + display_title = title if title else f"Proxmox Backup – {datetime.now().strftime('%d.%m.%Y')}" + talk_lines.append(f"{status_icon} **{display_title}**") + talk_lines.append("") + + # Details-Tabelle als Code-Block für korrekte Ausrichtung + talk_lines.append("```") + talk_lines.append(f"{'VMID':<6} {'Name':<22} {'Status':<8} {'Time':<6} {'Size':<10} Filename") + for b in backups: + dur = f"{b['duration_sec']}s" if b['duration_sec'] else "?" + talk_lines.append( + f"{b['vmid']:<6} {b['vm_name']:<22} {b['status']:<8} {dur:<6} {b['size']:<10} {b['filename']}" + ) + talk_lines.append("```") + talk_lines.append("") + + # Zusammenfassung + parts = [] + if total_time: + parts.append(f"⏱ {total_time}") + if total_size: + parts.append(f"📦 {total_size}") + if parts: + talk_lines.append(" | ".join(parts)) + + # Fehler hervorheben + if failed: + talk_lines.append("") + talk_lines.append("**❌ Fehler bei:**") + for b in failed: + talk_lines.append(f" • {b['vm_name']} ({b['vmid']})") + + talk_message = '\n'.join(talk_lines) + + if debug_mode: + print(f"[DEBUG] Generierte Talk-Nachricht:\n{talk_message}") + + return { + 'backups': backups, + 'batch_id': batch_id, + 'total_time': total_time, + 'total_size': total_size, + 'talk_message': talk_message, + 'raw_payload': {'title': title, 'message': message, 'severity': severity} + } diff --git a/f/Reporting/folder.meta.yaml b/f/Reporting/folder.meta.yaml new file mode 100644 index 0000000..c01de72 --- /dev/null +++ b/f/Reporting/folder.meta.yaml @@ -0,0 +1,6 @@ +summary: null +display_name: Reporting +extra_perms: + sebastianserfling@stines.de: true +owners: + - sebastianserfling@stines.de diff --git a/f/Reporting/rdp_logins__flow/einzelnen_login-eintrag_einfügen.lock b/f/Reporting/rdp_logins__flow/einzelnen_login-eintrag_einfügen.lock new file mode 100644 index 0000000..e75571f --- /dev/null +++ b/f/Reporting/rdp_logins__flow/einzelnen_login-eintrag_einfügen.lock @@ -0,0 +1,44 @@ +{ + "dependencies": { + "mysql2": "latest" + } +} +//bun.lock +{ + "lockfileVersion": 1, + "configVersion": 1, + "workspaces": { + "": { + "dependencies": { + "mysql2": "latest", + }, + }, + }, + "packages": { + "@types/node": ["@types/node@25.5.2", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-tO4ZIRKNC+MDWV4qKVZe3Ql/woTnmHDr5JD8UI5hn2pwBrHEwOEMZK7WlNb5RKB6EoJ02gwmQS9OrjuFnZYdpg=="], + + "aws-ssl-profiles": ["aws-ssl-profiles@1.1.2", "", {}, "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g=="], + + "denque": ["denque@2.1.0", "", {}, "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw=="], + + "generate-function": ["generate-function@2.3.1", "", { "dependencies": { "is-property": "^1.0.2" } }, "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ=="], + + "iconv-lite": ["iconv-lite@0.7.2", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw=="], + + "is-property": ["is-property@1.0.2", "", {}, "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g=="], + + "long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="], + + "lru.min": ["lru.min@1.1.4", "", {}, "sha512-DqC6n3QQ77zdFpCMASA1a3Jlb64Hv2N2DciFGkO/4L9+q/IpIAuRlKOvCXabtRW6cQf8usbmM6BE/TOPysCdIA=="], + + "mysql2": ["mysql2@3.21.0", "", { "dependencies": { "aws-ssl-profiles": "^1.1.2", "denque": "^2.1.0", "generate-function": "^2.3.1", "iconv-lite": "^0.7.2", "long": "^5.3.2", "lru.min": "^1.1.4", "named-placeholders": "^1.1.6", "sql-escaper": "^1.3.3" }, "peerDependencies": { "@types/node": ">= 8" } }, "sha512-CYNKIuhnalXHTa4gonZ+KhzLESKllvo1qQIDYUVuatpN4NgMk+lsA3WwHYno5AS4PACUiD2qEmiVD9pr3bXWOw=="], + + "named-placeholders": ["named-placeholders@1.1.6", "", { "dependencies": { "lru.min": "^1.1.0" } }, "sha512-Tz09sEL2EEuv5fFowm419c1+a/jSMiBjI9gHxVLrVdbUkkNUUfjsVYs9pVZu5oCon/kmRh9TfLEObFtkVxmY0w=="], + + "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], + + "sql-escaper": ["sql-escaper@1.3.3", "", {}, "sha512-BsTCV265VpTp8tm1wyIm1xqQCS+Q9NHx2Sr+WcnUrgLrQ6yiDIvHYJV5gHxsj1lMBy2zm5twLaZao8Jd+S8JJw=="], + + "undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="], + } +} diff --git a/f/Reporting/rdp_logins__flow/einzelnen_login-eintrag_einfügen.ts b/f/Reporting/rdp_logins__flow/einzelnen_login-eintrag_einfügen.ts new file mode 100644 index 0000000..8232ba1 --- /dev/null +++ b/f/Reporting/rdp_logins__flow/einzelnen_login-eintrag_einfügen.ts @@ -0,0 +1,39 @@ +type Mysql = { + host: string; + port: number; + user: string; + password: string; + database: string; +}; + +type LoginRecord = { + username: string; + lastaccess: string; + ipaddress: string; + groups: string; +}; + +export async function main( + database: Mysql, + record: LoginRecord +): Promise<{ inserted: boolean }> { + const mysql2 = await import("mysql2/promise"); + + const conn = await mysql2.createConnection({ + host: database.host, + port: database.port, + user: database.user, + password: database.password, + database: database.database, + }); + + try { + await conn.execute( + "INSERT INTO `bronze.services.reporting` (username, lastaccess, ipaddress, add_date, memberof) VALUES (?, ?, ?, NOW(), ?)", + [record.username, record.lastaccess, record.ipaddress, record.groups] + ); + return { inserted: true }; + } finally { + await conn.end(); + } +} diff --git a/f/Reporting/rdp_logins__flow/flow.yaml b/f/Reporting/rdp_logins__flow/flow.yaml new file mode 100644 index 0000000..89429db --- /dev/null +++ b/f/Reporting/rdp_logins__flow/flow.yaml @@ -0,0 +1,97 @@ +summary: RDP Logins Collector +description: > + Lädt alle aktiven RDS-Server aus bronze.server, gleicht sie mit den + verbundenen rport.io Clients ab (per Hostname oder IP), führt auf jedem den + PS-Login-Collector aus und schreibt die Ergebnisse in + bronze.services.reporting. +value: + modules: + - id: find_rds_clients + summary: RDS-Server mit rport.io Clients abgleichen + value: + type: rawscript + content: '!inline rds-server_mit_rport.io_clients_abgleichen.ts' + input_transforms: + database: + type: static + value: $res:u/sebastianserfling/fascinating_mysql + rportio_api_token: + type: static + value: $var:f/Reporting/rportio_api_token + rportio_base_url: + type: static + value: $var:f/Reporting/rportio_base_url + rportio_username: + type: static + value: $var:f/Reporting/rportio_username + lock: '!inline rds-server_mit_rport.io_clients_abgleichen.lock' + language: bun + - id: process_servers + summary: Pro Server Logins sammeln und speichern + value: + type: forloopflow + modules: + - id: execute_ps + summary: PowerShell via rport.io ausführen + value: + type: rawscript + content: '!inline powershell_via_rport.io_ausführen.ts' + input_transforms: + client_id: + type: javascript + expr: flow_input.iter.value.rport_client_id + hours_back: + type: javascript + expr: flow_input.hours_back ?? 1 + rportio_api_token: + type: static + value: $var:f/Reporting/rportio_api_token + rportio_base_url: + type: static + value: $var:f/Reporting/rportio_base_url + rportio_username: + type: static + value: $var:f/Reporting/rportio_username + server_ip: + type: javascript + expr: flow_input.iter.value.ipaddress + lock: '!inline powershell_via_rport.io_ausführen.lock' + language: bun + - id: insert_logins + summary: Login-Einträge in MySQL speichern + value: + type: forloopflow + modules: + - id: insert_login + summary: Einzelnen Login-Eintrag einfügen + value: + type: rawscript + content: '!inline einzelnen_login-eintrag_einfügen.ts' + input_transforms: + database: + type: static + value: $res:u/sebastianserfling/fascinating_mysql + record: + type: javascript + expr: flow_input.iter.value + lock: '!inline einzelnen_login-eintrag_einfügen.lock' + language: bun + iterator: + type: javascript + expr: results.execute_ps + parallel: false + skip_failures: false + iterator: + type: javascript + expr: results.find_rds_clients + parallel: false + skip_failures: true +schema: + $schema: https://json-schema.org/draft/2019-09/schema + type: object + properties: + hours_back: + type: integer + description: 'Wie viele Stunden zurückschauen (Standard: 1)' + default: 1 + required: [] diff --git a/f/Reporting/rdp_logins__flow/powershell_via_rport.io_ausführen.lock b/f/Reporting/rdp_logins__flow/powershell_via_rport.io_ausführen.lock new file mode 100644 index 0000000..c24eb1c --- /dev/null +++ b/f/Reporting/rdp_logins__flow/powershell_via_rport.io_ausführen.lock @@ -0,0 +1,5 @@ +{ + "dependencies": {} +} +//bun.lock + \ No newline at end of file diff --git a/f/Reporting/rdp_logins__flow/powershell_via_rport.io_ausführen.ts b/f/Reporting/rdp_logins__flow/powershell_via_rport.io_ausführen.ts new file mode 100644 index 0000000..b04438b --- /dev/null +++ b/f/Reporting/rdp_logins__flow/powershell_via_rport.io_ausführen.ts @@ -0,0 +1,133 @@ +type LoginRecord = { + username: string; + lastaccess: string; + ipaddress: string; + groups: string; +}; + +export async function main( + rportio_base_url: string, + rportio_username: string, + rportio_api_token: string, + client_id: string, + server_ip: string, + hours_back: number = 1 +): Promise { + const psScript = ` +$ErrorActionPreference = 'SilentlyContinue' +$startTime = (Get-Date).AddHours(-${hours_back}) +$endTime = Get-Date +$filterHashTable = @{ + LogName = 'Security' + Id = 4624 + StartTime = $startTime + EndTime = $endTime +} +$events = Get-WinEvent -FilterHashtable $filterHashTable -ErrorAction SilentlyContinue +$userLogins = @{} +if ($events) { + foreach ($event in $events) { + $eventDetails = [xml]$event.ToXml() + $timeCreated = $event.TimeCreated + $username = $eventDetails.Event.EventData.Data | Where-Object { $_.Name -eq 'TargetUserName' } | Select-Object -ExpandProperty '#text' + $logonType = $eventDetails.Event.EventData.Data | Where-Object { $_.Name -eq 'LogonType' } | Select-Object -ExpandProperty '#text' + if ($logonType -ne '10' -or $username -like 'DWM*' -or $username -like '*UMFD*') { continue } + $ipaddress = '${server_ip}' + $formattedTime = $timeCreated.ToString('yyyy-MM-dd HH:mm:ss') + if (-not $userLogins.ContainsKey($username) -or $userLogins[$username]._raw -lt $timeCreated) { + $userLogins[$username] = [PSCustomObject]@{ + lastaccess = $formattedTime + username = $username + ipaddress = $ipaddress + _raw = $timeCreated + } + } + } +} +$result = [System.Collections.Generic.List[object]]::new() +foreach ($entry in $userLogins.GetEnumerator()) { + $u = $entry.Value + $adGroups = $null + try { + $adGroups = @(Get-ADPrincipalGroupMembership -Identity $u.username -ErrorAction Stop | Select-Object -ExpandProperty Name) + } catch {} + if (-not $adGroups -or $adGroups.Count -eq 0) { $adGroups = @('G-RDP-User') } + foreach ($group in $adGroups) { + $result.Add([PSCustomObject]@{ + username = $u.username + lastaccess = $u.lastaccess + ipaddress = $u.ipaddress + groups = $group + }) + } +} +if ($result.Count -eq 0) { Write-Output '[]' } else { $result | ConvertTo-Json -Depth 3 -Compress } +`.trim(); + + // rport.io powershell interpreter executes the script directly as PS code + const command = psScript; + + // API token is used as Basic Auth password (bypasses 2FA) + const auth = Buffer.from(`${rportio_username}:${rportio_api_token}`).toString("base64"); + const headers: Record = { + Authorization: `Basic ${auth}`, + "Content-Type": "application/json", + }; + + const tlsOpts = { tls: { rejectUnauthorized: false } }; + + // Submit command to rport.io + // @ts-ignore - Bun-specific TLS option for self-signed certificates + const execResp = await fetch( + `${rportio_base_url}/api/v1/clients/${client_id}/commands`, + { + method: "POST", + headers, + body: JSON.stringify({ command, interpreter: "powershell", timeout_sec: 120 }), + ...tlsOpts, + } + ); + if (!execResp.ok) { + const text = await execResp.text(); + throw new Error(`rport.io execute failed [${execResp.status}]: ${text}`); + } + const execData = await execResp.json(); + const jid: string = execData?.data?.jid; + if (!jid) throw new Error(`No job ID from rport.io: ${JSON.stringify(execData)}`); + + // Poll until finished (max 120s) + let cmdResult: Record | null = null; + for (let i = 0; i < 60; i++) { + await new Promise((r) => setTimeout(r, 2000)); + // @ts-ignore - Bun-specific TLS option + const statusResp = await fetch( + `${rportio_base_url}/api/v1/clients/${client_id}/commands/${jid}`, + { headers, ...tlsOpts } + ); + if (!statusResp.ok) continue; + const statusData = await statusResp.json(); + const cmd = statusData?.data as Record; + if (cmd?.finished_at) { + cmdResult = cmd; + break; + } + } + if (!cmdResult) throw new Error("Timeout waiting for rport.io command result"); + + const status = cmdResult.status as string; + if (status === "failed" || status === "unknown") { + const result = cmdResult.result as Record ?? {}; + throw new Error(`PowerShell failed [${status}]: ${cmdResult.error ?? result.stderr ?? ""}`); + } + + const result = cmdResult.result as Record ?? {}; + const stdout = (result.stdout ?? "").trim(); + if (!stdout || stdout === "[]") return []; + + try { + const parsed = JSON.parse(stdout); + return Array.isArray(parsed) ? parsed : [parsed]; + } catch { + throw new Error(`Failed to parse PowerShell JSON output: ${stdout}`); + } +} diff --git a/f/Reporting/rdp_logins__flow/rds-server_mit_rport.io_clients_abgleichen.lock b/f/Reporting/rdp_logins__flow/rds-server_mit_rport.io_clients_abgleichen.lock new file mode 100644 index 0000000..e75571f --- /dev/null +++ b/f/Reporting/rdp_logins__flow/rds-server_mit_rport.io_clients_abgleichen.lock @@ -0,0 +1,44 @@ +{ + "dependencies": { + "mysql2": "latest" + } +} +//bun.lock +{ + "lockfileVersion": 1, + "configVersion": 1, + "workspaces": { + "": { + "dependencies": { + "mysql2": "latest", + }, + }, + }, + "packages": { + "@types/node": ["@types/node@25.5.2", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-tO4ZIRKNC+MDWV4qKVZe3Ql/woTnmHDr5JD8UI5hn2pwBrHEwOEMZK7WlNb5RKB6EoJ02gwmQS9OrjuFnZYdpg=="], + + "aws-ssl-profiles": ["aws-ssl-profiles@1.1.2", "", {}, "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g=="], + + "denque": ["denque@2.1.0", "", {}, "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw=="], + + "generate-function": ["generate-function@2.3.1", "", { "dependencies": { "is-property": "^1.0.2" } }, "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ=="], + + "iconv-lite": ["iconv-lite@0.7.2", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw=="], + + "is-property": ["is-property@1.0.2", "", {}, "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g=="], + + "long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="], + + "lru.min": ["lru.min@1.1.4", "", {}, "sha512-DqC6n3QQ77zdFpCMASA1a3Jlb64Hv2N2DciFGkO/4L9+q/IpIAuRlKOvCXabtRW6cQf8usbmM6BE/TOPysCdIA=="], + + "mysql2": ["mysql2@3.21.0", "", { "dependencies": { "aws-ssl-profiles": "^1.1.2", "denque": "^2.1.0", "generate-function": "^2.3.1", "iconv-lite": "^0.7.2", "long": "^5.3.2", "lru.min": "^1.1.4", "named-placeholders": "^1.1.6", "sql-escaper": "^1.3.3" }, "peerDependencies": { "@types/node": ">= 8" } }, "sha512-CYNKIuhnalXHTa4gonZ+KhzLESKllvo1qQIDYUVuatpN4NgMk+lsA3WwHYno5AS4PACUiD2qEmiVD9pr3bXWOw=="], + + "named-placeholders": ["named-placeholders@1.1.6", "", { "dependencies": { "lru.min": "^1.1.0" } }, "sha512-Tz09sEL2EEuv5fFowm419c1+a/jSMiBjI9gHxVLrVdbUkkNUUfjsVYs9pVZu5oCon/kmRh9TfLEObFtkVxmY0w=="], + + "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], + + "sql-escaper": ["sql-escaper@1.3.3", "", {}, "sha512-BsTCV265VpTp8tm1wyIm1xqQCS+Q9NHx2Sr+WcnUrgLrQ6yiDIvHYJV5gHxsj1lMBy2zm5twLaZao8Jd+S8JJw=="], + + "undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="], + } +} diff --git a/f/Reporting/rdp_logins__flow/rds-server_mit_rport.io_clients_abgleichen.ts b/f/Reporting/rdp_logins__flow/rds-server_mit_rport.io_clients_abgleichen.ts new file mode 100644 index 0000000..3a6eb2f --- /dev/null +++ b/f/Reporting/rdp_logins__flow/rds-server_mit_rport.io_clients_abgleichen.ts @@ -0,0 +1,88 @@ +type Mysql = { + host: string; + port: number; + user: string; + password: string; + database: string; +}; + +type RportClient = { + rport_client_id: string; + hostname: string; + ipaddress: string; +}; + +export async function main( + database: Mysql, + rportio_base_url: string, + rportio_username: string, + rportio_api_token: string +): Promise { + const mysql2 = await import("mysql2/promise"); + + // 1. Query MySQL for all active RDS servers + const conn = await mysql2.createConnection({ + host: database.host, + port: database.port, + user: database.user, + password: database.password, + database: database.database, + }); + + const [rows] = await conn.execute( + "SELECT hostname, privat_ipaddress FROM `bronze.server` WHERE services LIKE '%RDS%' AND (disable_date IS NULL OR disable_date > NOW())" + ); + await conn.end(); + + const dbServers = rows as Array<{ hostname: string; privat_ipaddress: string }>; + if (dbServers.length === 0) return []; + + // Build lookup maps for fast matching (hostname → DB row) + const byHostname = new Map(dbServers.map((s) => [s.hostname.toLowerCase(), s])); + const byIp = new Map(dbServers.map((s) => [s.privat_ipaddress, s])); + + // 2. Query rport.io for all connected clients + const auth = Buffer.from(`${rportio_username}:${rportio_api_token}`).toString("base64"); + const headers = { + Authorization: `Basic ${auth}`, + "Content-Type": "application/json", + }; + + // @ts-ignore - Bun-specific TLS option to allow self-signed certificates + const resp = await fetch( + `${rportio_base_url}/api/v1/clients?filter[connection_state]=connected&fields[clients]=id,name,hostname,ipv4&page[limit]=500`, + { headers, tls: { rejectUnauthorized: false } } + ); + + if (!resp.ok) { + const err = await resp.text(); + throw new Error(`rport.io clients list failed [${resp.status}]: ${err}`); + } + + const data = await resp.json(); + const clients = data?.data ?? []; + + // 3. Match rport.io clients against DB server list (hostname or IP) + const matched: RportClient[] = []; + for (const client of clients) { + const rportHostname = (client.hostname ?? "").toLowerCase(); + const rportIps: string[] = client.ipv4 ?? []; + + const dbRow = byHostname.get(rportHostname) + ?? rportIps.map((ip) => byIp.get(ip)).find(Boolean); + + if (dbRow) { + matched.push({ + rport_client_id: client.id, + hostname: client.hostname ?? client.name, + ipaddress: dbRow.privat_ipaddress, // use IP from DB, not from PS script + }); + } + } + + console.log( + `Found ${dbServers.length} RDS servers in DB, ${clients.length} connected rport.io clients, ${matched.length} matched` + ); + + return matched; +} diff --git a/f/Server/Bitwarden_Data_Export__flow/c.lock b/f/Server/Bitwarden_Data_Export__flow/c.lock new file mode 100644 index 0000000..e7729a1 --- /dev/null +++ b/f/Server/Bitwarden_Data_Export__flow/c.lock @@ -0,0 +1,9 @@ +# py: 3.12 +anyio==4.12.1 +certifi==2026.2.25 +h11==0.16.0 +httpcore==1.0.9 +httpx==0.28.1 +idna==3.11 +typing-extensions==4.15.0 +wmill==1.657.2 \ No newline at end of file diff --git a/f/Server/Bitwarden_Data_Export__flow/c.py b/f/Server/Bitwarden_Data_Export__flow/c.py new file mode 100644 index 0000000..b55396b --- /dev/null +++ b/f/Server/Bitwarden_Data_Export__flow/c.py @@ -0,0 +1,127 @@ +import subprocess +import sys +import json +import os +import wmill + + +def main( + client_name: str, + bw_url: str = "https://bitwarden.stines.de", +): + # ── Credentials aus Windmill-Secret holen ───────────────────────────────── + bw_creds = json.loads(wmill.get_variable("f/Backup/bitwarden_api_login")) + bw_clientid = bw_creds["bw_clientid"] + bw_clientsecret = bw_creds["bw_clientsecret"] + bw_password = bw_creds["bw_masterpassword"] + + search_term = f"{client_name}" + + env = os.environ.copy() + env["BW_CLIENTID"] = bw_clientid + env["BW_CLIENTSECRET"] = bw_clientsecret + env["BW_PASSWORD"] = bw_password + + def run(cmd, check=True, capture=True): + return subprocess.run( + cmd, env=env, text=True, capture_output=capture, check=check + ) + + # ── 1. Bitwarden CLI prüfen ─────────────────────────────────────────────── + print("==> Prüfe Bitwarden CLI...", file=sys.stderr) + if subprocess.run(["which", "bw"], capture_output=True).returncode != 0: + print(" Installiere bw CLI...", file=sys.stderr) + run( + [ + "wget", + "https://github.com/bitwarden/cli/releases/download/v1.22.1/bw-linux-1.22.1.zip", + "-O", + "bw.zip", + ] + ) + run(["unzip", "bw.zip"]) + run(["chmod", "+x", "bw"]) + run(["mv", "bw", "/usr/local/bin/bw"]) + + bw_version = run(["bw", "--version"]).stdout.strip() + print(f" Bitwarden CLI Version: {bw_version}", file=sys.stderr) + + # ── Hostfile setzen ─────────────────────────────────────────────────────── + with open("/etc/hosts", "a") as f: + f.write("172.17.1.3 bitwarden.stines.de\n") + + # ── 2. Server-URL konfigurieren ─────────────────────────────────────────── + print(f"==> Setze Server-URL: {bw_url}", file=sys.stderr) + run(["bw", "config", "server", bw_url]) + + # ── 3. Login ────────────────────────────────────────────────────────────── + print("==> Melde bei Bitwarden an...", file=sys.stderr) + run(["bw", "logout"], check=False) + + result = run(["bw", "login", "--apikey"], check=False) + if result.returncode != 0: + print(f"ERROR: API-Key-Login fehlgeschlagen.\n{result.stderr}", file=sys.stderr) + sys.exit(1) + print(" Login erfolgreich.", file=sys.stderr) + + # ── 4. Vault entsperren ─────────────────────────────────────────────────── + print("==> Entsperre Vault...", file=sys.stderr) + unlock = run(["bw", "unlock", bw_password, "--raw"]) + bw_session = unlock.stdout.strip() + if not bw_session: + print("ERROR: Vault konnte nicht entsperrt werden.", file=sys.stderr) + run(["bw", "logout"], check=False) + sys.exit(1) + env["BW_SESSION"] = bw_session + print(" Vault entsperrt.", file=sys.stderr) + + # ── 5. Vault synchronisieren ────────────────────────────────────────────── + print("==> Synchronisiere Vault...", file=sys.stderr) + run(["bw", "sync", "--session", bw_session]) + print(" Sync abgeschlossen.", file=sys.stderr) + + # ── 6. Eintrag suchen ───────────────────────────────────────────────────── + print(f"==> Suche Eintrag: '{search_term}'...", file=sys.stderr) + search = run( + ["bw", "list", "items", "--search", search_term, "--session", bw_session] + ) + items = json.loads(search.stdout) + + if not items: + print(f"ERROR: Kein Eintrag gefunden für: '{search_term}'", file=sys.stderr) + run(["bw", "logout"], check=False) + sys.exit(1) + + print(f" {len(items)} Treffer gefunden.", file=sys.stderr) + + # Exakten Treffer bevorzugen, sonst ersten nehmen + exact = next( + ( + i + for i in items + if i.get("name", "").strip().lower() == search_term.strip().lower() + ), + None, + ) + item = exact if exact else items[0] + + # ── 7. Abmelden ─────────────────────────────────────────────────────────── + run(["bw", "logout"], check=False) + print("==> Abgemeldet.", file=sys.stderr) + + # ── 8. Rückgabe als Objekt ──────────────────────────────────────────────── + return { + "id": item.get("id", ""), + "name": item.get("name", ""), + "client": item.get("name", "").split("// ")[-1], + "username": item.get("login", {}).get("username", "") + if item.get("login") + else "", + "password": item.get("login", {}).get("password", "") + if item.get("login") + else "", + "notes": item.get("notes", "") or "", + "url": ((item.get("login", {}).get("uris") or [{}])[0].get("uri", "")) + if item.get("login") + else "", + } diff --git a/f/Server/Bitwarden_Data_Export__flow/flow.yaml b/f/Server/Bitwarden_Data_Export__flow/flow.yaml new file mode 100644 index 0000000..808a26f --- /dev/null +++ b/f/Server/Bitwarden_Data_Export__flow/flow.yaml @@ -0,0 +1,29 @@ +summary: Bitwarden Backup-Info Export +description: Sucht nach dem passenden Eintrag in der Datenbank vom Bitwarden mit + Password und Notes (Entcrypt-KEy) +value: + modules: + - id: c + value: + type: rawscript + content: '!inline c.py' + input_transforms: + bw_url: + type: static + value: https://bitwarden.stines.de + client_name: + type: javascript + expr: flow_input.search + lock: '!inline c.lock' + language: python3 +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - search + properties: + search: + type: string + description: '' + default: '' + required: [] diff --git a/f/Server/folder.meta.yaml b/f/Server/folder.meta.yaml new file mode 100644 index 0000000..449d424 --- /dev/null +++ b/f/Server/folder.meta.yaml @@ -0,0 +1,6 @@ +summary: '' +display_name: Server +extra_perms: + sebastianserfling@stines.de: true +owners: + - sebastianserfling@stines.de diff --git a/f/app_custom/folder.meta.yaml b/f/app_custom/folder.meta.yaml new file mode 100644 index 0000000..573f64a --- /dev/null +++ b/f/app_custom/folder.meta.yaml @@ -0,0 +1,5 @@ +summary: null +display_name: App Custom Components +extra_perms: + g/all: false +owners: [] diff --git a/f/app_groups/folder.meta.yaml b/f/app_groups/folder.meta.yaml new file mode 100644 index 0000000..d224ebe --- /dev/null +++ b/f/app_groups/folder.meta.yaml @@ -0,0 +1,5 @@ +summary: null +display_name: App Groups +extra_perms: + g/all: false +owners: [] diff --git a/f/app_themes/folder.meta.yaml b/f/app_themes/folder.meta.yaml new file mode 100644 index 0000000..7c672ae --- /dev/null +++ b/f/app_themes/folder.meta.yaml @@ -0,0 +1,5 @@ +summary: null +display_name: App Themes +extra_perms: + g/all: false +owners: [] diff --git a/f/app_themes/theme_0.resource.yaml b/f/app_themes/theme_0.resource.yaml new file mode 100644 index 0000000..c9f2984 --- /dev/null +++ b/f/app_themes/theme_0.resource.yaml @@ -0,0 +1,5 @@ +description: The default app theme +value: + name: Default Theme + value: '' +resource_type: app_theme diff --git a/f/random_stuff/folder.meta.yaml b/f/random_stuff/folder.meta.yaml new file mode 100644 index 0000000..965a6e8 --- /dev/null +++ b/f/random_stuff/folder.meta.yaml @@ -0,0 +1,8 @@ +summary: '' +display_name: random_stuff +extra_perms: + g/all: true + sebastianserfling@stines.de: true +owners: + - sebastianserfling@stines.de + - g/all diff --git a/faunadb.resource-type.yaml b/faunadb.resource-type.yaml new file mode 100644 index 0000000..1d96ed6 --- /dev/null +++ b/faunadb.resource-type.yaml @@ -0,0 +1,22 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + region: + type: string + description: >- + Region of your database. Current possible values: us, eu, classic. + + Learn more at + https://docs.fauna.com/fauna/current/learn/understanding/region_groups + default: '' + secret: + type: string + description: '' + default: '' + required: + - region + - secret diff --git a/figma.resource-type.yaml b/figma.resource-type.yaml new file mode 100644 index 0000000..e0271b1 --- /dev/null +++ b/figma.resource-type.yaml @@ -0,0 +1,13 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: Follow the OAuth flow described at + https://www.figma.com/developers/api#authentication + required: + - token diff --git a/firebase.resource-type.yaml b/firebase.resource-type.yaml new file mode 100644 index 0000000..e4e064b --- /dev/null +++ b/firebase.resource-type.yaml @@ -0,0 +1,44 @@ +description: After you have a Firebase project, register a web app with that + project. In the Firebase console's project overview page, click the "Add app" + button, then the "Web" icon (****) to start the setup. +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: '' + default: '' + appId: + type: string + description: '' + default: '' + authDomain: + type: string + description: 'eg.: [PROJECT_ID].firebaseapp.com' + default: '' + measurementId: + type: string + description: '(optional) Used for Firebase Analytics ' + default: '' + messagingSenderId: + type: string + description: '' + default: '' + projectId: + type: string + description: '' + default: '' + storageBucket: + type: string + description: 'eg.: [PROJECT_ID].appspot.com' + default: '' + required: + - apiKey + - authDomain + - projectId + - storageBucket + - messagingSenderId + - appId diff --git a/fly.resource-type.yaml b/fly.resource-type.yaml new file mode 100644 index 0000000..3ec54bf --- /dev/null +++ b/fly.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: '' + required: + - token diff --git a/formstack.resource-type.yaml b/formstack.resource-type.yaml new file mode 100644 index 0000000..241c95f --- /dev/null +++ b/formstack.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: Personal access token + required: + - token diff --git a/foxentry.resource-type.yaml b/foxentry.resource-type.yaml new file mode 100644 index 0000000..88e9755 --- /dev/null +++ b/foxentry.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: API key generated against the application on Foxentry dashboard. + required: + - apiKey diff --git a/freshdesk.resource-type.yaml b/freshdesk.resource-type.yaml new file mode 100644 index 0000000..cab7bbb --- /dev/null +++ b/freshdesk.resource-type.yaml @@ -0,0 +1,20 @@ +description: > + 1. Open up `Profile Settings` by clicking on the profile picture icon at the + top-right corner + + 2. Copy the API key and the base URL +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: API key for the user with required permission level + baseUrl: + type: string + description: Base URL of the support portal + required: + - apiKey + - baseUrl diff --git a/funkwhale.resource-type.yaml b/funkwhale.resource-type.yaml new file mode 100644 index 0000000..3a93ea2 --- /dev/null +++ b/funkwhale.resource-type.yaml @@ -0,0 +1,19 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + baseUrl: + type: string + description: '' + default: '' + token: + type: string + description: An access token to act as a logged-in user. You can create an + application by visiting /settings. Leave this empty, if you want to + perform unauthenticated requests. + default: '' + required: + - baseUrl diff --git a/gcal.resource-type.yaml b/gcal.resource-type.yaml new file mode 100644 index 0000000..0dc3c8e --- /dev/null +++ b/gcal.resource-type.yaml @@ -0,0 +1,12 @@ +description: GCalendar OAuth credentials +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: The OAuth token, refreshed if necessary + required: + - token diff --git a/gcloud.resource-type.yaml b/gcloud.resource-type.yaml new file mode 100644 index 0000000..41f9d35 --- /dev/null +++ b/gcloud.resource-type.yaml @@ -0,0 +1,43 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + type: + type: string + auth_provider_x509_cert_url: + type: string + format: url + auth_uri: + type: string + format: url + client_email: + type: string + format: email + client_id: + type: string + client_x509_cert_url: + type: string + format: url + private_key: + type: string + private_key_id: + type: string + project_id: + type: string + token_uri: + type: string + format: url + required: + - type + - auth_uri + - client_id + - token_uri + - project_id + - private_key + - client_email + - private_key_id + - client_x509_cert_url + - auth_provider_x509_cert_url diff --git a/gcloud_storage.resource-type.yaml b/gcloud_storage.resource-type.yaml new file mode 100644 index 0000000..7129637 --- /dev/null +++ b/gcloud_storage.resource-type.yaml @@ -0,0 +1,19 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - bucket + - serviceAccountKey + properties: + bucket: + type: string + default: '' + serviceAccountKey: + type: object + format: resource-gcloud + required: + - bucket + - serviceAccountKey diff --git a/gcp_service_account.resource-type.yaml b/gcp_service_account.resource-type.yaml new file mode 100644 index 0000000..bc9fc39 --- /dev/null +++ b/gcp_service_account.resource-type.yaml @@ -0,0 +1,33 @@ +description: '' +format_extension: null +is_fileset: false +schema: + type: object + additionalProperties: false + properties: + type: + type: string + auth_provider_x509_cert_url: + type: string + format: url + auth_uri: + type: string + format: url + client_email: + type: string + format: email + client_id: + type: string + client_x509_cert_url: + type: string + format: url + private_key: + type: string + private_key_id: + type: string + project_id: + type: string + token_uri: + type: string + format: url + required: [] diff --git a/gdocs.resource-type.yaml b/gdocs.resource-type.yaml new file mode 100644 index 0000000..ba1e1fb --- /dev/null +++ b/gdocs.resource-type.yaml @@ -0,0 +1,12 @@ +description: GDocs OAuth credentials +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: The OAuth token, refreshed if necessary + required: + - token diff --git a/gdrive.resource-type.yaml b/gdrive.resource-type.yaml new file mode 100644 index 0000000..732843a --- /dev/null +++ b/gdrive.resource-type.yaml @@ -0,0 +1,12 @@ +description: GDrive OAuth credentials +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: '' + required: + - token diff --git a/gforms.resource-type.yaml b/gforms.resource-type.yaml new file mode 100644 index 0000000..fcde4f1 --- /dev/null +++ b/gforms.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: Google OAuth2 token + required: + - token diff --git a/gfw.resource-type.yaml b/gfw.resource-type.yaml new file mode 100644 index 0000000..bd26b58 --- /dev/null +++ b/gfw.resource-type.yaml @@ -0,0 +1,16 @@ +description: An API key to access Global Forest Watch API resources +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - api_key + properties: + api_key: + type: string + description: API key to authenticate with the GFW API. + default: '' + nullable: false + required: + - api_key diff --git a/ghostcms.resource-type.yaml b/ghostcms.resource-type.yaml new file mode 100644 index 0000000..97deed1 --- /dev/null +++ b/ghostcms.resource-type.yaml @@ -0,0 +1,22 @@ +description: >- + 1. On the blog dashboard open up `Settings` -> `Integrations` + + 2. Press the `Add Custom Integration` button, provide a unique name, and add + the integration + + 3. Copy the `Admin API Key` and the `API URL` +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: Admin API Key for Ghost CMS. + apiUrl: + type: string + description: Base URL of the Blog and the API. + required: + - apiKey + - apiUrl diff --git a/git_repository.resource-type.yaml b/git_repository.resource-type.yaml new file mode 100644 index 0000000..a27e15c --- /dev/null +++ b/git_repository.resource-type.yaml @@ -0,0 +1,50 @@ +description: |- + Remote Git repository + + Only token-based authentication is supported for this resource type currently. When authentication is needed, the username and token can be included directly in the URL (i.e. `https://[USERNAME]:[TOKEN]@github.com/[ORG|USER]/[REPO_NAME].git`). + + Scoped token can be generated from most git repository platforms (see [Github](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens), [Gitlab](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html) or [Bitbucket](https://support.atlassian.com/bitbucket-cloud/docs/create-a-repository-access-token/), [Azure DevOps PAT](https://learn.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&tabs=Windows), [Azure DevOps Service Principal](https://windmill.dev/docs/advanced/git_sync#azure-devops-with-service-principal-setup)) + + Instead of using a PAT for GitHub, you can also install the [Windmill GitHub App](https://windmill.dev/docs/integrations/git_repository#github-app) to authenticate with GitHub using a short lived token. +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - url + - branch + - folder + - gpg_key + - is_github_app + properties: + branch: + type: string + description: Custom branch to use for this repository. If unset, the repository + default branch will be used. Certain script might expects that the + branch is already created (it is the case of the Windmill Git Sync + script). + default: '' + folder: + type: string + description: Optional path to a folder inside the repository. The path should be + relative to the root of the repository. Certain scripts might expects + that the folder already exists in the repo (it is the case of the + Windmill Git Sync script). + default: '' + gpg_key: + type: object + description: Optional GPG Key resource if the repo requires signed commits + format: resource-gpg_key + is_github_app: + type: boolean + description: Use GitHub App installation token for authentication. Requires a + GitHub App installation in your organization / user account as well as + configuring it in the customer portal. + default: false + url: + type: string + description: URL of the remote + default: '' + required: + - url diff --git a/gitbook.resource-type.yaml b/gitbook.resource-type.yaml new file mode 100644 index 0000000..2243a80 --- /dev/null +++ b/gitbook.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: '{property1 description}' + required: + - token diff --git a/github.resource-type.yaml b/github.resource-type.yaml new file mode 100644 index 0000000..f7c0201 --- /dev/null +++ b/github.resource-type.yaml @@ -0,0 +1,12 @@ +description: The github OAuth credentials +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: '' + required: + - token diff --git a/gitlab.resource-type.yaml b/gitlab.resource-type.yaml new file mode 100644 index 0000000..dcafbd3 --- /dev/null +++ b/gitlab.resource-type.yaml @@ -0,0 +1,17 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + baseUrl: + type: string + description: '' + default: https://gitlab.com + token: + type: string + description: '' + default: '' + required: + - token diff --git a/gmail.resource-type.yaml b/gmail.resource-type.yaml new file mode 100644 index 0000000..490266c --- /dev/null +++ b/gmail.resource-type.yaml @@ -0,0 +1,12 @@ +description: OAuth2 token for gmail +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: '' + required: + - token diff --git a/googleai.resource-type.yaml b/googleai.resource-type.yaml new file mode 100644 index 0000000..45aff6a --- /dev/null +++ b/googleai.resource-type.yaml @@ -0,0 +1,22 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - api_key + - base_url + properties: + api_key: + type: string + description: '' + default: '' + nullable: false + password: true + base_url: + type: string + description: Optional. Only needed to overwrite the default base URL. + default: '' + required: + - api_key diff --git a/gorgias.resource-type.yaml b/gorgias.resource-type.yaml new file mode 100644 index 0000000..cb84109 --- /dev/null +++ b/gorgias.resource-type.yaml @@ -0,0 +1,20 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: API key retrieved from the dashboard. + domain: + type: string + description: Domain of the workspace. + username: + type: string + description: Email used to register for Gorgias. + required: + - username + - apiKey + - domain diff --git a/gpg_key.resource-type.yaml b/gpg_key.resource-type.yaml new file mode 100644 index 0000000..22bdbd0 --- /dev/null +++ b/gpg_key.resource-type.yaml @@ -0,0 +1,49 @@ +description: GPG Key for signing git commits. +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - email + - private_key + - passphrase + properties: + email: + type: string + description: Make sure the email address matches both the address set in the gpg + key and the corresponding git users gpg public key. + default: '' + format: email + nullable: false + pattern: ^[\w-+.]+@([\w-]+\.)+[\w-]{2,4}$ + passphrase: + type: string + description: >- + Please add a passphrase if the private key is protected by a passphrase. + + + NOTE: the private key is obfuscated in the input field but is currently + not encrypted. We recommend to create a new gpg key pair without a + passphrase for git_sync + default: '' + password: true + private_key: + type: string + description: >- + GPG private key of the corresponding public key added to git for commit + signing. + + + Use `gpg --armor --export-secret-keys ` to extract the private + key + customErrorMessage: invalid private key format + default: '' + minRows: 20 + nullable: false + password: true + pattern: ^-----BEGIN PGP PRIVATE KEY BLOCK-----[\s\S]*?-----END PGP PRIVATE KEY + BLOCK-----$ + required: + - email + - private_key diff --git a/graphql.resource-type.yaml b/graphql.resource-type.yaml new file mode 100644 index 0000000..daba7fb --- /dev/null +++ b/graphql.resource-type.yaml @@ -0,0 +1,23 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + base_url: + type: string + description: '' + default: '' + format: uri + bearer_token: + type: string + description: '' + default: '' + custom_headers: + type: object + description: '' + properties: {} + required: [] + required: + - base_url diff --git a/greip.resource-type.yaml b/greip.resource-type.yaml new file mode 100644 index 0000000..0656c17 --- /dev/null +++ b/greip.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: API key retrieved from the Greip dashboard. + required: + - apiKey diff --git a/grist.resource-type.yaml b/grist.resource-type.yaml new file mode 100644 index 0000000..1b3bfdc --- /dev/null +++ b/grist.resource-type.yaml @@ -0,0 +1,16 @@ +description: Schema for the resource configuration +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: API key retrieved from the profile settings. + host: + type: string + description: Base URL of the API - for personal workspace, use docs.getgrist.com + and for team workspace, use team URL. + required: + - '{property1}' diff --git a/groq.resource-type.yaml b/groq.resource-type.yaml new file mode 100644 index 0000000..45aff6a --- /dev/null +++ b/groq.resource-type.yaml @@ -0,0 +1,22 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - api_key + - base_url + properties: + api_key: + type: string + description: '' + default: '' + nullable: false + password: true + base_url: + type: string + description: Optional. Only needed to overwrite the default base URL. + default: '' + required: + - api_key diff --git a/groqai.resource-type.yaml b/groqai.resource-type.yaml new file mode 100644 index 0000000..064ade2 --- /dev/null +++ b/groqai.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + api_key: + type: string + description: API key retrieved from the dashboard. + required: + - api_key diff --git a/gsheets.resource-type.yaml b/gsheets.resource-type.yaml new file mode 100644 index 0000000..882f753 --- /dev/null +++ b/gsheets.resource-type.yaml @@ -0,0 +1,12 @@ +description: GSheet OAuth credentials +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: The OAuth token, refreshed if necessary + required: + - token diff --git a/gworkspace.resource-type.yaml b/gworkspace.resource-type.yaml new file mode 100644 index 0000000..ec6514c --- /dev/null +++ b/gworkspace.resource-type.yaml @@ -0,0 +1,14 @@ +description: 'A google workspace api token, see: + https://developers.google.com/admin-sdk/admin-api-list?hl=en' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: OAuth token + default: '' + required: + - token diff --git a/holded.resource-type.yaml b/holded.resource-type.yaml new file mode 100644 index 0000000..b5fc830 --- /dev/null +++ b/holded.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: API key generated from the Holded dashboard. + required: + - apiKey diff --git a/hubspot.resource-type.yaml b/hubspot.resource-type.yaml new file mode 100644 index 0000000..7eacf18 --- /dev/null +++ b/hubspot.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: Access token of a private app + default: '' + required: [] diff --git a/ifs_cloud_oidc.resource-type.yaml b/ifs_cloud_oidc.resource-type.yaml new file mode 100644 index 0000000..1f793ba --- /dev/null +++ b/ifs_cloud_oidc.resource-type.yaml @@ -0,0 +1,40 @@ +description: >- + Create new IFS IAM client, use client ID and client secret in resource. + + Specify base URL as the server, ex: https://mycorp-cfg.ifs.cloud + + Get OIDC path from API Docs generated for your deployment, ex: + /auth/realms/mycocfg1/.well-known/openid-configuration +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - server + - oidcPath + - clientId + - clientSecret + properties: + clientId: + type: string + description: The exact clientId from the IAM Client created in IFS Cloud + default: '' + clientSecret: + type: string + description: The exact client secret from the IAM Client created in IFS Cloud + default: '' + oidcPath: + type: string + description: Path from the full URL for the OIDC configuration, found in the API + Docs generated within the IFS Cloud deployment + default: '' + server: + type: string + description: Base URL of IFS Cloud deployment + default: '' + required: + - server + - oidcPath + - clientId + - clientSecret diff --git a/intercom.resource-type.yaml b/intercom.resource-type.yaml new file mode 100644 index 0000000..89b96cb --- /dev/null +++ b/intercom.resource-type.yaml @@ -0,0 +1,16 @@ +description: Visit apps.intercom.com, create an app, navigate inside, check the + API Version it is using and find the access token inside the authentication + tab. +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiVersion: + type: string + token: + type: string + required: + - apiVersion + - token diff --git a/ipinfo.resource-type.yaml b/ipinfo.resource-type.yaml new file mode 100644 index 0000000..77a8846 --- /dev/null +++ b/ipinfo.resource-type.yaml @@ -0,0 +1,13 @@ +description: ipinfo API token +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: API token + default: '' + required: + - token diff --git a/jira.resource-type.yaml b/jira.resource-type.yaml new file mode 100644 index 0000000..124f0dc --- /dev/null +++ b/jira.resource-type.yaml @@ -0,0 +1,23 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + domain: + type: string + description: '' + default: '' + password: + type: string + description: '' + default: '' + username: + type: string + description: '' + default: '' + required: + - username + - password + - domain diff --git a/jotform.resource-type.yaml b/jotform.resource-type.yaml new file mode 100644 index 0000000..02bb9ce --- /dev/null +++ b/jotform.resource-type.yaml @@ -0,0 +1,26 @@ +description: >- + 1. Head to `settings` by clicking the avatar on the top-right corner. + + 2. Select `API` from the navigation bar on the left, and create a new key. + + 3. Copy the generated API key. + + 5. Visit [this](https://api.jotform.com/docs/#overview) URL to review the API + endpoints available. + + 6. Copy the API endpoint for your relevant region. +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: API Key generated from the dashboard. + baseUrl: + type: string + description: Base URL of the API to use - US, EU, HIPAA, or custom domain + required: + - apiKey + - baseUrl diff --git a/json_schema.resource-type.yaml b/json_schema.resource-type.yaml new file mode 100644 index 0000000..b36898d --- /dev/null +++ b/json_schema.resource-type.yaml @@ -0,0 +1,14 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - schema + properties: + schema: + type: object + description: '' + format: json-schema + required: [] diff --git a/kafka.resource-type.yaml b/kafka.resource-type.yaml new file mode 100644 index 0000000..33942f4 --- /dev/null +++ b/kafka.resource-type.yaml @@ -0,0 +1,220 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - brokers + - security + properties: + brokers: + type: array + description: '' + default: [] + items: + type: string + nullable: false + security: + type: object + description: '' + oneOf: + - type: object + properties: + label: + type: string + enum: + - PLAINTEXT + title: PLAINTEXT + - type: object + order: + - mechanism + - username + - password + properties: + label: + type: string + enum: + - SASL_PLAINTEXT + mechanism: + type: string + description: '' + default: '' + disableCreate: true + enum: + - PLAIN + - SCRAM-SHA-256 + - SCRAM-SHA-512 + enumLabels: {} + nullable: false + password: + type: string + description: '' + default: '' + nullable: false + password: true + username: + type: string + description: '' + default: '' + nullable: false + required: + - mechanism + - username + - password + title: SASL_PLAINTEXT + - type: object + order: + - ca + - certificate + - key + - key_password + properties: + ca: + type: string + description: CA certificate to verify the server certificate, in PEM format + default: '' + certificate: + type: string + description: Client certificate for authentication to the server, in PEM format + key: + type: string + description: Client key for authentication to the server, in PEM format + default: '' + key_password: + type: string + description: Password to decrypt the client key, if encrypted + password: true + label: + type: string + enum: + - SSL + title: SSL + - type: object + order: + - mechanism + - username + - password + - ca + - certificate + - key + - key_password + properties: + ca: + type: string + description: CA certificate to verify the server certificate, in PEM format + certificate: + type: string + description: Client certificate for authentication to the server, in PEM format + key: + type: string + description: Client key for authentication to the server, in PEM format + default: '' + key_password: + type: string + description: Password to decrypt the client key, if encrypted + default: '' + password: true + label: + type: string + enum: + - SASL_SSL + mechanism: + type: string + description: '' + default: '' + disableCreate: true + enum: + - PLAIN + - SCRAM-SHA-256 + - SCRAM-SHA-512 + enumLabels: {} + nullable: false + password: + type: string + description: '' + default: '' + nullable: false + password: true + username: + type: string + description: '' + default: '' + nullable: false + required: + - mechanism + - username + - password + title: SASL_SSL + - type: object + order: + - kerberos_service_name + - kerberos_principal + - keytab_path + - keytab_base64 + properties: + kerberos_principal: + type: string + description: Client's Kerberos principal (e.g., user@REALM.COM) + kerberos_service_name: + type: string + description: Kerberos principal name of the Kafka broker service + default: kafka + keytab_base64: + type: string + description: Base64-encoded keytab content (alternative to keytab_path) + password: true + keytab_path: + type: string + description: Path to keytab file mounted on the worker + label: + type: string + enum: + - SASL_GSSAPI + title: SASL_GSSAPI + - type: object + order: + - kerberos_service_name + - kerberos_principal + - keytab_path + - keytab_base64 + - ca + - certificate + - key + - key_password + properties: + ca: + type: string + description: CA certificate to verify the server certificate, in PEM format + certificate: + type: string + description: Client certificate for authentication to the server, in PEM format + kerberos_principal: + type: string + description: Client's Kerberos principal (e.g., user@REALM.COM) + kerberos_service_name: + type: string + description: Kerberos principal name of the Kafka broker service + default: kafka + key: + type: string + description: Client key for authentication to the server, in PEM format + key_password: + type: string + description: Password to decrypt the client key, if encrypted + password: true + keytab_base64: + type: string + description: Base64-encoded keytab content (alternative to keytab_path) + password: true + keytab_path: + type: string + description: Path to keytab file mounted on the worker + label: + type: string + enum: + - SASL_SSL_GSSAPI + title: SASL_SSL_GSSAPI + required: + - brokers + - security diff --git a/klaviyo.resource-type.yaml b/klaviyo.resource-type.yaml new file mode 100644 index 0000000..c78340c --- /dev/null +++ b/klaviyo.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: Private API key generated from Klaviyo dashboard + required: + - apiKey diff --git a/kobotoolbox.resource-type.yaml b/kobotoolbox.resource-type.yaml new file mode 100644 index 0000000..244ef8d --- /dev/null +++ b/kobotoolbox.resource-type.yaml @@ -0,0 +1,23 @@ +description: An API Key to access a KoboToolbox server +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - server_url + - api_key + properties: + api_key: + type: string + description: In KoboToolbox, found under Account Settings > Security + default: '' + server_url: + type: string + description: The base URL of your KoboToolbox server + default: '' + nullable: false + pattern: ^(https?://)([^/]+)$ + placeholder: https://kf.kobotoolbox.org + required: + - server_url diff --git a/kustomer.resource-type.yaml b/kustomer.resource-type.yaml new file mode 100644 index 0000000..be72cc7 --- /dev/null +++ b/kustomer.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: API key retrieved from the dashboard. + required: + - apiKey diff --git a/langfuse.resource-type.yaml b/langfuse.resource-type.yaml new file mode 100644 index 0000000..a9c9c90 --- /dev/null +++ b/langfuse.resource-type.yaml @@ -0,0 +1,34 @@ +description: Langfuse is an open-source LLM observability platform that supports + self-hosting. +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - base_url + - public_key + - secret_key + properties: + base_url: + type: string + description: Official cloud service URL or a custom domain for self-hosted + environments. + default: https://cloud.langfuse.com + nullable: false + public_key: + type: string + description: public key of workspace + default: '' + nullable: false + placeholder: pk-lf-xxxx + secret_key: + type: string + description: secret key of workspace + default: '' + nullable: false + password: true + placeholder: sk-lf-xxxx + required: + - public_key + - secret_key diff --git a/ldap.resource-type.yaml b/ldap.resource-type.yaml new file mode 100644 index 0000000..076075e --- /dev/null +++ b/ldap.resource-type.yaml @@ -0,0 +1,44 @@ +description: Connection parameters for binding to an LDAP server using the + Python ldap3 library +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - server + - bind_user + - bind_password + - use_ssl + - ssl_validate + properties: + bind_password: + type: string + description: '' + default: '' + password: true + bind_user: + type: string + description: for Active Directory, you may use DOMAIN\username or UPN here. For + normal LDAP, use the distinguished name of the user. + default: '' + server: + type: string + description: 'Use format like: ldap://ipa.demo1.freeipa.org:389. If you use SSL, + specify ldaps:// as the scheme and usually port 636.' + default: '' + ssl_validate: + type: boolean + description: validate SSL server certificate? + default: true + showExpr: fields.use_ssl == true + use_ssl: + type: boolean + description: Whether to use SSL/TLS when connecting to LDAP. If not further + specified in the server string, this implies connecting to the server on + port 636 instead of 389. + default: true + required: + - server + - bind_user + - bind_password diff --git a/leonardoai.resource-type.yaml b/leonardoai.resource-type.yaml new file mode 100644 index 0000000..e4c707f --- /dev/null +++ b/leonardoai.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: API key generated from the dashboard + required: + - apiKey diff --git a/linear.resource-type.yaml b/linear.resource-type.yaml new file mode 100644 index 0000000..083d763 --- /dev/null +++ b/linear.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: The API key for the Linear API + required: + - apiKey diff --git a/linkding.resource-type.yaml b/linkding.resource-type.yaml new file mode 100644 index 0000000..0d3fb87 --- /dev/null +++ b/linkding.resource-type.yaml @@ -0,0 +1,17 @@ +description: https://github.com/sissbruecker/linkding/blob/master/README.md +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + baseUrl: + type: string + description: The baseUrl of the instance + default: '' + token: + type: string + description: API token to connect to the API + default: '' + required: + - token diff --git a/linkedin.resource-type.yaml b/linkedin.resource-type.yaml new file mode 100644 index 0000000..8911548 --- /dev/null +++ b/linkedin.resource-type.yaml @@ -0,0 +1,13 @@ +description: The OAuth token for LinkedIn +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: OAuth token + default: '' + required: + - token diff --git a/linode.resource-type.yaml b/linode.resource-type.yaml new file mode 100644 index 0000000..41ededf --- /dev/null +++ b/linode.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: Personal access token for Linode API. + required: + - token diff --git a/localcontexts.resource-type.yaml b/localcontexts.resource-type.yaml new file mode 100644 index 0000000..da29d1c --- /dev/null +++ b/localcontexts.resource-type.yaml @@ -0,0 +1,35 @@ +description: Local Contexts is a global initiative that supports Indigenous + communities with tools that can reassert cultural authority in heritage + collections and data. This resource type contains the URL (since there are two + different Local Contexts Hub URLs), the project ID, and the account API key. +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - server_url + - api_key + - project_id + properties: + api_key: + type: string + description: '' + default: '' + nullable: false + password: true + project_id: + type: string + description: '' + default: '' + nullable: false + server_url: + type: string + description: '' + default: https://localcontextshub.org/api/ + nullable: false + placeholder: '' + required: + - server_url + - api_key + - project_id diff --git a/lumaai.resource-type.yaml b/lumaai.resource-type.yaml new file mode 100644 index 0000000..e590ae4 --- /dev/null +++ b/lumaai.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: API key retrieved from LUMA dashboard. + required: + - apiKey diff --git a/magento.resource-type.yaml b/magento.resource-type.yaml new file mode 100644 index 0000000..7c856a0 --- /dev/null +++ b/magento.resource-type.yaml @@ -0,0 +1,29 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - consumerKey + - consumerSecret + - accessToken + - accessTokenSecret + properties: + accessToken: + type: string + description: '' + default: '' + accessTokenSecret: + type: string + description: '' + default: '' + consumerKey: + type: string + description: '' + default: '' + consumerSecret: + type: string + description: '' + default: '' + required: [] diff --git a/mailchimp.resource-type.yaml b/mailchimp.resource-type.yaml new file mode 100644 index 0000000..a6b1254 --- /dev/null +++ b/mailchimp.resource-type.yaml @@ -0,0 +1,16 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + api_key: + type: string + description: '' + default: '' + server: + type: string + description: 'The data center for your Mailchimp account. (For example: us12)' + default: '' + required: [] diff --git a/mailerlite.resource-type.yaml b/mailerlite.resource-type.yaml new file mode 100644 index 0000000..2812341 --- /dev/null +++ b/mailerlite.resource-type.yaml @@ -0,0 +1,14 @@ +description: |- + 1. Open up `Integrations` from the navigation bar and then select `API` + 2. Generate a new API token and copy it +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiToken: + type: string + description: API Token for authenticating the MailerLite API request + required: + - apiToken diff --git a/mailgun.resource-type.yaml b/mailgun.resource-type.yaml new file mode 100644 index 0000000..fe036af --- /dev/null +++ b/mailgun.resource-type.yaml @@ -0,0 +1,13 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + api_key: + type: string + description: Mailgun API key + default: '' + required: + - api_key diff --git a/mastodon.resource-type.yaml b/mastodon.resource-type.yaml new file mode 100644 index 0000000..083ff34 --- /dev/null +++ b/mastodon.resource-type.yaml @@ -0,0 +1,18 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + baseUrl: + type: string + description: The URL of the Mastodon instance, like "https://mastodon.example.com". + default: '' + token: + type: string + description: An access token to act as a logged-in user. Leave this empty, if + you want to perform unauthenticated requests. + default: '' + required: + - baseUrl diff --git a/matrix.resource-type.yaml b/matrix.resource-type.yaml new file mode 100644 index 0000000..99fc882 --- /dev/null +++ b/matrix.resource-type.yaml @@ -0,0 +1,18 @@ +description: Login credentials for a user on a Matrix server +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + baseUrl: + type: string + description: The URL of a Matrix server, like "https://matrix.example.com" + default: '' + token: + type: string + description: An access token to act as a logged-in user. Leave this empty, if + you want to perform unauthenticated requests. + default: '' + required: + - baseUrl diff --git a/matteroom.resource-type.yaml b/matteroom.resource-type.yaml new file mode 100644 index 0000000..22a2ba4 --- /dev/null +++ b/matteroom.resource-type.yaml @@ -0,0 +1,27 @@ +description: Matteroom Key Resource +format_extension: null +is_fileset: false +schema: + type: object + order: + - base_url + - username + - password + properties: + base_url: + type: string + description: '' + default: https://qa-prime.matteroom.com + title: Base API URL + password: + type: string + format: password + title: Password + username: + type: string + title: Username (Email) + required: + - base_url + - username + - password + title: Matteroom API Connector diff --git a/mcp.resource-type.yaml b/mcp.resource-type.yaml new file mode 100644 index 0000000..669fd76 --- /dev/null +++ b/mcp.resource-type.yaml @@ -0,0 +1,32 @@ +description: MCP (Model Context Protocol) server resource type +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - name + - url + - token + - headers + properties: + name: + type: string + description: The name of the MCP server + default: '' + nullable: false + headers: + type: object + description: Optional headers to be sent with the request + token: + type: string + description: Optional bearer token to be used for authentication + default: '' + url: + type: string + description: The URL of the HTTP streamable endpoint of the MCP server + default: '' + nullable: false + required: + - name + - url diff --git a/meteosource.resource-type.yaml b/meteosource.resource-type.yaml new file mode 100644 index 0000000..bf221a8 --- /dev/null +++ b/meteosource.resource-type.yaml @@ -0,0 +1,19 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft-07/schema# + type: object + properties: + apiKey: + type: string + description: Token for X-API-Key header authentication + tier: + type: string + description: API tier level + enum: + - free + - standard + required: + - apiKey + - tier diff --git a/mezmo.resource-type.yaml b/mezmo.resource-type.yaml new file mode 100644 index 0000000..3f51888 --- /dev/null +++ b/mezmo.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft-07/schema# + type: object + properties: + apiKey: + type: string + description: API key retrieved from the dashboard. + required: + - apiKey diff --git a/miro.resource-type.yaml b/miro.resource-type.yaml new file mode 100644 index 0000000..fe8f823 --- /dev/null +++ b/miro.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: Access token retrieved from the OAuth flow. + required: + - token diff --git a/mistral.resource-type.yaml b/mistral.resource-type.yaml new file mode 100644 index 0000000..e149a2f --- /dev/null +++ b/mistral.resource-type.yaml @@ -0,0 +1,20 @@ +description: Connect to Mistral API +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - apiKey + - base_url + properties: + apiKey: + type: string + description: https://docs.mistral.ai/ + default: '' + base_url: + type: string + description: Optional. Only needed to overwrite the default base URL. + default: '' + required: + - apiKey diff --git a/mollie.resource-type.yaml b/mollie.resource-type.yaml new file mode 100644 index 0000000..884ae3a --- /dev/null +++ b/mollie.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: Access token (OAuth/Organization) or the API key for authentication. + required: + - token diff --git a/mongodb.resource-type.yaml b/mongodb.resource-type.yaml new file mode 100644 index 0000000..e6a8e2f --- /dev/null +++ b/mongodb.resource-type.yaml @@ -0,0 +1,41 @@ +description: MongoDb connection infos +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + credential: + db: + type: string + description: '' + mechanism: + type: string + description: '' + default: SCRAM-SHA-1 + password: + type: string + description: '' + username: + type: string + description: '' + db: + type: string + description: '' + servers: + - host: + type: string + description: '' + port: + type: integer + description: '' + default: 27017 + tls: + type: boolean + description: '' + default: true + required: + - db + - tls + - servers + - credential diff --git a/mongodb_rest.resource-type.yaml b/mongodb_rest.resource-type.yaml new file mode 100644 index 0000000..18e6473 --- /dev/null +++ b/mongodb_rest.resource-type.yaml @@ -0,0 +1,18 @@ +description: Resource type to access MongoDB through the Atlas Data API +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + api_key: + type: string + description: '' + default: '' + endpoint: + type: string + description: 'For example: https://data.mongodb-api.com/app//endpoint/data/v1' + default: '' + required: + - endpoint + - api_key diff --git a/motimate.resource-type.yaml b/motimate.resource-type.yaml new file mode 100644 index 0000000..05833c6 --- /dev/null +++ b/motimate.resource-type.yaml @@ -0,0 +1,11 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + required: + - token diff --git a/mqtt.resource-type.yaml b/mqtt.resource-type.yaml new file mode 100644 index 0000000..defb35b --- /dev/null +++ b/mqtt.resource-type.yaml @@ -0,0 +1,78 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + additionalProperties: false + description: Configuration settings for connecting to an MQTT broker + order: + - broker + - port + - credentials + - tls + properties: + broker: + type: string + description: The hostname or IP address of the MQTT broker + default: '' + examples: + - mqtt.example.com + - 192.168.1.100 + credentials: + type: object + description: Authentication credentials for the MQTT broker + order: + - username + - password + properties: + password: + type: string + description: Password for broker authentication + format: password + username: + type: string + description: Username for broker authentication + port: + type: integer + description: The port number for the MQTT broker connection + default: 1883 + examples: + - 1883 + - 8883 + tls: + type: object + description: TLS/SSL configuration for secure connections. For standard TLS, + only the 'enabled' property needs to be set to true. For mutual TLS + (mTLS) with client authentication, the CA certificate, client + certificate, and certificate password are also required. + order: + - enabled + - ca_certificate + - pkcs12_client_certificate + - pkcs12_certificate_password + properties: + ca_certificate: + type: string + description: CA certificate in PEM format for verifying the broker identity. + Optional for standard TLS, required for mTLS. + default: '' + enabled: + type: boolean + description: Enable TLS/SSL for the connection + default: false + pkcs12_certificate_password: + type: string + description: Password used to decrypt and access the protected PKCS#12 client + certificate + format: password + pkcs12_client_certificate: + type: string + description: DER-formatted PKCS#12 certificate encoded in Base64. Contains both + the client certificate and private key for authentication + contentEncoding: base64 + default: '' + required: + - broker + - port + title: MQTT resource diff --git a/ms_sql_server.resource-type.yaml b/ms_sql_server.resource-type.yaml new file mode 100644 index 0000000..01511d2 --- /dev/null +++ b/ms_sql_server.resource-type.yaml @@ -0,0 +1,75 @@ +description: Microsoft SQL Server resource. Supports username/password, AAD + token, or Windows Integrated Authentication. +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - host + - user + - password + - integrated_auth + - aad_token + - port + - dbname + - instance_name + - trust_cert + - ca_cert + - encrypt + properties: + aad_token: + type: object + description: AAD token for authentication + format: resource-azure_oauth + nullable: true + ca_cert: + type: string + description: CA certificate in PEM format for verifying the server identity. + Only needed if the certificate used by the server is not in the + workers's trust store. + default: '' + pattern: ^(-----BEGIN CERTIFICATE-----\s+([A-Za-z0-9+/=\s]+?)-----END + CERTIFICATE-----)?$ + dbname: + type: string + description: '' + default: '' + encrypt: + type: boolean + description: Enable TLS encryption. When false, all data including passwords are + sent unencrypted over the network. Set to false only for local + development. + default: true + host: + type: string + description: '' + default: '' + instance_name: + type: string + description: '' + default: '' + integrated_auth: + type: boolean + description: Use Windows Integrated Authentication (Kerberos). When enabled, the + worker's service account credentials are used instead of + username/password. Requires the worker to have a valid Kerberos ticket. + default: false + password: + type: string + description: '' + default: '' + port: + type: number + description: '' + trust_cert: + type: boolean + description: Trust any certificate presented by the server + default: true + user: + type: string + description: '' + default: '' + required: + - host + - dbname diff --git a/ms_teams_webhook.resource-type.yaml b/ms_teams_webhook.resource-type.yaml new file mode 100644 index 0000000..19458f2 --- /dev/null +++ b/ms_teams_webhook.resource-type.yaml @@ -0,0 +1,16 @@ +description: This resource type connects to an individual Microsoft Teams + Channels via a webhook +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + webhook_url: + type: string + description: See + https://learn.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/add-incoming-webhook?tabs=dotnet + for detais on how to create a webhook + default: '' + required: + - webhook_url diff --git a/mysql.resource-type.yaml b/mysql.resource-type.yaml new file mode 100644 index 0000000..9c848f3 --- /dev/null +++ b/mysql.resource-type.yaml @@ -0,0 +1,47 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - host + - port + - user + - database + - password + - ssl + - root_certificate_pem + properties: + database: + type: string + description: database name + default: '' + host: + type: string + description: instance host + default: '' + password: + type: string + description: user's password + default: '' + port: + type: number + description: instance port + default: 3306 + root_certificate_pem: + type: string + description: '' + default: '' + ssl: + type: boolean + description: use ssl + default: false + user: + type: string + description: username + default: '' + required: + - user + - database + - password diff --git a/nats.resource-type.yaml b/nats.resource-type.yaml new file mode 100644 index 0000000..5a88ba7 --- /dev/null +++ b/nats.resource-type.yaml @@ -0,0 +1,98 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - servers + - require_tls + - auth + properties: + auth: + type: object + description: '' + default: + label: NO_AUTH + oneOf: + - type: object + properties: + label: + type: string + enum: + - NO_AUTH + title: NO_AUTH + - type: object + order: + - token + properties: + label: + type: string + enum: + - TOKEN + token: + type: string + password: true + required: + - token + title: TOKEN + - type: object + properties: + label: + type: string + enum: + - USER_PASSWORD + password: + type: string + password: true + user: + type: string + required: + - user + - password + title: USER_PASSWORD + - type: object + order: + - nkey + properties: + label: + type: string + enum: + - NKEY + seed: + type: string + password: true + required: + - nkey + title: NKEY + - type: object + properties: + jwt: + type: string + password: true + label: + type: string + enum: + - JWT + seed: + type: string + password: true + required: + - jwt + - seed + title: JWT + title: Authentication + require_tls: + type: boolean + description: '' + default: false + title: Require TLS + servers: + type: array + description: '' + default: + - '' + items: + type: string + title: Servers + required: [] diff --git a/neondb.resource-type.yaml b/neondb.resource-type.yaml new file mode 100644 index 0000000..b702a76 --- /dev/null +++ b/neondb.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: API Key generated from the account settings of NeonDB console. + required: + - apiKey diff --git a/netbox.resource-type.yaml b/netbox.resource-type.yaml new file mode 100644 index 0000000..23517e4 --- /dev/null +++ b/netbox.resource-type.yaml @@ -0,0 +1,21 @@ +description: API credential for connecting with NetBox +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - url + - token + properties: + token: + type: string + description: User API token + default: '' + url: + type: string + description: NetBox API URL + default: '' + required: + - url + - token diff --git a/netlify.resource-type.yaml b/netlify.resource-type.yaml new file mode 100644 index 0000000..3a2ecaa --- /dev/null +++ b/netlify.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: Access token retrieved using the OAuth flow. + required: + - token diff --git a/newsapi.resource-type.yaml b/newsapi.resource-type.yaml new file mode 100644 index 0000000..8c70c9c --- /dev/null +++ b/newsapi.resource-type.yaml @@ -0,0 +1,11 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + required: + - apiKey diff --git a/nextcloud.resource-type.yaml b/nextcloud.resource-type.yaml new file mode 100644 index 0000000..576cf9d --- /dev/null +++ b/nextcloud.resource-type.yaml @@ -0,0 +1,39 @@ +description: Nextcloud instance credentials +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - baseUrl + - userId + - token + - username + - password + properties: + baseUrl: + type: string + description: 'The URL where the Nextcloud instance can be reached. Example: + https://nextcloud.example.com' + default: '' + password: + type: string + description: Deprecated, use token instead + default: '' + token: + type: string + description: An app/device token or the user's main password. To create a token + Settings -> Security -> Devices & sessions. + default: '' + nullable: false + userId: + type: string + description: '' + default: '' + username: + type: string + description: Deprecated, use userId instead + default: '' + required: + - baseUrl + - token diff --git a/nocodb.resource-type.yaml b/nocodb.resource-type.yaml new file mode 100644 index 0000000..c3988cb --- /dev/null +++ b/nocodb.resource-type.yaml @@ -0,0 +1,16 @@ +description: 'Noco DB table request structure ' +format_extension: null +is_fileset: false +schema: + type: object + additionalProperties: false + properties: + apiUrl: + type: string + table: + type: string + workspace: + type: string + xc_token: + type: string + required: [] diff --git a/notion.resource-type.yaml b/notion.resource-type.yaml new file mode 100644 index 0000000..daf3e45 --- /dev/null +++ b/notion.resource-type.yaml @@ -0,0 +1,15 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: |- + Access token for the Notion API. + Learn more at https://developers.notion.com/docs/authorization + default: '' + required: + - token diff --git a/odk.resource-type.yaml b/odk.resource-type.yaml new file mode 100644 index 0000000..2bfffee --- /dev/null +++ b/odk.resource-type.yaml @@ -0,0 +1,37 @@ +description: Parameters required to access an ODK Central server. +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - base_url + - username + - password + - default_project_id + properties: + base_url: + type: string + description: The base URL of your ODK server + default: '' + nullable: false + pattern: ^(https?://)([^/]+)$ + placeholder: https://your-odk-central-instance.org + default_project_id: + type: integer + description: The default project ID of your ODK project + password: + type: string + description: The password to authenticate with the ODK server + default: '' + nullable: false + password: true + username: + type: string + description: The username to authenticate with the ODK server + default: '' + nullable: false + required: + - password + - username + - base_url diff --git a/openai.resource-type.yaml b/openai.resource-type.yaml new file mode 100644 index 0000000..66b0a3f --- /dev/null +++ b/openai.resource-type.yaml @@ -0,0 +1,26 @@ +description: Resource for authentication to the OpenAI API +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - api_key + - organization_id + - base_url + properties: + api_key: + type: string + description: '' + default: '' + base_url: + type: string + description: Optional. Only needed to overwrite the default base URL. + default: '' + organization_id: + type: string + description: Only needs to be set for users who belong to multiple organizations + and they want to use an organization other than the default one + default: '' + required: + - api_key diff --git a/openrouter.resource-type.yaml b/openrouter.resource-type.yaml new file mode 100644 index 0000000..45aff6a --- /dev/null +++ b/openrouter.resource-type.yaml @@ -0,0 +1,22 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - api_key + - base_url + properties: + api_key: + type: string + description: '' + default: '' + nullable: false + password: true + base_url: + type: string + description: Optional. Only needed to overwrite the default base URL. + default: '' + required: + - api_key diff --git a/oracledb.resource-type.yaml b/oracledb.resource-type.yaml new file mode 100644 index 0000000..367f655 --- /dev/null +++ b/oracledb.resource-type.yaml @@ -0,0 +1,32 @@ +description: The connection credentials for oracledb +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - user + - password + - database + properties: + database: + type: string + description: The database connection string + default: '' + nullable: false + placeholder: server_name:1521/db_name + password: + type: string + description: The pasword for the user + default: '' + nullable: false + password: true + user: + type: string + description: The database username + default: '' + nullable: false + required: + - password + - database + - user diff --git a/pandadoc.resource-type.yaml b/pandadoc.resource-type.yaml new file mode 100644 index 0000000..8c70c9c --- /dev/null +++ b/pandadoc.resource-type.yaml @@ -0,0 +1,11 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + required: + - apiKey diff --git a/paychex.resource-type.yaml b/paychex.resource-type.yaml new file mode 100644 index 0000000..023cc64 --- /dev/null +++ b/paychex.resource-type.yaml @@ -0,0 +1,16 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft-07/schema# + type: object + properties: + client_id: + type: string + description: OAuth client ID + client_secret: + type: string + description: OAuth client secret + required: + - client_id + - client_secret diff --git a/paylocity.resource-type.yaml b/paylocity.resource-type.yaml new file mode 100644 index 0000000..3c7ebae --- /dev/null +++ b/paylocity.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: Access token generated using the OAuth flow. + required: + - token diff --git a/paypal.resource-type.yaml b/paypal.resource-type.yaml new file mode 100644 index 0000000..25fd9be --- /dev/null +++ b/paypal.resource-type.yaml @@ -0,0 +1,23 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - clientId + - clientSecret + properties: + clientId: + type: string + description: '' + default: '' + clientSecret: + type: string + description: '' + default: '' + nullable: false + password: true + required: + - clientId + - clientSecret diff --git a/persona.resource-type.yaml b/persona.resource-type.yaml new file mode 100644 index 0000000..be72cc7 --- /dev/null +++ b/persona.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: API key retrieved from the dashboard. + required: + - apiKey diff --git a/personio.resource-type.yaml b/personio.resource-type.yaml new file mode 100644 index 0000000..f6de670 --- /dev/null +++ b/personio.resource-type.yaml @@ -0,0 +1,16 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + clientId: + type: string + description: Client ID taken from the Personio dashboard. + clientSecret: + type: string + description: Client Secret taken from the Personio dashboard. + required: + - clientId + - clientSecret diff --git a/phrase.resource-type.yaml b/phrase.resource-type.yaml new file mode 100644 index 0000000..15979fd --- /dev/null +++ b/phrase.resource-type.yaml @@ -0,0 +1,17 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + baseUrl: + type: string + description: 'Different URLs for EU and US data centers: + https://api.phrase.com/v2/ or https://api.us.app.phrase.com/v2' + token: + type: string + description: Access token generated in user settings. + required: + - token + - baseUrl diff --git a/pinecone.resource-type.yaml b/pinecone.resource-type.yaml new file mode 100644 index 0000000..45a48cb --- /dev/null +++ b/pinecone.resource-type.yaml @@ -0,0 +1,18 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: '' + default: '' + environment: + type: string + description: '' + default: '' + required: + - apiKey + - environment diff --git a/pinterest.resource-type.yaml b/pinterest.resource-type.yaml new file mode 100644 index 0000000..05833c6 --- /dev/null +++ b/pinterest.resource-type.yaml @@ -0,0 +1,11 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + required: + - token diff --git a/pipedrive.resource-type.yaml b/pipedrive.resource-type.yaml new file mode 100644 index 0000000..39700da --- /dev/null +++ b/pipedrive.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiToken: + type: string + description: API token retrieved from the dashboard. + required: + - apiToken diff --git a/planetscale.resource-type.yaml b/planetscale.resource-type.yaml new file mode 100644 index 0000000..1cb3280 --- /dev/null +++ b/planetscale.resource-type.yaml @@ -0,0 +1,18 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + serviceToken: + type: string + description: The OAuth token to use for authentication + (https://api-docs.planetscale.com/reference/oauth) + serviceTokenId: + type: string + description: The OAuth token ID to use for authentication + (https://api-docs.planetscale.com/reference/oauth) + required: + - oauthTokenId + - oauthToken diff --git a/postgresql.resource-type.yaml b/postgresql.resource-type.yaml new file mode 100644 index 0000000..79a2aa6 --- /dev/null +++ b/postgresql.resource-type.yaml @@ -0,0 +1,41 @@ +description: PostgreSQL connection +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + dbname: + type: string + description: The database name + host: + type: string + description: The instance host + password: + type: string + description: The postgres users password + port: + type: integer + description: The instance port + root_certificate_pem: + type: string + description: The root certificate in pe format + default: '' + sslmode: + type: string + description: Most cloud databases (Heroku, AWS, Supabase, etc.) require SSL. + Self-hosted databases typically don't. + enum: + - disable + - allow + - prefer + - require + - verify-ca + - verify-full + user: + type: string + description: The postgres username + required: + - dbname + - user + - password diff --git a/pushover.resource-type.yaml b/pushover.resource-type.yaml new file mode 100644 index 0000000..3cca4a0 --- /dev/null +++ b/pushover.resource-type.yaml @@ -0,0 +1,24 @@ +description: Account info for pushover +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - token + - user + properties: + token: + type: string + description: '' + default: '' + user: + type: string + description: 'your user/group key (or that of your target user), viewable when + logged into our dashboard; often referred to as USER_KEY in our + documentation and code examples ' + default: '' + nullable: false + required: + - token + - user diff --git a/qovery.resource-type.yaml b/qovery.resource-type.yaml new file mode 100644 index 0000000..97c6468 --- /dev/null +++ b/qovery.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft-07/schema# + type: object + properties: + apiKey: + type: string + description: API key for authentication + required: + - apiKey diff --git a/quickbooks.resource-type.yaml b/quickbooks.resource-type.yaml new file mode 100644 index 0000000..7dc1a9b --- /dev/null +++ b/quickbooks.resource-type.yaml @@ -0,0 +1,25 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - token + - realmId + - isSandBox + properties: + isSandBox: + type: boolean + description: Flag indicating whether the environment is a sandbox + realmId: + type: string + description: The realm ID + token: + type: string + description: The access token for authentication + default: '' + required: + - token + - realmId + - isSandBox diff --git a/readme.resource-type.yaml b/readme.resource-type.yaml new file mode 100644 index 0000000..3f51888 --- /dev/null +++ b/readme.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft-07/schema# + type: object + properties: + apiKey: + type: string + description: API key retrieved from the dashboard. + required: + - apiKey diff --git a/recraft.resource-type.yaml b/recraft.resource-type.yaml new file mode 100644 index 0000000..be72cc7 --- /dev/null +++ b/recraft.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: API key retrieved from the dashboard. + required: + - apiKey diff --git a/reddit.resource-type.yaml b/reddit.resource-type.yaml new file mode 100644 index 0000000..ae9218c --- /dev/null +++ b/reddit.resource-type.yaml @@ -0,0 +1,27 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + clientId: + type: string + description: The client ID for the Reddit app + clientSecret: + type: string + description: The client secret for the Reddit app + password: + type: string + description: The password for the Reddit account. + userAgent: + type: string + description: The user agent to use for the Reddit API requests. + username: + type: string + description: The username for the Reddit account. + required: + - clientId + - clientSecret + - username + - password diff --git a/render.resource-type.yaml b/render.resource-type.yaml new file mode 100644 index 0000000..be72cc7 --- /dev/null +++ b/render.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: API key retrieved from the dashboard. + required: + - apiKey diff --git a/replicate.resource-type.yaml b/replicate.resource-type.yaml new file mode 100644 index 0000000..848630e --- /dev/null +++ b/replicate.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: API Token retrieved from the dashboard. + required: + - token diff --git a/resend.resource-type.yaml b/resend.resource-type.yaml new file mode 100644 index 0000000..1b46413 --- /dev/null +++ b/resend.resource-type.yaml @@ -0,0 +1,13 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: '' + default: '' + required: + - token diff --git a/rss.resource-type.yaml b/rss.resource-type.yaml new file mode 100644 index 0000000..dbfa573 --- /dev/null +++ b/rss.resource-type.yaml @@ -0,0 +1,14 @@ +description: RSS 2.0 / Atom Feed +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + url: + type: string + description: Feed URL + default: '' + format: uri + required: + - url diff --git a/rt.d.ts b/rt.d.ts new file mode 100644 index 0000000..e85ab57 --- /dev/null +++ b/rt.d.ts @@ -0,0 +1,1271 @@ +declare namespace RT { + type Ably = { + apiKye: string + } + + type Abstractapi = { + apiKey: string + } + + type Accelo = { + clientId: string, + deployment: string, + clientSecret: string + } + + type Actimo = { + apiKey: string + } + + type Acumbamail = { + authToken: string + } + + type Adhook = { + token: string + } + + type Adrapid = { + apiToken: string + } + + type AeroWorkflow = { + apiKey: string + } + + type AgentInstructions = any + + type Ai21 = { + apiKey: string + } + + type Airtable = { + apiKey: string + } + + type AirtableTable = { + baseId: string, + tableName: string + } + + type AnsibleInventory = { + content: string + } + + type Anthropic = { + apiKey: string, + base_url: string, + platform: string, + enable_1M_context: boolean + } + + type Apify = { + token: string + } + + type ApifyApiKey = { + api_key: string + } + + type ApifyWebhookConfig = { + url: string, + token: string + } + + type ApiKeyAuth = { + api_key_header: string, + api_key_secret: string + } + + type Apollo = { + apiKey: string + } + + type Appwrite = { + key: string, + project: string, + endpoint: string, + self_signed: boolean + } + + type ArcgisAccount = { + password: string, + username: string + } + + type Asana = { + token: string + } + + type Assemblyai = { + apiKey: string + } + + type Attio = { + token: string + } + + type Aws = { + region: string, + awsAccessKeyId: string, + awsSecretAccessKey: string + } + + type AwsBedrock = { + apiKey: string, + region: string, + awsAccessKeyId: string, + awsSessionToken: string, + awsSecretAccessKey: string + } + + type AwsOidc = { + region: string, + roleArn: string + } + + type Azure = { + azureClientId: string, + azureTenantId: string, + azureClientSecret: string + } + + type AzureBlob = { + useSSL: boolean, + endpoint: string, + accessKey: string, + accountName: string, + containerName: string + } + + type AzureOauth = { + token: string + } + + type AzureOpenai = { + apiKey: string, + baseUrl: string + } + + type AzureWorkloadIdentity = { + useSSL: boolean, + accountName: string, + containerName: string + } + + type BambooHr = { + apiKey: string, + companyDomain: string + } + + type Baremetrics = { + apiKey: string + } + + type Baserow = { + token: string, + base_url: string + } + + type BaserowTable = { + table_id: number, + database_id: number + } + + type BasicHttpAuth = { + password: string, + username: string + } + + type BasisTheory = { + apiKey: string + } + + type Beamer = { + apiKey: string + } + + type Bigquery = { + type: string, + auth_uri: string, + client_id: string, + token_uri: string, + project_id: string, + private_key: string, + client_email: string, + private_key_id: string, + client_x509_cert_url: string, + auth_provider_x509_cert_url: string + } + + type Bitbucket = { + password: string, + username: string + } + + type Bitly = { + token: string + } + + type Bluesky = { + password: string, + username: string + } + + type Botify = { + token: string + } + + type Box = { + token: string + } + + type Brevo = { + apiKey: string + } + + type Brex = { + token: string + } + + type Buttondown = { + token: string + } + + type Cacertificate = { + certificate: string + } + + type Calendly = { + token: string + } + + type Campayn = { + apiKey: string + } + + type Certopus = { + apiKey: string + } + + type Chromadb = { + ssl: boolean, + host: string, + port: number, + tenant: string, + database: string + } + + type Circleci = { + token: string + } + + type Clerk = { + apiKey: string + } + + type Clickhouse = { + host: string, + password: string, + username: string + } + + type Clickup = { + token: string + } + + type Cloudflare = { + key: string, + email: string, + token: string + } + + type Cockroachdb = { + token: string + } + + type Codat = { + encodedKey: string + } + + type Cohere = { + apiKey: string + } + + type ComapeoServer = { + server_url: string, + access_token: string + } + + type Confluence = { + email: string, + baseUrl: string, + apiToken: string + } + + type Contentful = { + spaceId: string, + accessToken: string, + environment: string + } + + type Contiguity = { + token: string + } + + type Convertkit = { + apiSecret: string + } + + type Currencyapi = { + apiKey: string + } + + type Customai = { + api_key: string, + headers: any, + base_url: string + } + + type Datadog = { + apiKey: string, + appKey: string, + apiBase: string + } + + type Datocms = { + apiKey: string + } + + type Deel = { + apiKey: string + } + + type DeepInfra = { + token: string + } + + type Deepl = { + apiKey: string, + baseUrl: string + } + + type Deepseek = { + api_key: string, + base_url: string + } + + type Digitalocean = { + token: string + } + + type DiscordBotConfiguration = { + public_key: string, + application_id: string + } + + type DiscordWebhook = { + webhook_url: string + } + + type Discourse = { + apiKey: string, + apiUsername: string, + defaultHost: string + } + + type Docspring = { + tokenId: string, + tokenSecret: string + } + + type Dust = { + apiKey: string, + workspaceId: string + } + + type Dynatrace = { + accessToken: string, + environmentId: string, + environmentUrl: string + } + + type Edgedb = { + dsn: string, + host: string, + port: number, + user: string, + database: string, + password: string, + secretKey: string, + instanceName: string + } + + type Enode = { + token: string + } + + type Exa = { + apiKey: string + } + + type Faunadb = { + region: string, + secret: string + } + + type Figma = { + token: string + } + + type Firebase = { + appId: string, + apiKey: string, + projectId: string, + authDomain: string, + measurementId: string, + storageBucket: string, + messagingSenderId: string + } + + type Fly = { + token: string + } + + type Formstack = { + token: string + } + + type Foxentry = { + apiKey: string + } + + type Freshdesk = { + apiKey: string, + baseUrl: string + } + + type Funkwhale = { + token: string, + baseUrl: string + } + + type Gcal = { + token: string + } + + type Gcloud = { + type: string, + auth_uri: string, + client_id: string, + token_uri: string, + project_id: string, + private_key: string, + client_email: string, + private_key_id: string, + client_x509_cert_url: string, + auth_provider_x509_cert_url: string + } + + type GcloudStorage = { + bucket: string, + serviceAccountKey: any + } + + type GcpServiceAccount = { + type: string, + auth_uri: string, + client_id: string, + token_uri: string, + project_id: string, + private_key: string, + client_email: string, + private_key_id: string, + client_x509_cert_url: string, + auth_provider_x509_cert_url: string + } + + type Gdocs = { + token: string + } + + type Gdrive = { + token: string + } + + type Gforms = { + token: string + } + + type Gfw = { + api_key: string + } + + type Ghostcms = { + apiKey: string, + apiUrl: string + } + + type Gitbook = { + token: string + } + + type Github = { + token: string + } + + type Gitlab = { + token: string, + baseUrl: string + } + + type GitRepository = { + url: string, + branch: string, + folder: string, + gpg_key: any, + is_github_app: boolean + } + + type Gmail = { + token: string + } + + type Googleai = { + api_key: string, + base_url: string, + platform: string + } + + type Gorgias = { + apiKey: string, + domain: string, + username: string + } + + type GpgKey = { + email: string, + passphrase: string, + private_key: string + } + + type Graphql = { + base_url: string, + bearer_token: string, + custom_headers: any + } + + type Greip = { + apiKey: string + } + + type Grist = { + host: string, + apiKey: string + } + + type Groq = { + api_key: string, + base_url: string + } + + type Groqai = { + api_key: string + } + + type Gsheets = { + token: string + } + + type Gworkspace = { + token: string + } + + type Holded = { + apiKey: string + } + + type Hubspot = { + token: string + } + + type IfsCloudOidc = { + server: string, + clientId: string, + oidcPath: string, + clientSecret: string + } + + type Imap = { + host: string, + port: number, + user: string, + mailbox: string, + password: string + } + + type Intercom = { + token: string, + apiVersion: string + } + + type Ipinfo = { + token: string + } + + type Jira = { + domain: string, + password: string, + username: string + } + + type Jotform = { + apiKey: string, + baseUrl: string + } + + type JsonSchema = { + schema: any + } + + type Kafka = { + brokers: string[], + security: any + } + + type Klaviyo = { + apiKey: string + } + + type Kobotoolbox = { + api_key: string, + server_url: string + } + + type Kustomer = { + apiKey: string + } + + type Langfuse = { + base_url: string, + public_key: string, + secret_key: string + } + + type Ldap = { + server: string, + use_ssl: boolean, + bind_user: string, + ssl_validate: boolean, + bind_password: string + } + + type Leonardoai = { + apiKey: string + } + + type Linear = { + apiKey: string + } + + type Linkding = { + token: string, + baseUrl: string + } + + type Linkedin = { + token: string + } + + type Linode = { + token: string + } + + type Localcontexts = { + api_key: string, + project_id: string, + server_url: string + } + + type Lumaai = { + apiKey: string + } + + type Magento = { + accessToken: string, + consumerKey: string, + consumerSecret: string, + accessTokenSecret: string + } + + type Mailchimp = { + server: string, + api_key: string + } + + type Mailerlite = { + apiToken: string + } + + type Mailgun = { + api_key: string + } + + type Mapbox = { + username: string, + access_token: string + } + + type Mastodon = { + token: string, + baseUrl: string + } + + type Matrix = { + token: string, + baseUrl: string + } + + type Matteroom = { + base_url: string, + password: string, + username: string + } + + type Mcp = { + url: string, + name: string, + token: string, + headers: any + } + + type Meteosource = { + tier: string, + apiKey: string + } + + type Mezmo = { + apiKey: string + } + + type Miro = { + token: string + } + + type Mistral = { + apiKey: string, + base_url: string + } + + type Mollie = { + token: string + } + + type Mongodb = { + db: string, + tls: boolean, + servers: any, + credential: any + } + + type MongodbRest = { + api_key: string, + endpoint: string + } + + type Motimate = { + token: string + } + + type Mqtt = { + tls: { + enabled: boolean, + ca_certificate: string, + pkcs12_client_certificate: string, + pkcs12_certificate_password: string + }, + port: number, + broker: string, + credentials: { + password: string, + username: string + } + } + + type MsSqlServer = { + host: string, + port: number, + user: string, + dbname: string, + ca_cert: string, + encrypt: boolean, + password: string, + aad_token: any, + trust_cert: boolean, + instance_name: string, + integrated_auth: boolean + } + + type MsTeamsWebhook = { + webhook_url: string + } + + type Mysql = { + ssl: boolean, + host: string, + port: number, + user: string, + database: string, + password: string, + root_certificate_pem: string + } + + type Nats = { + auth: any, + servers: string[], + require_tls: boolean + } + + type Neondb = { + apiKey: string + } + + type Netbox = { + url: string, + token: string + } + + type Netlify = { + token: string + } + + type Newsapi = { + apiKey: string + } + + type Nextcloud = { + token: string, + userId: string, + baseUrl: string, + password: string, + username: string + } + + type Nocodb = { + table: string, + apiUrl: string, + xc_token: string, + workspace: string + } + + type Notion = { + token: string + } + + type OauthClientCredentials = { + domain: string, + client_id: string, + client_secret: string + } + + type Odk = { + base_url: string, + password: string, + username: string, + default_project_id: number + } + + type Openai = { + api_key: string, + base_url: string, + organization_id: string + } + + type Openrouter = { + api_key: string, + base_url: string + } + + type Oracledb = { + user: string, + database: string, + password: string + } + + type Pandadoc = { + apiKey: string + } + + type Paychex = { + client_id: string, + client_secret: string + } + + type Paylocity = { + token: string + } + + type Paypal = { + clientId: string, + clientSecret: string + } + + type Persona = { + apiKey: string + } + + type Personio = { + clientId: string, + clientSecret: string + } + + type Phrase = { + token: string, + baseUrl: string + } + + type Pinecone = { + apiKey: string, + environment: string + } + + type Pinterest = { + token: string + } + + type Pipedrive = { + apiToken: string + } + + type Planetscale = { + serviceToken: string, + serviceTokenId: string + } + + type Postgresql = { + host: string, + port: number, + user: string, + dbname: string, + sslmode: string, + password: string, + root_certificate_pem: string + } + + type Pushover = { + user: string, + token: string + } + + type Qovery = { + apiKey: string + } + + type Quickbooks = { + token: string, + realmId: string, + isSandBox: boolean + } + + type Readme = { + apiKey: string + } + + type Recraft = { + apiKey: string + } + + type Reddit = { + clientId: string, + password: string, + username: string, + userAgent: string, + clientSecret: string + } + + type Render = { + apiKey: string + } + + type Replicate = { + token: string + } + + type Resend = { + token: string + } + + type Rss = { + url: string + } + + type S3 = { + port: number, + bucket: string, + region: string, + useSSL: boolean, + endPoint: string, + accessKey: string, + pathStyle: boolean, + secretKey: string + } + + type S3AwsOidc = { + bucket: string, + region: string, + roleArn: string + } + + type SageIntacct = { + token: string + } + + type Salesflare = { + apiKey: string + } + + type Segment = { + token: string, + baseUrl: string + } + + type Sendgrid = { + token: string + } + + type Sensortower = { + base_url: string, + auth_token: string + } + + type Sentry = { + token: string, + region: string, + organizationSlug: string + } + + type Shopify = { + token: string, + store_name: string + } + + type Shutterstock = { + token: string + } + + type SignatureAuth = { + secret_key: string, + signature_provider: string, + authentication_config: { + encoding: string, + algorithm: string, + signature_prefix: string, + signature_header_name: string + } + } + + type Signoz = { + apiKey: string, + baseUrl: string + } + + type Slack = { + token: string + } + + type Smartsheet = { + token: string, + baseUrl: string + } + + type Smtp = { + host: string, + port: number, + user: string, + password: string + } + + type Snowflake = { + role: string, + schema: string, + database: string, + username: string, + warehouse: string, + public_key: string, + private_key: string, + account_identifier: string + } + + type Speechify = { + token: string + } + + type Spotify = { + token: string + } + + type Square = { + token: string + } + + type Stripe = { + token: string + } + + type Supabase = { + key: string, + url: string + } + + type Surrealdb = { + url: string, + token: string + } + + type Taskade = { + token: string + } + + type Telegram = { + token: string + } + + type Telnyx = { + apiKey: string + } + + type Terra = { + devId: string, + apiKey: string + } + + type TheirStack = { + apiKey: string + } + + type Todoist = { + token: string + } + + type Togetherai = { + api_key: string, + base_url: string + } + + type Toggl = { + token: string + } + + type Tomorrow = { + apiKey: string + } + + type Trello = { + key: string, + token: string + } + + type Tripadvisor = { + apiKey: string + } + + type Turso = { + apiToken: string + } + + type Twilio = { + token: string, + accountSid: string + } + + type TwilioMessageTemplate = { + auth_token: string, + recipients: string[], + account_sid: string, + content_sid: string, + origin_number: string, + message_service_sid: string + } + + type Typeform = { + token: string, + baseUrl: string + } + + type Ultravox = { + apiKey: string + } + + type Vectara = { + apiKey: string + } + + type Vercel = { + token: string + } + + type Visma = { + token: string + } + + type Weatherapi = { + apiKey: string + } + + type Webflow = { + token: string + } + + type Webscrapingai = { + apiKey: string + } + + type Woocommerce = { + url: string, + version: string, + consumerKey: string, + consumerSecret: string, + queryStringAuth: boolean + } + + type Xata = { + apiKey: string + } + + type Xero = { + token: string + } + + type Yelp = { + apiKey: string + } + + type Ynab = { + token: string + } + + type Zendesk = { + password: string, + username: string, + subdomain: string + } + + type Zixflow = { + apiKey: string + } + + type Zoho = { + token: string + } + + type Zoom = { + accountId: string, + oauthClientId: string, + oauthClientSecret: string, + webhookSecretToken: string + } + + type Zuplo = { + apiKey: string + } +} \ No newline at end of file diff --git a/s3.resource-type.yaml b/s3.resource-type.yaml new file mode 100644 index 0000000..9432db8 --- /dev/null +++ b/s3.resource-type.yaml @@ -0,0 +1,52 @@ +description: An s3 bucket connection info +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - endPoint + - region + - pathStyle + - bucket + - accessKey + - secretKey + - port + - useSSL + properties: + accessKey: + type: string + description: '' + default: '' + bucket: + type: string + description: '' + default: '' + endPoint: + type: string + description: The full URL of the S3 endpoint (e.g. https://s3.us-east-1.amazonaws.com) + default: '' + pathStyle: + type: boolean + description: // instead of ./ + default: true + port: + type: number + description: 'Deprecated: pass in a complete URL to `endPoint` instead, + including a port number if needed' + region: + type: string + description: AWS region (e.g. us-east-1). Used to auto-generate the S3 endpoint + URL when endPoint is not specified + default: '' + secretKey: + type: string + description: '' + default: '' + useSSL: + type: boolean + description: "Deprecated: pass in a complete URL to `endPoint` instead, + including 'https://' or 'http://'" + default: true + required: + - bucket diff --git a/s3_aws_oidc.resource-type.yaml b/s3_aws_oidc.resource-type.yaml new file mode 100644 index 0000000..4f34cd7 --- /dev/null +++ b/s3_aws_oidc.resource-type.yaml @@ -0,0 +1,28 @@ +description: The configuration to use s3 with the oidc integration + https://www.windmill.dev/docs/core_concepts/oidc#use-oidc-with-aws +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - bucket + - roleArn + - region + properties: + bucket: + type: string + description: '' + default: '' + region: + type: string + description: '' + default: '' + roleArn: + type: string + description: '' + default: '' + required: + - bucket + - region + - roleArn diff --git a/sage_intacct.resource-type.yaml b/sage_intacct.resource-type.yaml new file mode 100644 index 0000000..fe8f823 --- /dev/null +++ b/sage_intacct.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: Access token retrieved from the OAuth flow. + required: + - token diff --git a/salesflare.resource-type.yaml b/salesflare.resource-type.yaml new file mode 100644 index 0000000..be72cc7 --- /dev/null +++ b/salesflare.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: API key retrieved from the dashboard. + required: + - apiKey diff --git a/segment.resource-type.yaml b/segment.resource-type.yaml new file mode 100644 index 0000000..faa0416 --- /dev/null +++ b/segment.resource-type.yaml @@ -0,0 +1,17 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + baseUrl: + type: string + description: https://api.segmentapis.com for US workspace and + https://eu1.api.segmentapis.com for EU workspace. + token: + type: string + description: Access token generated using the OAuth flow. + required: + - token + - baseUrl diff --git a/sendgrid.resource-type.yaml b/sendgrid.resource-type.yaml new file mode 100644 index 0000000..1104aa7 --- /dev/null +++ b/sendgrid.resource-type.yaml @@ -0,0 +1,13 @@ +description: The Sendgrid API token +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: API token + default: '' + required: + - token diff --git a/sensortower.resource-type.yaml b/sensortower.resource-type.yaml new file mode 100644 index 0000000..b2c9872 --- /dev/null +++ b/sensortower.resource-type.yaml @@ -0,0 +1,23 @@ +description: SensorTower offers insights into mobile applications, and also + accessible through an API. +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - base_url + - auth_token + properties: + auth_token: + type: string + description: API authentication token + default: '' + password: true + base_url: + type: string + description: Endpoint of the API server + default: https://api.sensortower.com + nullable: false + required: + - base_url diff --git a/sentry.resource-type.yaml b/sentry.resource-type.yaml new file mode 100644 index 0000000..d26bab7 --- /dev/null +++ b/sentry.resource-type.yaml @@ -0,0 +1,23 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft-07/schema# + type: object + properties: + organizationSlug: + type: string + description: Organization slug + region: + type: string + description: The data-storage-location for an organization + default: us + enum: + - us + - de + token: + type: string + description: Auth token + required: + - region + - token diff --git a/shopify.resource-type.yaml b/shopify.resource-type.yaml new file mode 100644 index 0000000..4e0d181 --- /dev/null +++ b/shopify.resource-type.yaml @@ -0,0 +1,18 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + store_name: + type: string + description: '' + default: '' + token: + type: string + description: '' + default: '' + required: + - store_name + - token diff --git a/shutterstock.resource-type.yaml b/shutterstock.resource-type.yaml new file mode 100644 index 0000000..f5f998f --- /dev/null +++ b/shutterstock.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: Access token retrieved from the application details page. + required: + - token diff --git a/signature_auth.resource-type.yaml b/signature_auth.resource-type.yaml new file mode 100644 index 0000000..3f18b0e --- /dev/null +++ b/signature_auth.resource-type.yaml @@ -0,0 +1,78 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - signature_provider + - secret_key + - authentication_config + properties: + authentication_config: + type: object + description: '' + format: '' + order: + - signature_header_name + - algorithm + - encoding + - signature_prefix + properties: + algorithm: + type: string + description: '' + default: sha256 + disableCreate: true + enum: + - sha1 + - sha256 + - sha512 + enumLabels: {} + nullable: false + encoding: + type: string + description: '' + default: hex + disableCreate: true + enum: + - hex + - base64 + - base64uri + enumLabels: {} + nullable: false + signature_header_name: + type: string + description: '' + default: '' + nullable: false + signature_prefix: + type: string + description: '' + default: '' + required: + - signature_header_name + - algorithm + - encoding + showExpr: fields.signature_provider === 'Custom' + secret_key: + type: string + default: '' + signature_provider: + type: string + description: '' + default: Custom + disableCreate: true + enum: + - Github + - Slack + - Stripe + - TikTok + - Twitch + - Zoom + - Custom + enumLabels: {} + nullable: false + required: + - signature_provider + - secret_key diff --git a/signoz.resource-type.yaml b/signoz.resource-type.yaml new file mode 100644 index 0000000..abd3164 --- /dev/null +++ b/signoz.resource-type.yaml @@ -0,0 +1,16 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: API key retrieved from the dashboard. + baseUrl: + type: string + description: Base URL for the Signoz API - signoz.io for Cloud Hosted version. + required: + - apiKey + - baseUrl diff --git a/slack.resource-type.yaml b/slack.resource-type.yaml new file mode 100644 index 0000000..d594da9 --- /dev/null +++ b/slack.resource-type.yaml @@ -0,0 +1,11 @@ +description: Slack token +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: The slack token + required: [] diff --git a/smartsheet.resource-type.yaml b/smartsheet.resource-type.yaml new file mode 100644 index 0000000..752b04c --- /dev/null +++ b/smartsheet.resource-type.yaml @@ -0,0 +1,16 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + baseUrl: + type: string + description: BaseURL of the API. + token: + type: string + description: Token retrieved from the dashboard. + required: + - token + - baseUrl diff --git a/smtp.resource-type.yaml b/smtp.resource-type.yaml new file mode 100644 index 0000000..31a7c0d --- /dev/null +++ b/smtp.resource-type.yaml @@ -0,0 +1,23 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + host: + type: string + description: SMTP host address + default: mail.smtpbucket.com + password: + type: string + description: '' + port: + type: integer + description: port number on which to connect + default: 8025 + user: + type: string + description: '' + required: + - host diff --git a/snowflake.resource-type.yaml b/snowflake.resource-type.yaml new file mode 100644 index 0000000..d7966b1 --- /dev/null +++ b/snowflake.resource-type.yaml @@ -0,0 +1,50 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + account_identifier: + type: string + description: - + default: '' + database: + type: string + description: '' + default: '' + private_key: + type: string + description: |- + -----BEGIN PRIVATE KEY----- + .... + -----END PRIVATE KEY----- + default: '' + public_key: + type: string + description: |- + -----BEGIN PUBLIC KEY----- + .... + -----END PUBLIC KEY----- + default: '' + role: + type: string + description: '' + default: '' + schema: + type: string + description: '' + default: '' + username: + type: string + description: '' + default: '' + warehouse: + type: string + description: '' + default: '' + required: + - account_identifier + - private_key + - public_key + - username diff --git a/speechify.resource-type.yaml b/speechify.resource-type.yaml new file mode 100644 index 0000000..24a58d9 --- /dev/null +++ b/speechify.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: Speechify API key + required: + - token diff --git a/spotify.resource-type.yaml b/spotify.resource-type.yaml new file mode 100644 index 0000000..cefb044 --- /dev/null +++ b/spotify.resource-type.yaml @@ -0,0 +1,15 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - token + properties: + token: + type: string + description: '' + default: '' + required: + - token diff --git a/square.resource-type.yaml b/square.resource-type.yaml new file mode 100644 index 0000000..f0a221a --- /dev/null +++ b/square.resource-type.yaml @@ -0,0 +1,13 @@ +description: Square OAuth token +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: Either of personal access token or oauth access token. + default: '' + required: + - token diff --git a/stripe.resource-type.yaml b/stripe.resource-type.yaml new file mode 100644 index 0000000..0856af9 --- /dev/null +++ b/stripe.resource-type.yaml @@ -0,0 +1,11 @@ +description: Stripe api key +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: '' + required: [] diff --git a/supabase.resource-type.yaml b/supabase.resource-type.yaml new file mode 100644 index 0000000..091c165 --- /dev/null +++ b/supabase.resource-type.yaml @@ -0,0 +1,19 @@ +description: Supabase API credentials for a project. Retrieve the info in + "Project Settings -> API" +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + key: + type: string + description: The unique Supabase Key which is supplied when you create a new + project in your project dashboard. + default: '' + url: + type: string + description: The unique Supabase URL which is supplied when you create a new + project in your project dashboard. + default: '' + required: [] diff --git a/surrealdb.resource-type.yaml b/surrealdb.resource-type.yaml new file mode 100644 index 0000000..b50f327 --- /dev/null +++ b/surrealdb.resource-type.yaml @@ -0,0 +1,18 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: Authentication token + default: '' + url: + type: string + description: The endpoint of the database you want to connect to. + default: '' + required: + - url + - token diff --git a/taskade.resource-type.yaml b/taskade.resource-type.yaml new file mode 100644 index 0000000..05833c6 --- /dev/null +++ b/taskade.resource-type.yaml @@ -0,0 +1,11 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + required: + - token diff --git a/telegram.resource-type.yaml b/telegram.resource-type.yaml new file mode 100644 index 0000000..751a396 --- /dev/null +++ b/telegram.resource-type.yaml @@ -0,0 +1,12 @@ +description: Telegram resource type for the Bot API. +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: Bot API token + default: '' + required: [] diff --git a/telnyx.resource-type.yaml b/telnyx.resource-type.yaml new file mode 100644 index 0000000..7a2e69e --- /dev/null +++ b/telnyx.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: API key generate from the account settings on dashboard. + required: + - apiKey diff --git a/terra.resource-type.yaml b/terra.resource-type.yaml new file mode 100644 index 0000000..cae374f --- /dev/null +++ b/terra.resource-type.yaml @@ -0,0 +1,16 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft-07/schema# + type: object + properties: + apiKey: + type: string + description: API key from the dashboard + devId: + type: string + description: Developer ID from the dashboard + required: + - apiKey + - devId diff --git a/their_stack.resource-type.yaml b/their_stack.resource-type.yaml new file mode 100644 index 0000000..26427cf --- /dev/null +++ b/their_stack.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: API key retrieved from the dashboard + required: + - apiKey diff --git a/todoist.resource-type.yaml b/todoist.resource-type.yaml new file mode 100644 index 0000000..cf97ab6 --- /dev/null +++ b/todoist.resource-type.yaml @@ -0,0 +1,11 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: http://json-schema.org/draft-04/schema# + type: object + properties: + token: + type: string + required: + - token diff --git a/togetherai.resource-type.yaml b/togetherai.resource-type.yaml new file mode 100644 index 0000000..7229c0a --- /dev/null +++ b/togetherai.resource-type.yaml @@ -0,0 +1,22 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - api_key + - base_url + properties: + api_key: + type: string + description: API key retrieved from the dashboard. + default: '' + nullable: false + password: true + base_url: + type: string + description: Optional. Only needed to overwrite the default base URL. + default: '' + required: + - api_key diff --git a/toggl.resource-type.yaml b/toggl.resource-type.yaml new file mode 100644 index 0000000..cad7b21 --- /dev/null +++ b/toggl.resource-type.yaml @@ -0,0 +1,12 @@ +description: Toggle Track API Token +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: '' + required: + - token diff --git a/tomorrow.resource-type.yaml b/tomorrow.resource-type.yaml new file mode 100644 index 0000000..be72cc7 --- /dev/null +++ b/tomorrow.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: API key retrieved from the dashboard. + required: + - apiKey diff --git a/trello.resource-type.yaml b/trello.resource-type.yaml new file mode 100644 index 0000000..e335cc4 --- /dev/null +++ b/trello.resource-type.yaml @@ -0,0 +1,18 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + key: + type: string + description: '' + default: '' + token: + type: string + description: '' + default: '' + required: + - key + - token diff --git a/tripadvisor.resource-type.yaml b/tripadvisor.resource-type.yaml new file mode 100644 index 0000000..8c70c9c --- /dev/null +++ b/tripadvisor.resource-type.yaml @@ -0,0 +1,11 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + required: + - apiKey diff --git a/turso.resource-type.yaml b/turso.resource-type.yaml new file mode 100644 index 0000000..70d94e2 --- /dev/null +++ b/turso.resource-type.yaml @@ -0,0 +1,16 @@ +description: >- + 1. On the dashboard, click the avatar/initials in the top-right corner to open + up a dropdown and select `Platform API Tokens`. + + 2. Create a new API token, copy it. +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiToken: + type: string + description: API token obtained from the Turso dashboard. + required: + - apiToken diff --git a/twilio.resource-type.yaml b/twilio.resource-type.yaml new file mode 100644 index 0000000..e59b45d --- /dev/null +++ b/twilio.resource-type.yaml @@ -0,0 +1,18 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + accountSid: + type: string + description: '' + default: '' + token: + type: string + description: '' + default: '' + required: + - token + - accountSid diff --git a/twilio_message_template.resource-type.yaml b/twilio_message_template.resource-type.yaml new file mode 100644 index 0000000..8f451a2 --- /dev/null +++ b/twilio_message_template.resource-type.yaml @@ -0,0 +1,59 @@ +description: A Twilio resource type for sending messages to a number of + recipients via the Message Service. +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - account_sid + - auth_token + - message_service_sid + - content_sid + - origin_number + - recipients + properties: + account_sid: + type: string + description: The 34 letter SID used to represent a Twilio resource. + default: '' + nullable: false + pattern: ^.{34}$ + auth_token: + type: string + description: The token used to authenticate Twilio API requests + default: '' + nullable: false + content_sid: + type: string + description: The SID for the message content template. + default: '' + nullable: false + message_service_sid: + type: string + description: The SID for a messaging service, which is a container that bundle + messaging functionality for your specific use cases (such as WhatsApp). + It can be found in the Messaging Services menu; each service has their + own SID. By including it, you can retrieve usage statistics for the + service. + default: '' + origin_number: + type: string + description: 'The phone number from which messages will originate. This number + must be initially approved and authenticated in the Twilio UI before it + can be activated and used. If you are sending via a WhatsApp number, + prefix your phone number with whatsapp:' + default: '' + nullable: false + recipients: + type: array + description: 'The list of phone numbers to which alerts will be sent. If you are + sending to WhatsApp numbers, prefix your phone numbers with whatsapp:' + default: [] + items: + type: string + required: + - account_sid + - auth_token + - content_sid + - origin_number diff --git a/typeform.resource-type.yaml b/typeform.resource-type.yaml new file mode 100644 index 0000000..7a77d34 --- /dev/null +++ b/typeform.resource-type.yaml @@ -0,0 +1,21 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - token + - baseUrl + properties: + baseUrl: + type: string + description: '' + default: https://api.typeform.com + token: + type: string + description: '' + default: '' + required: + - token + - baseUrl diff --git a/ultravox.resource-type.yaml b/ultravox.resource-type.yaml new file mode 100644 index 0000000..be72cc7 --- /dev/null +++ b/ultravox.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: API key retrieved from the dashboard. + required: + - apiKey diff --git a/vectara.resource-type.yaml b/vectara.resource-type.yaml new file mode 100644 index 0000000..8c70c9c --- /dev/null +++ b/vectara.resource-type.yaml @@ -0,0 +1,11 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + required: + - apiKey diff --git a/vercel.resource-type.yaml b/vercel.resource-type.yaml new file mode 100644 index 0000000..05833c6 --- /dev/null +++ b/vercel.resource-type.yaml @@ -0,0 +1,11 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + required: + - token diff --git a/visma.resource-type.yaml b/visma.resource-type.yaml new file mode 100644 index 0000000..cefb044 --- /dev/null +++ b/visma.resource-type.yaml @@ -0,0 +1,15 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - token + properties: + token: + type: string + description: '' + default: '' + required: + - token diff --git a/weatherapi.resource-type.yaml b/weatherapi.resource-type.yaml new file mode 100644 index 0000000..8c70c9c --- /dev/null +++ b/weatherapi.resource-type.yaml @@ -0,0 +1,11 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + required: + - apiKey diff --git a/webflow.resource-type.yaml b/webflow.resource-type.yaml new file mode 100644 index 0000000..05833c6 --- /dev/null +++ b/webflow.resource-type.yaml @@ -0,0 +1,11 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + required: + - token diff --git a/webscrapingai.resource-type.yaml b/webscrapingai.resource-type.yaml new file mode 100644 index 0000000..8c70c9c --- /dev/null +++ b/webscrapingai.resource-type.yaml @@ -0,0 +1,11 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + required: + - apiKey diff --git a/wmill-lock.yaml b/wmill-lock.yaml new file mode 100644 index 0000000..811f644 --- /dev/null +++ b/wmill-lock.yaml @@ -0,0 +1,24 @@ +version: v2 +locks: + f/Backup/backup_restore_orchestrator__flow+__flow_hash: 6579d1cc5b707758f5c529c9c0b453405a99cfa90aa14dc5f9fdd4495005be10 + f/Backup/backup_restore_orchestrator__flow+aktive_datastores_aus_db_holen.my.sql: 7565dc4d025614f12cc4e54ca92a74d331d920dbd7b6ebee29d4ce3d5a5fe4dc + f/Backup/backup_restore_orchestrator__flow+alle_freien_restore-server_holen.py: 2e1b0c1cabe1a48ec69f1633c75aa381bf0484a0f06ec7720652bc4dd0a1c8bb + f/Backup/backup_restore_orchestrator__flow+alte_restore-ordner_auf_backup-server_loeschen.py: cc49da8a46103d3efb447cd6171212e95047311ebd350217034b8e87b65b8d09 + f/Backup/backup_restore_orchestrator__flow+ersten_restore_pro_server_starten.py: b809e5fafa560de53fcbd73fa18801f33920460e83d7affe572809e1cbc45974 + f/Backup/backup_restore_orchestrator__flow+job_initialisieren_&_backup-queue_aus_pbs_aufbauen.py: 31bbfac68741bf617a8ce3fe501e3cb3d74512db8bb7e72055f29e9e0af70be2 + f/Backup/backup_restore_orchestrator__flow+script_deployen_&_pbs-datastores_auf_allen_servern_registrieren.py: 72cd9c759e2716cb13a0df0f4867af6bbbde1dcd353f25cb2f3dd48d703cd7f1 + f/Backup/backup_restore_orchestrator__flow+ssh-credentials_fuer_alle_restore-server_aus_bitwarden.py: 231782a10f9e9379f3b11ca2df1db30eecbcc211618ec4cc58bf10b36fd7d870 + f/Backup/backup_restore_orchestrator__flow+webhook_verarbeiten_&_naechsten_restore_auf_demselben_server_starten.py: 086c41014a56f4aa24abe0233793614005646227e4564e7c310a2ca17331fe28 + f/Backup/backup_restore_report___nextcloud_talk__flow+__flow_hash: f3c1a6a92392d6a7217b07f74799698b6be048e4706f2114f905cdbcf336a176 + f/Backup/backup_restore_report___nextcloud_talk__flow+letzten_job_aus_db_holen_&_report_zusammenbauen.py: 10fce98d17bacb4c3314e50b9bbd321ce4a407ed27304f52f108088601f12ff5 + f/Backup/backup_restore_report___nextcloud_talk__flow+nachricht_an_nextcloud_talk_senden.py: eb69eafe6fc5e3012774e1c8ce37b00540c6662e9c7302f915f6562d3dae0c0a + f/Proxmox/proxmox_backup_webhook__flow+__flow_hash: 47428b1bccf563b4b976bf2c36410fc018e429711b5d0c2cf77829c26ffea5fa + f/Proxmox/proxmox_backup_webhook__flow+in_mysql_speichern.py: 6d2538c237800143595937eb64dcfdc1483e84a888e8c00dbd8820ae4aff95dc + f/Proxmox/proxmox_backup_webhook__flow+nachricht_an_nextcloud_talk.py: f2993562a0f827bc8720a49b3246d34f6a0135c0f28845e5495eed5514d2476c + f/Proxmox/proxmox_backup_webhook__flow+payload_parsen_&_aufbereiten.py: 563813669ff3fdef34311459bed488fbfd3725ce645ad70b483b4731c05f4e78 + f/Reporting/rdp_logins__flow+__flow_hash: 08fa7852bd83a57bb43363c7398c43dea022b8a5cdc639cc34456281459a6034 + f/Reporting/rdp_logins__flow+einzelnen_login-eintrag_einfügen.ts: 37bbfc68c31c7ebf6046b87c66a05996ef5ae38ad24dcb4de152879d969ab6f9 + f/Reporting/rdp_logins__flow+powershell_via_rport.io_ausführen.ts: fec88de017a5f9566e9cdbd7b4b49ff9c96447629ef211b51d047026aa051726 + f/Reporting/rdp_logins__flow+rds-server_mit_rport.io_clients_abgleichen.ts: dea12a10507f9dc7357d4ba06b306b921381bbab9a5ed7f95682e6e49787c224 + f/Server/Bitwarden_Data_Export__flow+__flow_hash: 72c83e1fd73a374808b1be09a46a286ecc4b4eee806141a2570fc1703942cbbc + f/Server/Bitwarden_Data_Export__flow+c.py: 90f7b8c407a4632f882bc1051c6b3827d97df336d787d2d1c3b4bcd5f0063db5 diff --git a/wmill.yaml b/wmill.yaml new file mode 100644 index 0000000..bdfcb95 --- /dev/null +++ b/wmill.yaml @@ -0,0 +1,151 @@ +# yaml-language-server: $schema=wmill.schema.json +# wmill.yaml — Windmill CLI configuration +# Full reference: run "wmill config" + +# Default TypeScript runtime for new scripts +defaultTs: bun + +# Glob patterns for files to include in sync +includes: + - "f/**" + +# Additional glob patterns merged with includes (useful in branch overrides) +# extraIncludes: [] + +# Glob patterns for files to exclude from sync +excludes: [] + +# --- What to sync ----------------------------------------------------- +# "skip" options default to false (synced), "include" options default to false (not synced) + +# Skip syncing variables +skipVariables: false + +# Skip syncing resources +skipResources: false + +# Skip syncing resource types +skipResourceTypes: false + +# Skip syncing secrets (true by default for security) +skipSecrets: true # true by default — secrets are not synced for security + +# Skip syncing scripts +skipScripts: false + +# Skip syncing flows +skipFlows: false + +# Skip syncing apps +skipApps: false + +# Skip syncing folders +skipFolders: false + +# Skip syncing workspace dependencies +skipWorkspaceDependencies: false + +# Uncomment to include these (excluded by default): +# Include schedules in sync +# includeSchedules: true + +# Include triggers (http, websocket, kafka, etc.) in sync +# includeTriggers: true + +# Include workspace users in sync +# includeUsers: true + +# Include workspace groups in sync +# includeGroups: true + +# Include workspace settings in sync +# includeSettings: true + +# Include encryption key in sync +# includeKey: true + +# --- Sync behavior ---------------------------------------------------- + +# Number of parallel operations during sync +# parallel: 4 + +# Require lock files for all scripts +# locksRequired: true + +# Run linting before push +# lint: true + +# Handle secrets as plain text (not recommended) +# plainSecrets: false + +# Default commit message for sync operations +# message: "my commit message" + +# Branch name to use promotion overrides from during sync +# promotion: staging + +# Skip validation that current git branch matches a configured branch +# skipBranchValidation: false + +# Use __flow/__app/__raw_app suffixes instead of .flow/.app/.raw_app +nonDottedPaths: true + +# --- Codebase bundling (shared libraries) ----------------------------- +# Bundle TypeScript/JavaScript codebases that scripts import from. +# Each entry is bundled and uploaded so scripts can import shared code. + +# Codebase bundling configurations for shared libraries +codebases: [] +# codebases: +# - relative_path: ./shared # path to the codebase +# includes: ["**/*.ts"] # files to include in bundle +# excludes: ["node_modules/**"] # files to exclude +# format: esm # bundle format: "cjs" or "esm" +# external: ["pg", "axios"] # dependencies to leave unbundled +# assets: # static files to copy into bundle +# - from: ./static +# to: ./dist +# # customBundler: ./build.ts # custom bundler script (replaces esbuild) +# # inject: ["./polyfills.ts"] # files to inject into every entry point +# # define: # compile-time constants +# # API_URL: '"https://api.example.com"' +# # banner: # text prepended to output files +# # js: "/* bundled by windmill */" +# # loader: # esbuild loader overrides +# # ".png": "dataurl" + +# --- Git branch / environment bindings -------------------------------- +# Map git branches to Windmill workspaces and override settings per branch. +# Use "environments" as an alias if you prefer environment-based terminology. + +# Map git branches to workspaces and per-branch sync overrides +gitBranches: + main: + overrides: {} + # baseUrl: https://app.windmill.dev # Windmill instance URL for this branch + # workspaceId: my-workspace # workspace to sync with + # promotionOverrides: # overrides applied during --promotion + # skipSecrets: false + # specificItems: # only sync these specific items + # variables: ["f/my_folder/my_var"] + # resources: ["f/my_folder/my_res"] + # triggers: ["f/my_folder/my_trigger"] + # folders: ["my_folder"] + # settings: true + + # Example: staging branch bound to a different workspace + # staging: + # baseUrl: https://staging.windmill.dev + # workspaceId: staging-workspace + # overrides: + # skipSecrets: false + # includeSchedules: true + + # Items shared across ALL branches + # commonSpecificItems: + # variables: ["f/shared/api_key"] + # resources: ["f/shared/db_conn"] + # folders: ["shared"] + +# Alias for gitBranches — use if you prefer environment-based terminology +# environments: {} diff --git a/woocommerce.resource-type.yaml b/woocommerce.resource-type.yaml new file mode 100644 index 0000000..6a57289 --- /dev/null +++ b/woocommerce.resource-type.yaml @@ -0,0 +1,35 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + order: + - url + - consumerKey + - consumerSecret + - version + - queryStringAuth + properties: + version: + type: string + description: The version of the WooCommerce API, default is v3 + default: wc/v3 + consumerKey: + type: string + description: The consumer key for WooCommerce API authentication + consumerSecret: + type: string + description: The consumer secret for WooCommerce API authentication + queryStringAuth: + type: boolean + description: When true and using under HTTPS, forces Basic Authentication as + query string, default is false + default: false + url: + type: string + description: Your Store URL + required: + - url + - consumerKey + - consumerSecret diff --git a/xata.resource-type.yaml b/xata.resource-type.yaml new file mode 100644 index 0000000..dedbe24 --- /dev/null +++ b/xata.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: API key generated from the account settings of Xata dashboard. + required: + - apiKey diff --git a/xero.resource-type.yaml b/xero.resource-type.yaml new file mode 100644 index 0000000..da858d6 --- /dev/null +++ b/xero.resource-type.yaml @@ -0,0 +1,12 @@ +description: 'Find the instructions to generate a token here: + https://developer.xero.com/documentation/sdks-and-tools/tools/postman' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + required: + - token diff --git a/yelp.resource-type.yaml b/yelp.resource-type.yaml new file mode 100644 index 0000000..be72cc7 --- /dev/null +++ b/yelp.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: API key retrieved from the dashboard. + required: + - apiKey diff --git a/ynab.resource-type.yaml b/ynab.resource-type.yaml new file mode 100644 index 0000000..05833c6 --- /dev/null +++ b/ynab.resource-type.yaml @@ -0,0 +1,11 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + required: + - token diff --git a/zendesk.resource-type.yaml b/zendesk.resource-type.yaml new file mode 100644 index 0000000..8b2c9c8 --- /dev/null +++ b/zendesk.resource-type.yaml @@ -0,0 +1,23 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + password: + type: string + description: password or api token + default: '' + subdomain: + type: string + description: '' + default: '' + username: + type: string + description: email or "{email}/token" if using an api token + default: '' + required: + - username + - subdomain + - password diff --git a/zixflow.resource-type.yaml b/zixflow.resource-type.yaml new file mode 100644 index 0000000..f7e6b1f --- /dev/null +++ b/zixflow.resource-type.yaml @@ -0,0 +1,15 @@ +description: |- + 1. Click on "account settings" at the bottom-left corner of the screen. + 2. Inside settings, open "developer", and create a new API key. + 3. Copy the API key +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: API Key generated inside the settings dashboard. + required: + - apiKey diff --git a/zoho.resource-type.yaml b/zoho.resource-type.yaml new file mode 100644 index 0000000..3a2ecaa --- /dev/null +++ b/zoho.resource-type.yaml @@ -0,0 +1,12 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + token: + type: string + description: Access token retrieved using the OAuth flow. + required: + - token diff --git a/zoom.resource-type.yaml b/zoom.resource-type.yaml new file mode 100644 index 0000000..8ce2f66 --- /dev/null +++ b/zoom.resource-type.yaml @@ -0,0 +1,19 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: http://json-schema.org/draft-04/schema# + type: object + properties: + accountId: + type: string + oauthClientId: + type: string + oauthClientSecret: + type: string + webhookSecretToken: + type: string + required: + - accountId + - oauthClientId + - oauthClientSecret diff --git a/zuplo.resource-type.yaml b/zuplo.resource-type.yaml new file mode 100644 index 0000000..bd5522a --- /dev/null +++ b/zuplo.resource-type.yaml @@ -0,0 +1,13 @@ +description: '' +format_extension: null +is_fileset: false +schema: + $schema: https://json-schema.org/draft/2020-12/schema + type: object + properties: + apiKey: + type: string + description: API key retrieved from settings inside the dropdown of logged-in + user avatar. + required: + - apiKey