diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 88adf46f..5811b63b 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -19,6 +19,7 @@ /plugins/Ivanti-ITSM/ @shawn149 /plugins/MetOffice/ @blackgrouse /plugins/Notion/ @clarkd +/plugins/OctopusDeploy/ @clarkd /plugins/Phare/ @vinbab /plugins/Postcoder/ @richbenwell /plugins/RDAP/ @richbenwell diff --git a/plugins/OctopusDeploy/v1/configValidation.json b/plugins/OctopusDeploy/v1/configValidation.json new file mode 100644 index 00000000..f5b0316a --- /dev/null +++ b/plugins/OctopusDeploy/v1/configValidation.json @@ -0,0 +1,25 @@ +{ + "steps": [ + { + "displayName": "Authenticate", + "dataStream": { + "name": "currentUser" + }, + "required": true, + "error": "Could not connect to Octopus Deploy. Check the server URL is reachable from SquaredUp and the API key is valid and has not expired.", + "success": "Connected to Octopus Deploy successfully." + }, + { + "displayName": "Check data access", + "dataStream": { + "name": "spaces", + "config": { + "errorOnEmptyResults": true + } + }, + "required": false, + "error": "Connected, but no spaces were returned. Check the user the API key belongs to is a member of a team with access to at least one space.", + "success": "Spaces are accessible." + } + ] +} diff --git a/plugins/OctopusDeploy/v1/correlationRules/relate-deployment-target-to-environment.json b/plugins/OctopusDeploy/v1/correlationRules/relate-deployment-target-to-environment.json new file mode 100644 index 00000000..8a768121 --- /dev/null +++ b/plugins/OctopusDeploy/v1/correlationRules/relate-deployment-target-to-environment.json @@ -0,0 +1,20 @@ +{ + "displayName": "Deployment Target belongs to Environment", + "source": { + "types": "Deployment Target" + }, + "target": { + "types": "Environment" + }, + "conditions": [ + { + "sourceProperty": "environmentIds", + "operator": "equals", + "targetProperty": "rawId" + } + ], + "labels": { + "forward": "in environment", + "reverse": "contains" + } +} diff --git a/plugins/OctopusDeploy/v1/correlationRules/relate-deployment-target-to-tenant.json b/plugins/OctopusDeploy/v1/correlationRules/relate-deployment-target-to-tenant.json new file mode 100644 index 00000000..2b76d763 --- /dev/null +++ b/plugins/OctopusDeploy/v1/correlationRules/relate-deployment-target-to-tenant.json @@ -0,0 +1,20 @@ +{ + "displayName": "Deployment Target serves Tenant", + "source": { + "types": "Deployment Target" + }, + "target": { + "types": "Tenant" + }, + "conditions": [ + { + "sourceProperty": "tenantIds", + "operator": "equals", + "targetProperty": "rawId" + } + ], + "labels": { + "forward": "serves tenant", + "reverse": "served by" + } +} diff --git a/plugins/OctopusDeploy/v1/correlationRules/relate-runbook-to-project.json b/plugins/OctopusDeploy/v1/correlationRules/relate-runbook-to-project.json new file mode 100644 index 00000000..94f4609e --- /dev/null +++ b/plugins/OctopusDeploy/v1/correlationRules/relate-runbook-to-project.json @@ -0,0 +1,20 @@ +{ + "displayName": "Runbook belongs to Project", + "source": { + "types": "Runbook" + }, + "target": { + "types": "Project" + }, + "conditions": [ + { + "sourceProperty": "projectId", + "operator": "equals", + "targetProperty": "rawId" + } + ], + "labels": { + "forward": "belongs to", + "reverse": "has runbook" + } +} diff --git a/plugins/OctopusDeploy/v1/correlationRules/relate-worker-to-worker-pool.json b/plugins/OctopusDeploy/v1/correlationRules/relate-worker-to-worker-pool.json new file mode 100644 index 00000000..c4fd2877 --- /dev/null +++ b/plugins/OctopusDeploy/v1/correlationRules/relate-worker-to-worker-pool.json @@ -0,0 +1,20 @@ +{ + "displayName": "Worker belongs to Worker Pool", + "source": { + "types": "Worker" + }, + "target": { + "types": "Worker Pool" + }, + "conditions": [ + { + "sourceProperty": "workerPoolIds", + "operator": "equals", + "targetProperty": "rawId" + } + ], + "labels": { + "forward": "member of", + "reverse": "has member" + } +} diff --git a/plugins/OctopusDeploy/v1/custom_types.json b/plugins/OctopusDeploy/v1/custom_types.json new file mode 100644 index 00000000..5aadcb54 --- /dev/null +++ b/plugins/OctopusDeploy/v1/custom_types.json @@ -0,0 +1,58 @@ +[ + { + "name": "Space", + "sourceType": "Space", + "icon": "cubes", + "singular": "Space", + "plural": "Spaces" + }, + { + "name": "Project", + "sourceType": "Project", + "icon": "diagram-project", + "singular": "Project", + "plural": "Projects" + }, + { + "name": "Environment", + "sourceType": "Environment", + "icon": "layer-group", + "singular": "Environment", + "plural": "Environments" + }, + { + "name": "Deployment Target", + "sourceType": "Deployment Target", + "icon": "server", + "singular": "Deployment Target", + "plural": "Deployment Targets" + }, + { + "name": "Tenant", + "sourceType": "Tenant", + "icon": "users", + "singular": "Tenant", + "plural": "Tenants" + }, + { + "name": "Runbook", + "sourceType": "Runbook", + "icon": "book", + "singular": "Runbook", + "plural": "Runbooks" + }, + { + "name": "Worker Pool", + "sourceType": "Worker Pool", + "icon": "people-group", + "singular": "Worker Pool", + "plural": "Worker Pools" + }, + { + "name": "Worker", + "sourceType": "Worker", + "icon": "gears", + "singular": "Worker", + "plural": "Workers" + } +] diff --git a/plugins/OctopusDeploy/v1/dataStreams/auditEvents.json b/plugins/OctopusDeploy/v1/dataStreams/auditEvents.json new file mode 100644 index 00000000..3066e8b2 --- /dev/null +++ b/plugins/OctopusDeploy/v1/dataStreams/auditEvents.json @@ -0,0 +1,176 @@ +{ + "name": "auditEvents", + "displayName": "Audit Events", + "description": "Octopus audit log of who changed or did what and when, such as deployments, configuration changes and logins", + "tags": [ + "Audit" + ], + "baseDataSourceName": "httpRequestScopedSingle", + "config": { + "httpMethod": "get", + "endpointPath": "api/{{ object.rawId.startsWith('Spaces-') ? object.rawId : object.spaceId }}/events", + "getArgs": [ + { + "key": "from", + "value": "{{ timeframe.start }}" + }, + { + "key": "to", + "value": "{{ timeframe.end }}" + }, + { + "key": "regarding", + "value": "{{ object.rawId.startsWith('Spaces-') ? null : object.rawId }}" + }, + { + "key": "eventCategories", + "value": "{{ (typeof category !== 'undefined' && category && category.length) ? [].concat(category).join(',') : null }}" + } + ], + "paging": { + "mode": "offset", + "pageSize": { + "realm": "queryArg", + "path": "take", + "value": "200" + }, + "offset": { + "mode": "row", + "base": 0, + "rowCountIn": { + "realm": "payloadArraySize", + "path": "Items" + } + }, + "out": { + "realm": "queryArg", + "path": "skip" + } + }, + "postRequestScript": "auditEvents.js" + }, + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Space", + "Project", + "Environment", + "Tenant", + "Runbook", + "Deployment Target", + "Worker" + ] + } + }, + "ui": [ + { + "type": "choiceChips", + "name": "category", + "label": "Category(s)", + "isMulti": true, + "options": [ + { "value": "DeploymentQueued", "label": "Deployment queued" }, + { "value": "DeploymentStarted", "label": "Deployment started" }, + { "value": "DeploymentSucceeded", "label": "Deployment succeeded" }, + { "value": "DeploymentFailed", "label": "Deployment failed" }, + { "value": "Created", "label": "Created" }, + { "value": "Modified", "label": "Modified" }, + { "value": "Deleted", "label": "Deleted" }, + { "value": "LoginSucceeded", "label": "Login succeeded" }, + { "value": "LoginFailed", "label": "Login failed" } + ] + } + ], + "metadata": [ + { + "name": "Id", + "displayName": "ID", + "shape": "string", + "role": "id", + "visible": false + }, + { + "name": "Message", + "displayName": "Message", + "shape": "string", + "role": "label" + }, + { + "name": "Category", + "displayName": "Category", + "shape": "string" + }, + { + "name": "Username", + "displayName": "User", + "shape": "string" + }, + { + "name": "IsService", + "displayName": "Service Account", + "shape": "boolean" + }, + { + "name": "Occurred", + "displayName": "Occurred", + "shape": "date", + "role": "timestamp" + }, + { + "name": "IpAddress", + "displayName": "IP Address", + "shape": "string" + }, + { + "name": "ProjectId", + "displayName": "Project ID", + "shape": "string", + "visible": false + }, + { + "name": "EnvironmentId", + "displayName": "Environment ID", + "shape": "string", + "visible": false + }, + { + "name": "SpaceId", + "displayName": "Space ID", + "shape": "string", + "visible": false + }, + { + "name": "projectName", + "displayName": "Project", + "sourceId": "ProjectId", + "sourceType": "Project", + "objectPropertyPath": "name", + "valueExpression": "{{ object && object.name ? object.name : '' }}" + }, + { + "name": "environmentName", + "displayName": "Environment", + "sourceId": "EnvironmentId", + "sourceType": "Environment", + "objectPropertyPath": "name", + "valueExpression": "{{ object && object.name ? object.name : '' }}" + }, + { + "sourceId": "ProjectId", + "sourceType": "Project", + "name": "projectName" + }, + { + "sourceId": "EnvironmentId", + "sourceType": "Environment", + "name": "environmentName" + } + ], + "timeframes": [ + "last1hour", + "last12hours", + "last24hours", + "last7days" + ] +} diff --git a/plugins/OctopusDeploy/v1/dataStreams/certificates.json b/plugins/OctopusDeploy/v1/dataStreams/certificates.json new file mode 100644 index 00000000..a9a74895 --- /dev/null +++ b/plugins/OctopusDeploy/v1/dataStreams/certificates.json @@ -0,0 +1,137 @@ +{ + "name": "certificates", + "displayName": "Certificates", + "description": "Certificates in the Octopus certificate library with their expiry dates and days remaining", + "tags": [ + "Security", + "Infrastructure" + ], + "baseDataSourceName": "httpRequestScopedSingle", + "config": { + "httpMethod": "get", + "endpointPath": "api/{{ object.rawId.startsWith('Spaces-') ? object.rawId : object.spaceId }}/certificates", + "getArgs": [ + { + "key": "archived", + "value": "false" + } + ], + "paging": { + "mode": "offset", + "pageSize": { + "realm": "queryArg", + "path": "take", + "value": "250" + }, + "offset": { + "mode": "row", + "base": 0, + "rowCountIn": { + "realm": "payloadArraySize", + "path": "Items" + } + }, + "out": { + "realm": "queryArg", + "path": "skip" + } + }, + "postRequestScript": "certificates.js" + }, + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Space", + "Environment", + "Tenant" + ] + } + }, + "metadata": [ + { + "name": "Id", + "displayName": "ID", + "shape": "string", + "role": "id", + "visible": false + }, + { + "name": "Name", + "displayName": "Name", + "shape": "string", + "role": "label" + }, + { + "name": "SubjectCommonName", + "displayName": "Subject", + "shape": "string" + }, + { + "name": "IssuerCommonName", + "displayName": "Issuer", + "shape": "string" + }, + { + "name": "NotAfter", + "displayName": "Expires", + "shape": "date" + }, + { + "name": "NotBefore", + "displayName": "Valid From", + "shape": "date" + }, + { + "name": "DaysUntilExpiry", + "displayName": "Days Until Expiry", + "shape": "number" + }, + { + "name": "ExpiryStatus", + "displayName": "Expiry Status", + "shape": [ + "state", + { + "map": { + "success": [ + "Valid" + ], + "warning": [ + "Expiring soon" + ], + "error": [ + "Expired" + ] + } + } + ] + }, + { + "name": "EnvironmentIds", + "displayName": "Environment IDs", + "shape": ["array", { "itemShape": "string" }] + }, + { + "name": "SelfSigned", + "displayName": "Self Signed", + "shape": "boolean" + }, + { + "name": "HasPrivateKey", + "displayName": "Has Private Key", + "shape": "boolean" + }, + { + "name": "Thumbprint", + "displayName": "Thumbprint", + "shape": "string" + }, + { + "name": "SubjectAlternativeNames", + "displayName": "Subject Alternative Names", + "shape": ["array", { "itemShape": "string" }] + } + ], + "timeframes": false +} diff --git a/plugins/OctopusDeploy/v1/dataStreams/currentUser.json b/plugins/OctopusDeploy/v1/dataStreams/currentUser.json new file mode 100644 index 00000000..627154a3 --- /dev/null +++ b/plugins/OctopusDeploy/v1/dataStreams/currentUser.json @@ -0,0 +1,46 @@ +{ + "name": "currentUser", + "displayName": "Current User", + "description": "The Octopus user the API key belongs to (used to validate the configuration)", + "tags": [ + "Status" + ], + "baseDataSourceName": "httpRequestUnscoped", + "config": { + "httpMethod": "get", + "endpointPath": "api/users/me" + }, + "matches": "none", + "visibility": { + "type": "hidden" + }, + "metadata": [ + { + "name": "Id", + "displayName": "ID", + "shape": "string" + }, + { + "name": "DisplayName", + "displayName": "Name", + "shape": "string", + "role": "label" + }, + { + "name": "Username", + "displayName": "Username", + "shape": "string" + }, + { + "name": "IsService", + "displayName": "Service Account", + "shape": "boolean" + }, + { + "name": "IsActive", + "displayName": "Active", + "shape": "boolean" + } + ], + "timeframes": false +} diff --git a/plugins/OctopusDeploy/v1/dataStreams/deploymentFreezes.json b/plugins/OctopusDeploy/v1/dataStreams/deploymentFreezes.json new file mode 100644 index 00000000..097d68d9 --- /dev/null +++ b/plugins/OctopusDeploy/v1/dataStreams/deploymentFreezes.json @@ -0,0 +1,142 @@ +{ + "name": "deploymentFreezes", + "displayName": "Deployment Freezes", + "description": "Deployment freezes that are active now or scheduled, with the projects, environments and tenants they block [expired freezes are excluded]", + "tags": [ + "Deployments" + ], + "baseDataSourceName": "httpRequestScopedSingle", + "config": { + "httpMethod": "get", + "endpointPath": "api/deploymentfreezes", + "postRequestScript": "deploymentFreezes.js", + "getArgs": [ + { + "key": "skip", + "value": "0" + }, + { + "key": "take", + "value": "1000" + } + ] + }, + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Space", + "Project", + "Environment", + "Tenant" + ] + } + }, + "metadata": [ + { + "name": "name", + "displayName": "Name", + "shape": "string", + "role": "label" + }, + { + "name": "freezeState", + "displayName": "Freeze State", + "shape": [ + "state", + { + "map": { + "error": [ + "Active" + ], + "warning": [ + "Scheduled" + ], + "success": [ + "Expired" + ] + } + } + ] + }, + { + "name": "status", + "displayName": "Status", + "shape": "string" + }, + { + "name": "description", + "displayName": "Description", + "shape": "string" + }, + { + "name": "start", + "displayName": "Start", + "shape": "date" + }, + { + "name": "end", + "displayName": "End", + "shape": "date", + "role": "timestamp" + }, + { + "name": "hoursRemaining", + "displayName": "Hours Remaining", + "shape": [ + "number", + { + "decimalPlaces": 1 + } + ] + }, + { + "name": "startsInHours", + "displayName": "Starts In (Hours)", + "shape": [ + "number", + { + "decimalPlaces": 1 + } + ] + }, + { + "name": "recurring", + "displayName": "Recurring", + "shape": "boolean" + }, + { + "name": "schedule", + "displayName": "Schedule", + "shape": "string" + }, + { + "name": "projectCount", + "displayName": "Projects", + "shape": "number" + }, + { + "name": "environmentCount", + "displayName": "Environments", + "shape": "number" + }, + { + "name": "tenantCount", + "displayName": "Tenants", + "shape": "number" + }, + { + "name": "scopeSummary", + "displayName": "Scope", + "shape": "string" + }, + { + "name": "id", + "displayName": "ID", + "shape": "string", + "role": "id", + "visible": false + } + ], + "timeframes": false +} diff --git a/plugins/OctopusDeploy/v1/dataStreams/deploymentStatus.json b/plugins/OctopusDeploy/v1/dataStreams/deploymentStatus.json new file mode 100644 index 00000000..0736568e --- /dev/null +++ b/plugins/OctopusDeploy/v1/dataStreams/deploymentStatus.json @@ -0,0 +1,181 @@ +{ + "name": "deploymentStatus", + "displayName": "Deployment Status", + "description": "Latest deployment of each project to each environment and tenant, for a space, project, environment or tenant", + "tags": [ + "Deployments" + ], + "baseDataSourceName": "httpRequestScopedSingle", + "config": { + "httpMethod": "get", + "endpointPath": "api/{{ object.rawId.startsWith('Spaces-') ? object.rawId : object.spaceId }}/dashboard", + "postRequestScript": "deploymentStatus.js", + "getArgs": [ + { + "key": "projectId", + "value": "{{ object.rawId.startsWith('Projects-') ? object.rawId : null }}" + } + ] + }, + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Space", + "Project", + "Environment", + "Tenant" + ] + } + }, + "metadata": [ + { + "name": "projectGroupName", + "displayName": "Project Group", + "shape": "string" + }, + { + "name": "projectName", + "displayName": "Project", + "shape": "string", + "role": "label" + }, + { + "name": "environmentName", + "displayName": "Environment", + "shape": "string" + }, + { + "name": "tenantName", + "displayName": "Tenant", + "shape": "string" + }, + { + "name": "releaseVersion", + "displayName": "Release", + "shape": "string" + }, + { + "name": "status", + "displayName": "Status", + "shape": [ + "state", + { + "map": { + "success": [ + "Success" + ], + "warning": [ + "Canceled", + "Cancelling", + "AwaitingIntervention" + ], + "error": [ + "Failed", + "TimedOut" + ], + "unknown": [ + "Queued", + "Executing" + ] + } + } + ] + }, + { + "name": "state", + "displayName": "State", + "shape": "string" + }, + { + "name": "completedTime", + "displayName": "Completed", + "shape": "date", + "role": "timestamp" + }, + { + "name": "startTime", + "displayName": "Started", + "shape": "date" + }, + { + "name": "queueTime", + "displayName": "Queued", + "shape": "date" + }, + { + "name": "durationSeconds", + "displayName": "Duration", + "shape": "seconds" + }, + { + "name": "hasWarningsOrErrors", + "displayName": "Has warnings or errors", + "shape": "boolean" + }, + { + "name": "hasPendingInterruptions", + "displayName": "Awaiting manual intervention", + "shape": "boolean" + }, + { + "name": "errorMessage", + "displayName": "Error message", + "shape": "string" + }, + { + "name": "environmentSortOrder", + "displayName": "Environment sort order", + "shape": "number", + "visible": false + }, + { + "name": "projectId", + "displayName": "Project ID", + "shape": "string", + "visible": false + }, + { + "name": "environmentId", + "displayName": "Environment ID", + "shape": "string", + "visible": false + }, + { + "name": "tenantId", + "displayName": "Tenant ID", + "shape": "string", + "visible": false + }, + { + "name": "taskId", + "displayName": "Task ID", + "shape": "string", + "visible": false + }, + { + "name": "deploymentId", + "displayName": "Deployment ID", + "shape": "string", + "role": "id", + "visible": false + }, + { + "name": "spaceId", + "displayName": "Space ID", + "shape": "string", + "visible": false + }, + { + "sourceId": "projectId", + "sourceType": "Project", + "name": "projectName" + }, + { + "sourceId": "environmentId", + "sourceType": "Environment", + "name": "environmentName" + } + ], + "timeframes": false +} diff --git a/plugins/OctopusDeploy/v1/dataStreams/deploymentTargets.json b/plugins/OctopusDeploy/v1/dataStreams/deploymentTargets.json new file mode 100644 index 00000000..ab61b33d --- /dev/null +++ b/plugins/OctopusDeploy/v1/dataStreams/deploymentTargets.json @@ -0,0 +1,199 @@ +{ + "name": "deploymentTargets", + "displayName": "Deployment Targets", + "description": "Deployment targets with their current health status, target tags, environments and agent versions", + "tags": [ + "Infrastructure", + "Health" + ], + "baseDataSourceName": "httpRequestScopedSingle", + "config": { + "httpMethod": "get", + "endpointPath": "api/{{ object.rawId.startsWith('Spaces-') ? object.rawId : object.spaceId }}/machines", + "getArgs": [ + { + "key": "environmentIds", + "value": "{{ object.rawId.startsWith('Environments-') ? object.rawId : null }}" + }, + { + "key": "ids", + "value": "{{ object.rawId.startsWith('Machines-') ? object.rawId : null }}" + }, + { + "key": "tenantIds", + "value": "{{ object.rawId.startsWith('Tenants-') ? object.rawId : null }}" + } + ], + "paging": { + "mode": "offset", + "pageSize": { + "realm": "queryArg", + "path": "take", + "value": "250" + }, + "offset": { + "mode": "row", + "base": 0, + "rowCountIn": { + "realm": "payloadArraySize", + "path": "Items" + } + }, + "out": { + "realm": "queryArg", + "path": "skip" + } + }, + "postRequestScript": "deploymentTargets.js" + }, + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Space", + "Environment", + "Deployment Target", + "Tenant" + ] + } + }, + "metadata": [ + { + "name": "Id", + "displayName": "ID", + "shape": "string", + "role": "id", + "visible": false + }, + { + "name": "Name", + "displayName": "Name", + "shape": "string", + "role": "label" + }, + { + "name": "health", + "displayName": "Health", + "computed": true, + "valueExpression": "{{ $['IsDisabled'] ? 'Disabled' : $['HealthStatus'] }}", + "shape": [ + "state", + { + "map": { + "success": [ + "Healthy" + ], + "warning": [ + "HasWarnings" + ], + "error": [ + "Unhealthy", + "Unavailable" + ], + "unknown": [ + "Unknown" + ], + "unmonitored": [ + "Disabled" + ] + } + } + ] + }, + { + "name": "HealthStatus", + "displayName": "Health Status", + "shape": "string" + }, + { + "name": "StatusSummary", + "displayName": "Status Summary", + "shape": "string" + }, + { + "name": "IsDisabled", + "displayName": "Disabled", + "shape": "boolean" + }, + { + "name": "Roles", + "displayName": "Target Tags", + "shape": ["array", { "itemShape": "string" }] + }, + { + "name": "EnvironmentIds", + "displayName": "Environment IDs", + "shape": ["array", { "itemShape": "string" }] + }, + { + "name": "TenantIds", + "displayName": "Tenant IDs", + "shape": ["array", { "itemShape": "string" }] + }, + { + "name": "CommunicationStyle", + "displayName": "Communication Style", + "shape": "string" + }, + { + "name": "OperatingSystem", + "displayName": "Operating System", + "shape": "string" + }, + { + "name": "ShellName", + "displayName": "Shell", + "shape": "string" + }, + { + "name": "TentacleVersion", + "displayName": "Tentacle Version", + "shape": "string" + }, + { + "name": "TentacleUpgrade", + "displayName": "Tentacle Upgrade", + "shape": "string" + }, + { + "name": "HasLatestCalamari", + "displayName": "Latest Calamari", + "shape": "boolean" + }, + { + "name": "agentStatus", + "displayName": "Agent Status", + "computed": true, + "valueExpression": "{{ $['TentacleUpgrade'] === 'Required' ? 'Upgrade required' : ($['TentacleUpgrade'] === 'Suggested' ? 'Upgrade suggested' : ($['HasLatestCalamari'] === false ? 'Calamari update' : 'Up to date')) }}", + "shape": [ + "state", + { + "map": { + "success": [ + "Up to date" + ], + "warning": [ + "Upgrade suggested", + "Calamari update" + ], + "error": [ + "Upgrade required" + ] + } + } + ] + }, + { + "name": "SpaceId", + "displayName": "Space ID", + "shape": "string", + "visible": false + }, + { + "sourceId": "Id", + "sourceType": "Deployment Target", + "name": "Name" + } + ], + "timeframes": false +} diff --git a/plugins/OctopusDeploy/v1/dataStreams/deployments.json b/plugins/OctopusDeploy/v1/dataStreams/deployments.json new file mode 100644 index 00000000..6b6874f7 --- /dev/null +++ b/plugins/OctopusDeploy/v1/dataStreams/deployments.json @@ -0,0 +1,206 @@ +{ + "name": "deployments", + "displayName": "Deployments", + "description": "Deployment history with project, environment, tenant, release, outcome and duration, for a space, project, environment or tenant (deployments completed within the timeframe)", + "tags": [ + "Deployments" + ], + "baseDataSourceName": "httpRequestScopedSingle", + "config": { + "httpMethod": "get", + "endpointPath": "api/{{ object.rawId.startsWith('Spaces-') ? object.rawId : object.spaceId }}/reporting/deployments/xml", + "getArgs": [ + { + "key": "fromCompletedTime", + "value": "{{timeframe.start}}" + }, + { + "key": "toCompletedTime", + "value": "{{timeframe.end}}" + }, + { + "key": "projectId", + "value": "{{ object.rawId.startsWith('Projects-') ? object.rawId : null }}" + }, + { + "key": "environmentId", + "value": "{{ object.rawId.startsWith('Environments-') ? object.rawId : null }}" + } + ], + "postRequestScript": "deployments.js" + }, + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Space", + "Project", + "Environment", + "Tenant" + ] + } + }, + "metadata": [ + { + "name": "projectName", + "displayName": "Project", + "shape": "string", + "role": "label" + }, + { + "name": "environmentName", + "displayName": "Environment", + "shape": "string" + }, + { + "name": "tenantName", + "displayName": "Tenant", + "shape": "string" + }, + { + "name": "channelName", + "displayName": "Channel", + "shape": "string" + }, + { + "name": "releaseVersion", + "displayName": "Release", + "shape": "string" + }, + { + "name": "status", + "displayName": "Status", + "computed": true, + "valueExpression": "{{ $['state'] }}", + "shape": [ + "state", + { + "map": { + "success": [ + "Success" + ], + "error": [ + "Failed", + "TimedOut" + ], + "warning": [ + "Canceled", + "Cancelling" + ], + "unknown": [ + "Queued", + "Executing" + ] + } + } + ] + }, + { + "name": "state", + "displayName": "State", + "shape": "string" + }, + { + "name": "succeeded", + "displayName": "Success Rate", + "computed": true, + "valueExpression": "{{ $['state'] === 'Success' ? 100 : 0 }}", + "shape": [ + "percent", + { + "decimalPlaces": 0 + } + ] + }, + { + "name": "deployedBy", + "displayName": "Deployed By", + "shape": "string" + }, + { + "name": "queueTime", + "displayName": "Queued", + "shape": "date" + }, + { + "name": "startTime", + "displayName": "Started", + "shape": "date" + }, + { + "name": "completedTime", + "displayName": "Completed", + "shape": "date", + "role": "timestamp" + }, + { + "name": "durationSeconds", + "displayName": "Duration", + "shape": "seconds" + }, + { + "name": "projectId", + "displayName": "Project ID", + "shape": "string", + "visible": false + }, + { + "name": "environmentId", + "displayName": "Environment ID", + "shape": "string", + "visible": false + }, + { + "name": "tenantId", + "displayName": "Tenant ID", + "shape": "string", + "visible": false + }, + { + "name": "releaseId", + "displayName": "Release ID", + "shape": "string", + "visible": false + }, + { + "name": "deploymentId", + "displayName": "Deployment ID", + "shape": "string", + "role": "id", + "visible": false + }, + { + "name": "taskId", + "displayName": "Task ID", + "shape": "string", + "visible": false + }, + { + "name": "spaceId", + "displayName": "Space ID", + "shape": "string", + "visible": false + }, + { + "sourceId": "projectId", + "sourceType": "Project", + "name": "projectName" + }, + { + "sourceId": "environmentId", + "sourceType": "Environment", + "name": "environmentName" + } + ], + "timeframes": [ + "last1hour", + "last12hours", + "last24hours", + "last7days", + "last30days", + "thisMonth", + "lastMonth", + "thisQuarter", + "lastQuarter" + ] +} diff --git a/plugins/OctopusDeploy/v1/dataStreams/environments.json b/plugins/OctopusDeploy/v1/dataStreams/environments.json new file mode 100644 index 00000000..fc30f9d1 --- /dev/null +++ b/plugins/OctopusDeploy/v1/dataStreams/environments.json @@ -0,0 +1,85 @@ +{ + "name": "environments", + "displayName": "Environments", + "description": "Environments in a space, in lifecycle sort order", + "tags": [ + "Inventory" + ], + "baseDataSourceName": "httpRequestScopedSingle", + "config": { + "httpMethod": "get", + "endpointPath": "api/{{object.rawId}}/environments", + "paging": { + "mode": "offset", + "pageSize": { + "realm": "queryArg", + "path": "take", + "value": "250" + }, + "offset": { + "mode": "row", + "base": 0, + "rowCountIn": { + "realm": "payloadArraySize", + "path": "Items" + } + }, + "out": { + "realm": "queryArg", + "path": "skip" + } + }, + "pathToData": "Items" + }, + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Space" + ] + } + }, + "visibility": { + "type": "hidden" + }, + "metadata": [ + { + "name": "Id", + "displayName": "ID", + "shape": "string", + "role": "id" + }, + { + "name": "Name", + "displayName": "Name", + "shape": "string", + "role": "label" + }, + { + "name": "Description", + "displayName": "Description", + "shape": "string" + }, + { + "name": "SortOrder", + "displayName": "Sort Order", + "shape": "number" + }, + { + "name": "UseGuidedFailure", + "displayName": "Guided Failure", + "shape": "boolean" + }, + { + "name": "SpaceId", + "displayName": "Space ID", + "shape": "string" + }, + { + "sourceId": "Id", + "sourceType": "Environment", + "name": "Name" + } + ], + "timeframes": false +} diff --git a/plugins/OctopusDeploy/v1/dataStreams/license.json b/plugins/OctopusDeploy/v1/dataStreams/license.json new file mode 100644 index 00000000..654900a9 --- /dev/null +++ b/plugins/OctopusDeploy/v1/dataStreams/license.json @@ -0,0 +1,125 @@ +{ + "name": "license", + "displayName": "License", + "description": "Octopus license or Cloud subscription expiry and compliance, with usage against each licensed limit (one row per limit)", + "tags": [ + "License", + "Usage" + ], + "baseDataSourceName": "httpRequestScopedSingle", + "config": { + "httpMethod": "get", + "endpointPath": "api/licenses/licenses-current-status", + "postRequestScript": "license.js" + }, + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Space" + ] + } + }, + "metadata": [ + { + "name": "limitName", + "displayName": "Limit", + "shape": "string", + "role": "label" + }, + { + "name": "currentUsage", + "displayName": "Usage", + "shape": "number" + }, + { + "name": "limit", + "displayName": "Licensed Limit", + "shape": "number" + }, + { + "name": "isUnlimited", + "displayName": "Unlimited", + "shape": "boolean" + }, + { + "name": "usagePercent", + "displayName": "Usage %", + "shape": [ + "percent", + { + "decimalPlaces": 0 + } + ], + "role": "value" + }, + { + "name": "limitState", + "displayName": "Limit State", + "computed": true, + "valueExpression": "{{ $['limitStatus'] }}", + "shape": [ + "state", + { + "map": { + "success": [ + "UnderLimit" + ], + "warning": [ + "AtLimit", + "NearLimit", + "ApproachingLimit" + ], + "error": [ + "OverLimit", + "ExceedsLimit" + ] + } + } + ] + }, + { + "name": "limitStatus", + "displayName": "Limit Status", + "shape": "string" + }, + { + "name": "limitMessage", + "displayName": "Message", + "shape": "string" + }, + { + "name": "expiryDate", + "displayName": "Expires", + "shape": "date" + }, + { + "name": "daysToExpiry", + "displayName": "Days to Expiry", + "shape": "number" + }, + { + "name": "expiryState", + "displayName": "Expiry State", + "computed": true, + "valueExpression": "{{ $['daysToExpiry'] === null || $['daysToExpiry'] === undefined ? 'unknown' : ($['daysToExpiry'] < 0 ? 'error' : ($['daysToExpiry'] < 30 ? 'warning' : 'success')) }}", + "shape": "state" + }, + { + "name": "isCompliant", + "displayName": "Compliant", + "shape": "boolean" + }, + { + "name": "complianceSummary", + "displayName": "Compliance Summary", + "shape": "string" + }, + { + "name": "hostingEnvironment", + "displayName": "Hosting", + "shape": "string" + } + ], + "timeframes": false +} diff --git a/plugins/OctopusDeploy/v1/dataStreams/pendingInterventions.json b/plugins/OctopusDeploy/v1/dataStreams/pendingInterventions.json new file mode 100644 index 00000000..8f628f06 --- /dev/null +++ b/plugins/OctopusDeploy/v1/dataStreams/pendingInterventions.json @@ -0,0 +1,163 @@ +{ + "name": "pendingInterventions", + "displayName": "Pending Interventions", + "description": "Deployments and runbook runs waiting for a person, with how long they have been waiting and who has taken responsibility", + "tags": [ + "Deployments", + "Tasks" + ], + "baseDataSourceName": "httpRequestScopedSingle", + "config": { + "httpMethod": "get", + "endpointPath": "api/{{ object.rawId.startsWith('Spaces-') ? object.rawId : object.spaceId }}/interruptions", + "getArgs": [ + { + "key": "pendingOnly", + "value": "true" + } + ], + "paging": { + "mode": "offset", + "pageSize": { + "realm": "queryArg", + "path": "take", + "value": "200" + }, + "offset": { + "mode": "row", + "base": 0, + "rowCountIn": { + "realm": "payloadArraySize", + "path": "Items" + } + }, + "out": { + "realm": "queryArg", + "path": "skip" + } + }, + "postRequestScript": "pendingInterventions.js" + }, + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Space", + "Project", + "Environment", + "Tenant" + ] + } + }, + "metadata": [ + { + "name": "title", + "displayName": "Title", + "shape": "string", + "role": "label" + }, + { + "name": "type", + "displayName": "Type", + "shape": "string" + }, + { + "name": "status", + "displayName": "Status", + "shape": [ + "state", + { + "map": { + "warning": [ + "Pending" + ] + } + } + ] + }, + { + "name": "instructions", + "displayName": "Instructions", + "shape": "string" + }, + { + "name": "created", + "displayName": "Created", + "shape": "date", + "role": "timestamp" + }, + { + "name": "waitingMinutes", + "displayName": "Waiting", + "shape": "minutes" + }, + { + "name": "hasResponsibility", + "displayName": "Responsibility taken", + "shape": "boolean" + }, + { + "name": "responsibleUserId", + "displayName": "Responsible User ID", + "shape": "string" + }, + { + "name": "canTakeResponsibility", + "displayName": "Can take responsibility", + "shape": "boolean" + }, + { + "name": "responsibleTeamIds", + "displayName": "Responsible Team IDs", + "shape": ["array", { "itemShape": "string" }] + }, + { + "name": "projectId", + "displayName": "Project ID", + "shape": "string", + "visible": false + }, + { + "name": "environmentId", + "displayName": "Environment ID", + "shape": "string", + "visible": false + }, + { + "name": "tenantId", + "displayName": "Tenant ID", + "shape": "string", + "visible": false + }, + { + "name": "taskId", + "displayName": "Task ID", + "shape": "string", + "visible": false + }, + { + "name": "interruptionId", + "displayName": "Interruption ID", + "shape": "string", + "role": "id", + "visible": false + }, + { + "name": "spaceId", + "displayName": "Space ID", + "shape": "string", + "visible": false + }, + { + "sourceId": "projectId", + "sourceType": "Project", + "name": "title" + }, + { + "sourceId": "environmentId", + "sourceType": "Environment", + "name": "title" + } + ], + "timeframes": false +} diff --git a/plugins/OctopusDeploy/v1/dataStreams/projects.json b/plugins/OctopusDeploy/v1/dataStreams/projects.json new file mode 100644 index 00000000..3e67aee6 --- /dev/null +++ b/plugins/OctopusDeploy/v1/dataStreams/projects.json @@ -0,0 +1,95 @@ +{ + "name": "projects", + "displayName": "Projects", + "description": "Projects in a space, with project group, lifecycle and disabled status", + "tags": [ + "Inventory" + ], + "baseDataSourceName": "httpRequestScopedSingle", + "config": { + "httpMethod": "get", + "endpointPath": "api/{{object.rawId}}/projects", + "paging": { + "mode": "offset", + "pageSize": { + "realm": "queryArg", + "path": "take", + "value": "250" + }, + "offset": { + "mode": "row", + "base": 0, + "rowCountIn": { + "realm": "payloadArraySize", + "path": "Items" + } + }, + "out": { + "realm": "queryArg", + "path": "skip" + } + }, + "pathToData": "Items" + }, + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Space" + ] + } + }, + "visibility": { + "type": "hidden" + }, + "metadata": [ + { + "name": "Id", + "displayName": "ID", + "shape": "string", + "role": "id" + }, + { + "name": "Name", + "displayName": "Name", + "shape": "string", + "role": "label" + }, + { + "name": "Slug", + "displayName": "Slug", + "shape": "string" + }, + { + "name": "Description", + "displayName": "Description", + "shape": "string" + }, + { + "name": "IsDisabled", + "displayName": "Disabled", + "shape": "boolean" + }, + { + "name": "ProjectGroupId", + "displayName": "Project Group ID", + "shape": "string" + }, + { + "name": "LifecycleId", + "displayName": "Lifecycle ID", + "shape": "string" + }, + { + "name": "SpaceId", + "displayName": "Space ID", + "shape": "string" + }, + { + "sourceId": "Id", + "sourceType": "Project", + "name": "Name" + } + ], + "timeframes": false +} diff --git a/plugins/OctopusDeploy/v1/dataStreams/releaseProgression.json b/plugins/OctopusDeploy/v1/dataStreams/releaseProgression.json new file mode 100644 index 00000000..85eb1b08 --- /dev/null +++ b/plugins/OctopusDeploy/v1/dataStreams/releaseProgression.json @@ -0,0 +1,143 @@ +{ + "name": "releaseProgression", + "displayName": "Release Progression", + "description": "Recent releases of a project and the status of their deployment to each environment, one row per release and environment", + "tags": [ + "Deployments" + ], + "baseDataSourceName": "httpRequestScopedSingle", + "config": { + "httpMethod": "get", + "endpointPath": "api/{{object.spaceId}}/progression/{{object.rawId}}", + "postRequestScript": "releaseProgression.js" + }, + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Project" + ] + } + }, + "ui": [ + { + "type": "number", + "name": "releaseCount", + "label": "Number of releases", + "defaultValue": 10 + } + ], + "metadata": [ + { + "name": "releaseVersion", + "displayName": "Release", + "shape": "string", + "role": "label" + }, + { + "name": "environmentName", + "displayName": "Environment", + "shape": "string" + }, + { + "name": "status", + "displayName": "Status", + "computed": true, + "valueExpression": "{{ $['state'] }}", + "shape": [ + "state", + { + "map": { + "success": [ + "Success" + ], + "error": [ + "Failed", + "TimedOut" + ], + "warning": [ + "Canceled", + "Cancelling", + "AwaitingIntervention" + ], + "unknown": [ + "Queued", + "Executing", + "ReadyToDeploy" + ], + "unmonitored": [ + "NotDeployed" + ] + } + } + ] + }, + { + "name": "state", + "displayName": "State", + "shape": "string" + }, + { + "name": "detail", + "displayName": "Detail", + "shape": "string" + }, + { + "name": "deployedTime", + "displayName": "Deployed", + "shape": "date" + }, + { + "name": "channelName", + "displayName": "Channel", + "shape": "string" + }, + { + "name": "releaseCreated", + "displayName": "Release Created", + "shape": "date" + }, + { + "name": "releaseSortOrder", + "displayName": "Release Order", + "shape": "number", + "visible": false + }, + { + "name": "environmentSortOrder", + "displayName": "Environment Order", + "shape": "number", + "visible": false + }, + { + "name": "gridOrder", + "displayName": "Grid Order", + "shape": "number", + "visible": false + }, + { + "name": "releaseId", + "displayName": "Release ID", + "shape": "string", + "visible": false + }, + { + "name": "projectId", + "displayName": "Project ID", + "shape": "string", + "visible": false + }, + { + "name": "environmentId", + "displayName": "Environment ID", + "shape": "string", + "visible": false + }, + { + "sourceId": "environmentId", + "sourceType": "Environment", + "name": "environmentName" + } + ], + "timeframes": false +} diff --git a/plugins/OctopusDeploy/v1/dataStreams/runbookStatus.json b/plugins/OctopusDeploy/v1/dataStreams/runbookStatus.json new file mode 100644 index 00000000..49e03895 --- /dev/null +++ b/plugins/OctopusDeploy/v1/dataStreams/runbookStatus.json @@ -0,0 +1,133 @@ +{ + "name": "runbookStatus", + "displayName": "Runbook Status", + "description": "Latest run of a runbook in each environment it can run in, in lifecycle order", + "tags": [ + "Deployments" + ], + "baseDataSourceName": "httpRequestScopedSingle", + "config": { + "httpMethod": "get", + "endpointPath": "api/{{object.spaceId}}/progression/runbooks/{{object.rawId}}", + "postRequestScript": "runbookStatus.js" + }, + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Runbook" + ] + } + }, + "metadata": [ + { + "name": "environmentName", + "displayName": "Environment", + "shape": "string", + "role": "label" + }, + { + "name": "status", + "displayName": "Status", + "computed": true, + "valueExpression": "{{ $['state'] }}", + "shape": [ + "state", + { + "map": { + "success": [ + "Success" + ], + "error": [ + "Failed", + "TimedOut" + ], + "warning": [ + "Canceled", + "Cancelling", + "AwaitingIntervention" + ], + "unknown": [ + "Queued", + "Executing" + ], + "unmonitored": [ + "NeverRun" + ] + } + } + ] + }, + { + "name": "state", + "displayName": "State", + "shape": "string" + }, + { + "name": "detail", + "displayName": "Detail", + "shape": "string" + }, + { + "name": "lastRunTime", + "displayName": "Last Run", + "shape": "date" + }, + { + "name": "durationSeconds", + "displayName": "Duration", + "shape": "seconds" + }, + { + "name": "runBy", + "displayName": "Run By", + "shape": "string" + }, + { + "name": "snapshotName", + "displayName": "Snapshot", + "shape": "string" + }, + { + "name": "errorMessage", + "displayName": "Error", + "shape": "string" + }, + { + "name": "environmentSortOrder", + "displayName": "Environment Order", + "shape": "number", + "visible": false + }, + { + "name": "runbookId", + "displayName": "Runbook ID", + "shape": "string", + "visible": false + }, + { + "name": "projectId", + "displayName": "Project ID", + "shape": "string", + "visible": false + }, + { + "name": "environmentId", + "displayName": "Environment ID", + "shape": "string", + "visible": false + }, + { + "name": "taskId", + "displayName": "Task ID", + "shape": "string", + "visible": false + }, + { + "sourceId": "environmentId", + "sourceType": "Environment", + "name": "environmentName" + } + ], + "timeframes": false +} diff --git a/plugins/OctopusDeploy/v1/dataStreams/runbooks.json b/plugins/OctopusDeploy/v1/dataStreams/runbooks.json new file mode 100644 index 00000000..3a7dfa8c --- /dev/null +++ b/plugins/OctopusDeploy/v1/dataStreams/runbooks.json @@ -0,0 +1,95 @@ +{ + "name": "runbooks", + "displayName": "Runbooks", + "description": "Runbooks in a space, with their project and environment scope", + "tags": [ + "Inventory" + ], + "baseDataSourceName": "httpRequestScopedSingle", + "config": { + "httpMethod": "get", + "endpointPath": "api/{{object.rawId}}/runbooks", + "paging": { + "mode": "offset", + "pageSize": { + "realm": "queryArg", + "path": "take", + "value": "250" + }, + "offset": { + "mode": "row", + "base": 0, + "rowCountIn": { + "realm": "payloadArraySize", + "path": "Items" + } + }, + "out": { + "realm": "queryArg", + "path": "skip" + } + }, + "pathToData": "Items" + }, + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Space" + ] + } + }, + "visibility": { + "type": "hidden" + }, + "metadata": [ + { + "name": "Id", + "displayName": "ID", + "shape": "string", + "role": "id" + }, + { + "name": "Name", + "displayName": "Name", + "shape": "string", + "role": "label" + }, + { + "name": "Description", + "displayName": "Description", + "shape": "string" + }, + { + "name": "ProjectId", + "displayName": "Project ID", + "shape": "string" + }, + { + "name": "EnvironmentScope", + "displayName": "Environment Scope", + "shape": "string" + }, + { + "name": "MultiTenancyMode", + "displayName": "Multi-Tenancy Mode", + "shape": "string" + }, + { + "name": "PublishedRunbookSnapshotId", + "displayName": "Published Snapshot ID", + "shape": "string" + }, + { + "name": "SpaceId", + "displayName": "Space ID", + "shape": "string" + }, + { + "sourceId": "Id", + "sourceType": "Runbook", + "name": "Name" + } + ], + "timeframes": false +} diff --git a/plugins/OctopusDeploy/v1/dataStreams/scripts/auditEvents.js b/plugins/OctopusDeploy/v1/dataStreams/scripts/auditEvents.js new file mode 100644 index 00000000..21497ae6 --- /dev/null +++ b/plugins/OctopusDeploy/v1/dataStreams/scripts/auditEvents.js @@ -0,0 +1,14 @@ +const first = (ids, prefix) => (ids || []).find((id) => typeof id === 'string' && id.startsWith(prefix)) || null; + +result = (data.Items || []).map((e) => ({ + Id: e.Id, + Message: e.Message, + Category: e.Category, + Username: e.Username, + IsService: e.IsService, + Occurred: e.Occurred, + IpAddress: e.IpAddress || null, + ProjectId: first(e.RelatedDocumentIds, 'Projects-'), + EnvironmentId: first(e.RelatedDocumentIds, 'Environments-'), + SpaceId: e.SpaceId +})); diff --git a/plugins/OctopusDeploy/v1/dataStreams/scripts/certificates.js b/plugins/OctopusDeploy/v1/dataStreams/scripts/certificates.js new file mode 100644 index 00000000..c1d75564 --- /dev/null +++ b/plugins/OctopusDeploy/v1/dataStreams/scripts/certificates.js @@ -0,0 +1,34 @@ +// Certificates expiring in fewer days than this are flagged as a warning. +const EXPIRING_SOON_DAYS = 30; +const MS_PER_DAY = 24 * 60 * 60 * 1000; + +// An empty scope list means the certificate is available to every environment or tenant. +const inScope = (ids, scopedId) => !Array.isArray(ids) || ids.length === 0 || ids.includes(scopedId); + +const scoped = context.objects[0].rawId; +const now = Date.now(); + +result = (data.Items || []) + .filter((c) => !c.Archived) + .filter((c) => (scoped.startsWith('Environments-') ? inScope(c.EnvironmentIds, scoped) : true)) + .filter((c) => (scoped.startsWith('Tenants-') ? inScope(c.TenantIds, scoped) : true)) + .map((c) => { + const expiry = c.NotAfter ? new Date(c.NotAfter).getTime() : NaN; + const daysUntilExpiry = Number.isNaN(expiry) ? null : Math.trunc((expiry - now) / MS_PER_DAY); + const expired = c.IsExpired === true || (daysUntilExpiry !== null && daysUntilExpiry < 0); + return { + Id: c.Id, + Name: c.Name, + SubjectCommonName: c.SubjectCommonName || null, + IssuerCommonName: c.IssuerCommonName || null, + NotAfter: c.NotAfter || null, + NotBefore: c.NotBefore || null, + DaysUntilExpiry: daysUntilExpiry, + ExpiryStatus: expired ? 'Expired' : daysUntilExpiry !== null && daysUntilExpiry < EXPIRING_SOON_DAYS ? 'Expiring soon' : 'Valid', + EnvironmentIds: c.EnvironmentIds || [], + SelfSigned: c.SelfSigned, + HasPrivateKey: c.HasPrivateKey, + Thumbprint: c.Thumbprint || null, + SubjectAlternativeNames: c.SubjectAlternativeNames || [] + }; + }); diff --git a/plugins/OctopusDeploy/v1/dataStreams/scripts/deploymentFreezes.js b/plugins/OctopusDeploy/v1/dataStreams/scripts/deploymentFreezes.js new file mode 100644 index 00000000..1000f07a --- /dev/null +++ b/plugins/OctopusDeploy/v1/dataStreams/scripts/deploymentFreezes.js @@ -0,0 +1,101 @@ +// Freezes are server-level and carry no status: work out whether each is active, scheduled or expired here. +const HOUR = 3600000; +const now = Date.now(); +const scoped = context.objects[0].rawId; +const iso = (ms) => new Date(ms).toISOString(); + +const scopeIds = (f) => { + const projects = new Set(Object.keys(f.ProjectEnvironmentScope || {})); + const environments = new Set([].concat(...Object.values(f.ProjectEnvironmentScope || {}))); + const tenants = new Set(); + (f.TenantProjectEnvironmentScope || []).forEach((t) => { + projects.add(t.ProjectId); + environments.add(t.EnvironmentId); + tenants.add(t.TenantId); + }); + return { projects, environments, tenants }; +}; + +// Shift a start time forward by n recurrence intervals +const shift = (ms, type, unit, n) => { + const d = new Date(ms); + const step = unit * n; + if (type === 'Daily') d.setUTCDate(d.getUTCDate() + step); + else if (type === 'Weekly') d.setUTCDate(d.getUTCDate() + 7 * step); + else if (type === 'Monthly') d.setUTCMonth(d.getUTCMonth() + step); + else if (type === 'Annually') d.setUTCFullYear(d.getUTCFullYear() + step); + return d.getTime(); +}; + +// Returns the current or next window for a freeze, or null if there is none left +const nextWindow = (f) => { + const start = Date.parse(f.Start); + const end = Date.parse(f.End); + const r = f.RecurringSchedule; + if (!r || !r.Type || !(start <= end)) return now < end ? { start, end } : null; + const unit = r.Unit || 1; + const length = end - start; + const lastEnd = r.EndType === 'OnDate' && r.EndOnDate ? Date.parse(r.EndOnDate) : Infinity; + const maxN = r.EndType === 'AfterOccurrences' && r.EndAfterOccurrences ? r.EndAfterOccurrences - 1 : Infinity; + for (let n = 0; n <= Math.min(maxN, 5000); n++) { + const s = shift(start, r.Type, unit, n); + if (s > lastEnd) return null; + if (s + length > now) return { start: s, end: s + length }; + } + return null; +}; + +const describe = (r) => { + if (!r || !r.Type) return null; + const unit = r.Unit || 1; + const noun = { Daily: 'day', Weekly: 'week', Monthly: 'month', Annually: 'year' }[r.Type] || r.Type; + const every = unit === 1 ? `Every ${noun}` : `Every ${unit} ${noun}s`; + const until = + r.EndType === 'OnDate' && r.EndOnDate + ? `, until ${r.EndOnDate.slice(0, 10)}` + : r.EndType === 'AfterOccurrences' + ? `, ${r.EndAfterOccurrences} times` + : ''; + return every + until; +}; + +// Freezes are server-wide and carry no space, so a Space scope returns them only for the +// default space; otherwise every space in a multi-space tile would repeat them. +const isDefaultSpace = String([].concat(context.objects[0].isDefault)[0]) === 'true'; + +const keep = (ids) => + (!scoped.startsWith('Spaces-') || isDefaultSpace) && + (!scoped.startsWith('Projects-') || ids.projects.has(scoped)) && + (!scoped.startsWith('Environments-') || ids.environments.has(scoped)) && + (!scoped.startsWith('Tenants-') || ids.tenants.has(scoped)); + +// pathToData is ignored when a post-request script is set, so read the array here. +result = ((data && data.DeploymentFreezes) || []) + .map((f) => ({ f, ids: scopeIds(f), w: nextWindow(f) })) + .filter((x) => x.w && keep(x.ids)) + .map(({ f, ids, w }) => { + const active = w.start <= now; + const status = active ? 'Active' : 'Scheduled'; + const scopes = Object.entries(f.ProjectEnvironmentScope || {}).map(([p, envs]) => `${p}: ${envs.join(', ')}`); + const tenantScopes = (f.TenantProjectEnvironmentScope || []).map( + (t) => `${t.TenantId}/${t.ProjectId}/${t.EnvironmentId}` + ); + return { + id: f.Id, + name: f.Name, + description: f.Description || null, + status, + freezeState: status, + start: iso(w.start), + end: iso(w.end), + hoursRemaining: active ? (w.end - now) / HOUR : null, + startsInHours: active ? null : (w.start - now) / HOUR, + recurring: !!(f.RecurringSchedule && f.RecurringSchedule.Type), + schedule: describe(f.RecurringSchedule), + projectCount: ids.projects.size, + environmentCount: ids.environments.size, + tenantCount: ids.tenants.size, + scopeSummary: scopes.concat(tenantScopes).join('; ') || null + }; + }) + .sort((a, b) => Date.parse(a.start) - Date.parse(b.start)); diff --git a/plugins/OctopusDeploy/v1/dataStreams/scripts/deploymentStatus.js b/plugins/OctopusDeploy/v1/dataStreams/scripts/deploymentStatus.js new file mode 100644 index 00000000..8b50cb53 --- /dev/null +++ b/plugins/OctopusDeploy/v1/dataStreams/scripts/deploymentStatus.js @@ -0,0 +1,51 @@ +// The dashboard returns deployments (Items) plus lookup arrays; join the names here. +const unwrap = (v) => (Array.isArray(v) ? v[0] : v); +const byId = (arr) => Object.fromEntries((arr || []).map((x) => [x.Id, x])); +const iso = (s) => (s ? new Date(s).toISOString() : null); +const seconds = (a, b) => { + const s = Date.parse(a); + const e = Date.parse(b); + return Number.isFinite(s) && Number.isFinite(e) ? Math.round((e - s) / 1000) : null; +}; + +const projects = byId(data.Projects); +const projectGroups = byId(data.ProjectGroups); +const environments = byId(data.Environments); +const tenants = byId(data.Tenants); +// The dashboard lists environments in lifecycle sort order, so position is the sort order +const envOrder = Object.fromEntries((data.Environments || []).map((e, i) => [e.Id, i + 1])); +// Narrow to the scoped object; a Space scope keeps everything. +const scoped = context.objects[0].rawId; +const spaceId = scoped.startsWith('Spaces-') ? scoped : unwrap(context.objects[0].spaceId); +const keep = (d) => + (!scoped.startsWith('Projects-') || d.ProjectId === scoped) && + (!scoped.startsWith('Environments-') || d.EnvironmentId === scoped) && + (!scoped.startsWith('Tenants-') || d.TenantId === scoped); + +const current = (data.Items || []).filter((d) => d.IsCurrent !== false && keep(d)); +const groupName = (projectId) => (projectGroups[(projects[projectId] || {}).ProjectGroupId] || {}).Name || null; + +result = current + .map((d) => ({ + projectGroupName: groupName(d.ProjectId), + projectName: (projects[d.ProjectId] || {}).Name || d.ProjectId, + environmentName: (environments[d.EnvironmentId] || {}).Name || d.EnvironmentId, + environmentSortOrder: envOrder[d.EnvironmentId] || null, + tenantName: d.TenantId ? (tenants[d.TenantId] || {}).Name || d.TenantId : null, + releaseVersion: d.ReleaseVersion, + status: d.HasPendingInterruptions ? 'AwaitingIntervention' : d.State, + state: d.State, + queueTime: iso(d.QueueTime), + startTime: iso(d.StartTime), + completedTime: iso(d.CompletedTime), + durationSeconds: seconds(d.StartTime, d.CompletedTime), + hasWarningsOrErrors: !!d.HasWarningsOrErrors, + hasPendingInterruptions: !!d.HasPendingInterruptions, + errorMessage: d.ErrorMessage || null, + projectId: d.ProjectId, + environmentId: d.EnvironmentId, + tenantId: d.TenantId || null, + taskId: d.TaskId, + deploymentId: d.DeploymentId || d.Id, + spaceId + })); diff --git a/plugins/OctopusDeploy/v1/dataStreams/scripts/deploymentTargets.js b/plugins/OctopusDeploy/v1/dataStreams/scripts/deploymentTargets.js new file mode 100644 index 00000000..cb8ecd04 --- /dev/null +++ b/plugins/OctopusDeploy/v1/dataStreams/scripts/deploymentTargets.js @@ -0,0 +1,21 @@ +result = (data.Items || []).map((m) => { + // Only listening and polling Tentacles report a Tentacle version; SSH, cloud and Kubernetes targets don't. + const tentacle = m.Endpoint && m.Endpoint.TentacleVersionDetails; + return { + Id: m.Id, + Name: m.Name, + HealthStatus: m.HealthStatus, + StatusSummary: m.StatusSummary, + IsDisabled: m.IsDisabled, + EnvironmentIds: m.EnvironmentIds || [], + TenantIds: m.TenantIds || [], + Roles: m.Roles || [], + CommunicationStyle: m.Endpoint ? m.Endpoint.CommunicationStyle : null, + OperatingSystem: m.OperatingSystem || null, + ShellName: m.ShellName || null, + TentacleVersion: tentacle ? tentacle.Version : null, + TentacleUpgrade: !tentacle ? null : tentacle.UpgradeRequired ? 'Required' : tentacle.UpgradeSuggested ? 'Suggested' : 'Up to date', + HasLatestCalamari: m.HasLatestCalamari, + SpaceId: m.SpaceId + }; +}); diff --git a/plugins/OctopusDeploy/v1/dataStreams/scripts/deployments.js b/plugins/OctopusDeploy/v1/dataStreams/scripts/deployments.js new file mode 100644 index 00000000..ed315269 --- /dev/null +++ b/plugins/OctopusDeploy/v1/dataStreams/scripts/deployments.js @@ -0,0 +1,37 @@ +// The report is XML, so every field arrives as a single-element array; unwrap and drop empty strings. +const v = (x) => { + const s = Array.isArray(x) ? x[0] : x; + return s === '' || s === undefined ? null : s; +}; +// Report timestamps are UTC but carry no offset. +const utc = (x) => (v(x) ? v(x) + 'Z' : null); + +// The report filters projects and environments itself; tenants are filtered here. A Space scope keeps everything. +const scoped = context.objects[0].rawId; +const spaceId = scoped.startsWith('Spaces-') ? scoped : [].concat(context.objects[0].spaceId)[0]; + +const rows = [].concat((data && data.Deployments && data.Deployments.Deployment) || []); + +result = rows + .map((d) => ({ + projectName: v(d.ProjectName), + environmentName: v(d.EnvironmentName), + tenantName: v(d.TenantName), + channelName: v(d.ChannelName), + releaseVersion: v(d.ReleaseVersion), + state: v(d.TaskState), + deployedBy: v(d.DeployedBy), + queueTime: utc(d.QueueTime), + startTime: utc(d.StartTime), + completedTime: utc(d.CompletedTime), + durationSeconds: v(d.DurationSeconds) === null ? null : Number(v(d.DurationSeconds)), + projectId: v(d.ProjectId), + environmentId: v(d.EnvironmentId), + tenantId: v(d.TenantId), + releaseId: v(d.ReleaseId), + deploymentId: v(d.DeploymentId), + taskId: v(d.TaskId), + spaceId + })) + .filter((r) => r.deploymentId) + .filter((r) => !scoped.startsWith('Tenants-') || r.tenantId === scoped); diff --git a/plugins/OctopusDeploy/v1/dataStreams/scripts/license.js b/plugins/OctopusDeploy/v1/dataStreams/scripts/license.js new file mode 100644 index 00000000..96c9624f --- /dev/null +++ b/plugins/OctopusDeploy/v1/dataStreams/scripts/license.js @@ -0,0 +1,24 @@ +// The license is server-wide and carries no space, so a Space scope returns it only for the +// default space; otherwise every space in a multi-space tile would repeat it. +const isDefaultSpace = String([].concat(context.objects[0].isDefault)[0]) === 'true'; + +const license = { + hostingEnvironment: data.HostingEnvironment || null, + isCompliant: data.IsCompliant === true, + complianceSummary: data.ComplianceSummary || null, + expiryDate: data.EffectiveExpiryDate || null, + daysToExpiry: typeof data.DaysToEffectiveExpiryDate === 'number' ? data.DaysToEffectiveExpiryDate : null +}; + +result = !isDefaultSpace + ? [] + : (data.Limits || []).map((l) => ({ + limitName: l.Name, + currentUsage: l.CurrentUsage, + limit: l.IsUnlimited ? null : l.EffectiveLimit, + isUnlimited: l.IsUnlimited === true, + usagePercent: !l.IsUnlimited && l.EffectiveLimit > 0 ? Math.round((l.CurrentUsage / l.EffectiveLimit) * 100) : null, + limitStatus: l.LimitStatus, + limitMessage: l.Message, + ...license + })); diff --git a/plugins/OctopusDeploy/v1/dataStreams/scripts/pendingInterventions.js b/plugins/OctopusDeploy/v1/dataStreams/scripts/pendingInterventions.js new file mode 100644 index 00000000..b2e28c12 --- /dev/null +++ b/plugins/OctopusDeploy/v1/dataStreams/scripts/pendingInterventions.js @@ -0,0 +1,43 @@ +// Interruptions link to their deployment or run through RelatedDocumentIds; pick the ids out by prefix. +const unwrap = (v) => (Array.isArray(v) ? v[0] : v); +const scoped = context.objects[0].rawId; +const spaceId = scoped.startsWith('Spaces-') ? scoped : unwrap(context.objects[0].spaceId); +const iso = (s) => (s && Number.isFinite(Date.parse(s)) ? new Date(s).toISOString() : null); +const minutes = (s) => (Number.isFinite(Date.parse(s)) ? Math.max(0, Math.round((Date.now() - Date.parse(s)) / 60000)) : null); +const related = (i) => i.RelatedDocumentIds || []; +const pick = (i, prefix) => related(i).find((id) => id.startsWith(prefix)) || null; + +// The instructions are the paragraph text in the form, when the step has one +const instructions = (i) => { + const elements = (i.Form && i.Form.Elements) || []; + const text = elements + .map((e) => e.Control && e.Control.Type === 'Paragraph' && e.Control.Text) + .filter(Boolean); + return text.length ? text.join('\n') : null; +}; + +const typeLabel = { ManualIntervention: 'Manual intervention', GuidedFailure: 'Guided failure' }; + +// Narrow to the scoped object; a Space scope keeps everything. +const keep = (i) => scoped.startsWith('Spaces-') || related(i).includes(scoped); + +result = (data.Items || []) + .filter((i) => i.IsPending !== false && keep(i)) + .map((i) => ({ + title: i.Title, + type: typeLabel[i.Type] || i.Type || null, + status: 'Pending', + instructions: instructions(i), + created: iso(i.Created), + waitingMinutes: minutes(i.Created), + hasResponsibility: !!i.HasResponsibility, + responsibleUserId: i.ResponsibleUserId || null, + canTakeResponsibility: !!i.CanTakeResponsibility, + responsibleTeamIds: i.ResponsibleTeamIds || [], + projectId: pick(i, 'Projects-'), + environmentId: pick(i, 'Environments-'), + tenantId: pick(i, 'Tenants-'), + taskId: i.TaskId || pick(i, 'ServerTasks-'), + interruptionId: i.Id, + spaceId: i.SpaceId || spaceId + })); diff --git a/plugins/OctopusDeploy/v1/dataStreams/scripts/releaseProgression.js b/plugins/OctopusDeploy/v1/dataStreams/scripts/releaseProgression.js new file mode 100644 index 00000000..dbe4da7b --- /dev/null +++ b/plugins/OctopusDeploy/v1/dataStreams/scripts/releaseProgression.js @@ -0,0 +1,40 @@ +// One row per release and environment (lifecycle order), so a status grid can draw the +// release-by-environment view. The request only targets the selected project's own space; +// other spaces return no Releases. +const MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; +const pad = (n) => String(n).padStart(2, '0'); +const when = (s) => { + const t = new Date(s); + return Number.isFinite(t.getTime()) ? `${t.getUTCDate()} ${MONTHS[t.getUTCMonth()]} ${pad(t.getUTCHours())}:${pad(t.getUTCMinutes())} UTC` : ''; +}; + +const limit = Number(context.config && context.config.releaseCount) || 10; +const envs = (data && data.Environments) || []; +const rows = []; + +((data && data.Releases) || []).slice(0, limit).forEach((r, releaseIndex) => { + envs.forEach((e, envIndex) => { + // An environment can hold several deployments of a release (redeployments, tenants); use the latest. + const deps = ((r.Deployments || {})[e.Id] || []).slice().sort((a, b) => Date.parse(b.Created) - Date.parse(a.Created)); + const d = deps[0]; + const ready = !d && (r.NextDeployments || []).includes(e.Id); + rows.push({ + releaseVersion: r.Release.Version, + releaseSortOrder: releaseIndex + 1, + channelName: r.Channel ? r.Channel.Name : null, + releaseCreated: r.Release.Assembled || null, + environmentName: e.Name, + environmentSortOrder: envIndex + 1, + // Newest release first, then environments in lifecycle order + gridOrder: releaseIndex * 1000 + envIndex, + state: d ? (d.HasPendingInterruptions ? 'AwaitingIntervention' : d.State) : ready ? 'ReadyToDeploy' : 'NotDeployed', + detail: d ? when(d.CompletedTime || d.StartTime || d.QueueTime) : ready ? 'Ready to deploy' : 'Not deployed', + deployedTime: d ? new Date(d.CompletedTime || d.StartTime || d.QueueTime).toISOString() : null, + releaseId: r.Release.Id, + projectId: r.Release.ProjectId, + environmentId: e.Id + }); + }); +}); + +result = rows; diff --git a/plugins/OctopusDeploy/v1/dataStreams/scripts/runbookStatus.js b/plugins/OctopusDeploy/v1/dataStreams/scripts/runbookStatus.js new file mode 100644 index 00000000..7165d03a --- /dev/null +++ b/plugins/OctopusDeploy/v1/dataStreams/scripts/runbookStatus.js @@ -0,0 +1,40 @@ +// One row per environment the runbook can run in (lifecycle order), showing the latest run there. +// The request only targets the selected runbook's own space. +const MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; +const pad = (n) => String(n).padStart(2, '0'); +const when = (s) => { + const t = new Date(s); + return Number.isFinite(t.getTime()) ? `${t.getUTCDate()} ${MONTHS[t.getUTCMonth()]} ${pad(t.getUTCHours())}:${pad(t.getUTCMinutes())} UTC` : ''; +}; +const iso = (s) => { + const t = new Date(s); + return s && Number.isFinite(t.getTime()) ? t.toISOString() : null; +}; + +const envs = (data && data.Environments) || []; +const runs = (data && data.RunbookRuns) || {}; +const scoped = (context.objects && context.objects[0]) || {}; +const anyRun = Object.values(runs).reduce((a, l) => a.concat(l), [])[0]; + +result = envs.map((e, envIndex) => { + // An environment can hold several runs (tenants, reruns); use the latest. + const list = (runs[e.Id] || []).slice().sort((a, b) => Date.parse(b.Created) - Date.parse(a.Created)); + const r = list[0]; + const finished = r ? r.CompletedTime || r.StartTime || r.QueueTime || r.Created : null; + const seconds = r && r.StartTime && r.CompletedTime ? Math.max(0, Math.round((Date.parse(r.CompletedTime) - Date.parse(r.StartTime)) / 1000)) : null; + return { + environmentName: e.Name, + environmentSortOrder: envIndex + 1, + state: r ? (r.HasPendingInterruptions ? 'AwaitingIntervention' : r.State) : 'NeverRun', + detail: r ? when(finished) : 'Never run', + lastRunTime: r ? iso(finished) : null, + durationSeconds: seconds, + runBy: r ? r.RunBy || null : null, + snapshotName: r ? r.RunbookSnapshotName || null : null, + errorMessage: r ? r.ErrorMessage || null : null, + runbookId: r ? r.RunbookId : scoped.rawId || null, + projectId: r ? r.ProjectId : anyRun ? anyRun.ProjectId : null, + environmentId: e.Id, + taskId: r ? r.TaskId : null + }; +}); diff --git a/plugins/OctopusDeploy/v1/dataStreams/scripts/tenants.js b/plugins/OctopusDeploy/v1/dataStreams/scripts/tenants.js new file mode 100644 index 00000000..03f139d5 --- /dev/null +++ b/plugins/OctopusDeploy/v1/dataStreams/scripts/tenants.js @@ -0,0 +1,8 @@ +result = (data.Items || []).map((t) => ({ + Id: t.Id, + Name: t.Name, + Description: t.Description, + IsDisabled: t.IsDisabled, + TenantTags: Array.isArray(t.TenantTags) ? t.TenantTags : [], + SpaceId: t.SpaceId +})); diff --git a/plugins/OctopusDeploy/v1/dataStreams/scripts/workers.js b/plugins/OctopusDeploy/v1/dataStreams/scripts/workers.js new file mode 100644 index 00000000..8bf98f3b --- /dev/null +++ b/plugins/OctopusDeploy/v1/dataStreams/scripts/workers.js @@ -0,0 +1,19 @@ +result = (data.Items || []).map((m) => { + // Only listening and polling Tentacles report a Tentacle version; SSH, cloud and Kubernetes targets don't. + const tentacle = m.Endpoint && m.Endpoint.TentacleVersionDetails; + return { + Id: m.Id, + Name: m.Name, + HealthStatus: m.HealthStatus, + StatusSummary: m.StatusSummary, + IsDisabled: m.IsDisabled, + WorkerPoolIds: m.WorkerPoolIds || [], + CommunicationStyle: m.Endpoint ? m.Endpoint.CommunicationStyle : null, + OperatingSystem: m.OperatingSystem || null, + ShellName: m.ShellName || null, + TentacleVersion: tentacle ? tentacle.Version : null, + TentacleUpgrade: !tentacle ? null : tentacle.UpgradeRequired ? 'Required' : tentacle.UpgradeSuggested ? 'Suggested' : 'Up to date', + HasLatestCalamari: m.HasLatestCalamari, + SpaceId: m.SpaceId + }; +}); diff --git a/plugins/OctopusDeploy/v1/dataStreams/spaces.json b/plugins/OctopusDeploy/v1/dataStreams/spaces.json new file mode 100644 index 00000000..e50b0f5a --- /dev/null +++ b/plugins/OctopusDeploy/v1/dataStreams/spaces.json @@ -0,0 +1,57 @@ +{ + "name": "spaces", + "displayName": "Spaces", + "description": "All spaces on the Octopus server", + "tags": [ + "Inventory" + ], + "baseDataSourceName": "httpRequestUnscoped", + "config": { + "httpMethod": "get", + "endpointPath": "api/spaces/all" + }, + "matches": "none", + "visibility": { + "type": "hidden" + }, + "metadata": [ + { + "name": "Id", + "displayName": "ID", + "shape": "string", + "role": "id" + }, + { + "name": "Name", + "displayName": "Name", + "shape": "string", + "role": "label" + }, + { + "name": "Slug", + "displayName": "Slug", + "shape": "string" + }, + { + "name": "Description", + "displayName": "Description", + "shape": "string" + }, + { + "name": "IsDefault", + "displayName": "Default Space", + "shape": "boolean" + }, + { + "name": "TaskQueueStopped", + "displayName": "Task Queue Stopped", + "shape": "boolean" + }, + { + "sourceId": "Id", + "sourceType": "Space", + "name": "Name" + } + ], + "timeframes": false +} diff --git a/plugins/OctopusDeploy/v1/dataStreams/tasks.json b/plugins/OctopusDeploy/v1/dataStreams/tasks.json new file mode 100644 index 00000000..c3162ae1 --- /dev/null +++ b/plugins/OctopusDeploy/v1/dataStreams/tasks.json @@ -0,0 +1,283 @@ +{ + "name": "tasks", + "displayName": "Tasks", + "description": "Octopus server tasks such as deployments, runbook runs and health checks with their state and timings (a timeframe of None returns queued and running tasks only)", + "tags": [ + "Tasks" + ], + "baseDataSourceName": "httpRequestScopedSingle", + "config": { + "httpMethod": "get", + "endpointPath": "api/{{ object.rawId.startsWith('Spaces-') ? object.rawId : object.spaceId }}/tasks", + "getArgs": [ + { + "key": "name", + "value": "{{ (typeof taskType !== 'undefined' && taskType && taskType.length) ? [].concat(taskType).join(',') : null }}" + }, + { + "key": "states", + "value": "{{ (typeof state !== 'undefined' && state && state.length) ? [].concat(state).join(',') : null }}" + }, + { + "key": "fromQueueDate", + "value": "{{ timeframe.enum === 'none' ? null : timeframe.start }}" + }, + { + "key": "toQueueDate", + "value": "{{ timeframe.enum === 'none' ? null : timeframe.end }}" + }, + { + "key": "active", + "value": "{{ timeframe.enum === 'none' ? 'true' : null }}" + }, + { + "key": "project", + "value": "{{ object.rawId.startsWith('Projects-') ? object.rawId : null }}" + }, + { + "key": "environment", + "value": "{{ object.rawId.startsWith('Environments-') ? object.rawId : null }}" + }, + { + "key": "tenant", + "value": "{{ object.rawId.startsWith('Tenants-') ? object.rawId : null }}" + }, + { + "key": "runbook", + "value": "{{ object.rawId.startsWith('Runbooks-') ? object.rawId : null }}" + } + ], + "paging": { + "mode": "offset", + "pageSize": { + "realm": "queryArg", + "path": "take", + "value": "200" + }, + "offset": { + "mode": "row", + "base": 0, + "rowCountIn": { + "realm": "payloadArraySize", + "path": "Items" + } + }, + "out": { + "realm": "queryArg", + "path": "skip" + } + }, + "pathToData": "Items" + }, + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Space", + "Project", + "Environment", + "Tenant", + "Runbook" + ] + } + }, + "ui": [ + { + "type": "choiceChips", + "name": "taskType", + "label": "Task type(s)", + "isMulti": true, + "options": [ + { + "value": "Deploy", + "label": "Deployment" + }, + { + "value": "RunbookRun", + "label": "Runbook run" + }, + { + "value": "Health", + "label": "Health check" + }, + { + "value": "Retention", + "label": "Retention" + }, + { + "value": "AdHocScript", + "label": "Ad hoc script" + }, + { + "value": "Upgrade", + "label": "Upgrade" + } + ] + }, + { + "type": "choiceChips", + "name": "state", + "label": "State(s)", + "isMulti": true, + "options": [ + { + "value": "Queued", + "label": "Queued" + }, + { + "value": "Executing", + "label": "Executing" + }, + { + "value": "Success", + "label": "Success" + }, + { + "value": "Failed", + "label": "Failed" + }, + { + "value": "TimedOut", + "label": "Timed out" + }, + { + "value": "Cancelling", + "label": "Cancelling" + }, + { + "value": "Canceled", + "label": "Canceled" + } + ] + } + ], + "metadata": [ + { + "name": "Id", + "displayName": "ID", + "shape": "string", + "role": "id", + "visible": false + }, + { + "name": "Description", + "displayName": "Description", + "shape": "string", + "role": "label" + }, + { + "name": "Name", + "displayName": "Task Type", + "shape": "string" + }, + { + "name": "State", + "displayName": "State", + "shape": "string" + }, + { + "name": "status", + "displayName": "Status", + "computed": true, + "valueExpression": "{{ $['HasPendingInterruptions'] ? 'warning' : ($['State'] === 'Success' ? 'success' : (['Failed','TimedOut'].includes($['State']) ? 'error' : (['Canceled','Cancelling'].includes($['State']) ? 'warning' : 'unknown'))) }}", + "shape": [ + "state", + { + "map": { + "success": [ + "success" + ], + "warning": [ + "warning" + ], + "error": [ + "error" + ], + "unknown": [ + "unknown" + ] + } + } + ] + }, + { + "name": "QueueTime", + "displayName": "Queued", + "shape": "date", + "role": "timestamp" + }, + { + "name": "StartTime", + "displayName": "Started", + "shape": "date" + }, + { + "name": "CompletedTime", + "displayName": "Completed", + "shape": "date" + }, + { + "name": "durationSeconds", + "displayName": "Duration", + "computed": true, + "valueExpression": "{{ $['StartTime'] ? Math.round(((($['CompletedTime'] ? new Date($['CompletedTime']) : new Date()) - new Date($['StartTime']))) / 1000) : null }}", + "shape": "seconds" + }, + { + "name": "queuedSeconds", + "displayName": "Wait time", + "computed": true, + "valueExpression": "{{ $['QueueTime'] ? Math.round(((($['StartTime'] ? new Date($['StartTime']) : new Date()) - new Date($['QueueTime']))) / 1000) : null }}", + "shape": "seconds" + }, + { + "name": "HasPendingInterruptions", + "displayName": "Awaiting Intervention", + "shape": "boolean" + }, + { + "name": "HasWarningsOrErrors", + "displayName": "Has Warnings Or Errors", + "shape": "boolean" + }, + { + "name": "ErrorMessage", + "displayName": "Error Message", + "shape": "string" + }, + { + "name": "ProjectId", + "displayName": "Project ID", + "shape": "string", + "visible": false + }, + { + "name": "projectName", + "displayName": "Project", + "sourceId": "ProjectId", + "sourceType": "Project", + "objectPropertyPath": "name", + "valueExpression": "{{ object && object.name ? object.name : '' }}" + }, + { + "name": "SpaceId", + "displayName": "Space ID", + "shape": "string", + "visible": false + }, + { + "sourceId": "ProjectId", + "sourceType": "Project", + "name": "projectName" + } + ], + "timeframes": [ + "last1hour", + "last12hours", + "last24hours", + "last7days", + "none" + ], + "supportsNoneTimeframe": true, + "defaultTimeframe": "none" +} diff --git a/plugins/OctopusDeploy/v1/dataStreams/tenants.json b/plugins/OctopusDeploy/v1/dataStreams/tenants.json new file mode 100644 index 00000000..715a7d68 --- /dev/null +++ b/plugins/OctopusDeploy/v1/dataStreams/tenants.json @@ -0,0 +1,85 @@ +{ + "name": "tenants", + "displayName": "Tenants", + "description": "Tenants in a space, with tags and disabled status", + "tags": [ + "Inventory" + ], + "baseDataSourceName": "httpRequestScopedSingle", + "config": { + "httpMethod": "get", + "endpointPath": "api/{{object.rawId}}/tenants", + "paging": { + "mode": "offset", + "pageSize": { + "realm": "queryArg", + "path": "take", + "value": "250" + }, + "offset": { + "mode": "row", + "base": 0, + "rowCountIn": { + "realm": "payloadArraySize", + "path": "Items" + } + }, + "out": { + "realm": "queryArg", + "path": "skip" + } + }, + "postRequestScript": "tenants.js" + }, + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Space" + ] + } + }, + "visibility": { + "type": "hidden" + }, + "metadata": [ + { + "name": "Id", + "displayName": "ID", + "shape": "string", + "role": "id" + }, + { + "name": "Name", + "displayName": "Name", + "shape": "string", + "role": "label" + }, + { + "name": "Description", + "displayName": "Description", + "shape": "string" + }, + { + "name": "IsDisabled", + "displayName": "Disabled", + "shape": "boolean" + }, + { + "name": "TenantTags", + "displayName": "Tags", + "shape": ["array", { "itemShape": "string" }] + }, + { + "name": "SpaceId", + "displayName": "Space ID", + "shape": "string" + }, + { + "sourceId": "Id", + "sourceType": "Tenant", + "name": "Name" + } + ], + "timeframes": false +} diff --git a/plugins/OctopusDeploy/v1/dataStreams/workerPoolList.json b/plugins/OctopusDeploy/v1/dataStreams/workerPoolList.json new file mode 100644 index 00000000..173fb0c5 --- /dev/null +++ b/plugins/OctopusDeploy/v1/dataStreams/workerPoolList.json @@ -0,0 +1,90 @@ +{ + "name": "workerPoolList", + "displayName": "Worker Pools", + "description": "Worker pools in a space, static or dynamic", + "tags": [ + "Inventory" + ], + "baseDataSourceName": "httpRequestScopedSingle", + "config": { + "httpMethod": "get", + "endpointPath": "api/{{object.rawId}}/workerpools", + "paging": { + "mode": "offset", + "pageSize": { + "realm": "queryArg", + "path": "take", + "value": "250" + }, + "offset": { + "mode": "row", + "base": 0, + "rowCountIn": { + "realm": "payloadArraySize", + "path": "Items" + } + }, + "out": { + "realm": "queryArg", + "path": "skip" + } + }, + "pathToData": "Items" + }, + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Space" + ] + } + }, + "visibility": { + "type": "hidden" + }, + "metadata": [ + { + "name": "Id", + "displayName": "ID", + "shape": "string", + "role": "id" + }, + { + "name": "Name", + "displayName": "Name", + "shape": "string", + "role": "label" + }, + { + "name": "Description", + "displayName": "Description", + "shape": "string" + }, + { + "name": "WorkerPoolType", + "displayName": "Pool Type", + "shape": "string" + }, + { + "name": "WorkerType", + "displayName": "Worker Type", + "shape": "string" + }, + { + "name": "IsDefault", + "displayName": "Default Pool", + "shape": "boolean" + }, + { + "name": "SpaceId", + "displayName": "Space ID", + "shape": "string" + }, + { + "sourceId": "Id", + "sourceType": "Worker Pool", + "name": "Name" + } + ], + "timeframes": false +} diff --git a/plugins/OctopusDeploy/v1/dataStreams/workers.json b/plugins/OctopusDeploy/v1/dataStreams/workers.json new file mode 100644 index 00000000..9900f19a --- /dev/null +++ b/plugins/OctopusDeploy/v1/dataStreams/workers.json @@ -0,0 +1,184 @@ +{ + "name": "workers", + "displayName": "Workers", + "description": "Workers with their current health status, worker pools and agent versions", + "tags": [ + "Infrastructure", + "Health" + ], + "baseDataSourceName": "httpRequestScopedSingle", + "config": { + "httpMethod": "get", + "endpointPath": "api/{{ object.rawId.startsWith('Spaces-') ? object.rawId : object.spaceId }}/workers", + "getArgs": [ + { + "key": "workerPoolIds", + "value": "{{ object.rawId.startsWith('WorkerPools-') ? object.rawId : null }}" + }, + { + "key": "ids", + "value": "{{ object.rawId.startsWith('Workers-') ? object.rawId : null }}" + } + ], + "paging": { + "mode": "offset", + "pageSize": { + "realm": "queryArg", + "path": "take", + "value": "250" + }, + "offset": { + "mode": "row", + "base": 0, + "rowCountIn": { + "realm": "payloadArraySize", + "path": "Items" + } + }, + "out": { + "realm": "queryArg", + "path": "skip" + } + }, + "postRequestScript": "workers.js" + }, + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Space", + "Worker Pool", + "Worker" + ] + } + }, + "metadata": [ + { + "name": "Id", + "displayName": "ID", + "shape": "string", + "role": "id", + "visible": false + }, + { + "name": "Name", + "displayName": "Name", + "shape": "string", + "role": "label" + }, + { + "name": "health", + "displayName": "Health", + "computed": true, + "valueExpression": "{{ $['IsDisabled'] ? 'Disabled' : $['HealthStatus'] }}", + "shape": [ + "state", + { + "map": { + "success": [ + "Healthy" + ], + "warning": [ + "HasWarnings" + ], + "error": [ + "Unhealthy", + "Unavailable" + ], + "unknown": [ + "Unknown" + ], + "unmonitored": [ + "Disabled" + ] + } + } + ] + }, + { + "name": "HealthStatus", + "displayName": "Health Status", + "shape": "string" + }, + { + "name": "StatusSummary", + "displayName": "Status Summary", + "shape": "string" + }, + { + "name": "IsDisabled", + "displayName": "Disabled", + "shape": "boolean" + }, + { + "name": "WorkerPoolIds", + "displayName": "Worker Pool IDs", + "shape": ["array", { "itemShape": "string" }] + }, + { + "name": "CommunicationStyle", + "displayName": "Communication Style", + "shape": "string" + }, + { + "name": "OperatingSystem", + "displayName": "Operating System", + "shape": "string" + }, + { + "name": "ShellName", + "displayName": "Shell", + "shape": "string" + }, + { + "name": "TentacleVersion", + "displayName": "Tentacle Version", + "shape": "string" + }, + { + "name": "TentacleUpgrade", + "displayName": "Tentacle Upgrade", + "shape": "string" + }, + { + "name": "HasLatestCalamari", + "displayName": "Latest Calamari", + "shape": "boolean" + }, + { + "name": "agentStatus", + "displayName": "Agent Status", + "computed": true, + "valueExpression": "{{ $['TentacleUpgrade'] === 'Required' ? 'Upgrade required' : ($['TentacleUpgrade'] === 'Suggested' ? 'Upgrade suggested' : ($['HasLatestCalamari'] === false ? 'Calamari update' : 'Up to date')) }}", + "shape": [ + "state", + { + "map": { + "success": [ + "Up to date" + ], + "warning": [ + "Upgrade suggested", + "Calamari update" + ], + "error": [ + "Upgrade required" + ] + } + } + ] + }, + { + "name": "SpaceId", + "displayName": "Space ID", + "shape": "string", + "visible": false + }, + { + "sourceId": "Id", + "sourceType": "Worker", + "name": "Name" + } + ], + "timeframes": false +} diff --git a/plugins/OctopusDeploy/v1/defaultContent/audit.dash.json b/plugins/OctopusDeploy/v1/defaultContent/audit.dash.json new file mode 100644 index 00000000..f3a96fde --- /dev/null +++ b/plugins/OctopusDeploy/v1/defaultContent/audit.dash.json @@ -0,0 +1,822 @@ +{ + "name": "Audit", + "schemaVersion": "1.5", + "timeframe": "last24hours", + "dashboard": { + "_type": "layout/grid", + "columns": 4, + "version": 1, + "contents": [ + { + "i": "8989043f-f707-4958-b193-9248668535b3", + "x": 0, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Events", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[auditEvents]}}", + "name": "auditEvents", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Events" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "scalar", + "encoding": { + "values": [ + { + "field": "count", + "type": "quantitative", + "title": "Events" + } + ] + }, + "style": { + "scalarLabelText": "Events" + } + } + } + } + }, + { + "i": "b2313e8a-ddee-43d3-9c0e-99b818cda13a", + "x": 1, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Active Users", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[auditEvents]}}", + "name": "auditEvents", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "Username", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Users" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "scalar", + "encoding": { + "values": [ + { + "field": "count", + "type": "quantitative", + "title": "Users" + } + ] + }, + "style": { + "scalarRowCount": true, + "scalarLabelText": "Users" + } + } + } + } + }, + { + "i": "3f663ba7-b8f1-48dd-9f6a-a46baef52025", + "x": 2, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Changes", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[auditEvents]}}", + "name": "auditEvents", + "pluginConfigId": "{{configId}}", + "filter": { + "multiOperation": "or", + "filters": [ + { + "column": "Category", + "operation": "equals", + "value": "Created" + }, + { + "column": "Category", + "operation": "equals", + "value": "Modified" + }, + { + "column": "Category", + "operation": "equals", + "value": "Deleted" + } + ] + }, + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Changes" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "scalar", + "encoding": { + "values": [ + { + "field": "count", + "type": "quantitative", + "title": "Created, modified or deleted" + } + ] + }, + "style": { + "scalarLabelText": "Created, modified or deleted", + "scalarValueColor": "#2F93E0" + } + } + } + } + }, + { + "i": "312a27de-1ff3-44f0-90df-0f267f634ef5", + "x": 3, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Failed Logins", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[auditEvents]}}", + "name": "auditEvents", + "pluginConfigId": "{{configId}}", + "filter": { + "multiOperation": "or", + "filters": [ + { + "column": "Category", + "operation": "equals", + "value": "LoginFailed" + } + ] + }, + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Failed logins" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "scalar", + "encoding": { + "values": [ + { + "field": "count", + "type": "quantitative", + "title": "Failed logins" + } + ] + }, + "style": { + "scalarLabelText": "Failed logins", + "scalarValueColor": "#d63939" + } + } + } + } + }, + { + "i": "f1bea7be-4b63-459a-9c35-28b89d4ca920", + "x": 0, + "y": 2, + "w": 3, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Activity Over Time", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[auditEvents]}}", + "name": "auditEvents", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "Occurred", + "byHour" + ], + [ + "Category", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-bar-chart", + "config": { + "data-stream-bar-chart": { + "xAxisData": "Occurred_byHour", + "yAxisData": [ + "count" + ], + "xAxisGroup": "none", + "xAxisLabel": "", + "yAxisLabel": "", + "showXAxisLabel": false, + "showYAxisLabel": false, + "showLegend": false, + "legendPosition": "bottom", + "showGrid": true, + "horizontalLayout": "vertical", + "displayMode": "actual", + "showTotals": false, + "showValue": false, + "grouping": false, + "range": { + "type": "auto" + } + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "bar", + "encoding": { + "x": { + "field": "Occurred_byHour", + "type": "temporal", + "title": "Hour" + }, + "y": { + "field": "count", + "type": "quantitative", + "title": "Events" + }, + "series": { + "field": "Category_uniqueValues", + "type": "nominal", + "title": "Category" + } + }, + "style": { + "cartesianStack": "on", + "cartesianBarBorderRadius": 3, + "legendPosition": "bottom" + } + } + } + } + }, + { + "i": "3d21bf96-cdba-429e-8d75-0407b01bbc7b", + "x": 3, + "y": 2, + "w": 1, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "By Category", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[auditEvents]}}", + "name": "auditEvents", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "Category", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-donut-chart", + "config": { + "data-stream-donut-chart": { + "valueColumn": "count", + "labelColumn": "Category_uniqueValues", + "hideCenterValue": false, + "showValuesAsPercentage": false, + "legendPosition": "auto", + "legendMode": "table" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "pie", + "encoding": { + "label": { + "field": "Category_uniqueValues", + "type": "nominal", + "title": "Category" + }, + "value": { + "field": "count", + "type": "quantitative", + "title": "Events" + } + }, + "style": { + "pieInnerRadius": 60, + "pieDonutCenterValue": "total", + "labelFontSize": 16, + "pieLegendStyle": "table", + "pieOthersThreshold": 8 + } + } + } + } + }, + { + "i": "e601e6fb-9952-45b3-a367-ad157cbad866", + "x": 0, + "y": 5, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Most Active Users", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[auditEvents]}}", + "name": "auditEvents", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "Username", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + }, + "sort": { + "by": [ + [ + "count", + "desc" + ] + ], + "top": 10 + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-bar-chart", + "config": { + "data-stream-bar-chart": { + "xAxisData": "Username_uniqueValues", + "yAxisData": [ + "count" + ], + "xAxisGroup": "none", + "xAxisLabel": "", + "yAxisLabel": "", + "showXAxisLabel": false, + "showYAxisLabel": false, + "showLegend": false, + "legendPosition": "bottom", + "showGrid": true, + "horizontalLayout": "vertical", + "displayMode": "actual", + "showTotals": false, + "showValue": false, + "grouping": false, + "range": { + "type": "auto" + } + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "bar", + "encoding": { + "x": { + "field": "Username_uniqueValues", + "type": "nominal", + "title": "User" + }, + "y": { + "field": "count", + "type": "quantitative", + "title": "Events" + } + }, + "style": { + "cartesianHorizontal": true, + "cartesianBarBorderRadius": 3, + "colors": [ + "#2F93E0" + ], + "showLabels": true + } + } + } + } + }, + { + "i": "864897fc-9e4c-49ff-9eb2-e4092b76a855", + "x": 2, + "y": 5, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Configuration Changes", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[auditEvents]}}", + "name": "auditEvents", + "pluginConfigId": "{{configId}}", + "filter": { + "multiOperation": "or", + "filters": [ + { + "column": "Category", + "operation": "equals", + "value": "Created" + }, + { + "column": "Category", + "operation": "equals", + "value": "Modified" + }, + { + "column": "Category", + "operation": "equals", + "value": "Deleted" + } + ] + }, + "sort": { + "by": [ + [ + "Occurred", + "desc" + ] + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "Occurred", + "Username", + "Category", + "Message" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "Occurred", + "title": "When", + "renderer": { + "type": "date", + "relative": true + } + }, + { + "field": "Username", + "title": "User", + "renderer": { + "type": "text" + } + }, + { + "field": "Category", + "title": "Category", + "renderer": { + "type": "badge", + "colors": { + "*Failed": "#d63939", + "Deleted": "#d63939", + "Created": "#2fb344", + "Modified": "#2F93E0", + "*Succeeded": "#2fb344" + }, + "defaultColor": "#6b7280" + } + }, + { + "field": "Message", + "title": "Event", + "renderer": { + "type": "text" + } + }, + { + "field": "projectName", + "title": "Project", + "renderer": { + "type": "text" + } + } + ] + }, + "style": { + "richTableCellPadding": 6, + "richTableWrapText": true + } + } + } + } + }, + { + "i": "c2751957-8c5f-451e-a5f8-2d088e561479", + "x": 0, + "y": 8, + "w": 4, + "h": 5, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Recent Events", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[auditEvents]}}", + "name": "auditEvents", + "pluginConfigId": "{{configId}}", + "sort": { + "by": [ + [ + "Occurred", + "desc" + ] + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "Occurred", + "Username", + "Category", + "Message" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "Occurred", + "title": "When", + "renderer": { + "type": "date", + "relative": true + } + }, + { + "field": "Username", + "title": "User", + "renderer": { + "type": "text" + } + }, + { + "field": "Category", + "title": "Category", + "renderer": { + "type": "badge", + "colors": { + "*Failed": "#d63939", + "Deleted": "#d63939", + "Created": "#2fb344", + "Modified": "#2F93E0", + "*Succeeded": "#2fb344" + }, + "defaultColor": "#6b7280" + } + }, + { + "field": "Message", + "title": "Event", + "renderer": { + "type": "text" + } + }, + { + "field": "projectName", + "title": "Project", + "renderer": { + "type": "text" + } + }, + { + "field": "IpAddress", + "title": "IP Address", + "renderer": { + "type": "text" + } + } + ] + }, + "style": { + "richTableCellPadding": 6, + "richTableWrapText": true + } + } + } + } + } + ] + } +} diff --git a/plugins/OctopusDeploy/v1/defaultContent/deploymentTarget.dash.json b/plugins/OctopusDeploy/v1/defaultContent/deploymentTarget.dash.json new file mode 100644 index 00000000..d31b3bad --- /dev/null +++ b/plugins/OctopusDeploy/v1/defaultContent/deploymentTarget.dash.json @@ -0,0 +1,253 @@ +{ + "name": "Deployment Target", + "schemaVersion": "1.5", + "timeframe": "last24hours", + "variables": [ + "{{variables.[Octopus Deployment Target]}}" + ], + "dashboard": { + "_type": "layout/grid", + "columns": 4, + "version": 1, + "contents": [ + { + "i": "3817750d-1f53-4b03-8518-fabd2db468bd", + "x": 0, + "y": 0, + "w": 1, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Target Properties", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "datastream-properties", + "name": "properties", + "pluginConfigId": "{{configId}}" + }, + "scope": { + "scope": "{{scopes.[Octopus Deployment Targets]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Deployment Target]}}" + }, + "variables": [ + "{{variables.[Octopus Deployment Target]}}" + ], + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": true, + "columnOrder": [ + "name" + ], + "hiddenColumns": [ + "id", + "links", + "type", + "label", + "sourceId", + "sourceType", + "spaceId" + ] + } + } + } + } + }, + { + "i": "d561d4df-d3a6-4d52-9dee-5873fdf5f597", + "x": 1, + "y": 0, + "w": 1, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Health", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[deploymentTargets]}}", + "name": "deploymentTargets", + "pluginConfigId": "{{configId}}" + }, + "scope": { + "scope": "{{scopes.[Octopus Deployment Targets]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Deployment Target]}}" + }, + "variables": [ + "{{variables.[Octopus Deployment Target]}}" + ], + "visualisation": { + "type": "data-stream-blocks", + "config": { + "data-stream-blocks": { + "labelColumn": "Name", + "stateColumn": "health", + "sublabel": "HealthStatus", + "linkColumn": "none", + "columns": 4 + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "statusGrid", + "encoding": { + "label": { + "field": "Name", + "type": "nominal" + }, + "status": { + "field": "health", + "type": "nominal" + }, + "value": { + "field": "HealthStatus", + "type": "nominal" + } + }, + "style": { + "statusGridColumnsPerRow": 1, + "statusGridBlockGap": 8, + "statusGridMaxBlockHeight": 110 + } + } + } + } + }, + { + "i": "aa89ab44-2130-41de-9a39-c11bc771c42a", + "x": 2, + "y": 0, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Target Details", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[deploymentTargets]}}", + "name": "deploymentTargets", + "pluginConfigId": "{{configId}}" + }, + "scope": { + "scope": "{{scopes.[Octopus Deployment Targets]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Deployment Target]}}" + }, + "variables": [ + "{{variables.[Octopus Deployment Target]}}" + ], + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": true, + "columnOrder": [ + "Name", + "health", + "StatusSummary", + "Roles", + "CommunicationStyle", + "OperatingSystem" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "health", + "title": "Health", + "renderer": { + "type": "status" + } + }, + { + "field": "StatusSummary", + "title": "Status", + "renderer": { + "type": "text" + } + }, + { + "field": "Roles", + "title": "Target Tags", + "renderer": { + "type": "tag-list", + "separator": ",", + "color": "#2F93E0" + } + }, + { + "field": "CommunicationStyle", + "title": "Communication", + "renderer": { + "type": "badge", + "defaultColor": "#6b7280" + } + }, + { + "field": "OperatingSystem", + "title": "Operating System", + "renderer": { + "type": "text" + } + }, + { + "field": "ShellName", + "title": "Shell", + "renderer": { + "type": "text" + } + }, + { + "field": "IsDisabled", + "title": "Disabled", + "renderer": { + "type": "boolean", + "trueLabel": "Yes", + "falseLabel": "No" + } + } + ] + }, + "style": { + "richTableCellPadding": 6, + "richTableTranspose": true, + "richTableWrapText": true + } + } + } + } + } + ] + } +} diff --git a/plugins/OctopusDeploy/v1/defaultContent/environment.dash.json b/plugins/OctopusDeploy/v1/defaultContent/environment.dash.json new file mode 100644 index 00000000..d0bad908 --- /dev/null +++ b/plugins/OctopusDeploy/v1/defaultContent/environment.dash.json @@ -0,0 +1,1459 @@ +{ + "name": "Environment", + "schemaVersion": "1.5", + "timeframe": "last30days", + "variables": [ + "{{variables.[Octopus Environment]}}" + ], + "dashboard": { + "_type": "layout/grid", + "columns": 4, + "version": 1, + "contents": [ + { + "i": "56ac92ee-2b6e-4a31-896b-11acd9cfc1ca", + "x": 0, + "y": 0, + "w": 1, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Environment Properties", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "datastream-properties", + "name": "properties", + "pluginConfigId": "{{configId}}" + }, + "scope": { + "scope": "{{scopes.[Octopus Environments]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Environment]}}" + }, + "variables": [ + "{{variables.[Octopus Environment]}}" + ], + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": true, + "columnOrder": [ + "name" + ], + "hiddenColumns": [ + "id", + "links", + "type", + "label", + "sourceId", + "sourceType", + "spaceId" + ] + } + } + } + } + }, + { + "i": "c8c26cca-d72c-4c6a-8973-8fa3a7923941", + "x": 1, + "y": 0, + "w": 3, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Deployed Here", + "description": "Current release of each project in this environment", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[deploymentStatus]}}", + "name": "deploymentStatus", + "pluginConfigId": "{{configId}}" + }, + "scope": { + "scope": "{{scopes.[Octopus Environments]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Environment]}}" + }, + "variables": [ + "{{variables.[Octopus Environment]}}" + ], + "visualisation": { + "type": "data-stream-blocks", + "config": { + "data-stream-blocks": { + "labelColumn": "projectName", + "stateColumn": "status", + "sublabel": "releaseVersion", + "linkColumn": "none", + "columns": 4 + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "statusGrid", + "encoding": { + "label": { + "field": "projectName", + "type": "nominal" + }, + "status": { + "field": "status", + "type": "nominal" + }, + "value": { + "field": "releaseVersion", + "type": "nominal" + }, + "group": { + "field": "projectGroupName", + "type": "nominal" + } + }, + "style": { + "statusGridColumnsPerRow": 6, + "statusGridBlockGap": 8, + "statusGridMaxBlockHeight": 110 + } + } + } + } + }, + { + "i": "2ca17fdc-9186-4208-bc26-71b960732ffb", + "x": 1, + "y": 2, + "w": 3, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Deployment Targets", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[deploymentTargets]}}", + "name": "deploymentTargets", + "pluginConfigId": "{{configId}}" + }, + "scope": { + "scope": "{{scopes.[Octopus Environments]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Environment]}}" + }, + "variables": [ + "{{variables.[Octopus Environment]}}" + ], + "visualisation": { + "type": "data-stream-blocks", + "config": { + "data-stream-blocks": { + "labelColumn": "Name", + "stateColumn": "health", + "sublabel": "HealthStatus", + "linkColumn": "none", + "columns": 4 + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "statusGrid", + "encoding": { + "label": { + "field": "Name", + "type": "nominal" + }, + "status": { + "field": "health", + "type": "nominal" + }, + "value": { + "field": "HealthStatus", + "type": "nominal" + } + }, + "style": { + "statusGridColumnsPerRow": 4, + "statusGridBlockGap": 8, + "statusGridMaxBlockHeight": 110 + } + } + } + } + }, + { + "i": "986bb4ee-419c-455e-9a10-3cdf8450c255", + "x": 0, + "y": 4, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Deployments", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[deployments]}}", + "name": "deployments", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Environments]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Environment]}}" + }, + "variables": [ + "{{variables.[Octopus Environment]}}" + ], + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Deployments" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "scalar", + "encoding": { + "values": [ + { + "field": "count", + "type": "quantitative", + "title": "Deployments" + } + ] + }, + "style": { + "scalarLabelText": "Deployments" + } + } + } + } + }, + { + "i": "de0fe82c-1e1a-40aa-b746-3bbec4f88bf0", + "x": 1, + "y": 4, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Success Rate", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[deployments]}}", + "name": "deployments", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "mean", + "names": [ + "succeeded" + ] + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Environments]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Environment]}}" + }, + "variables": [ + "{{variables.[Octopus Environment]}}" + ], + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "succeeded_mean", + "comparisonColumn": "none", + "label": "Success rate" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "gauge", + "encoding": { + "value": { + "field": "succeeded_mean", + "type": "quantitative", + "title": "Success rate" + } + }, + "style": { + "gaugeMin": 0, + "gaugeMax": 100, + "gaugeLabelText": "Success rate", + "gaugeBands": [ + { + "to": 0.8, + "color": "#d63939" + }, + { + "to": 0.95, + "color": "#f59f00" + }, + { + "to": 1, + "color": "#2fb344" + } + ] + } + } + } + } + }, + { + "i": "7a781540-b679-4384-a697-d719ecf202c5", + "x": 2, + "y": 4, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Failed Deployments", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[deployments]}}", + "name": "deployments", + "pluginConfigId": "{{configId}}", + "filter": { + "multiOperation": "or", + "filters": [ + { + "column": "state", + "operation": "equals", + "value": "Failed" + }, + { + "column": "state", + "operation": "equals", + "value": "TimedOut" + } + ] + }, + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Environments]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Environment]}}" + }, + "variables": [ + "{{variables.[Octopus Environment]}}" + ], + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Failed" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "scalar", + "encoding": { + "values": [ + { + "field": "count", + "type": "quantitative", + "title": "Failed" + } + ] + }, + "style": { + "scalarLabelText": "Failed", + "scalarValueColor": "#d63939" + } + } + } + } + }, + { + "i": "83688488-0d27-4d9b-a099-a6a1afdcc840", + "x": 3, + "y": 4, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Active Tasks", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[tasks]}}", + "name": "tasks", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Environments]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Environment]}}" + }, + "variables": [ + "{{variables.[Octopus Environment]}}" + ], + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Queued or running" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "scalar", + "encoding": { + "values": [ + { + "field": "count", + "type": "quantitative", + "title": "Queued or running" + } + ] + }, + "style": { + "scalarLabelText": "Queued or running", + "scalarValueColor": "#2F93E0" + } + } + } + } + }, + { + "i": "af7efb4d-56fe-4dfc-a896-23f6f83e57f0", + "x": 0, + "y": 6, + "w": 4, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Deployment History by Project", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[deployments]}}", + "name": "deployments", + "pluginConfigId": "{{configId}}", + "sort": { + "by": [ + [ + "completedTime", + "desc" + ] + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Environments]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Environment]}}" + }, + "variables": [ + "{{variables.[Octopus Environment]}}" + ], + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "completedTime", + "projectName", + "environmentName", + "releaseVersion", + "status", + "durationSeconds" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "healthHistory", + "encoding": { + "time": { + "field": "completedTime", + "type": "temporal" + }, + "status": { + "field": "state", + "type": "nominal" + }, + "label": { + "field": "projectName", + "type": "nominal" + } + }, + "style": { + "historyStatusMap": { + "Success": "success", + "Failed": "error", + "TimedOut": "error", + "Canceled": "warning", + "Cancelling": "warning", + "Queued": "unknown", + "Executing": "unknown" + }, + "historySlots": 30, + "statusGridLabelWidth": 140 + } + } + } + } + }, + { + "i": "4067792c-84fc-43cc-bdc5-a5f5cff6f2c5", + "x": 0, + "y": 9, + "w": 3, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Deployment Frequency", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[deployments]}}", + "name": "deployments", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "completedTime", + "byDay" + ], + [ + "state", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Environments]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Environment]}}" + }, + "variables": [ + "{{variables.[Octopus Environment]}}" + ], + "visualisation": { + "type": "data-stream-bar-chart", + "config": { + "data-stream-bar-chart": { + "xAxisData": "completedTime_byDay", + "yAxisData": [ + "count" + ], + "xAxisGroup": "none", + "xAxisLabel": "", + "yAxisLabel": "", + "showXAxisLabel": false, + "showYAxisLabel": false, + "showLegend": false, + "legendPosition": "bottom", + "showGrid": true, + "horizontalLayout": "vertical", + "displayMode": "actual", + "showTotals": false, + "showValue": false, + "grouping": false, + "range": { + "type": "auto" + } + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "bar", + "encoding": { + "x": { + "field": "completedTime_byDay", + "type": "temporal", + "title": "Day" + }, + "y": { + "field": "count", + "type": "quantitative", + "title": "Deployments" + }, + "series": { + "field": "state_uniqueValues", + "type": "nominal", + "title": "Outcome" + } + }, + "style": { + "cartesianStack": "on", + "cartesianBarBorderRadius": 4, + "mappedColors": { + "Success": "#2fb344", + "Failed": "#d63939", + "TimedOut": "#d63939", + "Canceled": "#f59f00", + "Cancelling": "#f59f00", + "Queued": "#6b7280", + "Executing": "#2F93E0" + }, + "legendPosition": "bottom" + } + } + } + } + }, + { + "i": "d1947cba-4b0b-4a2a-86f0-a74ba5abad30", + "x": 3, + "y": 9, + "w": 1, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Deployment Outcomes", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[deployments]}}", + "name": "deployments", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "state", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Environments]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Environment]}}" + }, + "variables": [ + "{{variables.[Octopus Environment]}}" + ], + "visualisation": { + "type": "data-stream-donut-chart", + "config": { + "data-stream-donut-chart": { + "valueColumn": "count", + "labelColumn": "state_uniqueValues", + "hideCenterValue": false, + "showValuesAsPercentage": false, + "legendPosition": "auto", + "legendMode": "table" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "pie", + "encoding": { + "label": { + "field": "state_uniqueValues", + "type": "nominal", + "title": "Outcome" + }, + "value": { + "field": "count", + "type": "quantitative", + "title": "Deployments" + } + }, + "style": { + "pieInnerRadius": 60, + "pieDonutCenterValue": "total", + "labelFontSize": 16, + "pieLegendStyle": "table", + "mappedColors": { + "Success": "#2fb344", + "Failed": "#d63939", + "TimedOut": "#d63939", + "Canceled": "#f59f00", + "Cancelling": "#f59f00", + "Queued": "#6b7280", + "Executing": "#2F93E0" + } + } + } + } + } + }, + { + "i": "8b36a6fe-d296-436f-b07d-1581de104b8a", + "x": 0, + "y": 12, + "w": 4, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Recent Deployments", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[deployments]}}", + "name": "deployments", + "pluginConfigId": "{{configId}}", + "sort": { + "by": [ + [ + "completedTime", + "desc" + ] + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Environments]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Environment]}}" + }, + "variables": [ + "{{variables.[Octopus Environment]}}" + ], + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "completedTime", + "projectName", + "environmentName", + "releaseVersion", + "status", + "durationSeconds" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "completedTime", + "title": "Completed", + "renderer": { + "type": "date", + "relative": true + } + }, + { + "field": "projectName", + "title": "Project", + "renderer": { + "type": "text" + } + }, + { + "field": "tenantName", + "title": "Tenant", + "renderer": { + "type": "text" + } + }, + { + "field": "releaseVersion", + "title": "Release", + "renderer": { + "type": "badge", + "defaultColor": "#2F93E0" + } + }, + { + "field": "state", + "title": "Outcome", + "renderer": { + "type": "badge", + "colors": { + "Success": "#2fb344", + "Failed": "#d63939", + "TimedOut": "#d63939", + "Canceled": "#f59f00", + "Cancelling": "#f59f00", + "Queued": "#6b7280", + "Executing": "#2F93E0" + }, + "defaultColor": "#6b7280" + } + }, + { + "field": "durationSeconds", + "title": "Duration", + "renderer": { + "type": "bar", + "color": "#2F93E0" + } + }, + { + "field": "deployedBy", + "title": "Deployed By", + "renderer": { + "type": "text" + } + } + ] + }, + "style": { + "richTableCellPadding": 6, + "richTableRowHighlight": { + "field": "state", + "colors": { + "Failed": "rgba(214,57,57,0.15)", + "TimedOut": "rgba(214,57,57,0.15)" + } + } + } + } + } + } + }, + { + "i": "3eb1b5f4-509e-4e0f-9c0a-d0e6334c70c9", + "x": 0, + "y": 16, + "w": 4, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Recent Tasks", + "description": "Deployments and other tasks in this environment in the last 7 days", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "last7days", + "dataStream": { + "id": "{{dataStreams.[tasks]}}", + "name": "tasks", + "pluginConfigId": "{{configId}}", + "sort": { + "by": [ + [ + "QueueTime", + "desc" + ] + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Environments]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Environment]}}" + }, + "variables": [ + "{{variables.[Octopus Environment]}}" + ], + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "QueueTime", + "Description", + "Name", + "status", + "durationSeconds" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "QueueTime", + "title": "Queued", + "renderer": { + "type": "date", + "relative": true + } + }, + { + "field": "Description", + "title": "Task", + "renderer": { + "type": "text" + } + }, + { + "field": "Name", + "title": "Type", + "renderer": { + "type": "badge", + "defaultColor": "#6b7280" + } + }, + { + "field": "State", + "title": "State", + "renderer": { + "type": "badge", + "colors": { + "Success": "#2fb344", + "Failed": "#d63939", + "TimedOut": "#d63939", + "Canceled": "#f59f00", + "Cancelling": "#f59f00", + "Queued": "#6b7280", + "Executing": "#2F93E0" + }, + "defaultColor": "#6b7280" + } + }, + { + "field": "queuedSeconds", + "title": "Waited", + "renderer": { + "type": "number", + "suffix": " s", + "decimals": 0 + } + }, + { + "field": "durationSeconds", + "title": "Duration", + "renderer": { + "type": "bar", + "color": "#2F93E0" + } + }, + { + "field": "HasPendingInterruptions", + "title": "Needs Input", + "renderer": { + "type": "boolean", + "trueLabel": "Yes", + "falseLabel": "", + "trueColor": "#f59f00" + } + }, + { + "field": "ErrorMessage", + "title": "Error", + "renderer": { + "type": "text" + } + } + ] + }, + "style": { + "richTableCellPadding": 6 + } + } + } + } + }, + { + "i": "d075d5b4-232c-4670-8dc7-b658ed9bed9a", + "x": 0, + "y": 19, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Deployment Freezes", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[deploymentFreezes]}}", + "name": "deploymentFreezes", + "pluginConfigId": "{{configId}}" + }, + "scope": { + "scope": "{{scopes.[Octopus Environments]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Environment]}}" + }, + "variables": [ + "{{variables.[Octopus Environment]}}" + ], + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "name", + "status", + "start", + "end" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "name", + "title": "Freeze", + "renderer": { + "type": "text" + } + }, + { + "field": "status", + "title": "Status", + "renderer": { + "type": "badge", + "colors": { + "Active": "#d63939", + "Scheduled": "#f59f00" + }, + "defaultColor": "#6b7280" + } + }, + { + "field": "start", + "title": "Starts", + "renderer": { + "type": "date" + } + }, + { + "field": "end", + "title": "Ends", + "renderer": { + "type": "date", + "relative": true + } + }, + { + "field": "schedule", + "title": "Repeats", + "renderer": { + "type": "text" + } + }, + { + "field": "projectCount", + "title": "Projects", + "renderer": { + "type": "number" + } + }, + { + "field": "environmentCount", + "title": "Environments", + "renderer": { + "type": "number" + } + } + ] + }, + "style": { + "richTableCellPadding": 6 + } + } + } + } + }, + { + "i": "8808faa7-91b4-42a1-ade1-0a05448a5eee", + "x": 2, + "y": 19, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Certificates", + "description": "Certificates available to this environment", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[certificates]}}", + "name": "certificates", + "pluginConfigId": "{{configId}}", + "sort": { + "by": [ + [ + "DaysUntilExpiry", + "asc" + ] + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Environments]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Environment]}}" + }, + "variables": [ + "{{variables.[Octopus Environment]}}" + ], + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "Name", + "ExpiryStatus", + "DaysUntilExpiry", + "NotAfter" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "Name", + "title": "Certificate", + "renderer": { + "type": "text" + } + }, + { + "field": "ExpiryStatus", + "title": "Expiry", + "renderer": { + "type": "badge", + "colors": { + "Expired": "#d63939", + "Expiring soon": "#f59f00", + "Valid": "#2fb344" + }, + "defaultColor": "#6b7280" + } + }, + { + "field": "DaysUntilExpiry", + "title": "Days Left", + "renderer": { + "type": "number", + "thresholds": [ + { + "to": 0, + "color": "#d63939" + }, + { + "to": 30, + "color": "#f59f00" + }, + { + "to": 100000, + "color": "#2fb344" + } + ] + } + }, + { + "field": "NotAfter", + "title": "Expires", + "renderer": { + "type": "date" + } + }, + { + "field": "SubjectCommonName", + "title": "Subject", + "renderer": { + "type": "text" + } + }, + { + "field": "IssuerCommonName", + "title": "Issuer", + "renderer": { + "type": "text" + } + }, + { + "field": "SelfSigned", + "title": "Self-signed", + "renderer": { + "type": "boolean", + "trueLabel": "Yes", + "falseLabel": "No" + } + } + ] + }, + "style": { + "richTableCellPadding": 6, + "richTableRowHighlight": { + "field": "ExpiryStatus", + "colors": { + "Expired": "rgba(214,57,57,0.15)", + "Expiring soon": "rgba(245,159,0,0.12)" + } + } + } + } + } + } + }, + { + "i": "b057bb78-6831-47a9-8151-06c63a8c3916", + "x": 0, + "y": 22, + "w": 4, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Audit Trail", + "description": "Changes and activity for this environment in the last 7 days", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "last7days", + "dataStream": { + "id": "{{dataStreams.[auditEvents]}}", + "name": "auditEvents", + "pluginConfigId": "{{configId}}", + "sort": { + "by": [ + [ + "Occurred", + "desc" + ] + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Environments]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Environment]}}" + }, + "variables": [ + "{{variables.[Octopus Environment]}}" + ], + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "Occurred", + "Username", + "Category", + "Message" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "Occurred", + "title": "When", + "renderer": { + "type": "date", + "relative": true + } + }, + { + "field": "Username", + "title": "User", + "renderer": { + "type": "text" + } + }, + { + "field": "Category", + "title": "Category", + "renderer": { + "type": "badge", + "colors": { + "*Failed": "#d63939", + "Deleted": "#d63939", + "Created": "#2fb344", + "Modified": "#2F93E0", + "*Succeeded": "#2fb344" + }, + "defaultColor": "#6b7280" + } + }, + { + "field": "Message", + "title": "Event", + "renderer": { + "type": "text" + } + }, + { + "field": "projectName", + "title": "Project", + "renderer": { + "type": "text" + } + }, + { + "field": "IpAddress", + "title": "IP Address", + "renderer": { + "type": "text" + } + } + ] + }, + "style": { + "richTableCellPadding": 6, + "richTableWrapText": true + } + } + } + } + } + ] + } +} diff --git a/plugins/OctopusDeploy/v1/defaultContent/infrastructure.dash.json b/plugins/OctopusDeploy/v1/defaultContent/infrastructure.dash.json new file mode 100644 index 00000000..863bb927 --- /dev/null +++ b/plugins/OctopusDeploy/v1/defaultContent/infrastructure.dash.json @@ -0,0 +1,873 @@ +{ + "name": "Infrastructure", + "schemaVersion": "1.5", + "timeframe": "last24hours", + "dashboard": { + "_type": "layout/grid", + "columns": 4, + "version": 1, + "contents": [ + { + "i": "5793947a-0087-4a7e-929a-3ccc4606efca", + "x": 0, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Deployment Targets", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[deploymentTargets]}}", + "name": "deploymentTargets", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Targets" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "scalar", + "encoding": { + "values": [ + { + "field": "count", + "type": "quantitative", + "title": "Targets" + } + ] + }, + "style": { + "scalarLabelText": "Targets" + } + } + } + } + }, + { + "i": "db8ff24c-c0c3-443f-9631-a71618623f6c", + "x": 1, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Unhealthy Targets", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[deploymentTargets]}}", + "name": "deploymentTargets", + "pluginConfigId": "{{configId}}", + "filter": { + "multiOperation": "and", + "filters": [ + { + "column": "HealthStatus", + "operation": "notequals", + "value": "Healthy" + } + ] + }, + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Not healthy" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "scalar", + "encoding": { + "values": [ + { + "field": "count", + "type": "quantitative", + "title": "Not healthy" + } + ] + }, + "style": { + "scalarLabelText": "Not healthy", + "scalarValueColor": "#d63939" + } + } + } + } + }, + { + "i": "5bddd94e-8d09-4926-8c0d-158dfc4a5de2", + "x": 2, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Agents Needing Update", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[deploymentTargets]}}", + "name": "deploymentTargets", + "pluginConfigId": "{{configId}}", + "filter": { + "multiOperation": "and", + "filters": [ + { + "column": "agentStatus", + "operation": "notequals", + "value": "Up to date" + } + ] + }, + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Tentacle or Calamari" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "scalar", + "encoding": { + "values": [ + { + "field": "count", + "type": "quantitative", + "title": "Tentacle or Calamari" + } + ] + }, + "style": { + "scalarLabelText": "Tentacle or Calamari", + "scalarValueColor": "#f59f00" + } + } + } + } + }, + { + "i": "3d37bfa8-e2de-4e71-ad63-59025283016e", + "x": 3, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Certificates Expiring", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[certificates]}}", + "name": "certificates", + "pluginConfigId": "{{configId}}", + "filter": { + "multiOperation": "and", + "filters": [ + { + "column": "DaysUntilExpiry", + "operation": "lt", + "value": 30 + } + ] + }, + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Within 30 days" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "scalar", + "encoding": { + "values": [ + { + "field": "count", + "type": "quantitative", + "title": "Within 30 days" + } + ] + }, + "style": { + "scalarLabelText": "Within 30 days", + "scalarValueColor": "#f59f00" + } + } + } + } + }, + { + "i": "30d02286-26fa-406f-a82b-7b008935f5ce", + "x": 0, + "y": 2, + "w": 4, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Deployment Targets", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[deploymentTargets]}}", + "name": "deploymentTargets", + "pluginConfigId": "{{configId}}" + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-blocks", + "config": { + "data-stream-blocks": { + "labelColumn": "Name", + "stateColumn": "health", + "sublabel": "HealthStatus", + "linkColumn": "none", + "columns": 4 + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "statusGrid", + "encoding": { + "label": { + "field": "Name", + "type": "nominal" + }, + "status": { + "field": "health", + "type": "nominal" + }, + "value": { + "field": "HealthStatus", + "type": "nominal" + } + }, + "style": { + "statusGridColumnsPerRow": 4, + "statusGridBlockGap": 8, + "statusGridMaxBlockHeight": 110 + } + } + } + } + }, + { + "i": "8c0c51ed-9b94-4d3d-99de-e9a47a91b395", + "x": 0, + "y": 5, + "w": 4, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Workers", + "description": "Workers in static worker pools (dynamic pools have none)", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[workers]}}", + "name": "workers", + "pluginConfigId": "{{configId}}" + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-blocks", + "config": { + "data-stream-blocks": { + "labelColumn": "Name", + "stateColumn": "health", + "sublabel": "HealthStatus", + "linkColumn": "none", + "columns": 4 + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "statusGrid", + "encoding": { + "label": { + "field": "Name", + "type": "nominal" + }, + "status": { + "field": "health", + "type": "nominal" + }, + "value": { + "field": "HealthStatus", + "type": "nominal" + } + }, + "style": { + "statusGridColumnsPerRow": 4, + "statusGridBlockGap": 8, + "statusGridMaxBlockHeight": 110 + } + } + } + } + }, + { + "i": "e9e91b48-9c71-4734-aab3-0328ac2cff5a", + "x": 0, + "y": 8, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Target Health", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[deploymentTargets]}}", + "name": "deploymentTargets", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "HealthStatus", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-donut-chart", + "config": { + "data-stream-donut-chart": { + "valueColumn": "count", + "labelColumn": "HealthStatus_uniqueValues", + "hideCenterValue": false, + "showValuesAsPercentage": false, + "legendPosition": "auto", + "legendMode": "table" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "pie", + "encoding": { + "label": { + "field": "HealthStatus_uniqueValues", + "type": "nominal", + "title": "Health" + }, + "value": { + "field": "count", + "type": "quantitative", + "title": "Targets" + } + }, + "style": { + "pieInnerRadius": 60, + "pieDonutCenterValue": "total", + "labelFontSize": 16, + "pieLegendStyle": "table", + "mappedColors": { + "Healthy": "#2fb344", + "HasWarnings": "#f59f00", + "Unhealthy": "#d63939", + "Unavailable": "#d63939", + "Unknown": "#6b7280" + } + } + } + } + } + }, + { + "i": "dc13fca9-78c9-4615-95bd-8007beb605d6", + "x": 2, + "y": 8, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Targets by Type", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[deploymentTargets]}}", + "name": "deploymentTargets", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "CommunicationStyle", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-bar-chart", + "config": { + "data-stream-bar-chart": { + "xAxisData": "CommunicationStyle_uniqueValues", + "yAxisData": [ + "count" + ], + "xAxisGroup": "none", + "xAxisLabel": "", + "yAxisLabel": "", + "showXAxisLabel": false, + "showYAxisLabel": false, + "showLegend": false, + "legendPosition": "bottom", + "showGrid": true, + "horizontalLayout": "vertical", + "displayMode": "actual", + "showTotals": false, + "showValue": false, + "grouping": false, + "range": { + "type": "auto" + } + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "bar", + "encoding": { + "x": { + "field": "CommunicationStyle_uniqueValues", + "type": "nominal", + "title": "Type" + }, + "y": { + "field": "count", + "type": "quantitative", + "title": "Targets" + } + }, + "style": { + "cartesianHorizontal": true, + "cartesianBarBorderRadius": 3, + "colors": [ + "#2F93E0" + ] + } + } + } + } + }, + { + "i": "d84f0f1f-35aa-4640-8670-7bac5642fdb9", + "x": 0, + "y": 11, + "w": 4, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Agent Versions", + "description": "Tentacle and Calamari versions on deployment targets", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[deploymentTargets]}}", + "name": "deploymentTargets", + "pluginConfigId": "{{configId}}", + "sort": { + "by": [ + [ + "agentStatus", + "asc" + ] + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "Name", + "agentStatus", + "TentacleVersion", + "HasLatestCalamari" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "Name", + "title": "Target", + "renderer": { + "type": "text" + } + }, + { + "field": "agentStatus", + "title": "Agent", + "renderer": { + "type": "status" + } + }, + { + "field": "TentacleVersion", + "title": "Tentacle", + "renderer": { + "type": "text" + } + }, + { + "field": "TentacleUpgrade", + "title": "Tentacle Upgrade", + "renderer": { + "type": "badge", + "colors": { + "Required": "#d63939", + "Suggested": "#f59f00", + "Up to date": "#2fb344" + }, + "defaultColor": "#6b7280" + } + }, + { + "field": "HasLatestCalamari", + "title": "Latest Calamari", + "renderer": { + "type": "boolean", + "trueLabel": "Yes", + "falseLabel": "No", + "trueColor": "#2fb344", + "falseColor": "#f59f00" + } + }, + { + "field": "CommunicationStyle", + "title": "Communication", + "renderer": { + "type": "badge", + "defaultColor": "#6b7280" + } + }, + { + "field": "OperatingSystem", + "title": "Operating System", + "renderer": { + "type": "text" + } + } + ] + }, + "style": { + "richTableCellPadding": 6 + } + } + } + } + }, + { + "i": "a919d8e8-4245-48e9-9743-6c13b16f27c8", + "x": 0, + "y": 15, + "w": 4, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Certificates", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[certificates]}}", + "name": "certificates", + "pluginConfigId": "{{configId}}", + "sort": { + "by": [ + [ + "DaysUntilExpiry", + "asc" + ] + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "Name", + "ExpiryStatus", + "DaysUntilExpiry", + "NotAfter" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "Name", + "title": "Certificate", + "renderer": { + "type": "text" + } + }, + { + "field": "ExpiryStatus", + "title": "Expiry", + "renderer": { + "type": "badge", + "colors": { + "Expired": "#d63939", + "Expiring soon": "#f59f00", + "Valid": "#2fb344" + }, + "defaultColor": "#6b7280" + } + }, + { + "field": "DaysUntilExpiry", + "title": "Days Left", + "renderer": { + "type": "number", + "thresholds": [ + { + "to": 0, + "color": "#d63939" + }, + { + "to": 30, + "color": "#f59f00" + }, + { + "to": 100000, + "color": "#2fb344" + } + ] + } + }, + { + "field": "NotAfter", + "title": "Expires", + "renderer": { + "type": "date" + } + }, + { + "field": "SubjectCommonName", + "title": "Subject", + "renderer": { + "type": "text" + } + }, + { + "field": "IssuerCommonName", + "title": "Issuer", + "renderer": { + "type": "text" + } + }, + { + "field": "SelfSigned", + "title": "Self-signed", + "renderer": { + "type": "boolean", + "trueLabel": "Yes", + "falseLabel": "No" + } + } + ] + }, + "style": { + "richTableCellPadding": 6, + "richTableRowHighlight": { + "field": "ExpiryStatus", + "colors": { + "Expired": "rgba(214,57,57,0.15)", + "Expiring soon": "rgba(245,159,0,0.12)" + } + } + } + } + } + } + } + ] + } +} diff --git a/plugins/OctopusDeploy/v1/defaultContent/manifest.json b/plugins/OctopusDeploy/v1/defaultContent/manifest.json new file mode 100644 index 00000000..b01501fd --- /dev/null +++ b/plugins/OctopusDeploy/v1/defaultContent/manifest.json @@ -0,0 +1,40 @@ +{ + "items": [ + { + "name": "overview", + "type": "dashboard" + }, + { + "name": "tasks", + "type": "dashboard" + }, + { + "name": "infrastructure", + "type": "dashboard" + }, + { + "name": "audit", + "type": "dashboard" + }, + { + "name": "project", + "type": "dashboard" + }, + { + "name": "environment", + "type": "dashboard" + }, + { + "name": "deploymentTarget", + "type": "dashboard" + }, + { + "name": "runbook", + "type": "dashboard" + }, + { + "name": "workerPool", + "type": "dashboard" + } + ] +} diff --git a/plugins/OctopusDeploy/v1/defaultContent/overview.dash.json b/plugins/OctopusDeploy/v1/defaultContent/overview.dash.json new file mode 100644 index 00000000..25279aa3 --- /dev/null +++ b/plugins/OctopusDeploy/v1/defaultContent/overview.dash.json @@ -0,0 +1,1512 @@ +{ + "name": "Overview", + "schemaVersion": "1.5", + "timeframe": "last7days", + "dashboard": { + "_type": "layout/grid", + "columns": 4, + "version": 1, + "contents": [ + { + "i": "694c70b3-9121-4f91-bb72-4858ae98f4a7", + "x": 0, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Deployments", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[deployments]}}", + "name": "deployments", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Deployments" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "scalar", + "encoding": { + "values": [ + { + "field": "count", + "type": "quantitative", + "title": "Deployments" + } + ] + }, + "style": { + "scalarLabelText": "Deployments" + } + } + } + } + }, + { + "i": "98783b2d-9060-40f4-afad-30af70bc9a5b", + "x": 1, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Success Rate", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[deployments]}}", + "name": "deployments", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "mean", + "names": [ + "succeeded" + ] + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "succeeded_mean", + "comparisonColumn": "none", + "label": "Success rate" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "gauge", + "encoding": { + "value": { + "field": "succeeded_mean", + "type": "quantitative", + "title": "Success rate" + } + }, + "style": { + "gaugeMin": 0, + "gaugeMax": 100, + "gaugeLabelText": "Success rate", + "gaugeBands": [ + { + "to": 0.8, + "color": "#d63939" + }, + { + "to": 0.95, + "color": "#f59f00" + }, + { + "to": 1, + "color": "#2fb344" + } + ] + } + } + } + } + }, + { + "i": "2578c384-e383-4122-a7c5-e86f80576bc6", + "x": 2, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Failed Deployments", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[deployments]}}", + "name": "deployments", + "pluginConfigId": "{{configId}}", + "filter": { + "multiOperation": "or", + "filters": [ + { + "column": "state", + "operation": "equals", + "value": "Failed" + }, + { + "column": "state", + "operation": "equals", + "value": "TimedOut" + } + ] + }, + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Failed" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "scalar", + "encoding": { + "values": [ + { + "field": "count", + "type": "quantitative", + "title": "Failed" + } + ] + }, + "style": { + "scalarLabelText": "Failed", + "scalarValueColor": "#d63939" + } + } + } + } + }, + { + "i": "618b4b21-2f6d-43e5-b7f5-854261330c99", + "x": 3, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Active Tasks", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[tasks]}}", + "name": "tasks", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Queued or running" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "scalar", + "encoding": { + "values": [ + { + "field": "count", + "type": "quantitative", + "title": "Queued or running" + } + ] + }, + "style": { + "scalarLabelText": "Queued or running", + "scalarValueColor": "#2F93E0" + } + } + } + } + }, + { + "i": "0fb95cf9-6f73-4519-929c-22e504d2be8b", + "x": 0, + "y": 2, + "w": 4, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Projects", + "description": "Current release of each project in each environment", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[deploymentStatus]}}", + "name": "deploymentStatus", + "pluginConfigId": "{{configId}}" + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-blocks", + "config": { + "data-stream-blocks": { + "labelColumn": "environmentName", + "stateColumn": "status", + "sublabel": "releaseVersion", + "linkColumn": "none", + "columns": 4 + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "statusGrid", + "encoding": { + "label": { + "field": "environmentName", + "type": "nominal" + }, + "status": { + "field": "status", + "type": "nominal" + }, + "value": { + "field": "releaseVersion", + "type": "nominal" + }, + "group": { + "field": "projectName", + "type": "nominal" + } + }, + "style": { + "statusGridColumnsPerRow": 6, + "statusGridBlockGap": 8, + "statusGridMaxBlockHeight": 110, + "statusGridOrderByField": "environmentSortOrder", + "statusGridOrderDirection": "asc" + } + } + } + } + }, + { + "i": "dfd77689-6637-4792-a86a-c909a195f2dc", + "x": 0, + "y": 6, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Deployment Frequency", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[deployments]}}", + "name": "deployments", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "completedTime", + "byDay" + ], + [ + "state", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-bar-chart", + "config": { + "data-stream-bar-chart": { + "xAxisData": "completedTime_byDay", + "yAxisData": [ + "count" + ], + "xAxisGroup": "none", + "xAxisLabel": "", + "yAxisLabel": "", + "showXAxisLabel": false, + "showYAxisLabel": false, + "showLegend": false, + "legendPosition": "bottom", + "showGrid": true, + "horizontalLayout": "vertical", + "displayMode": "actual", + "showTotals": false, + "showValue": false, + "grouping": false, + "range": { + "type": "auto" + } + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "bar", + "encoding": { + "x": { + "field": "completedTime_byDay", + "type": "temporal", + "title": "Day" + }, + "y": { + "field": "count", + "type": "quantitative", + "title": "Deployments" + }, + "series": { + "field": "state_uniqueValues", + "type": "nominal", + "title": "Outcome" + } + }, + "style": { + "cartesianStack": "on", + "cartesianBarBorderRadius": 4, + "mappedColors": { + "Success": "#2fb344", + "Failed": "#d63939", + "TimedOut": "#d63939", + "Canceled": "#f59f00", + "Cancelling": "#f59f00", + "Queued": "#6b7280", + "Executing": "#2F93E0" + }, + "legendPosition": "bottom" + } + } + } + } + }, + { + "i": "8aca4b6f-cf7e-4664-be69-0bbfd3a62ae7", + "x": 2, + "y": 6, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Deployment Duration", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[deployments]}}", + "name": "deployments", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "completedTime", + "byDay" + ] + ], + "aggregate": [ + { + "type": "mean", + "names": [ + "durationSeconds" + ] + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-bar-chart", + "config": { + "data-stream-bar-chart": { + "xAxisData": "completedTime_byDay", + "yAxisData": [ + "durationSeconds_mean" + ], + "xAxisGroup": "none", + "xAxisLabel": "", + "yAxisLabel": "", + "showXAxisLabel": false, + "showYAxisLabel": false, + "showLegend": false, + "legendPosition": "bottom", + "showGrid": true, + "horizontalLayout": "vertical", + "displayMode": "actual", + "showTotals": false, + "showValue": false, + "grouping": false, + "range": { + "type": "auto" + } + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "line", + "encoding": { + "x": { + "field": "completedTime_byDay", + "type": "temporal", + "title": "Day" + }, + "y": { + "field": "durationSeconds_mean", + "type": "quantitative", + "title": "Mean duration" + } + }, + "style": { + "cartesianAreaGradient": true, + "cartesianSmooth": true, + "colors": [ + "#2F93E0" + ] + }, + "markLines": [ + { + "type": "average", + "label": "Average" + } + ] + } + } + } + }, + { + "i": "22db918e-2af5-4621-b610-75b0d4abe268", + "x": 0, + "y": 9, + "w": 4, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Deployment History by Project", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[deployments]}}", + "name": "deployments", + "pluginConfigId": "{{configId}}", + "sort": { + "by": [ + [ + "completedTime", + "desc" + ] + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "completedTime", + "projectName", + "environmentName", + "releaseVersion", + "status", + "durationSeconds" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "healthHistory", + "encoding": { + "time": { + "field": "completedTime", + "type": "temporal" + }, + "status": { + "field": "state", + "type": "nominal" + }, + "label": { + "field": "projectName", + "type": "nominal" + } + }, + "style": { + "historyStatusMap": { + "Success": "success", + "Failed": "error", + "TimedOut": "error", + "Canceled": "warning", + "Cancelling": "warning", + "Queued": "unknown", + "Executing": "unknown" + }, + "historySlots": 30, + "statusGridLabelWidth": 140 + } + } + } + } + }, + { + "i": "0f76f56d-4295-4a69-aa3f-04e9a79e6f03", + "x": 0, + "y": 12, + "w": 1, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Deployment Outcomes", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[deployments]}}", + "name": "deployments", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "state", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-donut-chart", + "config": { + "data-stream-donut-chart": { + "valueColumn": "count", + "labelColumn": "state_uniqueValues", + "hideCenterValue": false, + "showValuesAsPercentage": false, + "legendPosition": "auto", + "legendMode": "table" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "pie", + "encoding": { + "label": { + "field": "state_uniqueValues", + "type": "nominal", + "title": "Outcome" + }, + "value": { + "field": "count", + "type": "quantitative", + "title": "Deployments" + } + }, + "style": { + "pieInnerRadius": 60, + "pieDonutCenterValue": "total", + "labelFontSize": 16, + "pieLegendStyle": "table", + "mappedColors": { + "Success": "#2fb344", + "Failed": "#d63939", + "TimedOut": "#d63939", + "Canceled": "#f59f00", + "Cancelling": "#f59f00", + "Queued": "#6b7280", + "Executing": "#2F93E0" + } + } + } + } + } + }, + { + "i": "062e27e2-ac07-421e-8d61-e7b07271445c", + "x": 1, + "y": 12, + "w": 3, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Recent Failed Deployments", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[deployments]}}", + "name": "deployments", + "pluginConfigId": "{{configId}}", + "filter": { + "multiOperation": "or", + "filters": [ + { + "column": "state", + "operation": "equals", + "value": "Failed" + }, + { + "column": "state", + "operation": "equals", + "value": "TimedOut" + } + ] + }, + "sort": { + "by": [ + [ + "completedTime", + "desc" + ] + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "completedTime", + "projectName", + "environmentName", + "releaseVersion", + "status", + "durationSeconds" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "completedTime", + "title": "Completed", + "renderer": { + "type": "date", + "relative": true + } + }, + { + "field": "projectName", + "title": "Project", + "renderer": { + "type": "text" + } + }, + { + "field": "environmentName", + "title": "Environment", + "renderer": { + "type": "text" + } + }, + { + "field": "tenantName", + "title": "Tenant", + "renderer": { + "type": "text" + } + }, + { + "field": "releaseVersion", + "title": "Release", + "renderer": { + "type": "badge", + "defaultColor": "#2F93E0" + } + }, + { + "field": "state", + "title": "Outcome", + "renderer": { + "type": "badge", + "colors": { + "Success": "#2fb344", + "Failed": "#d63939", + "TimedOut": "#d63939", + "Canceled": "#f59f00", + "Cancelling": "#f59f00", + "Queued": "#6b7280", + "Executing": "#2F93E0" + }, + "defaultColor": "#6b7280" + } + }, + { + "field": "durationSeconds", + "title": "Duration", + "renderer": { + "type": "bar", + "color": "#2F93E0" + } + }, + { + "field": "deployedBy", + "title": "Deployed By", + "renderer": { + "type": "text" + } + } + ] + }, + "style": { + "richTableCellPadding": 6, + "richTableRowHighlight": { + "field": "state", + "colors": { + "Failed": "rgba(214,57,57,0.15)", + "TimedOut": "rgba(214,57,57,0.15)" + } + } + } + } + } + } + }, + { + "i": "c15bffae-6099-4143-86bf-3f42e5ef52a7", + "x": 0, + "y": 15, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Deployment Targets", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[deploymentTargets]}}", + "name": "deploymentTargets", + "pluginConfigId": "{{configId}}" + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-blocks", + "config": { + "data-stream-blocks": { + "labelColumn": "Name", + "stateColumn": "health", + "sublabel": "HealthStatus", + "linkColumn": "none", + "columns": 4 + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "statusGrid", + "encoding": { + "label": { + "field": "Name", + "type": "nominal" + }, + "status": { + "field": "health", + "type": "nominal" + }, + "value": { + "field": "HealthStatus", + "type": "nominal" + } + }, + "style": { + "statusGridColumnsPerRow": 4, + "statusGridBlockGap": 8, + "statusGridMaxBlockHeight": 110 + } + } + } + } + }, + { + "i": "af86033d-c18d-48ae-bfdf-721191508beb", + "x": 2, + "y": 15, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Active Tasks Queue", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[tasks]}}", + "name": "tasks", + "pluginConfigId": "{{configId}}", + "sort": { + "by": [ + [ + "QueueTime", + "asc" + ] + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "QueueTime", + "Description", + "Name", + "status", + "durationSeconds" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "QueueTime", + "title": "Queued", + "renderer": { + "type": "date", + "relative": true + } + }, + { + "field": "Description", + "title": "Task", + "renderer": { + "type": "text" + } + }, + { + "field": "Name", + "title": "Type", + "renderer": { + "type": "badge", + "defaultColor": "#6b7280" + } + }, + { + "field": "State", + "title": "State", + "renderer": { + "type": "badge", + "colors": { + "Success": "#2fb344", + "Failed": "#d63939", + "TimedOut": "#d63939", + "Canceled": "#f59f00", + "Cancelling": "#f59f00", + "Queued": "#6b7280", + "Executing": "#2F93E0" + }, + "defaultColor": "#6b7280" + } + }, + { + "field": "queuedSeconds", + "title": "Waited", + "renderer": { + "type": "number", + "suffix": " s", + "decimals": 0 + } + }, + { + "field": "durationSeconds", + "title": "Duration", + "renderer": { + "type": "bar", + "color": "#2F93E0" + } + }, + { + "field": "HasPendingInterruptions", + "title": "Needs Input", + "renderer": { + "type": "boolean", + "trueLabel": "Yes", + "falseLabel": "", + "trueColor": "#f59f00" + } + } + ] + }, + "style": { + "richTableCellPadding": 6 + } + } + } + } + }, + { + "i": "8b007aba-4779-45d2-be26-79c554eb39d5", + "x": 0, + "y": 18, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Awaiting Approval", + "description": "Deployments and runbook runs waiting on a manual intervention or guided failure", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[pendingInterventions]}}", + "name": "pendingInterventions", + "pluginConfigId": "{{configId}}", + "sort": { + "by": [ + [ + "created", + "asc" + ] + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "created", + "title", + "type", + "waitingMinutes" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "created", + "title": "Waiting Since", + "renderer": { + "type": "date", + "relative": true + } + }, + { + "field": "title", + "title": "Waiting For", + "renderer": { + "type": "text" + } + }, + { + "field": "type", + "title": "Type", + "renderer": { + "type": "badge", + "colors": { + "Manual intervention": "#f59f00", + "Guided failure": "#d63939" + }, + "defaultColor": "#6b7280" + } + }, + { + "field": "waitingMinutes", + "title": "Minutes", + "renderer": { + "type": "bar", + "color": "#f59f00" + } + }, + { + "field": "instructions", + "title": "Instructions", + "renderer": { + "type": "text" + } + }, + { + "field": "hasResponsibility", + "title": "Assigned", + "renderer": { + "type": "boolean", + "trueLabel": "Yes", + "falseLabel": "No" + } + } + ] + }, + "style": { + "richTableCellPadding": 6, + "richTableWrapText": true + } + } + } + } + }, + { + "i": "753e8a97-c48c-4f0c-a39c-46c3aff7d922", + "x": 2, + "y": 18, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Deployment Freezes", + "description": "Freezes in force now and coming up", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[deploymentFreezes]}}", + "name": "deploymentFreezes", + "pluginConfigId": "{{configId}}", + "sort": { + "by": [ + [ + "start", + "asc" + ] + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "name", + "status", + "start", + "end" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "name", + "title": "Freeze", + "renderer": { + "type": "text" + } + }, + { + "field": "status", + "title": "Status", + "renderer": { + "type": "badge", + "colors": { + "Active": "#d63939", + "Scheduled": "#f59f00" + }, + "defaultColor": "#6b7280" + } + }, + { + "field": "start", + "title": "Starts", + "renderer": { + "type": "date" + } + }, + { + "field": "end", + "title": "Ends", + "renderer": { + "type": "date", + "relative": true + } + }, + { + "field": "schedule", + "title": "Repeats", + "renderer": { + "type": "text" + } + }, + { + "field": "projectCount", + "title": "Projects", + "renderer": { + "type": "number" + } + }, + { + "field": "environmentCount", + "title": "Environments", + "renderer": { + "type": "number" + } + } + ] + }, + "style": { + "richTableCellPadding": 6 + } + } + } + } + }, + { + "i": "487fd86f-edf9-429f-a1e4-3b69c6abd2dd", + "x": 0, + "y": 21, + "w": 1, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "License Expires In", + "description": "Days until the Octopus license or Cloud subscription expires", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[license]}}", + "name": "license", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "min", + "names": [ + "daysToExpiry" + ] + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "daysToExpiry_min", + "comparisonColumn": "none", + "label": "Days" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "scalar", + "encoding": { + "values": [ + { + "field": "daysToExpiry_min", + "type": "quantitative", + "title": "Days" + } + ] + }, + "style": { + "scalarLabelText": "Days" + } + } + } + } + }, + { + "i": "5493fadd-f770-40ee-a1ce-17a4fca2db59", + "x": 1, + "y": 21, + "w": 3, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "License Usage", + "description": "Usage against each licensed limit; Octopus blocks new work at a limit", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[license]}}", + "name": "license", + "pluginConfigId": "{{configId}}", + "sort": { + "by": [ + [ + "usagePercent", + "desc" + ] + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "limitName", + "currentUsage", + "limit", + "limitStatus" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "limitName", + "title": "Limit", + "renderer": { + "type": "text" + } + }, + { + "field": "usagePercent", + "title": "Used", + "renderer": { + "type": "progress", + "max": 100 + } + }, + { + "field": "currentUsage", + "title": "Usage", + "renderer": { + "type": "number" + } + }, + { + "field": "limit", + "title": "Licensed", + "renderer": { + "type": "number" + } + }, + { + "field": "limitStatus", + "title": "Status", + "renderer": { + "type": "badge", + "colors": { + "UnderLimit": "#2fb344", + "AtLimit": "#f59f00", + "OverLimit": "#d63939" + }, + "defaultColor": "#6b7280" + } + } + ] + }, + "style": { + "richTableCellPadding": 6, + "richTableRowHighlight": { + "field": "limitStatus", + "colors": { + "AtLimit": "rgba(245,159,0,0.12)", + "OverLimit": "rgba(214,57,57,0.15)" + } + } + } + } + } + } + } + ] + } +} diff --git a/plugins/OctopusDeploy/v1/defaultContent/project.dash.json b/plugins/OctopusDeploy/v1/defaultContent/project.dash.json new file mode 100644 index 00000000..23dfd2f4 --- /dev/null +++ b/plugins/OctopusDeploy/v1/defaultContent/project.dash.json @@ -0,0 +1,1363 @@ +{ + "name": "Project", + "schemaVersion": "1.5", + "timeframe": "last30days", + "variables": [ + "{{variables.[Octopus Project]}}" + ], + "dashboard": { + "_type": "layout/grid", + "columns": 4, + "version": 1, + "contents": [ + { + "i": "467df1bd-577f-41cf-81f7-bc6dd97ea947", + "x": 0, + "y": 0, + "w": 1, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Project Properties", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "datastream-properties", + "name": "properties", + "pluginConfigId": "{{configId}}" + }, + "scope": { + "scope": "{{scopes.[Octopus Projects]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Project]}}" + }, + "variables": [ + "{{variables.[Octopus Project]}}" + ], + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": true, + "columnOrder": [ + "name" + ], + "hiddenColumns": [ + "id", + "links", + "type", + "label", + "sourceId", + "sourceType", + "spaceId" + ] + } + } + } + } + }, + { + "i": "d4b86509-d9eb-419c-bc5d-8a912e6ca8d9", + "x": 1, + "y": 0, + "w": 3, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Environments", + "description": "Current release in each environment", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[deploymentStatus]}}", + "name": "deploymentStatus", + "pluginConfigId": "{{configId}}" + }, + "scope": { + "scope": "{{scopes.[Octopus Projects]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Project]}}" + }, + "variables": [ + "{{variables.[Octopus Project]}}" + ], + "visualisation": { + "type": "data-stream-blocks", + "config": { + "data-stream-blocks": { + "labelColumn": "environmentName", + "stateColumn": "status", + "sublabel": "releaseVersion", + "linkColumn": "none", + "columns": 4 + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "statusGrid", + "encoding": { + "label": { + "field": "environmentName", + "type": "nominal" + }, + "status": { + "field": "status", + "type": "nominal" + }, + "value": { + "field": "releaseVersion", + "type": "nominal" + } + }, + "style": { + "statusGridColumnsPerRow": 6, + "statusGridBlockGap": 8, + "statusGridMaxBlockHeight": 110, + "statusGridOrderByField": "environmentSortOrder", + "statusGridOrderDirection": "asc" + } + } + } + } + }, + { + "i": "b2c45cae-4553-4bdd-9467-c0f93aadd2b3", + "x": 1, + "y": 2, + "w": 3, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Release Progression", + "description": "Latest releases and where each has been deployed (times in UTC)", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[releaseProgression]}}", + "name": "releaseProgression", + "pluginConfigId": "{{configId}}", + "dataSourceConfig": { + "releaseCount": 10 + } + }, + "scope": { + "scope": "{{scopes.[Octopus Projects]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Project]}}" + }, + "variables": [ + "{{variables.[Octopus Project]}}" + ], + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "releaseVersion", + "environmentName", + "status", + "detail" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "statusGrid", + "encoding": { + "label": { + "field": "environmentName", + "type": "nominal" + }, + "status": { + "field": "status", + "type": "nominal" + }, + "value": { + "field": "detail", + "type": "nominal" + }, + "group": { + "field": "releaseVersion", + "type": "nominal" + } + }, + "style": { + "statusGridColumnsPerRow": 6, + "statusGridBlockGap": 8, + "statusGridMaxBlockHeight": 110, + "statusGridOrderByField": "gridOrder", + "statusGridOrderDirection": "asc" + } + } + } + } + }, + { + "i": "3c519cef-aebc-4bab-9982-caefb73427df", + "x": 0, + "y": 6, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Deployments", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[deployments]}}", + "name": "deployments", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Projects]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Project]}}" + }, + "variables": [ + "{{variables.[Octopus Project]}}" + ], + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Deployments" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "scalar", + "encoding": { + "values": [ + { + "field": "count", + "type": "quantitative", + "title": "Deployments" + } + ] + }, + "style": { + "scalarLabelText": "Deployments" + } + } + } + } + }, + { + "i": "9202e4d8-e301-4ef9-b3cd-06c950c0cd7f", + "x": 1, + "y": 6, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Success Rate", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[deployments]}}", + "name": "deployments", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "mean", + "names": [ + "succeeded" + ] + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Projects]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Project]}}" + }, + "variables": [ + "{{variables.[Octopus Project]}}" + ], + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "succeeded_mean", + "comparisonColumn": "none", + "label": "Success rate" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "gauge", + "encoding": { + "value": { + "field": "succeeded_mean", + "type": "quantitative", + "title": "Success rate" + } + }, + "style": { + "gaugeMin": 0, + "gaugeMax": 100, + "gaugeLabelText": "Success rate", + "gaugeBands": [ + { + "to": 0.8, + "color": "#d63939" + }, + { + "to": 0.95, + "color": "#f59f00" + }, + { + "to": 1, + "color": "#2fb344" + } + ] + } + } + } + } + }, + { + "i": "93766b16-bcc9-426a-a607-214bbe0bf85f", + "x": 2, + "y": 6, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Mean Duration", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[deployments]}}", + "name": "deployments", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "mean", + "names": [ + "durationSeconds" + ] + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Projects]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Project]}}" + }, + "variables": [ + "{{variables.[Octopus Project]}}" + ], + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "durationSeconds_mean", + "comparisonColumn": "none", + "label": "Mean duration" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "scalar", + "encoding": { + "values": [ + { + "field": "durationSeconds_mean", + "type": "quantitative", + "title": "Mean duration" + } + ] + }, + "style": { + "scalarLabelText": "Mean duration" + } + } + } + } + }, + { + "i": "1a8222e5-1aa0-4724-a18a-e0146dc25d93", + "x": 3, + "y": 6, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Failed Deployments", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[deployments]}}", + "name": "deployments", + "pluginConfigId": "{{configId}}", + "filter": { + "multiOperation": "or", + "filters": [ + { + "column": "state", + "operation": "equals", + "value": "Failed" + }, + { + "column": "state", + "operation": "equals", + "value": "TimedOut" + } + ] + }, + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Projects]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Project]}}" + }, + "variables": [ + "{{variables.[Octopus Project]}}" + ], + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Failed" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "scalar", + "encoding": { + "values": [ + { + "field": "count", + "type": "quantitative", + "title": "Failed" + } + ] + }, + "style": { + "scalarLabelText": "Failed", + "scalarValueColor": "#d63939" + } + } + } + } + }, + { + "i": "6908d550-7e78-43d0-bf3b-546b41908148", + "x": 0, + "y": 8, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Deployment Frequency", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[deployments]}}", + "name": "deployments", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "completedTime", + "byDay" + ], + [ + "state", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Projects]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Project]}}" + }, + "variables": [ + "{{variables.[Octopus Project]}}" + ], + "visualisation": { + "type": "data-stream-bar-chart", + "config": { + "data-stream-bar-chart": { + "xAxisData": "completedTime_byDay", + "yAxisData": [ + "count" + ], + "xAxisGroup": "none", + "xAxisLabel": "", + "yAxisLabel": "", + "showXAxisLabel": false, + "showYAxisLabel": false, + "showLegend": false, + "legendPosition": "bottom", + "showGrid": true, + "horizontalLayout": "vertical", + "displayMode": "actual", + "showTotals": false, + "showValue": false, + "grouping": false, + "range": { + "type": "auto" + } + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "bar", + "encoding": { + "x": { + "field": "completedTime_byDay", + "type": "temporal", + "title": "Day" + }, + "y": { + "field": "count", + "type": "quantitative", + "title": "Deployments" + }, + "series": { + "field": "state_uniqueValues", + "type": "nominal", + "title": "Outcome" + } + }, + "style": { + "cartesianStack": "on", + "cartesianBarBorderRadius": 4, + "mappedColors": { + "Success": "#2fb344", + "Failed": "#d63939", + "TimedOut": "#d63939", + "Canceled": "#f59f00", + "Cancelling": "#f59f00", + "Queued": "#6b7280", + "Executing": "#2F93E0" + }, + "legendPosition": "bottom" + } + } + } + } + }, + { + "i": "98d3ae7a-17ac-4f0a-83dd-dbc620297938", + "x": 2, + "y": 8, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Deployment Duration", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[deployments]}}", + "name": "deployments", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "completedTime", + "byDay" + ] + ], + "aggregate": [ + { + "type": "mean", + "names": [ + "durationSeconds" + ] + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Projects]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Project]}}" + }, + "variables": [ + "{{variables.[Octopus Project]}}" + ], + "visualisation": { + "type": "data-stream-bar-chart", + "config": { + "data-stream-bar-chart": { + "xAxisData": "completedTime_byDay", + "yAxisData": [ + "durationSeconds_mean" + ], + "xAxisGroup": "none", + "xAxisLabel": "", + "yAxisLabel": "", + "showXAxisLabel": false, + "showYAxisLabel": false, + "showLegend": false, + "legendPosition": "bottom", + "showGrid": true, + "horizontalLayout": "vertical", + "displayMode": "actual", + "showTotals": false, + "showValue": false, + "grouping": false, + "range": { + "type": "auto" + } + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "line", + "encoding": { + "x": { + "field": "completedTime_byDay", + "type": "temporal", + "title": "Day" + }, + "y": { + "field": "durationSeconds_mean", + "type": "quantitative", + "title": "Mean duration" + } + }, + "style": { + "cartesianAreaGradient": true, + "cartesianSmooth": true, + "colors": [ + "#2F93E0" + ] + }, + "markLines": [ + { + "type": "average", + "label": "Average" + } + ] + } + } + } + }, + { + "i": "be6d9e68-8d41-43ed-b01f-0a63b505aaa6", + "x": 0, + "y": 11, + "w": 4, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Deployment History", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[deployments]}}", + "name": "deployments", + "pluginConfigId": "{{configId}}", + "sort": { + "by": [ + [ + "completedTime", + "desc" + ] + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Projects]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Project]}}" + }, + "variables": [ + "{{variables.[Octopus Project]}}" + ], + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "completedTime", + "projectName", + "environmentName", + "releaseVersion", + "status", + "durationSeconds" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "completedTime", + "title": "Completed", + "renderer": { + "type": "date", + "relative": true + } + }, + { + "field": "environmentName", + "title": "Environment", + "renderer": { + "type": "text" + } + }, + { + "field": "tenantName", + "title": "Tenant", + "renderer": { + "type": "text" + } + }, + { + "field": "releaseVersion", + "title": "Release", + "renderer": { + "type": "badge", + "defaultColor": "#2F93E0" + } + }, + { + "field": "state", + "title": "Outcome", + "renderer": { + "type": "badge", + "colors": { + "Success": "#2fb344", + "Failed": "#d63939", + "TimedOut": "#d63939", + "Canceled": "#f59f00", + "Cancelling": "#f59f00", + "Queued": "#6b7280", + "Executing": "#2F93E0" + }, + "defaultColor": "#6b7280" + } + }, + { + "field": "durationSeconds", + "title": "Duration", + "renderer": { + "type": "bar", + "color": "#2F93E0" + } + }, + { + "field": "deployedBy", + "title": "Deployed By", + "renderer": { + "type": "text" + } + } + ] + }, + "style": { + "richTableCellPadding": 6, + "richTableRowHighlight": { + "field": "state", + "colors": { + "Failed": "rgba(214,57,57,0.15)", + "TimedOut": "rgba(214,57,57,0.15)" + } + } + } + } + } + } + }, + { + "i": "25cd7273-aa37-468b-a11e-c893a6ee57ad", + "x": 0, + "y": 15, + "w": 4, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Recent Tasks", + "description": "Deployments and runbook runs in the last 7 days", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "last7days", + "dataStream": { + "id": "{{dataStreams.[tasks]}}", + "name": "tasks", + "pluginConfigId": "{{configId}}", + "sort": { + "by": [ + [ + "QueueTime", + "desc" + ] + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Projects]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Project]}}" + }, + "variables": [ + "{{variables.[Octopus Project]}}" + ], + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "QueueTime", + "Description", + "Name", + "status", + "durationSeconds" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "QueueTime", + "title": "Queued", + "renderer": { + "type": "date", + "relative": true + } + }, + { + "field": "Description", + "title": "Task", + "renderer": { + "type": "text" + } + }, + { + "field": "Name", + "title": "Type", + "renderer": { + "type": "badge", + "defaultColor": "#6b7280" + } + }, + { + "field": "State", + "title": "State", + "renderer": { + "type": "badge", + "colors": { + "Success": "#2fb344", + "Failed": "#d63939", + "TimedOut": "#d63939", + "Canceled": "#f59f00", + "Cancelling": "#f59f00", + "Queued": "#6b7280", + "Executing": "#2F93E0" + }, + "defaultColor": "#6b7280" + } + }, + { + "field": "queuedSeconds", + "title": "Waited", + "renderer": { + "type": "number", + "suffix": " s", + "decimals": 0 + } + }, + { + "field": "durationSeconds", + "title": "Duration", + "renderer": { + "type": "bar", + "color": "#2F93E0" + } + }, + { + "field": "HasPendingInterruptions", + "title": "Needs Input", + "renderer": { + "type": "boolean", + "trueLabel": "Yes", + "falseLabel": "", + "trueColor": "#f59f00" + } + }, + { + "field": "ErrorMessage", + "title": "Error", + "renderer": { + "type": "text" + } + } + ] + }, + "style": { + "richTableCellPadding": 6 + } + } + } + } + }, + { + "i": "90d1dd7f-9a88-4158-9614-9e30273b7ac0", + "x": 0, + "y": 18, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Deployment Freezes", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[deploymentFreezes]}}", + "name": "deploymentFreezes", + "pluginConfigId": "{{configId}}" + }, + "scope": { + "scope": "{{scopes.[Octopus Projects]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Project]}}" + }, + "variables": [ + "{{variables.[Octopus Project]}}" + ], + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "name", + "status", + "start", + "end" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "name", + "title": "Freeze", + "renderer": { + "type": "text" + } + }, + { + "field": "status", + "title": "Status", + "renderer": { + "type": "badge", + "colors": { + "Active": "#d63939", + "Scheduled": "#f59f00" + }, + "defaultColor": "#6b7280" + } + }, + { + "field": "start", + "title": "Starts", + "renderer": { + "type": "date" + } + }, + { + "field": "end", + "title": "Ends", + "renderer": { + "type": "date", + "relative": true + } + }, + { + "field": "schedule", + "title": "Repeats", + "renderer": { + "type": "text" + } + }, + { + "field": "projectCount", + "title": "Projects", + "renderer": { + "type": "number" + } + }, + { + "field": "environmentCount", + "title": "Environments", + "renderer": { + "type": "number" + } + } + ] + }, + "style": { + "richTableCellPadding": 6 + } + } + } + } + }, + { + "i": "fb6d1151-de0b-408b-8126-430ac67f9575", + "x": 2, + "y": 18, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Awaiting Approval", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[pendingInterventions]}}", + "name": "pendingInterventions", + "pluginConfigId": "{{configId}}", + "sort": { + "by": [ + [ + "created", + "asc" + ] + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Projects]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Project]}}" + }, + "variables": [ + "{{variables.[Octopus Project]}}" + ], + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "created", + "title", + "type", + "waitingMinutes" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "created", + "title": "Waiting Since", + "renderer": { + "type": "date", + "relative": true + } + }, + { + "field": "title", + "title": "Waiting For", + "renderer": { + "type": "text" + } + }, + { + "field": "type", + "title": "Type", + "renderer": { + "type": "badge", + "colors": { + "Manual intervention": "#f59f00", + "Guided failure": "#d63939" + }, + "defaultColor": "#6b7280" + } + }, + { + "field": "waitingMinutes", + "title": "Minutes", + "renderer": { + "type": "bar", + "color": "#f59f00" + } + }, + { + "field": "instructions", + "title": "Instructions", + "renderer": { + "type": "text" + } + }, + { + "field": "hasResponsibility", + "title": "Assigned", + "renderer": { + "type": "boolean", + "trueLabel": "Yes", + "falseLabel": "No" + } + } + ] + }, + "style": { + "richTableCellPadding": 6, + "richTableWrapText": true + } + } + } + } + }, + { + "i": "46528a10-2750-405a-8bde-e6776f9230d8", + "x": 0, + "y": 21, + "w": 4, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Audit Trail", + "description": "Changes and activity for this project in the last 7 days", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "last7days", + "dataStream": { + "id": "{{dataStreams.[auditEvents]}}", + "name": "auditEvents", + "pluginConfigId": "{{configId}}", + "sort": { + "by": [ + [ + "Occurred", + "desc" + ] + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Projects]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Project]}}" + }, + "variables": [ + "{{variables.[Octopus Project]}}" + ], + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "Occurred", + "Username", + "Category", + "Message" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "Occurred", + "title": "When", + "renderer": { + "type": "date", + "relative": true + } + }, + { + "field": "Username", + "title": "User", + "renderer": { + "type": "text" + } + }, + { + "field": "Category", + "title": "Category", + "renderer": { + "type": "badge", + "colors": { + "*Failed": "#d63939", + "Deleted": "#d63939", + "Created": "#2fb344", + "Modified": "#2F93E0", + "*Succeeded": "#2fb344" + }, + "defaultColor": "#6b7280" + } + }, + { + "field": "Message", + "title": "Event", + "renderer": { + "type": "text" + } + }, + { + "field": "IpAddress", + "title": "IP Address", + "renderer": { + "type": "text" + } + } + ] + }, + "style": { + "richTableCellPadding": 6, + "richTableWrapText": true + } + } + } + } + } + ] + } +} diff --git a/plugins/OctopusDeploy/v1/defaultContent/runbook.dash.json b/plugins/OctopusDeploy/v1/defaultContent/runbook.dash.json new file mode 100644 index 00000000..f44ec325 --- /dev/null +++ b/plugins/OctopusDeploy/v1/defaultContent/runbook.dash.json @@ -0,0 +1,714 @@ +{ + "name": "Runbook", + "schemaVersion": "1.5", + "timeframe": "last7days", + "variables": [ + "{{variables.[Octopus Runbook]}}" + ], + "dashboard": { + "_type": "layout/grid", + "columns": 4, + "version": 1, + "contents": [ + { + "i": "e7d9f424-8b3e-4bb0-a5c1-ddea70dbb245", + "x": 0, + "y": 0, + "w": 1, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Runbook Properties", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "datastream-properties", + "name": "properties", + "pluginConfigId": "{{configId}}" + }, + "scope": { + "scope": "{{scopes.[Octopus Runbooks]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Runbook]}}" + }, + "variables": [ + "{{variables.[Octopus Runbook]}}" + ], + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": true, + "columnOrder": [ + "name" + ], + "hiddenColumns": [ + "id", + "links", + "type", + "label", + "sourceId", + "sourceType", + "spaceId" + ] + } + } + } + } + }, + { + "i": "a0ad71f9-d550-4dc5-9069-a4c7a03fc818", + "x": 1, + "y": 0, + "w": 3, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Status by Environment", + "description": "Latest run in each environment (times in UTC)", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[runbookStatus]}}", + "name": "runbookStatus", + "pluginConfigId": "{{configId}}" + }, + "scope": { + "scope": "{{scopes.[Octopus Runbooks]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Runbook]}}" + }, + "variables": [ + "{{variables.[Octopus Runbook]}}" + ], + "visualisation": { + "type": "data-stream-blocks", + "config": { + "data-stream-blocks": { + "labelColumn": "environmentName", + "stateColumn": "status", + "sublabel": "detail", + "linkColumn": "none", + "columns": 4 + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "statusGrid", + "encoding": { + "label": { + "field": "environmentName", + "type": "nominal" + }, + "status": { + "field": "status", + "type": "nominal" + }, + "value": { + "field": "detail", + "type": "nominal" + } + }, + "style": { + "statusGridColumnsPerRow": 6, + "statusGridBlockGap": 8, + "statusGridMaxBlockHeight": 110, + "statusGridOrderByField": "environmentSortOrder", + "statusGridOrderDirection": "asc" + } + } + } + } + }, + { + "i": "19554ac5-74f0-48f2-81b8-926be7f4966d", + "x": 1, + "y": 2, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Runs", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[tasks]}}", + "name": "tasks", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Runbooks]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Runbook]}}" + }, + "variables": [ + "{{variables.[Octopus Runbook]}}" + ], + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Runs" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "scalar", + "encoding": { + "values": [ + { + "field": "count", + "type": "quantitative", + "title": "Runs" + } + ] + }, + "style": { + "scalarLabelText": "Runs" + } + } + } + } + }, + { + "i": "7a878060-7eca-4786-87ea-dd2e813e8239", + "x": 2, + "y": 2, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Failed Runs", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[tasks]}}", + "name": "tasks", + "pluginConfigId": "{{configId}}", + "filter": { + "multiOperation": "or", + "filters": [ + { + "column": "State", + "operation": "equals", + "value": "Failed" + }, + { + "column": "State", + "operation": "equals", + "value": "TimedOut" + } + ] + }, + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Runbooks]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Runbook]}}" + }, + "variables": [ + "{{variables.[Octopus Runbook]}}" + ], + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Failed" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "scalar", + "encoding": { + "values": [ + { + "field": "count", + "type": "quantitative", + "title": "Failed" + } + ] + }, + "style": { + "scalarLabelText": "Failed", + "scalarValueColor": "#d63939" + } + } + } + } + }, + { + "i": "484b3bd8-67b0-42d6-a3ed-d2d4defc44c0", + "x": 3, + "y": 2, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Mean Duration", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[tasks]}}", + "name": "tasks", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "mean", + "names": [ + "durationSeconds" + ] + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Runbooks]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Runbook]}}" + }, + "variables": [ + "{{variables.[Octopus Runbook]}}" + ], + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "durationSeconds_mean", + "comparisonColumn": "none", + "label": "Mean duration" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "scalar", + "encoding": { + "values": [ + { + "field": "durationSeconds_mean", + "type": "quantitative", + "title": "Mean duration" + } + ] + }, + "style": { + "scalarLabelText": "Mean duration" + } + } + } + } + }, + { + "i": "6839f820-e4a5-46fc-9b69-dfa3077a7014", + "x": 0, + "y": 4, + "w": 4, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Runs Over Time", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[tasks]}}", + "name": "tasks", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "QueueTime", + "byDay" + ], + [ + "State", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Runbooks]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Runbook]}}" + }, + "variables": [ + "{{variables.[Octopus Runbook]}}" + ], + "visualisation": { + "type": "data-stream-bar-chart", + "config": { + "data-stream-bar-chart": { + "xAxisData": "QueueTime_byDay", + "yAxisData": [ + "count" + ], + "xAxisGroup": "none", + "xAxisLabel": "", + "yAxisLabel": "", + "showXAxisLabel": false, + "showYAxisLabel": false, + "showLegend": false, + "legendPosition": "bottom", + "showGrid": true, + "horizontalLayout": "vertical", + "displayMode": "actual", + "showTotals": false, + "showValue": false, + "grouping": false, + "range": { + "type": "auto" + } + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "bar", + "encoding": { + "x": { + "field": "QueueTime_byDay", + "type": "temporal", + "title": "Day" + }, + "y": { + "field": "count", + "type": "quantitative", + "title": "Runs" + }, + "series": { + "field": "State_uniqueValues", + "type": "nominal", + "title": "Outcome" + } + }, + "style": { + "cartesianStack": "on", + "cartesianBarBorderRadius": 4, + "mappedColors": { + "Success": "#2fb344", + "Failed": "#d63939", + "TimedOut": "#d63939", + "Canceled": "#f59f00", + "Cancelling": "#f59f00", + "Queued": "#6b7280", + "Executing": "#2F93E0" + }, + "legendPosition": "bottom" + } + } + } + } + }, + { + "i": "09bad607-d684-4543-a57a-0324c05a7028", + "x": 0, + "y": 7, + "w": 4, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Recent Runs", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[tasks]}}", + "name": "tasks", + "pluginConfigId": "{{configId}}", + "sort": { + "by": [ + [ + "QueueTime", + "desc" + ] + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Runbooks]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Runbook]}}" + }, + "variables": [ + "{{variables.[Octopus Runbook]}}" + ], + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "QueueTime", + "Description", + "Name", + "status", + "durationSeconds" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "QueueTime", + "title": "Queued", + "renderer": { + "type": "date", + "relative": true + } + }, + { + "field": "Description", + "title": "Task", + "renderer": { + "type": "text" + } + }, + { + "field": "State", + "title": "State", + "renderer": { + "type": "badge", + "colors": { + "Success": "#2fb344", + "Failed": "#d63939", + "TimedOut": "#d63939", + "Canceled": "#f59f00", + "Cancelling": "#f59f00", + "Queued": "#6b7280", + "Executing": "#2F93E0" + }, + "defaultColor": "#6b7280" + } + }, + { + "field": "queuedSeconds", + "title": "Waited", + "renderer": { + "type": "number", + "suffix": " s", + "decimals": 0 + } + }, + { + "field": "durationSeconds", + "title": "Duration", + "renderer": { + "type": "bar", + "color": "#2F93E0" + } + }, + { + "field": "HasPendingInterruptions", + "title": "Needs Input", + "renderer": { + "type": "boolean", + "trueLabel": "Yes", + "falseLabel": "", + "trueColor": "#f59f00" + } + }, + { + "field": "ErrorMessage", + "title": "Error", + "renderer": { + "type": "text" + } + } + ] + }, + "style": { + "richTableCellPadding": 6 + } + } + } + } + }, + { + "i": "26019fdd-0b21-4194-a36e-9b2377ee8f98", + "x": 0, + "y": 11, + "w": 4, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Audit Trail", + "description": "Edits, snapshots and runs of this runbook", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[auditEvents]}}", + "name": "auditEvents", + "pluginConfigId": "{{configId}}", + "sort": { + "by": [ + [ + "Occurred", + "desc" + ] + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Runbooks]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Runbook]}}" + }, + "variables": [ + "{{variables.[Octopus Runbook]}}" + ], + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "Occurred", + "Username", + "Category", + "Message" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "Occurred", + "title": "When", + "renderer": { + "type": "date", + "relative": true + } + }, + { + "field": "Username", + "title": "User", + "renderer": { + "type": "text" + } + }, + { + "field": "Category", + "title": "Category", + "renderer": { + "type": "badge", + "colors": { + "*Failed": "#d63939", + "Deleted": "#d63939", + "Created": "#2fb344", + "Modified": "#2F93E0", + "*Succeeded": "#2fb344" + }, + "defaultColor": "#6b7280" + } + }, + { + "field": "Message", + "title": "Event", + "renderer": { + "type": "text" + } + }, + { + "field": "IpAddress", + "title": "IP Address", + "renderer": { + "type": "text" + } + } + ] + }, + "style": { + "richTableCellPadding": 6, + "richTableWrapText": true + } + } + } + } + } + ] + } +} diff --git a/plugins/OctopusDeploy/v1/defaultContent/scopes.json b/plugins/OctopusDeploy/v1/defaultContent/scopes.json new file mode 100644 index 00000000..d14480b8 --- /dev/null +++ b/plugins/OctopusDeploy/v1/defaultContent/scopes.json @@ -0,0 +1,104 @@ +[ + { + "name": "Octopus Spaces", + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Space" + ] + } + }, + "variable": { + "name": "Octopus Space", + "allowMultipleSelection": false, + "default": "none", + "type": "object" + } + }, + { + "name": "Octopus Projects", + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Project" + ] + } + }, + "variable": { + "name": "Octopus Project", + "allowMultipleSelection": false, + "default": "none", + "type": "object" + } + }, + { + "name": "Octopus Environments", + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Environment" + ] + } + }, + "variable": { + "name": "Octopus Environment", + "allowMultipleSelection": false, + "default": "none", + "type": "object" + } + }, + { + "name": "Octopus Deployment Targets", + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Deployment Target" + ] + } + }, + "variable": { + "name": "Octopus Deployment Target", + "allowMultipleSelection": false, + "default": "none", + "type": "object" + } + }, + { + "name": "Octopus Runbooks", + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Runbook" + ] + } + }, + "variable": { + "name": "Octopus Runbook", + "allowMultipleSelection": false, + "default": "none", + "type": "object" + } + }, + { + "name": "Octopus Worker Pools", + "matches": { + "sourceType": { + "type": "oneOf", + "values": [ + "Worker Pool" + ] + } + }, + "variable": { + "name": "Octopus Worker Pool", + "allowMultipleSelection": false, + "default": "none", + "type": "object" + } + } +] diff --git a/plugins/OctopusDeploy/v1/defaultContent/tasks.dash.json b/plugins/OctopusDeploy/v1/defaultContent/tasks.dash.json new file mode 100644 index 00000000..447e3336 --- /dev/null +++ b/plugins/OctopusDeploy/v1/defaultContent/tasks.dash.json @@ -0,0 +1,810 @@ +{ + "name": "Tasks", + "schemaVersion": "1.5", + "timeframe": "last24hours", + "dashboard": { + "_type": "layout/grid", + "columns": 4, + "version": 1, + "contents": [ + { + "i": "54aa8ae8-54eb-49b0-976d-3a7a99a9d6e0", + "x": 0, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Tasks", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[tasks]}}", + "name": "tasks", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Tasks" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "scalar", + "encoding": { + "values": [ + { + "field": "count", + "type": "quantitative", + "title": "Tasks" + } + ] + }, + "style": { + "scalarLabelText": "Tasks" + } + } + } + } + }, + { + "i": "d6538fa7-aa9b-4b7c-bd2e-0eaef2c1dc1f", + "x": 1, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Failed Tasks", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[tasks]}}", + "name": "tasks", + "pluginConfigId": "{{configId}}", + "filter": { + "multiOperation": "or", + "filters": [ + { + "column": "State", + "operation": "equals", + "value": "Failed" + }, + { + "column": "State", + "operation": "equals", + "value": "TimedOut" + } + ] + }, + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Failed" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "scalar", + "encoding": { + "values": [ + { + "field": "count", + "type": "quantitative", + "title": "Failed" + } + ] + }, + "style": { + "scalarLabelText": "Failed", + "scalarValueColor": "#d63939" + } + } + } + } + }, + { + "i": "b9da3e41-5652-4222-93ad-7acd12bc72d9", + "x": 2, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Awaiting Input", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[tasks]}}", + "name": "tasks", + "pluginConfigId": "{{configId}}", + "filter": { + "multiOperation": "and", + "filters": [ + { + "column": "HasPendingInterruptions", + "operation": "equals", + "value": "true" + } + ] + }, + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Manual intervention" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "scalar", + "encoding": { + "values": [ + { + "field": "count", + "type": "quantitative", + "title": "Manual intervention" + } + ] + }, + "style": { + "scalarLabelText": "Manual intervention", + "scalarValueColor": "#f59f00" + } + } + } + } + }, + { + "i": "60073c46-b7f5-45f8-b7a7-629821fd39e6", + "x": 3, + "y": 0, + "w": 1, + "h": 2, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Active Now", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[tasks]}}", + "name": "tasks", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Queued or running" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "scalar", + "encoding": { + "values": [ + { + "field": "count", + "type": "quantitative", + "title": "Queued or running" + } + ] + }, + "style": { + "scalarLabelText": "Queued or running", + "scalarValueColor": "#2F93E0" + } + } + } + } + }, + { + "i": "1b0c0505-6c7c-4ab7-8a78-4e350db666e0", + "x": 0, + "y": 2, + "w": 3, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Tasks Over Time", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[tasks]}}", + "name": "tasks", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "QueueTime", + "byHour" + ], + [ + "Name", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-bar-chart", + "config": { + "data-stream-bar-chart": { + "xAxisData": "QueueTime_byHour", + "yAxisData": [ + "count" + ], + "xAxisGroup": "none", + "xAxisLabel": "", + "yAxisLabel": "", + "showXAxisLabel": false, + "showYAxisLabel": false, + "showLegend": false, + "legendPosition": "bottom", + "showGrid": true, + "horizontalLayout": "vertical", + "displayMode": "actual", + "showTotals": false, + "showValue": false, + "grouping": false, + "range": { + "type": "auto" + } + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "bar", + "encoding": { + "x": { + "field": "QueueTime_byHour", + "type": "temporal", + "title": "Hour" + }, + "y": { + "field": "count", + "type": "quantitative", + "title": "Tasks" + }, + "series": { + "field": "Name_uniqueValues", + "type": "nominal", + "title": "Type" + } + }, + "style": { + "cartesianStack": "on", + "cartesianBarBorderRadius": 3, + "legendPosition": "bottom" + } + } + } + } + }, + { + "i": "e19c8f31-5a5f-4c2f-9358-271c6d9efeeb", + "x": 3, + "y": 2, + "w": 1, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Tasks by Type", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[tasks]}}", + "name": "tasks", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "Name", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-donut-chart", + "config": { + "data-stream-donut-chart": { + "valueColumn": "count", + "labelColumn": "Name_uniqueValues", + "hideCenterValue": false, + "showValuesAsPercentage": false, + "legendPosition": "auto", + "legendMode": "table" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "pie", + "encoding": { + "label": { + "field": "Name_uniqueValues", + "type": "nominal", + "title": "Type" + }, + "value": { + "field": "count", + "type": "quantitative", + "title": "Tasks" + } + }, + "style": { + "pieInnerRadius": 60, + "pieDonutCenterValue": "total", + "labelFontSize": 16, + "pieLegendStyle": "table" + } + } + } + } + }, + { + "i": "a6a6dfec-bf7a-4afa-9076-c168f2959cb2", + "x": 0, + "y": 5, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Outcomes by Type", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[tasks]}}", + "name": "tasks", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "Name", + "uniqueValues" + ], + [ + "State", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-bar-chart", + "config": { + "data-stream-bar-chart": { + "xAxisData": "Name_uniqueValues", + "yAxisData": [ + "count" + ], + "xAxisGroup": "none", + "xAxisLabel": "", + "yAxisLabel": "", + "showXAxisLabel": false, + "showYAxisLabel": false, + "showLegend": false, + "legendPosition": "bottom", + "showGrid": true, + "horizontalLayout": "vertical", + "displayMode": "actual", + "showTotals": false, + "showValue": false, + "grouping": false, + "range": { + "type": "auto" + } + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "bar", + "encoding": { + "x": { + "field": "Name_uniqueValues", + "type": "nominal", + "title": "Type" + }, + "y": { + "field": "count", + "type": "quantitative", + "title": "Tasks" + }, + "series": { + "field": "State_uniqueValues", + "type": "nominal", + "title": "State" + } + }, + "style": { + "cartesianHorizontal": true, + "cartesianStack": "on", + "cartesianBarBorderRadius": 3, + "mappedColors": { + "Success": "#2fb344", + "Failed": "#d63939", + "TimedOut": "#d63939", + "Canceled": "#f59f00", + "Cancelling": "#f59f00", + "Queued": "#6b7280", + "Executing": "#2F93E0" + }, + "legendPosition": "bottom" + } + } + } + } + }, + { + "i": "57593ee4-79f3-4b48-93ef-7d211ba2b3e6", + "x": 2, + "y": 5, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Duration and Wait by Type", + "description": "Mean run time and mean time spent queued, in seconds", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[tasks]}}", + "name": "tasks", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "Name", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "mean", + "names": [ + "durationSeconds", + "queuedSeconds" + ] + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-bar-chart", + "config": { + "data-stream-bar-chart": { + "xAxisData": "Name_uniqueValues", + "yAxisData": [ + "durationSeconds_mean", + "queuedSeconds_mean" + ], + "xAxisGroup": "none", + "xAxisLabel": "", + "yAxisLabel": "", + "showXAxisLabel": false, + "showYAxisLabel": false, + "showLegend": false, + "legendPosition": "bottom", + "showGrid": true, + "horizontalLayout": "vertical", + "displayMode": "actual", + "showTotals": false, + "showValue": false, + "grouping": false, + "range": { + "type": "auto" + } + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "bar", + "encoding": { + "x": { + "field": "Name_uniqueValues", + "type": "nominal", + "title": "Type" + } + }, + "style": { + "cartesianHorizontal": true, + "cartesianBarBorderRadius": 3, + "legendPosition": "bottom", + "colors": [ + "#2F93E0", + "#f59f00" + ] + } + } + } + } + }, + { + "i": "7656e11b-92d1-4edf-8d88-ebaab4970444", + "x": 0, + "y": 8, + "w": 4, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Recent Tasks", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "dataStream": { + "id": "{{dataStreams.[tasks]}}", + "name": "tasks", + "pluginConfigId": "{{configId}}", + "sort": { + "by": [ + [ + "QueueTime", + "desc" + ] + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Spaces]}}", + "workspace": "{{workspaceId}}" + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "QueueTime", + "Description", + "Name", + "status", + "durationSeconds" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "QueueTime", + "title": "Queued", + "renderer": { + "type": "date", + "relative": true + } + }, + { + "field": "Description", + "title": "Task", + "renderer": { + "type": "text" + } + }, + { + "field": "Name", + "title": "Type", + "renderer": { + "type": "badge", + "defaultColor": "#6b7280" + } + }, + { + "field": "State", + "title": "State", + "renderer": { + "type": "badge", + "colors": { + "Success": "#2fb344", + "Failed": "#d63939", + "TimedOut": "#d63939", + "Canceled": "#f59f00", + "Cancelling": "#f59f00", + "Queued": "#6b7280", + "Executing": "#2F93E0" + }, + "defaultColor": "#6b7280" + } + }, + { + "field": "queuedSeconds", + "title": "Waited", + "renderer": { + "type": "number", + "suffix": " s", + "decimals": 0 + } + }, + { + "field": "durationSeconds", + "title": "Duration", + "renderer": { + "type": "bar", + "color": "#2F93E0" + } + }, + { + "field": "HasPendingInterruptions", + "title": "Needs Input", + "renderer": { + "type": "boolean", + "trueLabel": "Yes", + "falseLabel": "", + "trueColor": "#f59f00" + } + }, + { + "field": "ErrorMessage", + "title": "Error", + "renderer": { + "type": "text" + } + } + ] + }, + "style": { + "richTableCellPadding": 6 + } + } + } + } + } + ] + } +} diff --git a/plugins/OctopusDeploy/v1/defaultContent/workerPool.dash.json b/plugins/OctopusDeploy/v1/defaultContent/workerPool.dash.json new file mode 100644 index 00000000..d372063f --- /dev/null +++ b/plugins/OctopusDeploy/v1/defaultContent/workerPool.dash.json @@ -0,0 +1,323 @@ +{ + "name": "Worker Pool", + "schemaVersion": "1.5", + "timeframe": "last24hours", + "variables": [ + "{{variables.[Octopus Worker Pool]}}" + ], + "dashboard": { + "_type": "layout/grid", + "columns": 4, + "version": 1, + "contents": [ + { + "i": "c8840343-65b5-4e8a-a047-e7f5250450b4", + "x": 0, + "y": 0, + "w": 1, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Worker Pool Properties", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "datastream-properties", + "name": "properties", + "pluginConfigId": "{{configId}}" + }, + "scope": { + "scope": "{{scopes.[Octopus Worker Pools]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Worker Pool]}}" + }, + "variables": [ + "{{variables.[Octopus Worker Pool]}}" + ], + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": true, + "columnOrder": [ + "name" + ], + "hiddenColumns": [ + "id", + "links", + "type", + "label", + "sourceId", + "sourceType", + "spaceId" + ] + } + } + } + } + }, + { + "i": "3f6e73f5-233c-457f-8094-515f08021e44", + "x": 1, + "y": 0, + "w": 1, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Workers", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[workers]}}", + "name": "workers", + "pluginConfigId": "{{configId}}", + "group": { + "by": [], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "scope": { + "scope": "{{scopes.[Octopus Worker Pools]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Worker Pool]}}" + }, + "variables": [ + "{{variables.[Octopus Worker Pool]}}" + ], + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "count", + "comparisonColumn": "none", + "label": "Workers" + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "scalar", + "encoding": { + "values": [ + { + "field": "count", + "type": "quantitative", + "title": "Workers" + } + ] + }, + "style": { + "scalarLabelText": "Workers" + } + } + } + } + }, + { + "i": "a1b5905a-5bb3-4790-a691-d9cd17a73555", + "x": 2, + "y": 0, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Worker Health", + "description": "Dynamic pools are managed by Octopus and list no workers", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[workers]}}", + "name": "workers", + "pluginConfigId": "{{configId}}" + }, + "scope": { + "scope": "{{scopes.[Octopus Worker Pools]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Worker Pool]}}" + }, + "variables": [ + "{{variables.[Octopus Worker Pool]}}" + ], + "visualisation": { + "type": "data-stream-blocks", + "config": { + "data-stream-blocks": { + "labelColumn": "Name", + "stateColumn": "health", + "sublabel": "HealthStatus", + "linkColumn": "none", + "columns": 4 + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "statusGrid", + "encoding": { + "label": { + "field": "Name", + "type": "nominal" + }, + "status": { + "field": "health", + "type": "nominal" + }, + "value": { + "field": "HealthStatus", + "type": "nominal" + } + }, + "style": { + "statusGridColumnsPerRow": 3, + "statusGridBlockGap": 8, + "statusGridMaxBlockHeight": 110 + } + } + } + } + }, + { + "i": "17bb9b7f-da7c-41ee-bc78-a919fe314dd7", + "x": 0, + "y": 3, + "w": 4, + "h": 4, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Agent Versions", + "description": "", + "activePluginConfigIds": [ + "{{configId}}" + ], + "timeframe": "none", + "dataStream": { + "id": "{{dataStreams.[workers]}}", + "name": "workers", + "pluginConfigId": "{{configId}}" + }, + "scope": { + "scope": "{{scopes.[Octopus Worker Pools]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Octopus Worker Pool]}}" + }, + "variables": [ + "{{variables.[Octopus Worker Pool]}}" + ], + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": [ + "Name", + "agentStatus", + "TentacleVersion", + "HasLatestCalamari" + ] + } + } + }, + "vizSpec": { + "version": "1.0", + "visualization": { + "chartType": "richTable", + "encoding": { + "columns": [ + { + "field": "Name", + "title": "Worker", + "renderer": { + "type": "text" + } + }, + { + "field": "agentStatus", + "title": "Agent", + "renderer": { + "type": "status" + } + }, + { + "field": "TentacleVersion", + "title": "Tentacle", + "renderer": { + "type": "text" + } + }, + { + "field": "TentacleUpgrade", + "title": "Tentacle Upgrade", + "renderer": { + "type": "badge", + "colors": { + "Required": "#d63939", + "Suggested": "#f59f00", + "Up to date": "#2fb344" + }, + "defaultColor": "#6b7280" + } + }, + { + "field": "HasLatestCalamari", + "title": "Latest Calamari", + "renderer": { + "type": "boolean", + "trueLabel": "Yes", + "falseLabel": "No", + "trueColor": "#2fb344", + "falseColor": "#f59f00" + } + }, + { + "field": "CommunicationStyle", + "title": "Communication", + "renderer": { + "type": "badge", + "defaultColor": "#6b7280" + } + }, + { + "field": "OperatingSystem", + "title": "Operating System", + "renderer": { + "type": "text" + } + } + ] + }, + "style": { + "richTableCellPadding": 6 + } + } + } + } + } + ] + } +} diff --git a/plugins/OctopusDeploy/v1/docs/README.md b/plugins/OctopusDeploy/v1/docs/README.md new file mode 100644 index 00000000..29b84c85 --- /dev/null +++ b/plugins/OctopusDeploy/v1/docs/README.md @@ -0,0 +1,79 @@ +Monitor your [Octopus Deploy](https://octopus.com) spaces in SquaredUp, including what is deployed where, deployment and runbook history, the task queue and deployment target health. Data comes from the [Octopus REST API](https://octopus.com/docs/api). Works with both Octopus Cloud and self-hosted Octopus Server. + +## Setup + +You will need the address of your Octopus server and an **API key**. Using a dedicated read-only service account is recommended, because the plugin only ever reads from Octopus. + +1. Sign in to Octopus Deploy as an administrator. +2. Create a service account. Go to **Configuration → Users**, click **Add User**, tick **The user is a service account**, and save. See [Service accounts](https://octopus.com/docs/security/users-and-teams/service-accounts). +3. Give the account read access. Go to **Configuration → Teams**, create or choose a team, add the service account, and include the **Project viewer** and **Environment viewer** roles for every space to monitor. See [User roles](https://octopus.com/docs/security/users-and-teams/user-roles). +4. Create an API key for the account. Open the service account under **Configuration → Users**, click **New API Key**, give it a purpose such as `SquaredUp`, and copy the key. It starts with `API-`. See [How to create an API key](https://octopus.com/docs/api/authentication/create-an-api-key). +5. In SquaredUp, enter the **Server URL** and paste the key into **API key**. + +## Configuration fields + +| Field | What it is | Where to find it | Required | +| ----- | ---------- | ---------------- | -------- | +| **Server URL** | The address of your Octopus server, e.g. `https://example.octopus.app` for Octopus Cloud or `https://octopus.example.com` for a self-hosted server. | The address in your browser's address bar when you open Octopus. | Yes | +| **API key** | The key used to authenticate every request. It is sent in the `X-Octopus-ApiKey` header. | Octopus → **Configuration → Users** → the service account → **API Keys**, or **Profile → My API Keys** for your own user. | Yes | + +When you save, the plugin checks the key by fetching the user it belongs to. If the server URL is unreachable, or the key is invalid or expired, setup fails with an authentication error. If a self-hosted server uses a certificate from an internal certificate authority that SquaredUp doesn't trust, **Ignore certificate errors** lets the connection succeed. It turns off certificate validation, so use it only where you trust the network path to the server. + +## What this plugin monitors + +- **Current deployment status**: the release deployed to each environment (and tenant) for every project, whether it succeeded, and whether it is waiting on manual intervention. +- **Deployment history**: every deployment with its outcome, duration and who deployed it, for tracking deployment frequency, success rate and failures. +- **Task queue and history**: queued and running tasks, plus recent runbook runs, health checks and other server tasks. +- **Deployment target health**: the health status of every deployment target, with its target tags, environments and operating system. +- **Workers and agents**: worker health in each worker pool, and which Tentacle and Calamari agents need upgrading. +- **Approvals and freezes**: deployments and runbook runs waiting on a manual intervention or guided failure, and deployment freezes in force now or coming up. +- **Runbooks**: the latest run of each runbook in each environment, and run history. +- **Certificates**: certificates in the Octopus library, and how soon they expire. +- **License**: when the Octopus license or Cloud subscription expires, and usage against each licensed limit. +- **Audit log**: who changed or did what, and when. + +The out-of-the-box dashboards include **Overview**, **Tasks**, **Infrastructure** and **Audit** dashboards, plus a perspective for each **Project**, **Environment**, **Deployment Target**, **Runbook** and **Worker Pool**. + +## Data streams + +Each stream can be scoped to whole **Spaces**, or to individual projects, environments, tenants or deployment targets to see just that object's data. + +- **Deployment Status**: the latest deployment of each project to each environment and tenant, with release version and status. +- **Release Progression**: the latest releases of one project, with a row for each release and environment showing whether it was deployed there, when, and where it is ready to deploy next, like the Octopus **Project Dashboard**. +- **Deployments**: deployment history for the timeframe, one row per deployment, with project, environment, tenant, channel, release, outcome, deployed by and duration. +- **Tasks**: server tasks in the timeframe, filterable by task type (deployment, runbook run, health check, and so on), state and project. With a timeframe of **None**, it returns only queued and running tasks. +- **Deployment Targets**: deployment targets with their current health, target tags, environments, communication style and agent versions. +- **Workers**: workers with their current health, worker pools and agent versions. +- **Runbook Status**: the latest run of one runbook in each environment, like the Octopus runbook overview. +- **Pending Interventions**: deployments and runbook runs waiting on a manual intervention or guided failure, with how long they have waited. +- **Deployment Freezes**: freezes that are active now or scheduled, with what they block. +- **Certificates**: certificates in the Octopus library, with days until expiry. +- **Audit Events**: the Octopus audit log, filterable by category, for up to the last 7 days. +- **License**: license or Cloud subscription expiry and compliance, with usage against each licensed limit such as projects, targets and tasks. + +## What gets indexed + +| Object type | API source | Represents | +| ----------- | ---------- | ---------- | +| **Space** | `GET /api/spaces/all` | An Octopus space, the container for all other objects. | +| **Project** | `GET /api/{spaceId}/projects` | A deployable project. | +| **Environment** | `GET /api/{spaceId}/environments` | An environment such as Development, Staging or Production. | +| **Deployment Target** | `GET /api/{spaceId}/machines` | A machine or cloud resource that Octopus deploys to. | +| **Tenant** | `GET /api/{spaceId}/tenants` | A tenant, for multi-tenant deployments. | +| **Runbook** | `GET /api/{spaceId}/runbooks` | A runbook belonging to a project. | +| **Worker Pool** | `GET /api/{spaceId}/workerpools` | A static or dynamic pool of workers. | +| **Worker** | `GET /api/{spaceId}/workers` | A machine in a static worker pool that runs deployment work. | + +**Relationships:** every object stores the `spaceId` of the space it belongs to. Deployment targets are related to their environments and tenants, workers to their worker pools, and runbooks to their project. + +## Known limitations + +- **New data sources import in two passes.** Projects, environments, deployment targets and tenants are imported per space, after spaces. On the first import of a new data source they can be skipped, and they appear on the next import. +- **Successful deployments that logged warnings show as successful**, as they do in Octopus. **Deployment Status** and **Tasks** have a separate warnings column. +- **Release Progression times are UTC.** The **Detail** column shows the deployment time as text in UTC. +- **Deployments only covers completed deployments.** Queued and running deployments appear in **Tasks** and **Deployment Status**. The timeframe is limited to the last quarter, because the deployment report isn't paged. +- **Tasks history is limited to the last 7 days.** Busy servers run many health check and retention tasks, so longer ranges could exceed response size limits. Filter by task type to keep results small. **Tasks** can't filter by environment, because the Octopus API accepts only a single environment there. Use **Deployments** or **Deployment Status** for environment views. +- **Deployment freezes and the license are server-wide.** Octopus doesn't record a space against either, so they are shown against the default space. +- **Dynamic worker pools list no workers.** Octopus Cloud's hosted pools are managed by Octopus and don't expose their workers. +- **Data freshness.** Objects are re-imported every 12 hours. Data streams query Octopus live. +- **Read-only.** The plugin never creates, changes or deletes anything in Octopus Deploy. diff --git a/plugins/OctopusDeploy/v1/icon.svg b/plugins/OctopusDeploy/v1/icon.svg new file mode 100644 index 00000000..3290d7a5 --- /dev/null +++ b/plugins/OctopusDeploy/v1/icon.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/plugins/OctopusDeploy/v1/indexDefinitions/default.json b/plugins/OctopusDeploy/v1/indexDefinitions/default.json new file mode 100644 index 00000000..3188f955 --- /dev/null +++ b/plugins/OctopusDeploy/v1/indexDefinitions/default.json @@ -0,0 +1,308 @@ +{ + "steps": [ + { + "name": "spaces", + "dataStream": { + "name": "spaces" + }, + "timeframe": "none", + "objectMapping": { + "id": "Id", + "name": "Name", + "type": { + "value": "Space" + }, + "properties": [ + { + "slug": "Slug" + }, + { + "description": "Description" + }, + { + "isDefault": "IsDefault" + }, + { + "taskQueueStopped": "TaskQueueStopped" + } + ] + } + }, + { + "name": "projects", + "dataStream": { + "name": "projects" + }, + "scope": { + "query": "g.V().has(\"sourceType\", \"Space\")" + }, + "timeframe": "none", + "objectMapping": { + "id": "Id", + "name": "Name", + "type": { + "value": "Project" + }, + "properties": [ + { + "spaceId": "SpaceId" + }, + { + "slug": "Slug" + }, + { + "description": "Description" + }, + { + "disabled": "IsDisabled" + }, + { + "projectGroupId": "ProjectGroupId" + }, + { + "lifecycleId": "LifecycleId" + } + ] + }, + "dependsOn": [ + "spaces" + ] + }, + { + "name": "environments", + "dataStream": { + "name": "environments" + }, + "scope": { + "query": "g.V().has(\"sourceType\", \"Space\")" + }, + "timeframe": "none", + "objectMapping": { + "id": "Id", + "name": "Name", + "type": { + "value": "Environment" + }, + "properties": [ + { + "spaceId": "SpaceId" + }, + { + "description": "Description" + }, + { + "sortOrder": "SortOrder" + } + ] + }, + "dependsOn": [ + "spaces" + ] + }, + { + "name": "deploymentTargets", + "dataStream": { + "name": "deploymentTargets" + }, + "scope": { + "query": "g.V().has(\"sourceType\", \"Space\")" + }, + "timeframe": "none", + "objectMapping": { + "id": "Id", + "name": "Name", + "type": { + "value": "Deployment Target" + }, + "properties": [ + { + "spaceId": "SpaceId" + }, + { + "healthStatus": "HealthStatus" + }, + { + "disabled": "IsDisabled" + }, + { + "targetTags": "Roles" + }, + { + "environmentIds": "EnvironmentIds" + }, + { + "tenantIds": "TenantIds" + }, + { + "communicationStyle": "CommunicationStyle" + }, + { + "operatingSystem": "OperatingSystem" + }, + { + "tentacleVersion": "TentacleVersion" + } + ] + }, + "optional": true, + "dependsOn": [ + "spaces" + ] + }, + { + "name": "tenants", + "dataStream": { + "name": "tenants" + }, + "scope": { + "query": "g.V().has(\"sourceType\", \"Space\")" + }, + "timeframe": "none", + "objectMapping": { + "id": "Id", + "name": "Name", + "type": { + "value": "Tenant" + }, + "properties": [ + { + "spaceId": "SpaceId" + }, + { + "description": "Description" + }, + { + "disabled": "IsDisabled" + }, + { + "tenantTags": "TenantTags" + } + ] + }, + "optional": true, + "dependsOn": [ + "spaces" + ] + }, + { + "name": "runbooks", + "dataStream": { + "name": "runbooks" + }, + "scope": { + "query": "g.V().has(\"sourceType\", \"Space\")" + }, + "timeframe": "none", + "objectMapping": { + "id": "Id", + "name": "Name", + "type": { + "value": "Runbook" + }, + "properties": [ + { + "spaceId": "SpaceId" + }, + { + "projectId": "ProjectId" + }, + { + "description": "Description" + }, + { + "environmentScope": "EnvironmentScope" + }, + { + "multiTenancyMode": "MultiTenancyMode" + } + ] + }, + "dependsOn": [ + "spaces" + ], + "optional": true + }, + { + "name": "workerPools", + "dataStream": { + "name": "workerPoolList" + }, + "scope": { + "query": "g.V().has(\"sourceType\", \"Space\")" + }, + "timeframe": "none", + "objectMapping": { + "id": "Id", + "name": "Name", + "type": { + "value": "Worker Pool" + }, + "properties": [ + { + "spaceId": "SpaceId" + }, + { + "description": "Description" + }, + { + "workerPoolType": "WorkerPoolType" + }, + { + "workerType": "WorkerType" + }, + { + "isDefault": "IsDefault" + } + ] + }, + "dependsOn": [ + "spaces" + ], + "optional": true + }, + { + "name": "workers", + "dataStream": { + "name": "workers" + }, + "scope": { + "query": "g.V().has(\"sourceType\", \"Space\")" + }, + "timeframe": "none", + "objectMapping": { + "id": "Id", + "name": "Name", + "type": { + "value": "Worker" + }, + "properties": [ + { + "spaceId": "SpaceId" + }, + { + "healthStatus": "HealthStatus" + }, + { + "disabled": "IsDisabled" + }, + { + "workerPoolIds": "WorkerPoolIds" + }, + { + "communicationStyle": "CommunicationStyle" + }, + { + "operatingSystem": "OperatingSystem" + }, + { + "tentacleVersion": "TentacleVersion" + } + ] + }, + "dependsOn": [ + "spaces" + ], + "optional": true + } + ] +} diff --git a/plugins/OctopusDeploy/v1/metadata.json b/plugins/OctopusDeploy/v1/metadata.json new file mode 100644 index 00000000..6f64737f --- /dev/null +++ b/plugins/OctopusDeploy/v1/metadata.json @@ -0,0 +1,78 @@ +{ + "name": "octopus-deploy", + "displayName": "Octopus Deploy", + "version": "1.0.0", + "author": { + "name": "@clarkd", + "type": "community" + }, + "description": "Track deployment status, release history, task queues and deployment target health across your Octopus Deploy spaces.", + "category": "CI/CD Tools", + "type": "hybrid", + "schemaVersion": "2.1", + "importNotSupported": false, + "restrictedToPlatforms": [], + "keywords": [ + "octopus", + "octopus deploy", + "deployment", + "release", + "continuous delivery", + "cd", + "devops", + "runbook", + "tentacle", + "worker", + "certificate", + "deployment freeze", + "audit" + ], + "objectTypes": [ + "Space", + "Project", + "Environment", + "Deployment Target", + "Tenant", + "Runbook", + "Worker Pool", + "Worker" + ], + "links": [ + { + "category": "documentation", + "url": "https://github.com/squaredup/plugins/blob/main/plugins/OctopusDeploy/v1/docs/README.md", + "label": "Help adding this plugin" + }, + { + "category": "source", + "url": "https://github.com/squaredup/plugins/tree/main/plugins/OctopusDeploy/v1", + "label": "Repository" + } + ], + "base": { + "plugin": "WebAPI", + "majorVersion": "1", + "config": { + "baseUrl": "{{ serverUrl.trim().replace(/[/]+$/, '').replace(/[/]api$/i, '') }}", + "authMode": "none", + "headers": [ + { + "key": "X-Octopus-ApiKey", + "value": "{{ apiKey.trim() }}" + }, + { + "key": "Accept", + "value": "application/json" + } + ], + "queryArgs": [] + } + }, + "screenshots": [ + "https://github.com/squaredup/plugins/blob/main/plugins/OctopusDeploy/v1/screenshots/overview.png", + "https://github.com/squaredup/plugins/blob/main/plugins/OctopusDeploy/v1/screenshots/tasks.png", + "https://github.com/squaredup/plugins/blob/main/plugins/OctopusDeploy/v1/screenshots/infrastructure.png", + "https://github.com/squaredup/plugins/blob/main/plugins/OctopusDeploy/v1/screenshots/project.png", + "https://github.com/squaredup/plugins/blob/main/plugins/OctopusDeploy/v1/screenshots/runbook.png" + ] +} diff --git a/plugins/OctopusDeploy/v1/screenshots/infrastructure.png b/plugins/OctopusDeploy/v1/screenshots/infrastructure.png new file mode 100644 index 00000000..750fc795 Binary files /dev/null and b/plugins/OctopusDeploy/v1/screenshots/infrastructure.png differ diff --git a/plugins/OctopusDeploy/v1/screenshots/overview.png b/plugins/OctopusDeploy/v1/screenshots/overview.png new file mode 100644 index 00000000..b6ae3af8 Binary files /dev/null and b/plugins/OctopusDeploy/v1/screenshots/overview.png differ diff --git a/plugins/OctopusDeploy/v1/screenshots/project.png b/plugins/OctopusDeploy/v1/screenshots/project.png new file mode 100644 index 00000000..4d498c53 Binary files /dev/null and b/plugins/OctopusDeploy/v1/screenshots/project.png differ diff --git a/plugins/OctopusDeploy/v1/screenshots/runbook.png b/plugins/OctopusDeploy/v1/screenshots/runbook.png new file mode 100644 index 00000000..7d6a082b Binary files /dev/null and b/plugins/OctopusDeploy/v1/screenshots/runbook.png differ diff --git a/plugins/OctopusDeploy/v1/screenshots/tasks.png b/plugins/OctopusDeploy/v1/screenshots/tasks.png new file mode 100644 index 00000000..20af6e6f Binary files /dev/null and b/plugins/OctopusDeploy/v1/screenshots/tasks.png differ diff --git a/plugins/OctopusDeploy/v1/ui.json b/plugins/OctopusDeploy/v1/ui.json new file mode 100644 index 00000000..66a13a73 --- /dev/null +++ b/plugins/OctopusDeploy/v1/ui.json @@ -0,0 +1,26 @@ +[ + { + "type": "text", + "name": "serverUrl", + "label": "Server URL", + "placeholder": "https://example.octopus.app", + "help": "The address used to open Octopus Deploy in a browser, for Octopus Cloud or a self-hosted Octopus Server", + "validation": { + "required": true, + "pattern": { + "value": "^https?://[^ ]+$", + "message": "Enter the full address of the Octopus server, e.g. https://example.octopus.app" + } + } + }, + { + "type": "password", + "name": "apiKey", + "label": "API key", + "placeholder": "API-XXXXXXXXXXXXXXXXXXXXXXXXXX", + "help": "Create an API key in Octopus under **Profile > My API Keys**. See [How to create an API key](https://octopus.com/docs/api/authentication/create-an-api-key)", + "validation": { + "required": true + } + } +]