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
3 changes: 2 additions & 1 deletion docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@
{
"group": "Integrations",
"pages": [
"integrations/cloudhealth"
"integrations/cloudhealth",
"integrations/cloudability"
]
},
{
Expand Down
Binary file added images/cloudability-actions.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/cloudability-connection.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
254 changes: 254 additions & 0 deletions integrations/cloudability.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
---
title: 'Cloudability'
description: "An overview of how Cloudability can be integrated with OpenOps."
icon: 'sprout'
---

import { NarrowImage } from '/snippets/narrow-image.jsx'

OpenOps integrates with [Cloudability](https://www.apptio.com/products/cloudability/) to automate receiving and managing cloud resource usage recommendations.

## Actions

OpenOps provides four [actions](/workflow-management/actions) for interacting with Cloudability:

<NarrowImage src="/images/cloudability-actions.png" alt="Cloudability actions" />

All Cloudability actions are based on the [Cloudability API](https://www.ibm.com/docs/en/cloudability-commercial/cloudability-standard/saas?topic=api-getting-started-cloudability-v3) and require configuring a Cloudability [connection](/cloud-access/access-levels-permissions) with your API key and an API URL.

<NarrowImage src="/images/cloudability-connection.png" alt="Configuring a Cloudability connection" />

The following are the four actions available in the Cloudability block.

### Get Recommendations
Retrieves cost optimization recommendations from Cloudability with extensive filtering options:
- **Vendor Type**: AWS, Azure, GCP, or Containers
- **Recommendation Type**: Dynamic dropdown based on selected vendor
- **Look-Back Period**: Last 10 or 30 days
- **Cost Basis**: On-Demand or Effective pricing
- **Recommendations Status**: Show only active, show all (including snoozed), or show only snoozed
- **Limit**: Optional maximum number of recommendations to return
- **Additional Filters**: Custom filters per [Cloudability's rightsizing API documentation](https://www.ibm.com/docs/en/cloudability-commercial/cloudability-standard/saas?topic=api-rightsizing-end-points)

Below is a sample output that this step returns when configured to request active AWS EC2 recommendations with a 10-day look-back period:

<Expandable title="Cloudability recommendations">
```json
{
"meta": {
"info": [],
"aggregates": [
{
"cost": 6.1,
"basis": "On-Demand",
"idleSavings": 0,
"optimizedSavings": 4.97,
"rightsizeSavings": 1.13
}
],
"totalCount": 1
},
"result": [
{
"os": "Linux",
"idle": 23,
"name": "LDN-APP03",
"cpuMax": 22,
"gpuMax": "N/A",
"region": "eu-west-2",
"service": "ec2-recs",
"snoozed": false,
"tenancy": "default",
"lastSeen": "2025-07-20T23:00:00Z",
"nodeType": "t2.small",
"provider": "NATIVE",
"memoryMax": "N/A",
"unitPrice": 0.03,
"totalSpend": 6.1,
"accountName": "Training Account - AL",
"cpuCapacity": 0.2,
"gpuCapacity": 0,
"localDrives": -1,
"tagMappings": [
{
"tag": "tag2",
"tagName": "Department",
"vendorTagValue": "shared services"
},
{
"tag": "tag3",
"tagName": "Business Unit",
"vendorTagValue": "shared services"
},
{
"tag": "tag5",
"tagName": "Resource Name",
"vendorTagValue": "ldn-app03"
},
{
"tag": "tag12",
"tagName": "Department Mispelling",
"vendorTagValue": "shared services"
},
{
"tag": "tag21",
"tagName": "Scaleup",
"vendorTagValue": "shared services"
}
],
"commentCount": 4,
"currencyCode": "USD",
"daysInactive": 0,
"gpuMemoryMax": "N/A",
"hoursRunning": 234.51,
"localCapacity": -1,
"instanceFamily": "t2",
"memoryCapacity": 2,
"networkCapacity": 100,
"recommendations": [
{
"risk": 0,
"action": "Rightsize",
"cpuRisk": 0,
"savings": 1.13,
"cpuRatio": 2,
"diskRisk": 0,
"gpuRatio": 0,
"nodeType": "t3a.small",
"memoryFit": true,
"unitPrice": 0.02,
"currentGen": true,
"inDefaults": true,
"memoryRisk": 0,
"sameFamily": false,
"sameMemory": true,
"savingsPct": 18,
"cpuCapacity": 0.4,
"gpuCapacity": 0,
"localDrives": -1,
"memoryRatio": 1,
"networkRisk": 0,
"maxInstances": 1,
"minInstances": 1,
"networkRatio": 50,
"defaultsOrder": 1,
"localCapacity": -1,
"gpuMemoryRatio": 0,
"instanceFamily": "t3a",
"memoryCapacity": 2,
"networkCapacity": 5000,
"preferenceOrder": 1,
"diskXPutCapacity": 160,
"gpuMemoryCapacity": 0,
"previousGenTarget": false,
"persistentStorageAdded": false
},
{
"risk": 0,
"action": "Rightsize",
"cpuRisk": 0,
"savings": 0.56,
"cpuRatio": 2,
"diskRisk": 0,
"gpuRatio": 0,
"nodeType": "t3.small",
"memoryFit": true,
"unitPrice": 0.02,
"currentGen": true,
"inDefaults": true,
"memoryRisk": 0,
"sameFamily": false,
"sameMemory": true,
"savingsPct": 9,
"cpuCapacity": 0.4,
"gpuCapacity": 0,
"localDrives": -1,
"memoryRatio": 1,
"networkRisk": 0,
"maxInstances": 1,
"minInstances": 1,
"networkRatio": 50,
"defaultsOrder": 2,
"localCapacity": -1,
"gpuMemoryRatio": 0,
"instanceFamily": "t3",
"memoryCapacity": 2,
"networkCapacity": 5000,
"preferenceOrder": 2,
"diskXPutCapacity": 160,
"gpuMemoryCapacity": 0,
"previousGenTarget": false,
"persistentStorageAdded": false
}
],
"snoozeExpiresOn": "",
"vendorAccountId": "366445176032",
"availabilityZone": "eu-west-2c",
"defaultMemoryFit": true,
"maxInstanceCount": 1,
"minInstanceCount": 1,
"defaultCurrentGen": true,
"defaultSameFamily": false,
"gpuMemoryCapacity": 0,
"resourceIdentifier": "i-0d380eee1c3bc4fed",
"defaultCrossArchitecture": false
}
]
}
```
</Expandable>

### Snooze Recommendations
Temporarily dismisses specific recommendations:
- **Vendor Type**: AWS, Azure, GCP, or Containers
- **Recommendation Type**: Dynamic dropdown based on vendor
- **Account ID**: The cloud account ID
- **Resource IDs**: Array of resource IDs to snooze
- **Snooze Until**: Date in yyyy-MM-dd format, or "never" for indefinite snoozing

### Unsnooze Recommendations
Reactivates previously snoozed recommendations:
- **Vendor Type**: AWS, Azure, GCP, or Containers
- **Recommendation Type**: Dynamic dropdown based on vendor
- **Account ID**: The cloud account ID
- **Resource IDs**: Array of resource IDs to unsnooze

### Custom API Call
Make direct calls to any [Cloudability API](https://www.ibm.com/docs/en/cloudability-commercial/cloudability-standard/saas?topic=api-getting-started-cloudability-v3) endpoint:
- **URL**: Dynamic endpoint selection
- **Method**: GET, POST, PATCH, PUT, DELETE, or HEAD
- **Headers**: Optional (authorization auto-injected)
- **Query Parameters**: Optional
- **Body**: Optional JSON payload
- **Timeout**: Configurable timeout in seconds
- **No Error on Failure**: Optional failsafe flag

## Designing a workflow

A typical Cloudability workflow starts with collecting active recommendations using the *Get Recommendations* action, then iterating through them, determining the owner of the affected resource, and deciding whether to request an action on the resource from the owner. If the owner approves the action, the workflow can perform a step to remediate the resource using the actions available for the [cloud platforms OpenOps supports](/cloud-access/supported-cloud-providers).

Below is a description of typical patterns that can be implemented in your Cloudability workflow.

### Owner mapping

Cloudability recommendations often need to be routed to the appropriate resource owners for review and action. OpenOps workflows can help you map cloud resources to their owners using tag values in the `tagMappings` array that the *Get Recommendations* action returns. Subsequent steps of your workflow may add owners or departments in the preconfigured [*Tag-owner mapping* table](/reporting-analytics/tables#tag-owner-mapping).

If your Cloudability instance returns specific owners, your workflow can add their contacts to the Tag-owner mapping table automatically. If it doesn't, you can fill the table manually once for each business unit to mamke sure that subsequent workflow runs know which team member should receive notifications or approval requests. This ensures that rightsizing, idle resource cleanup, or commitment purchase recommendations reach the people who can actually act on them.

For an example of implementing owner mapping as a separate workflow, see the [Creating a workflow to fill the project-owner mapping table](/integrations/cloudhealth#creating-a-workflow-to-fill-the-project-owner-mapping-table) in the CloudHealth integration guide. While the guide covers a different FinOps product, the principles of owner mapping apply to your Cloudability workflows as well.

### Recommendation tracking using OpenOps tables and states

Rather than acting on every recommendation once and then forgetting about its status, your OpenOps workflow can log Cloudability recommendations to the preconfigured [Opportunities table](/reporting-analytics/tables#opportunities) for centralized tracking and status management.

Workflows using the *Get Recommendations* action can create or update table records with details like estimated savings, resource IDs, recommendation types, and current status (*Created*, *Under Review*, *Dismissed*, *Snoozed*). This approach prevents duplicate notifications, provides audit trails, and enables reporting on realized vs. unrealized savings across your organization.

Learn how to implement opportunity tracking by following the [CloudHealth recommendation logging workflow](/integrations/cloudhealth#look-up-the-opportunity-in-the-openops-table).

### Handling recommendations via Slack

For recommendations requiring human judgment, OpenOps can send interactive Slack messages that allow resource owners to approve, dismiss, or snooze optimization opportunities directly from Slack.

After retrieving recommendations with *Get Recommendations*, workflows can use owner mapping to identify the appropriate Slack user, then send a Slack message using the *Request Action* with buttons for different responses. Based on the user's selection, the workflow can call *Snooze Recommendations* to temporarily dismiss false positives, update the Opportunities table to track decisions, or proceed with automated remediation actions.

See [Send a Slack notification with action buttons](/integrations/cloudhealth#send-a-slack-notification-with-action-buttons) in the CloudHealth guide for implementation details.