Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
apiVersion: runwhen.com/v1
kind: GenerationRules
spec:
platform: atlassian
generationRules:
- resourceTypes:
- atlassian_organization
matchRules:
- type: pattern
pattern: ".+"
properties: ["name"]
mode: substring
slxs:
- baseName: atlassian-org-license-utilization
qualifiers: ["ATLASSIAN_ORG_ID", "ATLASSIAN_ORG_NAME"]
baseTemplateName: atlassian-org-license-utilization
levelOfDetail: basic
outputItems:
- type: slx
- type: sli
templateName: atlassian-org-license-utilization-sli.yaml
- type: runbook
templateName: atlassian-org-license-utilization-taskset.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
apiVersion: runwhen.com/v1
kind: ServiceLevelIndicator
metadata:
name: {{slx_name}}
labels:
{% include "common-labels.yaml" %}
annotations:
{% include "common-annotations.yaml" %}
spec:
displayUnitsLong: Health Score
displayUnitsShort: score
locations:
- {{default_location}}
description: Measures Atlassian organization license health via API reachability, tier headroom, and utilization thresholds for {{ match_resource.name }}.
codeBundle:
{% if repo_url %}
repoUrl: {{repo_url}}
{% else %}
repoUrl: https://github.com/runwhen-contrib/rw-cli-codecollection.git
{% endif %}
{% if ref %}
ref: {{ref}}
{% else %}
ref: main
{% endif %}
pathToRobot: codebundles/atlassian-org-license-utilization/sli.robot
intervalStrategy: intermezzo
intervalSeconds: 300
configProvided:
- name: ATLASSIAN_ORG_ID
value: "{{ match_resource.org_id | default(match_resource.id) }}"
- name: ATLASSIAN_ORG_NAME
value: "{{ match_resource.name }}"
- name: ATLASSIAN_DIRECTORY_ID
value: "{{ custom.atlassian_directory_id | default('') }}"
- name: LICENSE_UTILIZATION_MIN_PERCENT
value: "{{ custom.license_utilization_min_percent | default('70') }}"
- name: USER_TIER_PROXIMITY_PERCENT
value: "{{ custom.user_tier_proximity_percent | default('80') }}"
- name: INACTIVE_DAYS_THRESHOLD
value: "{{ custom.inactive_days_threshold | default('90') }}"
- name: PRODUCTS
value: "{{ custom.products | default('All') }}"
- name: SLI_MAX_USER_PAGES
value: "{{ custom.sli_max_user_pages | default('10') }}"
secretsProvided:
{% if wb_version %}
{% include "atlassian-auth.yaml" ignore missing %}
{% else %}
- name: atlassian_org_api_key
workspaceKey: AUTH DETAILS NOT FOUND
{% endif %}
alertConfig:
tasks:
persona: eager-edgar
sessionTTL: 10m
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
apiVersion: runwhen.com/v1
kind: ServiceLevelX
metadata:
name: {{ slx_name }}
labels:
{% include "common-labels.yaml" %}
annotations:
{% include "common-annotations.yaml" %}
spec:
imageURL: https://storage.googleapis.com/runwhen-nonprod-shared-images/icons/atlassian/atlassian.svg
alias: {{ match_resource.name }} Atlassian License Utilization
asMeasuredBy: Active/billable license utilization and tier headroom across entitled Atlassian products. 1=healthy utilization and tier headroom, 0=failing thresholds.
configProvided:
- name: ATLASSIAN_ORG_ID
value: "{{ match_resource.org_id | default(match_resource.id) }}"
- name: ATLASSIAN_ORG_NAME
value: "{{ match_resource.name }}"
owners:
- {{ workspace.owner_email }}
statement: Atlassian organization {{ match_resource.name }} license utilization should remain above configured thresholds with tier headroom before renewal.
additionalContext:
{% include "atlassian-hierarchy.yaml" ignore missing %}
qualified_name: "{{ match_resource.qualified_name }}"
tags:
{% include "atlassian-tags.yaml" ignore missing %}
- name: cloud
value: saas
- name: service
value: atlassian-admin
- name: scope
value: organization
- name: access
value: read-only
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
apiVersion: runwhen.com/v1
kind: Runbook
metadata:
name: {{slx_name}}
labels:
{% include "common-labels.yaml" %}
annotations:
{% include "common-annotations.yaml" %}
spec:
location: {{default_location}}
description: Monitor Atlassian organization {{ match_resource.name }} license utilization, tier proximity, and active-user trends across entitled products.
codeBundle:
{% if repo_url %}
repoUrl: {{repo_url}}
{% else %}
repoUrl: https://github.com/runwhen-contrib/rw-cli-codecollection.git
{% endif %}
{% if ref %}
ref: {{ref}}
{% else %}
ref: main
{% endif %}
pathToRobot: codebundles/atlassian-org-license-utilization/runbook.robot
configProvided:
- name: ATLASSIAN_ORG_ID
value: "{{ match_resource.org_id | default(match_resource.id) }}"
- name: ATLASSIAN_ORG_NAME
value: "{{ match_resource.name }}"
- name: ATLASSIAN_DIRECTORY_ID
value: "{{ custom.atlassian_directory_id | default('') }}"
- name: LICENSE_UTILIZATION_MIN_PERCENT
value: "{{ custom.license_utilization_min_percent | default('70') }}"
- name: USER_TIER_PROXIMITY_PERCENT
value: "{{ custom.user_tier_proximity_percent | default('80') }}"
- name: INACTIVE_DAYS_THRESHOLD
value: "{{ custom.inactive_days_threshold | default('90') }}"
- name: PRODUCTS
value: "{{ custom.products | default('All') }}"
- name: TIMEOUT_SECONDS
value: "{{ custom.timeout_seconds | default('600') }}"
secretsProvided:
{% if wb_version %}
{% include "atlassian-auth.yaml" ignore missing %}
{% else %}
- name: atlassian_org_api_key
workspaceKey: AUTH DETAILS NOT FOUND
{% endif %}
12 changes: 12 additions & 0 deletions codebundles/atlassian-org-license-utilization/.test/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Test Infrastructure

Static validation only — Atlassian Cloud organizations cannot be provisioned via Terraform in this test harness.

## Run validation

```bash
cd .test
task
```

This verifies required bundle files, templates, generation rules, and shell scripts exist.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
version: "3"

tasks:
default:
desc: "Validate CodeBundle structure and generation artifacts"
cmds:
- task: validate-structure

validate-structure:
desc: "Run static checks for required files"
cmds:
- ./validate-atlassian-bundle-structure.sh

clean:
desc: "Remove local test outputs"
cmds:
- rm -rf output workspaceInfo.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
terraform {
backend "local" {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Atlassian organizations are SaaS resources registered manually in RunWhen.
# This placeholder satisfies the standard test-infra scaffold; no cloud resources are created.

output "note" {
value = "Atlassian org license utilization bundle uses static validation only."
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Outputs defined in main.tf for scaffold completeness.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
terraform {
required_version = ">= 1.0"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# No Terraform values required for static validation scaffold.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# No Terraform variables required for static validation scaffold.
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env bash
# Static validation for atlassian-org-license-utilization (no live Atlassian org required).
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
test -f "$ROOT/runbook.robot"
test -f "$ROOT/sli.robot"
test -f "$ROOT/README.md"
test -f "$ROOT/.runwhen/generation-rules/atlassian-org-license-utilization.yaml"
test -f "$ROOT/.runwhen/templates/atlassian-org-license-utilization-slx.yaml"
test -f "$ROOT/.runwhen/templates/atlassian-org-license-utilization-taskset.yaml"
test -f "$ROOT/.runwhen/templates/atlassian-org-license-utilization-sli.yaml"
for f in \
atlassian-api-helpers.sh \
generate-atlassian-license-utilization-report.sh \
analyze-atlassian-tier-proximity.sh \
evaluate-atlassian-utilization-thresholds.sh \
report-atlassian-active-user-trends.sh \
sli-atlassian-org-license-score.sh
do
test -f "$ROOT/$f"
done
echo "atlassian-org-license-utilization bundle structure OK"
76 changes: 76 additions & 0 deletions codebundles/atlassian-org-license-utilization/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Atlassian Organization License Utilization Report

Monitors Atlassian Cloud organization license utilization across Jira, Confluence, Jira Service Management, Loom, and other entitled products. Computes active-user versus billable-user ratios, tracks proximity to purchased user-tier limits, and raises issues when utilization falls below operator thresholds.

## Overview

This CodeBundle provides read-only SaaS license utilization reporting for Atlassian organizations:

- **License utilization report**: Per-product billable, active, and utilization percentages from managed accounts
- **Tier proximity analysis**: Billable seat fill versus purchased tier using workspaces `usage`/`capacity`
- **Utilization threshold evaluation**: Flags products below `LICENSE_UTILIZATION_MIN_PERCENT`
- **Active user trends**: Highlights declining active-user share versus billable seats for renewal planning

Last-active timestamps from the Organizations API may lag up to 24 hours. This bundle does not call suspend, revoke, or remove endpoints.

## Configuration

### Required Variables

- `ATLASSIAN_ORG_ID`: Atlassian Cloud organization UUID from Atlassian Administration
- `ATLASSIAN_ORG_NAME`: Human-readable organization name for reports and task titles

### Optional Variables

- `ATLASSIAN_DIRECTORY_ID`: Primary user directory ID when the org has multiple directories (default: discover first directory)
- `LICENSE_UTILIZATION_MIN_PERCENT`: Minimum acceptable active/billable utilization percentage per product before raising an issue (default: `70`)
- `USER_TIER_PROXIMITY_PERCENT`: Billable-user count as a percentage of purchased tier that triggers proximity alerts (default: `80`)
- `INACTIVE_DAYS_THRESHOLD`: Days without product activity before a user is treated as inactive for utilization math (default: `90`)
- `PRODUCTS`: Comma-separated product keys to include (e.g. `jira-software,confluence,loom`) or `All` (default: `All`)
- `TIMEOUT_SECONDS`: Per-task timeout; orgs with large user bases may need higher values (default: `600`)
- `SLI_MAX_USER_PAGES`: Maximum managed-account pages fetched during SLI scoring to cap runtime (default: `10`)

### Secrets

- `atlassian_org_api_key`: Organization Admin API key used as Bearer token for the [Organizations REST API](https://developer.atlassian.com/cloud/admin/organization/rest/intro/). Plain text API key string.

### Prerequisites

- Organization Admin role on the target Atlassian Cloud organization
- At least one paid subscription for full managed-accounts API access
- `curl` and `jq` available in the execution environment

## Tasks Overview

### Generate Atlassian License Utilization Report

Queries `GET /v1/orgs/{orgId}/users` (managed accounts) and aggregates per-product billable users, recently active users, and utilization percentage. Produces organization-wide summary tables suitable for finance and IT admin review. Raises issues on API access failures or empty directories.

### Analyze Billable User Counts Versus Tier Limits

Correlates billable counts with workspace `usage` and `capacity` from `POST /v2/orgs/{orgId}/workspaces`. Flags products at or above `USER_TIER_PROXIMITY_PERCENT` and overage conditions. Degrades gracefully when tier quantities are unavailable.

### Evaluate License Utilization Thresholds

Compares per-product active/billable ratios against `LICENSE_UTILIZATION_MIN_PERCENT`. Emits structured issues with expected versus actual utilization and remediation hints (review inactive users, suspend access, right-size tier).

### Report Active User Trends

Summarizes unique active users per product using `product_access.last_active` from managed accounts. Highlights products with declining active-user share versus billable seats to guide renewal decisions.

## API Notes

- **Managed accounts**: `GET https://api.atlassian.com/admin/v1/orgs/{orgId}/users` — includes `access_billable`, `product_access`, and `last_active`
- **Workspaces**: `POST https://api.atlassian.com/admin/v2/orgs/{orgId}/workspaces` — includes `usage` and `capacity` for tier proximity
- **Directories**: `GET https://api.atlassian.com/admin/v2/orgs/{orgId}/directories` — used for directory discovery and SLI auth checks
- **Rate limits**: HTTP 429 responses trigger exponential backoff; paginate with `cursor` from `links.next`

## Test Scenarios

| Scenario | Description | Expected issues |
|---|---|---|
| `healthy_high_utilization` | Org with >80% active/billable ratio and tier headroom | 0 |
| `low_utilization_jira` | Jira Software billable high but active below threshold | 2 (severity 3–4) |
| `tier_proximity_confluence` | Confluence billable at 85% of purchased tier | 1 (severity 3) |

Local static validation is available under `.test/` (no live Atlassian org required for structure checks).
Loading
Loading