mirror of
https://github.com/OneUptime/oneuptime.git
synced 2026-04-06 00:32:12 +02:00
Merge pull request #2234 from OneUptime/terraform-tests
Terraform tests
This commit is contained in:
71
.github/workflows/terraform-provider-e2e.yml
vendored
Normal file
71
.github/workflows/terraform-provider-e2e.yml
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
name: Terraform Provider E2E Tests
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- master
|
||||
- develop
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
terraform-e2e-tests:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
CI_PIPELINE_ID: ${{ github.run_number }}
|
||||
APP_TAG: latest
|
||||
|
||||
steps:
|
||||
- name: Free Disk Space (Ubuntu)
|
||||
uses: jlumbroso/free-disk-space@main
|
||||
with:
|
||||
tool-cache: true
|
||||
android: true
|
||||
dotnet: true
|
||||
haskell: true
|
||||
large-packages: true
|
||||
docker-images: true
|
||||
swap-storage: true
|
||||
|
||||
- name: Additional Disk Cleanup
|
||||
run: |
|
||||
sudo rm -rf /usr/local/lib/android || true
|
||||
sudo rm -rf /opt/ghc || true
|
||||
sudo rm -rf /usr/share/dotnet || true
|
||||
sudo rm -rf /opt/hostedtoolcache/CodeQL || true
|
||||
sudo rm -rf /usr/local/share/boost || true
|
||||
sudo rm -rf /usr/share/swift || true
|
||||
sudo apt-get clean || true
|
||||
sudo rm -rf /var/lib/apt/lists/* || true
|
||||
df -h
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: latest
|
||||
cache: 'npm'
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.21'
|
||||
cache: true
|
||||
|
||||
- name: Setup Terraform
|
||||
uses: hashicorp/setup-terraform@v3
|
||||
with:
|
||||
terraform_version: "1.6.0"
|
||||
terraform_wrapper: false
|
||||
|
||||
- name: Run E2E Tests
|
||||
run: |
|
||||
chmod +x ./E2E/Terraform/e2e-tests/scripts/*.sh
|
||||
./E2E/Terraform/e2e-tests/scripts/index.sh
|
||||
13
.gitignore
vendored
13
.gitignore
vendored
@@ -116,8 +116,8 @@ InfrastructureAgent/oneuptime-infrastructure-agent
|
||||
# Terraform generated files
|
||||
openapi.json
|
||||
|
||||
Terraform/**
|
||||
|
||||
Terraform/terraform-provider-oneuptime/**
|
||||
Terraform/openapi.json
|
||||
TerraformTest/**
|
||||
|
||||
terraform-provider-example/**
|
||||
@@ -129,3 +129,12 @@ MCP/node_modules
|
||||
Dashboard/public/sw.js
|
||||
.claude/settings.local.json
|
||||
Common/.claude/settings.local.json
|
||||
E2E/Terraform/e2e-tests/test-env.sh
|
||||
|
||||
# Terraform state and plan files
|
||||
*.tfplan
|
||||
tfplan
|
||||
terraform.tfstate
|
||||
terraform.tfstate.backup
|
||||
.terraform/
|
||||
.terraform.lock.hcl
|
||||
|
||||
@@ -318,6 +318,7 @@ export default class StatusPageDomain extends BaseModel {
|
||||
})
|
||||
@TableColumn({
|
||||
required: true,
|
||||
computed: true,
|
||||
type: TableColumnType.ShortText,
|
||||
title: "Full Domain",
|
||||
description:
|
||||
@@ -448,6 +449,7 @@ export default class StatusPageDomain extends BaseModel {
|
||||
})
|
||||
@TableColumn({
|
||||
required: true,
|
||||
computed: true,
|
||||
type: TableColumnType.ShortText,
|
||||
title: "CNAME Verification Token",
|
||||
description: "CNAME Verification Token",
|
||||
|
||||
@@ -59,7 +59,12 @@ import Text from "../../Types/Text";
|
||||
import Typeof from "../../Types/Typeof";
|
||||
import API from "../../Utils/API";
|
||||
import Slug from "../../Utils/Slug";
|
||||
import { DataSource, Repository, SelectQueryBuilder } from "typeorm";
|
||||
import {
|
||||
DataSource,
|
||||
EntityManager,
|
||||
Repository,
|
||||
SelectQueryBuilder,
|
||||
} from "typeorm";
|
||||
import { FindWhere } from "../../Types/BaseDatabase/Query";
|
||||
import Realtime from "../Utils/Realtime";
|
||||
import ModelEventType from "../../Types/Realtime/ModelEventType";
|
||||
@@ -129,6 +134,22 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
|
||||
throw new DatabaseNotConnectedException();
|
||||
}
|
||||
|
||||
public async executeTransaction<TResult>(
|
||||
runInTransaction: (entityManager: EntityManager) => Promise<TResult>,
|
||||
): Promise<TResult> {
|
||||
if (!PostgresAppInstance.isConnected()) {
|
||||
throw new DatabaseNotConnectedException();
|
||||
}
|
||||
|
||||
const dataSource: DataSource | null = PostgresAppInstance.getDataSource();
|
||||
|
||||
if (!dataSource) {
|
||||
throw new DatabaseNotConnectedException();
|
||||
}
|
||||
|
||||
return await dataSource.transaction(runInTransaction);
|
||||
}
|
||||
|
||||
protected isValid(data: TBaseModel): boolean {
|
||||
if (!data) {
|
||||
throw new BadDataException("Data cannot be null");
|
||||
@@ -1691,3 +1712,4 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
|
||||
}
|
||||
|
||||
export default DatabaseService;
|
||||
export { EntityManager };
|
||||
|
||||
@@ -35,10 +35,18 @@ export class Service extends DatabaseService<Model> {
|
||||
createBy.data.domain = new Domain(domain.trim().toLowerCase());
|
||||
}
|
||||
|
||||
/*
|
||||
* Prevent setting isVerified during creation, EXCEPT for test domains
|
||||
* Test domains can be auto-verified since they are reserved TLDs that can't have real DNS records
|
||||
*/
|
||||
if (!createBy.props.isRoot && createBy.data.isVerified) {
|
||||
throw new BadDataException(
|
||||
"Domain cannot be verified during creation. Please verify the domain after creation. Please set isVerified to false.",
|
||||
);
|
||||
const domainStr: string = createBy.data.domain?.toString() || "";
|
||||
|
||||
if (!Domain.isTestDomain(domainStr)) {
|
||||
throw new BadDataException(
|
||||
"Domain cannot be verified during creation. Please verify the domain after creation. Please set isVerified to false.",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
createBy.data.domainVerificationText =
|
||||
@@ -96,19 +104,22 @@ export class Service extends DatabaseService<Model> {
|
||||
);
|
||||
}
|
||||
|
||||
const isVerified: boolean = await Domain.verifyTxtRecord(
|
||||
domain,
|
||||
verificationText,
|
||||
);
|
||||
|
||||
if (!isVerified) {
|
||||
throw new BadDataException(
|
||||
"Verification TXT record " +
|
||||
verificationText +
|
||||
" not found in domain " +
|
||||
domain +
|
||||
". Please add a TXT record to verify the domain. If you have already added the TXT record, please wait for few hours to let DNS to propagate.",
|
||||
// Skip DNS verification for test domains (reserved TLDs for testing)
|
||||
if (!Domain.isTestDomain(domain)) {
|
||||
const isVerified: boolean = await Domain.verifyTxtRecord(
|
||||
domain,
|
||||
verificationText,
|
||||
);
|
||||
|
||||
if (!isVerified) {
|
||||
throw new BadDataException(
|
||||
"Verification TXT record " +
|
||||
verificationText +
|
||||
" not found in domain " +
|
||||
domain +
|
||||
". Please add a TXT record to verify the domain. If you have already added the TXT record, please wait for few hours to let DNS to propagate.",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import ObjectID from "../../Types/ObjectID";
|
||||
import CreateBy from "../Types/Database/CreateBy";
|
||||
import { OnCreate, OnUpdate } from "../Types/Database/Hooks";
|
||||
import DatabaseService from "./DatabaseService";
|
||||
import DatabaseService, { EntityManager } from "./DatabaseService";
|
||||
import OneUptimeDate from "../../Types/Date";
|
||||
import BadDataException from "../../Types/Exception/BadDataException";
|
||||
import MonitorProbe from "../../Models/DatabaseModels/MonitorProbe";
|
||||
@@ -69,6 +69,101 @@ export class Service extends DatabaseService<MonitorProbe> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically claims monitor probes for a specific probe instance.
|
||||
* Uses PostgreSQL's FOR UPDATE SKIP LOCKED to prevent multiple probe instances
|
||||
* from picking up the same monitors simultaneously.
|
||||
*
|
||||
* @param data - Object containing probeId, limit, and nextPingAt
|
||||
* @returns Array of claimed MonitorProbe IDs
|
||||
*/
|
||||
public async claimMonitorProbesForProbing(data: {
|
||||
probeId: ObjectID;
|
||||
limit: number;
|
||||
}): Promise<Array<ObjectID>> {
|
||||
const currentDate: Date = OneUptimeDate.getCurrentDate();
|
||||
|
||||
/*
|
||||
* Use a transaction with FOR UPDATE SKIP LOCKED to atomically claim monitors
|
||||
* This prevents multiple probe instances from picking up the same monitors
|
||||
*/
|
||||
const claimedIds: Array<ObjectID> = await this.executeTransaction(
|
||||
async (transactionalEntityManager: EntityManager) => {
|
||||
/*
|
||||
* First, select and lock the monitor probes that need to be processed
|
||||
* FOR UPDATE SKIP LOCKED ensures that:
|
||||
* 1. Rows are locked for this transaction
|
||||
* 2. Rows already locked by other transactions are skipped
|
||||
*/
|
||||
const selectQuery: string = `
|
||||
SELECT mp."_id"
|
||||
FROM "MonitorProbe" mp
|
||||
INNER JOIN "Monitor" m ON mp."monitorId" = m."_id"
|
||||
INNER JOIN "Project" p ON mp."projectId" = p."_id"
|
||||
WHERE mp."probeId" = $1
|
||||
AND mp."isEnabled" = true
|
||||
AND mp."deletedAt" IS NULL
|
||||
AND (mp."nextPingAt" IS NULL OR mp."nextPingAt" <= $2)
|
||||
AND m."disableActiveMonitoring" = false
|
||||
AND m."disableActiveMonitoringBecauseOfManualIncident" = false
|
||||
AND m."disableActiveMonitoringBecauseOfScheduledMaintenanceEvent" = false
|
||||
AND m."deletedAt" IS NULL
|
||||
AND p."deletedAt" IS NULL
|
||||
AND (p."paymentProviderSubscriptionStatus" IS NULL
|
||||
OR p."paymentProviderSubscriptionStatus" IN ('active', 'trialing'))
|
||||
AND (p."paymentProviderMeteredSubscriptionStatus" IS NULL
|
||||
OR p."paymentProviderMeteredSubscriptionStatus" IN ('active', 'trialing'))
|
||||
ORDER BY mp."nextPingAt" ASC NULLS FIRST
|
||||
LIMIT $3
|
||||
FOR UPDATE OF mp SKIP LOCKED
|
||||
`;
|
||||
|
||||
const selectedRows: Array<{ _id: string }> =
|
||||
await transactionalEntityManager.query(selectQuery, [
|
||||
data.probeId.toString(),
|
||||
currentDate,
|
||||
data.limit,
|
||||
]);
|
||||
|
||||
if (selectedRows.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const ids: Array<string> = selectedRows.map((row: { _id: string }) => {
|
||||
return row._id;
|
||||
});
|
||||
|
||||
/*
|
||||
* Update the claimed monitors to set nextPingAt to 1 minute from now
|
||||
* This is a temporary value; the actual nextPingAt will be calculated
|
||||
* based on the monitor's interval after the probe fetches the full details
|
||||
*/
|
||||
const tempNextPingAt: Date = OneUptimeDate.addRemoveMinutes(
|
||||
currentDate,
|
||||
1,
|
||||
);
|
||||
|
||||
const updateQuery: string = `
|
||||
UPDATE "MonitorProbe"
|
||||
SET "lastPingAt" = $1, "nextPingAt" = $2
|
||||
WHERE "_id" = ANY($3::uuid[])
|
||||
`;
|
||||
|
||||
await transactionalEntityManager.query(updateQuery, [
|
||||
currentDate,
|
||||
tempNextPingAt,
|
||||
ids,
|
||||
]);
|
||||
|
||||
return ids.map((id: string) => {
|
||||
return new ObjectID(id);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
return claimedIds;
|
||||
}
|
||||
|
||||
protected override async onBeforeCreate(
|
||||
createBy: CreateBy<MonitorProbe>,
|
||||
): Promise<OnCreate<MonitorProbe>> {
|
||||
|
||||
@@ -5,6 +5,29 @@ import { FindOperator } from "typeorm/find-options/FindOperator";
|
||||
import Zod, { ZodSchema } from "../Utils/Schema/Zod";
|
||||
|
||||
export default class Domain extends DatabaseProperty {
|
||||
/*
|
||||
* Reserved TLDs for testing and documentation (per IANA)
|
||||
* These domains can never have real DNS records, so they're safe for testing
|
||||
*/
|
||||
public static readonly TEST_DOMAIN_SUFFIXES: string[] = [
|
||||
".example.com",
|
||||
".example.org",
|
||||
".example.net",
|
||||
".test",
|
||||
];
|
||||
|
||||
/**
|
||||
* Checks if a domain is a test/reserved domain that can skip DNS verification.
|
||||
* Test domains include .example.com, .example.org, .example.net, and .test TLDs.
|
||||
* These are reserved by IANA for documentation and testing purposes.
|
||||
*/
|
||||
public static isTestDomain(domain: string): boolean {
|
||||
const domainLower: string = domain.toLowerCase().trim();
|
||||
return Domain.TEST_DOMAIN_SUFFIXES.some((suffix: string) => {
|
||||
return domainLower.endsWith(suffix);
|
||||
});
|
||||
}
|
||||
|
||||
private _domain: string = "";
|
||||
public get domain(): string {
|
||||
return this._domain;
|
||||
|
||||
22
Common/package-lock.json
generated
22
Common/package-lock.json
generated
@@ -408,6 +408,7 @@
|
||||
"integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@ampproject/remapping": "^2.2.0",
|
||||
"@babel/code-frame": "^7.26.0",
|
||||
@@ -904,6 +905,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@bull-board/ui/-/ui-5.23.0.tgz",
|
||||
"integrity": "sha512-iI/Ssl8T5ZEn9s899Qz67m92M6RU8thf/aqD7cUHB2yHmkCjqbw7s7NaODTsyArAsnyu7DGJMWm7EhbfFXDNgQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@bull-board/api": "5.23.0"
|
||||
}
|
||||
@@ -2266,6 +2268,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz",
|
||||
"integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
}
|
||||
@@ -5400,6 +5403,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz",
|
||||
"integrity": "sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/prop-types": "*",
|
||||
"csstype": "^3.0.2"
|
||||
@@ -5575,8 +5579,7 @@
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-1.0.6.tgz",
|
||||
"integrity": "sha512-230RC8sFeHoT6sSUlRO6a8cAnclO06eeiq1QDfiv2FGCLWFvvERWgwIQD4FWqD9A69BN7Lzee4OXwoMVnnsWDw==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/unist": {
|
||||
"version": "2.0.11",
|
||||
@@ -5740,6 +5743,7 @@
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
|
||||
"integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
@@ -6632,6 +6636,7 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"caniuse-lite": "^1.0.30001669",
|
||||
"electron-to-chromium": "^1.5.41",
|
||||
@@ -7510,6 +7515,7 @@
|
||||
"resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz",
|
||||
"integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==",
|
||||
"license": "ISC",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
@@ -10199,6 +10205,7 @@
|
||||
"integrity": "sha512-N4GT5on8UkZgH0O5LUavMRV1EDEhNTL0KEfRmDIeZHSV7p2XgLoY9t9VDUgL6o+yfdgYHVxuz81G8oB9VG5uyA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@jest/core": "^28.1.3",
|
||||
"@jest/types": "^28.1.3",
|
||||
@@ -13495,6 +13502,7 @@
|
||||
"resolved": "https://registry.npmjs.org/pg/-/pg-8.16.3.tgz",
|
||||
"integrity": "sha512-enxc1h0jA/aq5oSDMvqyW3q89ra6XIIDZgCX9vkMrnz5DFTw/Ny3Li2lFQ+pt3L6MCgm/5o2o8HW9hiJji+xvw==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"pg-connection-string": "^2.9.1",
|
||||
"pg-pool": "^3.10.1",
|
||||
@@ -13822,6 +13830,7 @@
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.4.0",
|
||||
"object-assign": "^4.1.1",
|
||||
@@ -14125,6 +14134,7 @@
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
|
||||
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0"
|
||||
},
|
||||
@@ -14209,6 +14219,7 @@
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
|
||||
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"scheduler": "^0.23.2"
|
||||
@@ -14739,7 +14750,8 @@
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz",
|
||||
"integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==",
|
||||
"license": "Apache-2.0"
|
||||
"license": "Apache-2.0",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/refractor": {
|
||||
"version": "5.0.0",
|
||||
@@ -17872,6 +17884,7 @@
|
||||
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
|
||||
"integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/colinhacks"
|
||||
}
|
||||
@@ -17880,7 +17893,8 @@
|
||||
"version": "0.14.10",
|
||||
"resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.14.10.tgz",
|
||||
"integrity": "sha512-YGAhaO7J5ywOXW6InXNlLmfU194F8lVgu7bRntUF3TiG8Y3nBK0x1UJJuHUP/e8IyihkjCYqhCScpSwnlaSRkQ==",
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/zustand": {
|
||||
"version": "4.5.5",
|
||||
|
||||
877
Docs/Plans/TerraformTest.md
Normal file
877
Docs/Plans/TerraformTest.md
Normal file
@@ -0,0 +1,877 @@
|
||||
# Terraform Provider E2E Tests - Implementation Plan
|
||||
|
||||
## Executive Summary
|
||||
|
||||
This document outlines the implementation plan for comprehensive end-to-end tests for the OneUptime Terraform provider. The tests will validate that Terraform can successfully create, read, update, and delete resources through the OneUptime API.
|
||||
|
||||
---
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Overview](#overview)
|
||||
2. [Architecture](#architecture)
|
||||
3. [Files to Create](#files-to-create)
|
||||
4. [GitHub Actions Workflow](#github-actions-workflow)
|
||||
5. [Test Setup Scripts](#test-setup-scripts)
|
||||
6. [Terraform Test Configurations](#terraform-test-configurations)
|
||||
7. [Resource Test Order](#resource-test-order)
|
||||
8. [Potential Generator Fixes](#potential-generator-fixes)
|
||||
9. [Verification Steps](#verification-steps)
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
### Goals
|
||||
1. Start OneUptime services in CI/CD environment
|
||||
2. Register a test account programmatically
|
||||
3. Create a project and API key with ProjectOwner permissions
|
||||
4. Generate the Terraform provider from source
|
||||
5. Run Terraform tests for: Labels, Monitors, Status Pages, Incidents, Alerts, and related resources
|
||||
|
||||
### Test Flow
|
||||
```
|
||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│ Start Services │────▶│ Setup Account │────▶│ Generate Provider│
|
||||
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
||||
│
|
||||
┌─────────────────┐ ┌─────────────────┐ ▼
|
||||
│ Run Cleanup │◀────│ Run TF Tests │◀────┌─────────────────┐
|
||||
└─────────────────┘ └─────────────────┘ │ Install Provider │
|
||||
└─────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Architecture
|
||||
|
||||
### Services Required
|
||||
The following Docker services must be running:
|
||||
- `postgres` - Database
|
||||
- `redis` - Cache/Queue
|
||||
- `clickhouse` - Analytics database
|
||||
- `app` - Main API server
|
||||
- `accounts` - Authentication service
|
||||
- `ingress` - NGINX reverse proxy
|
||||
- `worker` - Background jobs
|
||||
|
||||
### API Endpoints Used
|
||||
| Endpoint | Method | Purpose |
|
||||
|----------|--------|---------|
|
||||
| `/api/status` | GET | Health check |
|
||||
| `/api/identity/signup` | POST | Register user |
|
||||
| `/api/identity/login` | POST | Login user |
|
||||
| `/api/project` | POST | Create/List projects |
|
||||
| `/api/api-key` | POST | Create API key |
|
||||
| `/api/api-key-permission` | POST | Add permissions |
|
||||
|
||||
### Provider Authentication
|
||||
The generated provider uses the `APIKey` header:
|
||||
```go
|
||||
// From Scripts/TerraformProvider/Core/ProviderGenerator.ts:248
|
||||
req.Header.Set("APIKey", c.ApiKey)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Files to Create
|
||||
|
||||
### Directory Structure
|
||||
```
|
||||
E2E/Terraform/
|
||||
├── e2e-tests/
|
||||
│ ├── scripts/
|
||||
│ │ ├── wait-for-services.sh # Wait for OneUptime to be ready
|
||||
│ │ ├── setup-test-account.sh # Register user, create project, API key
|
||||
│ │ ├── run-tests.sh # Execute all Terraform tests
|
||||
│ │ └── cleanup.sh # Clean up test resources
|
||||
│ ├── tests/
|
||||
│ │ ├── 01-label/
|
||||
│ │ │ ├── main.tf
|
||||
│ │ │ ├── variables.tf
|
||||
│ │ │ └── outputs.tf
|
||||
│ │ ├── 02-monitor-status/
|
||||
│ │ │ ├── main.tf
|
||||
│ │ │ ├── variables.tf
|
||||
│ │ │ └── outputs.tf
|
||||
│ │ ├── 03-incident-severity/
|
||||
│ │ │ ├── main.tf
|
||||
│ │ │ ├── variables.tf
|
||||
│ │ │ └── outputs.tf
|
||||
│ │ ├── 04-incident-state/
|
||||
│ │ │ ├── main.tf
|
||||
│ │ │ ├── variables.tf
|
||||
│ │ │ └── outputs.tf
|
||||
│ │ ├── 05-status-page/
|
||||
│ │ │ ├── main.tf
|
||||
│ │ │ ├── variables.tf
|
||||
│ │ │ └── outputs.tf
|
||||
│ │ ├── 06-alert-severity/
|
||||
│ │ │ ├── main.tf
|
||||
│ │ │ ├── variables.tf
|
||||
│ │ │ └── outputs.tf
|
||||
│ │ └── 07-alert-state/
|
||||
│ │ ├── main.tf
|
||||
│ │ ├── variables.tf
|
||||
│ │ └── outputs.tf
|
||||
│ └── provider.tf # Common provider configuration
|
||||
└── terraform-provider-oneuptime/ # Generated provider (existing)
|
||||
|
||||
.github/workflows/
|
||||
└── terraform-provider-e2e.yml # New E2E test workflow
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## GitHub Actions Workflow
|
||||
|
||||
### File: `.github/workflows/terraform-provider-e2e.yml`
|
||||
|
||||
```yaml
|
||||
name: Terraform Provider E2E Tests
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- master
|
||||
- develop
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
terraform-e2e-tests:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
CI_PIPELINE_ID: ${{ github.run_number }}
|
||||
APP_TAG: latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: latest
|
||||
cache: 'npm'
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.21'
|
||||
cache: true
|
||||
|
||||
- name: Setup Terraform
|
||||
uses: hashicorp/setup-terraform@v3
|
||||
with:
|
||||
terraform_version: "1.6.0"
|
||||
terraform_wrapper: false
|
||||
|
||||
- name: Copy config.env
|
||||
run: cp config.example.env config.env
|
||||
|
||||
- name: Start OneUptime Services
|
||||
run: |
|
||||
docker compose -f docker-compose.yml up -d postgres redis clickhouse app accounts ingress worker
|
||||
chmod +x ./E2E/Terraform/e2e-tests/scripts/*.sh
|
||||
./E2E/Terraform/e2e-tests/scripts/wait-for-services.sh
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
npm install
|
||||
cd Common && npm install && cd ..
|
||||
cd Scripts && npm install && cd ..
|
||||
|
||||
- name: Generate Terraform Provider
|
||||
run: npm run generate-terraform-provider
|
||||
|
||||
- name: Setup Test Environment
|
||||
run: |
|
||||
cd E2E/Terraform/e2e-tests
|
||||
./scripts/setup-test-account.sh
|
||||
|
||||
- name: Run Terraform E2E Tests
|
||||
run: |
|
||||
cd E2E/Terraform/e2e-tests
|
||||
./scripts/run-tests.sh
|
||||
|
||||
- name: Cleanup
|
||||
if: always()
|
||||
run: |
|
||||
cd E2E/Terraform/e2e-tests
|
||||
./scripts/cleanup.sh || true
|
||||
docker compose down -v || true
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Test Setup Scripts
|
||||
|
||||
### 1. Wait for Services Script
|
||||
**File: `E2E/Terraform/e2e-tests/scripts/wait-for-services.sh`**
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
ONEUPTIME_URL="${ONEUPTIME_URL:-http://localhost}"
|
||||
MAX_RETRIES=60
|
||||
RETRY_INTERVAL=5
|
||||
|
||||
echo "Waiting for OneUptime services to be ready..."
|
||||
|
||||
for i in $(seq 1 $MAX_RETRIES); do
|
||||
if curl -sf "${ONEUPTIME_URL}/api/status" > /dev/null 2>&1; then
|
||||
echo "OneUptime API is ready!"
|
||||
exit 0
|
||||
fi
|
||||
echo "Attempt $i/$MAX_RETRIES - Services not ready yet, waiting ${RETRY_INTERVAL}s..."
|
||||
sleep $RETRY_INTERVAL
|
||||
done
|
||||
|
||||
echo "ERROR: OneUptime services failed to start within timeout"
|
||||
exit 1
|
||||
```
|
||||
|
||||
### 2. Setup Test Account Script
|
||||
**File: `E2E/Terraform/e2e-tests/scripts/setup-test-account.sh`**
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
TEST_DIR="$(dirname "$SCRIPT_DIR")"
|
||||
ONEUPTIME_URL="${ONEUPTIME_URL:-http://localhost}"
|
||||
|
||||
# Generate unique test values
|
||||
TIMESTAMP=$(date +%s)
|
||||
TEST_EMAIL="terraform-test-${TIMESTAMP}@test.oneuptime.com"
|
||||
TEST_PASSWORD="TestPassword123!"
|
||||
TEST_NAME="Terraform E2E Test User"
|
||||
|
||||
echo "=== Setting up test account ==="
|
||||
echo "Email: $TEST_EMAIL"
|
||||
|
||||
# Step 1: Register a new user
|
||||
echo "Step 1: Registering new user..."
|
||||
SIGNUP_RESPONSE=$(curl -sf -X POST "${ONEUPTIME_URL}/api/identity/signup" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{
|
||||
\"data\": {
|
||||
\"email\": \"$TEST_EMAIL\",
|
||||
\"password\": \"$TEST_PASSWORD\",
|
||||
\"name\": \"$TEST_NAME\",
|
||||
\"companyName\": \"Terraform E2E Test Company\",
|
||||
\"companyPhoneNumber\": \"+15551234567\"
|
||||
}
|
||||
}")
|
||||
|
||||
echo "User registered successfully"
|
||||
|
||||
# Step 2: Login to get session
|
||||
echo "Step 2: Logging in..."
|
||||
LOGIN_RESPONSE=$(curl -sf -X POST "${ONEUPTIME_URL}/api/identity/login" \
|
||||
-H "Content-Type: application/json" \
|
||||
-c "$TEST_DIR/cookies.txt" \
|
||||
-d "{
|
||||
\"data\": {
|
||||
\"email\": \"$TEST_EMAIL\",
|
||||
\"password\": \"$TEST_PASSWORD\"
|
||||
}
|
||||
}")
|
||||
|
||||
COOKIES="-b $TEST_DIR/cookies.txt"
|
||||
echo "Login successful"
|
||||
|
||||
# Step 3: Get or create project
|
||||
echo "Step 3: Fetching project..."
|
||||
sleep 3 # Wait for automatic project creation
|
||||
|
||||
PROJECT_RESPONSE=$(curl -sf -X POST "${ONEUPTIME_URL}/api/project/get-list" \
|
||||
-H "Content-Type: application/json" \
|
||||
$COOKIES \
|
||||
-d "{
|
||||
\"query\": {},
|
||||
\"select\": {\"_id\": true, \"name\": true},
|
||||
\"limit\": 1
|
||||
}")
|
||||
|
||||
PROJECT_ID=$(echo "$PROJECT_RESPONSE" | jq -r '.data[0]._id // empty')
|
||||
|
||||
if [ -z "$PROJECT_ID" ]; then
|
||||
echo "Creating new project..."
|
||||
PROJECT_CREATE=$(curl -sf -X POST "${ONEUPTIME_URL}/api/project" \
|
||||
-H "Content-Type: application/json" \
|
||||
$COOKIES \
|
||||
-d "{
|
||||
\"data\": {
|
||||
\"name\": \"Terraform E2E Test Project\"
|
||||
}
|
||||
}")
|
||||
PROJECT_ID=$(echo "$PROJECT_CREATE" | jq -r '.data._id // ._id')
|
||||
fi
|
||||
|
||||
echo "Project ID: $PROJECT_ID"
|
||||
|
||||
# Step 4: Create API Key
|
||||
echo "Step 4: Creating API key..."
|
||||
EXPIRES_AT=$(date -d "+1 year" -u +"%Y-%m-%dT%H:%M:%S.000Z" 2>/dev/null || \
|
||||
date -v+1y -u +"%Y-%m-%dT%H:%M:%S.000Z")
|
||||
|
||||
API_KEY_RESPONSE=$(curl -sf -X POST "${ONEUPTIME_URL}/api/api-key" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "projectid: $PROJECT_ID" \
|
||||
$COOKIES \
|
||||
-d "{
|
||||
\"data\": {
|
||||
\"name\": \"Terraform E2E Test API Key\",
|
||||
\"description\": \"API Key for Terraform E2E Tests\",
|
||||
\"expiresAt\": \"$EXPIRES_AT\",
|
||||
\"projectId\": \"$PROJECT_ID\"
|
||||
}
|
||||
}")
|
||||
|
||||
API_KEY_ID=$(echo "$API_KEY_RESPONSE" | jq -r '.data._id // ._id')
|
||||
API_KEY=$(echo "$API_KEY_RESPONSE" | jq -r '.data.apiKey // .apiKey')
|
||||
|
||||
echo "API Key ID: $API_KEY_ID"
|
||||
echo "API Key: $API_KEY"
|
||||
|
||||
# Step 5: Add ProjectOwner permission
|
||||
echo "Step 5: Adding ProjectOwner permission..."
|
||||
PERMISSION_RESPONSE=$(curl -sf -X POST "${ONEUPTIME_URL}/api/api-key-permission" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "projectid: $PROJECT_ID" \
|
||||
$COOKIES \
|
||||
-d "{
|
||||
\"data\": {
|
||||
\"apiKeyId\": \"$API_KEY_ID\",
|
||||
\"projectId\": \"$PROJECT_ID\",
|
||||
\"permission\": \"ProjectOwner\",
|
||||
\"isBlockPermission\": false
|
||||
}
|
||||
}")
|
||||
|
||||
echo "Permission added"
|
||||
|
||||
# Step 6: Write environment file
|
||||
echo "Step 6: Writing test environment..."
|
||||
cat > "$TEST_DIR/test-env.sh" << EOF
|
||||
#!/bin/bash
|
||||
export ONEUPTIME_URL="$ONEUPTIME_URL"
|
||||
export ONEUPTIME_API_KEY="$API_KEY"
|
||||
export ONEUPTIME_PROJECT_ID="$PROJECT_ID"
|
||||
export TF_VAR_project_id="$PROJECT_ID"
|
||||
export TF_VAR_api_key="$API_KEY"
|
||||
export TF_VAR_oneuptime_url="$ONEUPTIME_URL"
|
||||
EOF
|
||||
|
||||
chmod +x "$TEST_DIR/test-env.sh"
|
||||
|
||||
# Cleanup cookies
|
||||
rm -f "$TEST_DIR/cookies.txt"
|
||||
|
||||
echo ""
|
||||
echo "=== Setup Complete ==="
|
||||
echo "ONEUPTIME_URL: $ONEUPTIME_URL"
|
||||
echo "PROJECT_ID: $PROJECT_ID"
|
||||
echo "API_KEY: $API_KEY"
|
||||
```
|
||||
|
||||
### 3. Run Tests Script
|
||||
**File: `E2E/Terraform/e2e-tests/scripts/run-tests.sh`**
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
TEST_DIR="$(dirname "$SCRIPT_DIR")"
|
||||
PROVIDER_DIR="$TEST_DIR/../terraform-provider-oneuptime"
|
||||
|
||||
# Load test environment
|
||||
source "$TEST_DIR/test-env.sh"
|
||||
|
||||
echo "=== Running Terraform E2E Tests ==="
|
||||
echo "OneUptime URL: $ONEUPTIME_URL"
|
||||
echo "Project ID: $ONEUPTIME_PROJECT_ID"
|
||||
|
||||
# Build and install provider locally
|
||||
echo ""
|
||||
echo "=== Building Terraform Provider ==="
|
||||
cd "$PROVIDER_DIR"
|
||||
go mod tidy
|
||||
go build -o terraform-provider-oneuptime
|
||||
|
||||
# Install provider
|
||||
OS=$(go env GOOS)
|
||||
ARCH=$(go env GOARCH)
|
||||
INSTALL_DIR="$HOME/.terraform.d/plugins/registry.terraform.io/oneuptime/oneuptime/1.0.0/${OS}_${ARCH}"
|
||||
mkdir -p "$INSTALL_DIR"
|
||||
cp terraform-provider-oneuptime "$INSTALL_DIR/"
|
||||
|
||||
# Create Terraform CLI override config
|
||||
cat > "$HOME/.terraformrc" << EOF
|
||||
provider_installation {
|
||||
dev_overrides {
|
||||
"oneuptime/oneuptime" = "$INSTALL_DIR"
|
||||
}
|
||||
direct {}
|
||||
}
|
||||
EOF
|
||||
|
||||
echo "Provider installed to: $INSTALL_DIR"
|
||||
|
||||
# Test directories in order
|
||||
TEST_DIRS=(
|
||||
"01-label"
|
||||
"02-monitor-status"
|
||||
"03-incident-severity"
|
||||
"04-incident-state"
|
||||
"05-status-page"
|
||||
"06-alert-severity"
|
||||
"07-alert-state"
|
||||
)
|
||||
|
||||
PASSED=()
|
||||
FAILED=()
|
||||
|
||||
for test_name in "${TEST_DIRS[@]}"; do
|
||||
test_path="$TEST_DIR/tests/$test_name"
|
||||
|
||||
if [ ! -d "$test_path" ]; then
|
||||
echo "SKIP: $test_name (not found)"
|
||||
continue
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo "Testing: $test_name"
|
||||
echo "=========================================="
|
||||
|
||||
cd "$test_path"
|
||||
|
||||
# Init
|
||||
echo " [1/4] Initializing..."
|
||||
if ! terraform init -upgrade 2>&1; then
|
||||
echo " FAILED: Init failed"
|
||||
FAILED+=("$test_name")
|
||||
continue
|
||||
fi
|
||||
|
||||
# Plan
|
||||
echo " [2/4] Planning..."
|
||||
if ! terraform plan -out=tfplan 2>&1; then
|
||||
echo " FAILED: Plan failed"
|
||||
FAILED+=("$test_name")
|
||||
continue
|
||||
fi
|
||||
|
||||
# Apply
|
||||
echo " [3/4] Applying..."
|
||||
if ! terraform apply -auto-approve tfplan 2>&1; then
|
||||
echo " FAILED: Apply failed"
|
||||
FAILED+=("$test_name")
|
||||
# Try to cleanup anyway
|
||||
terraform destroy -auto-approve 2>&1 || true
|
||||
continue
|
||||
fi
|
||||
|
||||
# Show outputs
|
||||
echo " Outputs:"
|
||||
terraform output 2>&1 || true
|
||||
|
||||
# Destroy
|
||||
echo " [4/4] Destroying..."
|
||||
if ! terraform destroy -auto-approve 2>&1; then
|
||||
echo " WARNING: Destroy failed"
|
||||
FAILED+=("$test_name (destroy)")
|
||||
fi
|
||||
|
||||
# Cleanup state files
|
||||
rm -f tfplan terraform.tfstate terraform.tfstate.backup
|
||||
|
||||
echo " PASSED: $test_name"
|
||||
PASSED+=("$test_name")
|
||||
done
|
||||
|
||||
# Summary
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo "Test Summary"
|
||||
echo "=========================================="
|
||||
echo "Passed: ${#PASSED[@]}"
|
||||
for t in "${PASSED[@]}"; do echo " - $t"; done
|
||||
|
||||
if [ ${#FAILED[@]} -gt 0 ]; then
|
||||
echo "Failed: ${#FAILED[@]}"
|
||||
for t in "${FAILED[@]}"; do echo " - $t"; done
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "All tests passed!"
|
||||
```
|
||||
|
||||
### 4. Cleanup Script
|
||||
**File: `E2E/Terraform/e2e-tests/scripts/cleanup.sh`**
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
TEST_DIR="$(dirname "$SCRIPT_DIR")"
|
||||
|
||||
echo "=== Cleaning up ==="
|
||||
|
||||
# Remove Terraform state files
|
||||
find "$TEST_DIR/tests" -name "*.tfstate*" -delete 2>/dev/null || true
|
||||
find "$TEST_DIR/tests" -name ".terraform" -type d -exec rm -rf {} + 2>/dev/null || true
|
||||
find "$TEST_DIR/tests" -name ".terraform.lock.hcl" -delete 2>/dev/null || true
|
||||
find "$TEST_DIR/tests" -name "tfplan" -delete 2>/dev/null || true
|
||||
|
||||
# Remove test env file
|
||||
rm -f "$TEST_DIR/test-env.sh"
|
||||
rm -f "$TEST_DIR/cookies.txt"
|
||||
|
||||
# Remove Terraform CLI override
|
||||
rm -f "$HOME/.terraformrc"
|
||||
|
||||
# Remove local provider installation
|
||||
rm -rf "$HOME/.terraform.d/plugins/registry.terraform.io/oneuptime" 2>/dev/null || true
|
||||
|
||||
echo "Cleanup complete"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Terraform Test Configurations
|
||||
|
||||
### Common Variables File
|
||||
**File: `E2E/Terraform/e2e-tests/tests/*/variables.tf`** (same for all tests)
|
||||
|
||||
```hcl
|
||||
variable "oneuptime_url" {
|
||||
type = string
|
||||
description = "OneUptime API URL"
|
||||
}
|
||||
|
||||
variable "api_key" {
|
||||
type = string
|
||||
description = "OneUptime API Key"
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "project_id" {
|
||||
type = string
|
||||
description = "OneUptime Project ID"
|
||||
}
|
||||
```
|
||||
|
||||
### Test 1: Label
|
||||
**File: `E2E/Terraform/e2e-tests/tests/01-label/main.tf`**
|
||||
|
||||
```hcl
|
||||
terraform {
|
||||
required_providers {
|
||||
oneuptime = {
|
||||
source = "oneuptime/oneuptime"
|
||||
version = "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "oneuptime" {
|
||||
oneuptime_url = var.oneuptime_url
|
||||
api_key = var.api_key
|
||||
}
|
||||
|
||||
resource "oneuptime_label" "test" {
|
||||
project_id = var.project_id
|
||||
name = "terraform-e2e-label-${formatdate("YYYYMMDDhhmmss", timestamp())}"
|
||||
description = "Label created by Terraform E2E tests"
|
||||
color = "#FF5733"
|
||||
}
|
||||
|
||||
output "label_id" {
|
||||
value = oneuptime_label.test.id
|
||||
}
|
||||
|
||||
output "label_name" {
|
||||
value = oneuptime_label.test.name
|
||||
}
|
||||
```
|
||||
|
||||
### Test 2: Monitor Status
|
||||
**File: `E2E/Terraform/e2e-tests/tests/02-monitor-status/main.tf`**
|
||||
|
||||
```hcl
|
||||
terraform {
|
||||
required_providers {
|
||||
oneuptime = {
|
||||
source = "oneuptime/oneuptime"
|
||||
version = "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "oneuptime" {
|
||||
oneuptime_url = var.oneuptime_url
|
||||
api_key = var.api_key
|
||||
}
|
||||
|
||||
resource "oneuptime_monitor_status" "test" {
|
||||
project_id = var.project_id
|
||||
name = "terraform-e2e-status-${formatdate("YYYYMMDDhhmmss", timestamp())}"
|
||||
description = "Monitor status created by Terraform E2E tests"
|
||||
color = "#00FF00"
|
||||
priority = 99
|
||||
is_operational_state = true
|
||||
}
|
||||
|
||||
output "monitor_status_id" {
|
||||
value = oneuptime_monitor_status.test.id
|
||||
}
|
||||
```
|
||||
|
||||
### Test 3: Incident Severity
|
||||
**File: `E2E/Terraform/e2e-tests/tests/03-incident-severity/main.tf`**
|
||||
|
||||
```hcl
|
||||
terraform {
|
||||
required_providers {
|
||||
oneuptime = {
|
||||
source = "oneuptime/oneuptime"
|
||||
version = "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "oneuptime" {
|
||||
oneuptime_url = var.oneuptime_url
|
||||
api_key = var.api_key
|
||||
}
|
||||
|
||||
resource "oneuptime_incident_severity" "test" {
|
||||
project_id = var.project_id
|
||||
name = "terraform-e2e-severity-${formatdate("YYYYMMDDhhmmss", timestamp())}"
|
||||
description = "Incident severity created by Terraform E2E tests"
|
||||
color = "#FFA500"
|
||||
order = 99
|
||||
}
|
||||
|
||||
output "incident_severity_id" {
|
||||
value = oneuptime_incident_severity.test.id
|
||||
}
|
||||
```
|
||||
|
||||
### Test 4: Incident State
|
||||
**File: `E2E/Terraform/e2e-tests/tests/04-incident-state/main.tf`**
|
||||
|
||||
```hcl
|
||||
terraform {
|
||||
required_providers {
|
||||
oneuptime = {
|
||||
source = "oneuptime/oneuptime"
|
||||
version = "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "oneuptime" {
|
||||
oneuptime_url = var.oneuptime_url
|
||||
api_key = var.api_key
|
||||
}
|
||||
|
||||
resource "oneuptime_incident_state" "test" {
|
||||
project_id = var.project_id
|
||||
name = "terraform-e2e-state-${formatdate("YYYYMMDDhhmmss", timestamp())}"
|
||||
description = "Incident state created by Terraform E2E tests"
|
||||
color = "#0000FF"
|
||||
order = 99
|
||||
}
|
||||
|
||||
output "incident_state_id" {
|
||||
value = oneuptime_incident_state.test.id
|
||||
}
|
||||
```
|
||||
|
||||
### Test 5: Status Page
|
||||
**File: `E2E/Terraform/e2e-tests/tests/05-status-page/main.tf`**
|
||||
|
||||
```hcl
|
||||
terraform {
|
||||
required_providers {
|
||||
oneuptime = {
|
||||
source = "oneuptime/oneuptime"
|
||||
version = "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "oneuptime" {
|
||||
oneuptime_url = var.oneuptime_url
|
||||
api_key = var.api_key
|
||||
}
|
||||
|
||||
resource "oneuptime_status_page" "test" {
|
||||
project_id = var.project_id
|
||||
name = "terraform-e2e-statuspage-${formatdate("YYYYMMDDhhmmss", timestamp())}"
|
||||
description = "Status page created by Terraform E2E tests"
|
||||
page_title = "Terraform Test Status"
|
||||
page_description = "This is a test status page"
|
||||
is_public_status_page = false
|
||||
enable_email_subscribers = false
|
||||
enable_sms_subscribers = false
|
||||
}
|
||||
|
||||
output "status_page_id" {
|
||||
value = oneuptime_status_page.test.id
|
||||
}
|
||||
```
|
||||
|
||||
### Test 6: Alert Severity
|
||||
**File: `E2E/Terraform/e2e-tests/tests/06-alert-severity/main.tf`**
|
||||
|
||||
```hcl
|
||||
terraform {
|
||||
required_providers {
|
||||
oneuptime = {
|
||||
source = "oneuptime/oneuptime"
|
||||
version = "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "oneuptime" {
|
||||
oneuptime_url = var.oneuptime_url
|
||||
api_key = var.api_key
|
||||
}
|
||||
|
||||
resource "oneuptime_alert_severity" "test" {
|
||||
project_id = var.project_id
|
||||
name = "terraform-e2e-alert-sev-${formatdate("YYYYMMDDhhmmss", timestamp())}"
|
||||
description = "Alert severity created by Terraform E2E tests"
|
||||
color = "#FF0000"
|
||||
order = 99
|
||||
}
|
||||
|
||||
output "alert_severity_id" {
|
||||
value = oneuptime_alert_severity.test.id
|
||||
}
|
||||
```
|
||||
|
||||
### Test 7: Alert State
|
||||
**File: `E2E/Terraform/e2e-tests/tests/07-alert-state/main.tf`**
|
||||
|
||||
```hcl
|
||||
terraform {
|
||||
required_providers {
|
||||
oneuptime = {
|
||||
source = "oneuptime/oneuptime"
|
||||
version = "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "oneuptime" {
|
||||
oneuptime_url = var.oneuptime_url
|
||||
api_key = var.api_key
|
||||
}
|
||||
|
||||
resource "oneuptime_alert_state" "test" {
|
||||
project_id = var.project_id
|
||||
name = "terraform-e2e-alert-state-${formatdate("YYYYMMDDhhmmss", timestamp())}"
|
||||
description = "Alert state created by Terraform E2E tests"
|
||||
color = "#800080"
|
||||
order = 99
|
||||
}
|
||||
|
||||
output "alert_state_id" {
|
||||
value = oneuptime_alert_state.test.id
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Resource Test Order
|
||||
|
||||
Tests must run in this order to respect dependencies:
|
||||
|
||||
| Order | Resource | Dependencies | Purpose |
|
||||
|-------|----------|--------------|---------|
|
||||
| 1 | Label | None | Basic CRUD validation |
|
||||
| 2 | MonitorStatus | None | Required for Monitor tests |
|
||||
| 3 | IncidentSeverity | None | Required for Incident tests |
|
||||
| 4 | IncidentState | None | Required for Incident tests |
|
||||
| 5 | StatusPage | None | Status page CRUD |
|
||||
| 6 | AlertSeverity | None | Required for Alert tests |
|
||||
| 7 | AlertState | None | Required for Alert tests |
|
||||
|
||||
---
|
||||
|
||||
## Potential Generator Fixes
|
||||
|
||||
If bugs are discovered during E2E testing, fixes should be made in the generator code, not the generated provider:
|
||||
|
||||
| Issue | File to Modify |
|
||||
|-------|----------------|
|
||||
| API authentication issues | `Scripts/TerraformProvider/Core/ProviderGenerator.ts` |
|
||||
| Resource CRUD operations | `Scripts/TerraformProvider/Core/ResourceGenerator.ts` |
|
||||
| Schema parsing issues | `Scripts/TerraformProvider/Core/OpenAPIParser.ts` |
|
||||
| Data source issues | `Scripts/TerraformProvider/Core/DataSourceGenerator.ts` |
|
||||
| Type mapping issues | `Scripts/TerraformProvider/Core/Types.ts` |
|
||||
|
||||
### Known Areas to Watch
|
||||
1. **APIKey Header** (line 248 in ProviderGenerator.ts): Currently uses `APIKey`, verify this matches API expectations
|
||||
2. **Project ID**: Resources are tenant-scoped; ensure projectId is passed correctly
|
||||
3. **Response Parsing**: Complex object responses may need special handling
|
||||
|
||||
---
|
||||
|
||||
## Verification Steps
|
||||
|
||||
### Local Testing
|
||||
```bash
|
||||
# 1. Start services
|
||||
cp config.example.env config.env
|
||||
docker compose up -d postgres redis clickhouse app accounts ingress worker
|
||||
|
||||
# 2. Wait for services
|
||||
./E2E/Terraform/e2e-tests/scripts/wait-for-services.sh
|
||||
|
||||
# 3. Setup test account
|
||||
./E2E/Terraform/e2e-tests/scripts/setup-test-account.sh
|
||||
|
||||
# 4. Generate provider
|
||||
npm run generate-terraform-provider
|
||||
|
||||
# 5. Run tests
|
||||
./E2E/Terraform/e2e-tests/scripts/run-tests.sh
|
||||
|
||||
# 6. Cleanup
|
||||
./E2E/Terraform/e2e-tests/scripts/cleanup.sh
|
||||
docker compose down -v
|
||||
```
|
||||
|
||||
### CI/CD Verification
|
||||
1. Push changes to a branch
|
||||
2. Create a pull request
|
||||
3. Verify the `terraform-provider-e2e.yml` workflow runs successfully
|
||||
4. Check that all Terraform resource tests pass
|
||||
|
||||
---
|
||||
|
||||
## Environment Variables Reference
|
||||
|
||||
| Variable | Description | Example |
|
||||
|----------|-------------|---------|
|
||||
| `ONEUPTIME_URL` | OneUptime API base URL | `http://localhost` |
|
||||
| `ONEUPTIME_API_KEY` | API key for authentication | `abc123...` |
|
||||
| `ONEUPTIME_PROJECT_ID` | Project ID for resources | `6789...` |
|
||||
| `TF_VAR_project_id` | Terraform variable | Same as PROJECT_ID |
|
||||
| `TF_VAR_api_key` | Terraform variable | Same as API_KEY |
|
||||
| `TF_VAR_oneuptime_url` | Terraform variable | Same as ONEUPTIME_URL |
|
||||
92
E2E/Terraform/e2e-tests/README.md
Normal file
92
E2E/Terraform/e2e-tests/README.md
Normal file
@@ -0,0 +1,92 @@
|
||||
# Terraform Provider E2E Tests
|
||||
|
||||
End-to-end tests for the OneUptime Terraform Provider. These tests validate that the generated Terraform provider works correctly against a running OneUptime instance.
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```
|
||||
e2e-tests/
|
||||
├── scripts/
|
||||
│ ├── index.sh # Main entry point - orchestrates the full test flow
|
||||
│ ├── setup-test-account.sh # Creates test user, project, and API key
|
||||
│ ├── run-tests.sh # Builds provider and runs all test cases
|
||||
│ └── cleanup.sh # Cleans up test artifacts and state files
|
||||
└── tests/
|
||||
├── 01-label/ # Label resource tests
|
||||
├── 02-monitor-status/ # Monitor status resource tests
|
||||
├── 03-incident-severity/ # Incident severity resource tests
|
||||
├── 04-incident-state/ # Incident state resource tests
|
||||
├── 05-status-page/ # Status page resource tests
|
||||
├── 06-alert-severity/ # Alert severity resource tests
|
||||
└── 07-alert-state/ # Alert state resource tests
|
||||
```
|
||||
|
||||
## Running Tests
|
||||
|
||||
### Full E2E Test Suite (CI/CD)
|
||||
|
||||
The `index.sh` script runs the complete test flow:
|
||||
|
||||
```bash
|
||||
./scripts/index.sh
|
||||
```
|
||||
|
||||
This will:
|
||||
1. Set up `config.env` from the example file
|
||||
2. Start OneUptime services via Docker Compose
|
||||
3. Wait for services to be ready
|
||||
4. Install npm dependencies
|
||||
5. Generate the Terraform provider
|
||||
6. Create a test account with API key
|
||||
7. Run all Terraform tests
|
||||
8. Clean up on exit
|
||||
|
||||
### Running Individual Scripts
|
||||
|
||||
If you already have OneUptime running locally:
|
||||
|
||||
```bash
|
||||
# Set up test account and API key
|
||||
./scripts/setup-test-account.sh
|
||||
|
||||
# Run the Terraform tests
|
||||
./scripts/run-tests.sh
|
||||
|
||||
# Clean up after testing
|
||||
./scripts/cleanup.sh
|
||||
```
|
||||
|
||||
## Test Flow
|
||||
|
||||
Each test case in `tests/` follows this pattern:
|
||||
1. `terraform init` - Initialize the Terraform configuration
|
||||
2. `terraform plan` - Create an execution plan
|
||||
3. `terraform apply` - Create the resources
|
||||
4. `terraform output` - Display created resource information
|
||||
5. `terraform destroy` - Clean up created resources
|
||||
|
||||
## Environment Variables
|
||||
|
||||
The following environment variables are used:
|
||||
|
||||
| Variable | Default | Description |
|
||||
|----------|---------|-------------|
|
||||
| `ONEUPTIME_URL` | `http://localhost` | OneUptime instance URL |
|
||||
| `ONEUPTIME_API_KEY` | (generated) | API key for authentication |
|
||||
| `ONEUPTIME_PROJECT_ID` | (generated) | Project ID for resources |
|
||||
|
||||
## CI/CD
|
||||
|
||||
Tests run automatically via GitHub Actions on:
|
||||
- Pull requests
|
||||
- Pushes to `main`, `master`, or `develop` branches
|
||||
- Manual workflow dispatch
|
||||
|
||||
See `.github/workflows/terraform-provider-e2e.yml` for the workflow configuration.
|
||||
|
||||
## Adding New Tests
|
||||
|
||||
1. Create a new directory in `tests/` with the naming convention `XX-resource-name/`
|
||||
2. Add `main.tf` with the Terraform configuration
|
||||
3. Add `variables.tf` with required variables
|
||||
4. Add the test directory name to the `TEST_DIRS` array in `scripts/run-tests.sh`
|
||||
24
E2E/Terraform/e2e-tests/scripts/cleanup.sh
Executable file
24
E2E/Terraform/e2e-tests/scripts/cleanup.sh
Executable file
@@ -0,0 +1,24 @@
|
||||
#!/bin/bash
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
TEST_DIR="$(dirname "$SCRIPT_DIR")"
|
||||
|
||||
echo "=== Cleaning up ==="
|
||||
|
||||
# Remove Terraform state files
|
||||
find "$TEST_DIR/tests" -name "*.tfstate*" -delete 2>/dev/null || true
|
||||
find "$TEST_DIR/tests" -name ".terraform" -type d -exec rm -rf {} + 2>/dev/null || true
|
||||
find "$TEST_DIR/tests" -name ".terraform.lock.hcl" -delete 2>/dev/null || true
|
||||
find "$TEST_DIR/tests" -name "tfplan" -delete 2>/dev/null || true
|
||||
|
||||
# Remove test env file
|
||||
rm -f "$TEST_DIR/test-env.sh"
|
||||
rm -f "$TEST_DIR/cookies.txt"
|
||||
|
||||
# Remove Terraform CLI override
|
||||
rm -f "$HOME/.terraformrc"
|
||||
|
||||
# Remove local provider installation
|
||||
rm -rf "$HOME/.terraform.d/plugins/registry.terraform.io/oneuptime" 2>/dev/null || true
|
||||
|
||||
echo "Cleanup complete"
|
||||
52
E2E/Terraform/e2e-tests/scripts/index.sh
Executable file
52
E2E/Terraform/e2e-tests/scripts/index.sh
Executable file
@@ -0,0 +1,52 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
TEST_DIR="$(dirname "$SCRIPT_DIR")"
|
||||
ROOT_DIR="$(cd "$TEST_DIR/../../.." && pwd)"
|
||||
|
||||
echo "=========================================="
|
||||
echo "Terraform Provider E2E Tests"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
|
||||
|
||||
# Step 2: Start OneUptime services
|
||||
echo ""
|
||||
echo "=== Step 2: Starting OneUptime Services ==="
|
||||
npm run dev
|
||||
|
||||
# Step 3: Wait for services
|
||||
echo ""
|
||||
echo "=== Step 3: Waiting for services to be ready ==="
|
||||
cd "$ROOT_DIR"
|
||||
npm run status-check
|
||||
|
||||
# Step 4: Install dependencies
|
||||
echo ""
|
||||
echo "=== Step 4: Installing dependencies ==="
|
||||
cd "$ROOT_DIR"
|
||||
npm install
|
||||
cd Common && npm install && cd ..
|
||||
cd Scripts && npm install && cd ..
|
||||
|
||||
# Step 5: Generate Terraform Provider
|
||||
echo ""
|
||||
echo "=== Step 5: Generating Terraform Provider ==="
|
||||
npm run generate-terraform-provider
|
||||
|
||||
# Step 6: Setup test account
|
||||
echo ""
|
||||
echo "=== Step 6: Setting up test account ==="
|
||||
cd "$TEST_DIR"
|
||||
"$SCRIPT_DIR/setup-test-account.sh"
|
||||
|
||||
# Step 7: Run E2E tests (includes standard tests and CRUD tests with API validation)
|
||||
echo ""
|
||||
echo "=== Step 7: Running Terraform E2E Tests ==="
|
||||
"$SCRIPT_DIR/run-tests.sh"
|
||||
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo "E2E Tests Completed Successfully!"
|
||||
echo "=========================================="
|
||||
250
E2E/Terraform/e2e-tests/scripts/run-tests.sh
Executable file
250
E2E/Terraform/e2e-tests/scripts/run-tests.sh
Executable file
@@ -0,0 +1,250 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
TEST_DIR="$(dirname "$SCRIPT_DIR")"
|
||||
PROVIDER_DIR="$TEST_DIR/../../../Terraform/terraform-provider-oneuptime"
|
||||
|
||||
# Load test environment
|
||||
source "$TEST_DIR/test-env.sh"
|
||||
|
||||
echo "=== Running Terraform E2E Tests ==="
|
||||
echo "OneUptime URL: $ONEUPTIME_URL"
|
||||
echo "Project ID: $ONEUPTIME_PROJECT_ID"
|
||||
|
||||
# Build and install provider locally
|
||||
echo ""
|
||||
echo "=== Building Terraform Provider ==="
|
||||
cd "$PROVIDER_DIR"
|
||||
go mod tidy
|
||||
go build -o terraform-provider-oneuptime
|
||||
|
||||
# Install provider
|
||||
OS=$(go env GOOS)
|
||||
ARCH=$(go env GOARCH)
|
||||
INSTALL_DIR="$HOME/.terraform.d/plugins/registry.terraform.io/oneuptime/oneuptime/1.0.0/${OS}_${ARCH}"
|
||||
mkdir -p "$INSTALL_DIR"
|
||||
cp terraform-provider-oneuptime "$INSTALL_DIR/"
|
||||
|
||||
# Create Terraform CLI override config
|
||||
cat > "$HOME/.terraformrc" << EOF
|
||||
provider_installation {
|
||||
dev_overrides {
|
||||
"oneuptime/oneuptime" = "$INSTALL_DIR"
|
||||
}
|
||||
direct {}
|
||||
}
|
||||
EOF
|
||||
|
||||
echo "Provider installed to: $INSTALL_DIR"
|
||||
|
||||
#######################################
|
||||
# API Helper Functions (for verify.sh scripts)
|
||||
#######################################
|
||||
|
||||
# These functions are exported for use by verify.sh scripts
|
||||
|
||||
# Map output name to API endpoint
|
||||
# e.g., "label_id" -> "/api/label", "monitor_status_id" -> "/api/monitor-status"
|
||||
get_api_endpoint() {
|
||||
local output_name="$1"
|
||||
# Remove "_id" suffix and convert underscores to hyphens
|
||||
local resource_type="${output_name%_id}"
|
||||
resource_type="${resource_type//_/-}"
|
||||
echo "/api/${resource_type}"
|
||||
}
|
||||
|
||||
# Verify resource was deleted via API
|
||||
validate_resource_deleted() {
|
||||
local endpoint="$1"
|
||||
local resource_id="$2"
|
||||
|
||||
echo " Verifying deletion via API: POST ${ONEUPTIME_URL}${endpoint}/${resource_id}/get-item"
|
||||
|
||||
local http_code
|
||||
http_code=$(curl -s -o /dev/null -w "%{http_code}" -X POST "${ONEUPTIME_URL}${endpoint}/${resource_id}/get-item" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Apikey: $TF_VAR_api_key" \
|
||||
-H "projectid: $TF_VAR_project_id" \
|
||||
-d '{"select": {"_id": true}}' 2>&1)
|
||||
|
||||
# Resource should return 404 or 500 (not found) after deletion
|
||||
if [ "$http_code" -eq 404 ] || [ "$http_code" -eq 500 ]; then
|
||||
echo " ✓ Deletion verified: Resource no longer exists (HTTP $http_code)"
|
||||
return 0
|
||||
elif [ "$http_code" -ge 200 ] && [ "$http_code" -lt 300 ]; then
|
||||
echo " ✗ Deletion verification FAILED: Resource still exists (HTTP $http_code)"
|
||||
return 1
|
||||
else
|
||||
echo " ✓ Deletion likely successful (HTTP $http_code)"
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
# Validate all resources were deleted
|
||||
validate_all_deleted() {
|
||||
local test_path="$1"
|
||||
local saved_ids="$2" # Format: "output_name=id\noutput_name2=id2\n..."
|
||||
local validation_failed=0
|
||||
|
||||
echo " Verifying resources were deleted via API..."
|
||||
|
||||
while IFS= read -r output; do
|
||||
if [ -z "$output" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
local output_name="${output%%=*}"
|
||||
local resource_id="${output#*=}"
|
||||
|
||||
if [ -z "$resource_id" ] || [ "$resource_id" = "null" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
local endpoint=$(get_api_endpoint "$output_name")
|
||||
|
||||
if ! validate_resource_deleted "$endpoint" "$resource_id"; then
|
||||
validation_failed=1
|
||||
fi
|
||||
done <<< "$saved_ids"
|
||||
|
||||
return $validation_failed
|
||||
}
|
||||
|
||||
# Export functions and variables for verify.sh scripts
|
||||
export -f get_api_endpoint
|
||||
export ONEUPTIME_URL
|
||||
export TF_VAR_api_key
|
||||
export TF_VAR_project_id
|
||||
|
||||
#######################################
|
||||
# Main Test Runner
|
||||
#######################################
|
||||
|
||||
# Discover all test directories dynamically (sorted by name)
|
||||
TEST_DIRS=()
|
||||
while IFS= read -r dir; do
|
||||
TEST_DIRS+=("$(basename "$dir")")
|
||||
done < <(find "$TEST_DIR/tests" -mindepth 1 -maxdepth 1 -type d | sort)
|
||||
|
||||
echo "Discovered ${#TEST_DIRS[@]} test directories"
|
||||
|
||||
PASSED=()
|
||||
FAILED=()
|
||||
|
||||
for test_name in "${TEST_DIRS[@]}"; do
|
||||
test_path="$TEST_DIR/tests/$test_name"
|
||||
|
||||
if [ ! -d "$test_path" ]; then
|
||||
echo "SKIP: $test_name (not found)"
|
||||
continue
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo "Testing: $test_name"
|
||||
echo "=========================================="
|
||||
|
||||
cd "$test_path"
|
||||
rm -f tfplan terraform.tfstate terraform.tfstate.backup
|
||||
|
||||
# All tests get the same treatment:
|
||||
# 1. Plan
|
||||
# 2. Apply
|
||||
# 3. Run verify.sh (API Validation)
|
||||
# 4. Destroy
|
||||
# 5. Verify Deletion via API
|
||||
|
||||
# Step 1: Plan
|
||||
echo " [1/5] Planning..."
|
||||
if ! terraform plan -out=tfplan 2>&1; then
|
||||
echo " ✗ FAILED: Plan failed"
|
||||
FAILED+=("$test_name")
|
||||
rm -f tfplan terraform.tfstate terraform.tfstate.backup
|
||||
continue
|
||||
fi
|
||||
|
||||
# Step 2: Apply
|
||||
echo " [2/5] Applying..."
|
||||
if ! terraform apply -auto-approve tfplan 2>&1; then
|
||||
echo " ✗ FAILED: Apply failed"
|
||||
FAILED+=("$test_name")
|
||||
# Try to cleanup anyway
|
||||
terraform destroy -auto-approve 2>&1 || true
|
||||
rm -f tfplan terraform.tfstate terraform.tfstate.backup
|
||||
continue
|
||||
fi
|
||||
|
||||
# Show outputs
|
||||
echo ""
|
||||
echo " Terraform Outputs:"
|
||||
terraform output 2>&1 || true
|
||||
echo ""
|
||||
|
||||
# Save resource IDs for deletion verification later
|
||||
saved_ids=$(terraform output -json 2>/dev/null | jq -r 'to_entries[] | select(.key | endswith("_id")) | "\(.key)=\(.value.value)"' 2>/dev/null)
|
||||
|
||||
# Step 3: Run verify.sh for API Validation
|
||||
echo " [3/5] Running API validation (verify.sh)..."
|
||||
test_failed=0
|
||||
if [ -f "$test_path/verify.sh" ]; then
|
||||
chmod +x "$test_path/verify.sh"
|
||||
if ! "$test_path/verify.sh"; then
|
||||
echo " ✗ API validation failed"
|
||||
test_failed=1
|
||||
else
|
||||
echo " ✓ API validation passed"
|
||||
fi
|
||||
else
|
||||
echo " ⚠ No verify.sh found, skipping API validation"
|
||||
fi
|
||||
|
||||
# Step 4: Destroy
|
||||
echo ""
|
||||
echo " [4/5] Destroying..."
|
||||
cd "$test_path"
|
||||
if ! terraform destroy -auto-approve 2>&1; then
|
||||
echo " ⚠ WARNING: Destroy failed"
|
||||
FAILED+=("$test_name (destroy)")
|
||||
test_failed=1
|
||||
fi
|
||||
|
||||
# Step 5: Verify Deletion via API
|
||||
echo ""
|
||||
echo " [5/5] Verifying deletion..."
|
||||
if [ -n "$saved_ids" ]; then
|
||||
if ! validate_all_deleted "$test_path" "$saved_ids"; then
|
||||
echo " ⚠ WARNING: Some resources may not have been deleted"
|
||||
# Don't fail the test for deletion verification issues
|
||||
fi
|
||||
fi
|
||||
|
||||
# Cleanup state files
|
||||
rm -f tfplan terraform.tfstate terraform.tfstate.backup
|
||||
|
||||
# Mark test result
|
||||
if [ $test_failed -eq 0 ]; then
|
||||
echo ""
|
||||
echo " ✓ PASSED: $test_name"
|
||||
PASSED+=("$test_name")
|
||||
else
|
||||
FAILED+=("$test_name")
|
||||
fi
|
||||
done
|
||||
|
||||
# Summary
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo "Test Summary"
|
||||
echo "=========================================="
|
||||
echo "Passed: ${#PASSED[@]}"
|
||||
for t in "${PASSED[@]}"; do echo " ✓ $t"; done
|
||||
|
||||
if [ ${#FAILED[@]} -gt 0 ]; then
|
||||
echo "Failed: ${#FAILED[@]}"
|
||||
for t in "${FAILED[@]}"; do echo " ✗ $t"; done
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "All tests passed!"
|
||||
141
E2E/Terraform/e2e-tests/scripts/setup-test-account.sh
Executable file
141
E2E/Terraform/e2e-tests/scripts/setup-test-account.sh
Executable file
@@ -0,0 +1,141 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
TEST_DIR="$(dirname "$SCRIPT_DIR")"
|
||||
ONEUPTIME_URL="${ONEUPTIME_URL:-http://localhost}"
|
||||
|
||||
# Generate unique test values
|
||||
TIMESTAMP=$(date +%s)
|
||||
TEST_EMAIL="terraform-test-${TIMESTAMP}@test.oneuptime.com"
|
||||
TEST_PASSWORD="TestPassword123!"
|
||||
TEST_NAME="Terraform E2E Test User"
|
||||
|
||||
echo "=== Setting up test account ==="
|
||||
echo "Email: $TEST_EMAIL"
|
||||
|
||||
# Step 1: Register a new user
|
||||
echo "Step 1: Registering new user..."
|
||||
SIGNUP_RESPONSE=$(curl -sf -X POST "${ONEUPTIME_URL}/api/identity/signup" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{
|
||||
\"data\": {
|
||||
\"email\": {\"_type\": \"Email\", \"value\": \"$TEST_EMAIL\"},
|
||||
\"password\": {\"_type\": \"HashedString\", \"value\": \"$TEST_PASSWORD\"},
|
||||
\"name\": {\"_type\": \"Name\", \"value\": \"$TEST_NAME\"},
|
||||
\"companyName\": \"Terraform E2E Test Company\",
|
||||
\"companyPhoneNumber\": {\"_type\": \"Phone\", \"value\": \"+15551234567\"}
|
||||
}
|
||||
}")
|
||||
|
||||
echo "User registered successfully"
|
||||
|
||||
# Step 2: Login to get session
|
||||
echo "Step 2: Logging in..."
|
||||
LOGIN_RESPONSE=$(curl -sf -X POST "${ONEUPTIME_URL}/api/identity/login" \
|
||||
-H "Content-Type: application/json" \
|
||||
-c "$TEST_DIR/cookies.txt" \
|
||||
-d "{
|
||||
\"data\": {
|
||||
\"email\": {\"_type\": \"Email\", \"value\": \"$TEST_EMAIL\"},
|
||||
\"password\": {\"_type\": \"HashedString\", \"value\": \"$TEST_PASSWORD\"}
|
||||
}
|
||||
}")
|
||||
|
||||
COOKIES="-b $TEST_DIR/cookies.txt"
|
||||
echo "Login successful"
|
||||
|
||||
# Step 3: Get or create project
|
||||
echo "Step 3: Fetching project..."
|
||||
sleep 3 # Wait for automatic project creation
|
||||
|
||||
PROJECT_RESPONSE=$(curl -sf -X POST "${ONEUPTIME_URL}/api/project/get-list" \
|
||||
-H "Content-Type: application/json" \
|
||||
$COOKIES \
|
||||
-d "{
|
||||
\"query\": {},
|
||||
\"select\": {\"_id\": true, \"name\": true},
|
||||
\"limit\": 1
|
||||
}")
|
||||
|
||||
PROJECT_ID=$(echo "$PROJECT_RESPONSE" | jq -r '.data[0]._id // empty')
|
||||
|
||||
if [ -z "$PROJECT_ID" ]; then
|
||||
echo "Creating new project..."
|
||||
PROJECT_CREATE=$(curl -sf -X POST "${ONEUPTIME_URL}/api/project" \
|
||||
-H "Content-Type: application/json" \
|
||||
$COOKIES \
|
||||
-d "{
|
||||
\"data\": {
|
||||
\"name\": \"Terraform E2E Test Project\"
|
||||
}
|
||||
}")
|
||||
PROJECT_ID=$(echo "$PROJECT_CREATE" | jq -r '.data._id // ._id')
|
||||
fi
|
||||
|
||||
echo "Project ID: $PROJECT_ID"
|
||||
|
||||
# Step 4: Create API Key
|
||||
echo "Step 4: Creating API key..."
|
||||
EXPIRES_AT=$(date -d "+1 year" -u +"%Y-%m-%dT%H:%M:%S.000Z" 2>/dev/null || \
|
||||
date -v+1y -u +"%Y-%m-%dT%H:%M:%S.000Z")
|
||||
|
||||
API_KEY_RESPONSE=$(curl -sf -X POST "${ONEUPTIME_URL}/api/api-key" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "projectid: $PROJECT_ID" \
|
||||
$COOKIES \
|
||||
-d "{
|
||||
\"data\": {
|
||||
\"name\": \"Terraform E2E Test API Key\",
|
||||
\"description\": \"API Key for Terraform E2E Tests\",
|
||||
\"expiresAt\": \"$EXPIRES_AT\",
|
||||
\"projectId\": \"$PROJECT_ID\"
|
||||
}
|
||||
}")
|
||||
|
||||
API_KEY_ID=$(echo "$API_KEY_RESPONSE" | jq -r '.data._id // ._id')
|
||||
# Extract the value from the ObjectID object (apiKey is returned as {_type: "ObjectID", value: "..."})
|
||||
API_KEY=$(echo "$API_KEY_RESPONSE" | jq -r '(.data.apiKey.value // .apiKey.value) // (.data.apiKey // .apiKey)')
|
||||
|
||||
echo "API Key ID: $API_KEY_ID"
|
||||
echo "API Key: $API_KEY"
|
||||
|
||||
# Step 5: Add ProjectOwner permission
|
||||
echo "Step 5: Adding ProjectOwner permission..."
|
||||
PERMISSION_RESPONSE=$(curl -sf -X POST "${ONEUPTIME_URL}/api/api-key-permission" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "projectid: $PROJECT_ID" \
|
||||
$COOKIES \
|
||||
-d "{
|
||||
\"data\": {
|
||||
\"apiKeyId\": \"$API_KEY_ID\",
|
||||
\"projectId\": \"$PROJECT_ID\",
|
||||
\"permission\": \"ProjectOwner\",
|
||||
\"isBlockPermission\": false
|
||||
}
|
||||
}")
|
||||
|
||||
echo "Permission added"
|
||||
|
||||
# Step 6: Write environment file
|
||||
echo "Step 6: Writing test environment..."
|
||||
cat > "$TEST_DIR/test-env.sh" << EOF
|
||||
#!/bin/bash
|
||||
export ONEUPTIME_URL="$ONEUPTIME_URL"
|
||||
export ONEUPTIME_API_KEY="$API_KEY"
|
||||
export ONEUPTIME_PROJECT_ID="$PROJECT_ID"
|
||||
export TF_VAR_project_id="$PROJECT_ID"
|
||||
export TF_VAR_api_key="$API_KEY"
|
||||
export TF_VAR_oneuptime_url="$ONEUPTIME_URL"
|
||||
EOF
|
||||
|
||||
chmod +x "$TEST_DIR/test-env.sh"
|
||||
|
||||
# Cleanup cookies
|
||||
rm -f "$TEST_DIR/cookies.txt"
|
||||
|
||||
echo ""
|
||||
echo "=== Setup Complete ==="
|
||||
echo "ONEUPTIME_URL: $ONEUPTIME_URL"
|
||||
echo "PROJECT_ID: $PROJECT_ID"
|
||||
echo "API_KEY: $API_KEY"
|
||||
40
E2E/Terraform/e2e-tests/tests/01-label/main.tf
Normal file
40
E2E/Terraform/e2e-tests/tests/01-label/main.tf
Normal file
@@ -0,0 +1,40 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
oneuptime = {
|
||||
source = "oneuptime/oneuptime"
|
||||
version = "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "oneuptime" {
|
||||
oneuptime_url = var.oneuptime_url
|
||||
api_key = var.api_key
|
||||
}
|
||||
|
||||
resource "oneuptime_label" "test" {
|
||||
project_id = var.project_id
|
||||
name = "terraform-e2e-label-${formatdate("YYYYMMDDhhmmss", timestamp())}"
|
||||
description = "Label created by Terraform E2E tests"
|
||||
color = "#FF5733"
|
||||
}
|
||||
|
||||
output "label_id" {
|
||||
value = oneuptime_label.test.id
|
||||
description = "ID of the created label"
|
||||
}
|
||||
|
||||
output "label_name" {
|
||||
value = oneuptime_label.test.name
|
||||
description = "Name of the created label"
|
||||
}
|
||||
|
||||
output "label_description" {
|
||||
value = oneuptime_label.test.description
|
||||
description = "Description of the created label"
|
||||
}
|
||||
|
||||
output "label_color" {
|
||||
value = oneuptime_label.test.color
|
||||
description = "Color of the created label"
|
||||
}
|
||||
15
E2E/Terraform/e2e-tests/tests/01-label/variables.tf
Normal file
15
E2E/Terraform/e2e-tests/tests/01-label/variables.tf
Normal file
@@ -0,0 +1,15 @@
|
||||
variable "oneuptime_url" {
|
||||
type = string
|
||||
description = "OneUptime API URL"
|
||||
}
|
||||
|
||||
variable "api_key" {
|
||||
type = string
|
||||
description = "OneUptime API Key"
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "project_id" {
|
||||
type = string
|
||||
description = "OneUptime Project ID"
|
||||
}
|
||||
56
E2E/Terraform/e2e-tests/tests/01-label/verify.sh
Executable file
56
E2E/Terraform/e2e-tests/tests/01-label/verify.sh
Executable file
@@ -0,0 +1,56 @@
|
||||
#!/bin/bash
|
||||
# Verify script for 01-label test
|
||||
# Validates that the label resource was created correctly via API
|
||||
|
||||
set -e
|
||||
|
||||
# Get terraform outputs
|
||||
LABEL_ID=$(terraform output -raw label_id)
|
||||
LABEL_NAME=$(terraform output -raw label_name)
|
||||
LABEL_DESCRIPTION=$(terraform output -raw label_description)
|
||||
LABEL_COLOR=$(terraform output -raw label_color)
|
||||
|
||||
echo " Verifying label resource via API..."
|
||||
echo " Label ID: $LABEL_ID"
|
||||
|
||||
# Call API to get the label
|
||||
RESPONSE=$(curl -s -X POST "${ONEUPTIME_URL}/api/label/${LABEL_ID}/get-item" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Apikey: $TF_VAR_api_key" \
|
||||
-H "projectid: $TF_VAR_project_id" \
|
||||
-d '{"select": {"_id": true, "name": true, "description": true, "color": true}}')
|
||||
|
||||
# Check if response contains the label
|
||||
API_ID=$(echo "$RESPONSE" | jq -r '._id // empty')
|
||||
if [ -z "$API_ID" ] || [ "$API_ID" = "null" ]; then
|
||||
echo " ✗ FAILED: Label not found in API response"
|
||||
echo " Response: $RESPONSE"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Label exists in API"
|
||||
|
||||
# Validate name
|
||||
API_NAME=$(echo "$RESPONSE" | jq -r '.name // empty')
|
||||
if [ "$API_NAME" != "$LABEL_NAME" ]; then
|
||||
echo " ✗ FAILED: Name mismatch - Expected: '$LABEL_NAME', Got: '$API_NAME'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Name matches: $API_NAME"
|
||||
|
||||
# Validate description
|
||||
API_DESCRIPTION=$(echo "$RESPONSE" | jq -r '.description // empty')
|
||||
if [ "$API_DESCRIPTION" != "$LABEL_DESCRIPTION" ]; then
|
||||
echo " ✗ FAILED: Description mismatch - Expected: '$LABEL_DESCRIPTION', Got: '$API_DESCRIPTION'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Description matches: $API_DESCRIPTION"
|
||||
|
||||
# Validate color
|
||||
API_COLOR=$(echo "$RESPONSE" | jq -r '.color // empty')
|
||||
if [ "$API_COLOR" != "$LABEL_COLOR" ]; then
|
||||
echo " ✗ FAILED: Color mismatch - Expected: '$LABEL_COLOR', Got: '$API_COLOR'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Color matches: $API_COLOR"
|
||||
|
||||
echo " ✓ All label validations passed"
|
||||
52
E2E/Terraform/e2e-tests/tests/02-monitor-status/main.tf
Normal file
52
E2E/Terraform/e2e-tests/tests/02-monitor-status/main.tf
Normal file
@@ -0,0 +1,52 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
oneuptime = {
|
||||
source = "oneuptime/oneuptime"
|
||||
version = "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "oneuptime" {
|
||||
oneuptime_url = var.oneuptime_url
|
||||
api_key = var.api_key
|
||||
}
|
||||
|
||||
resource "oneuptime_monitor_status" "test" {
|
||||
project_id = var.project_id
|
||||
name = "terraform-e2e-status-${formatdate("YYYYMMDDhhmmss", timestamp())}"
|
||||
description = "Monitor status created by Terraform E2E tests"
|
||||
color = "#00FF00"
|
||||
priority = 99
|
||||
is_operational_state = true
|
||||
}
|
||||
|
||||
output "monitor_status_id" {
|
||||
value = oneuptime_monitor_status.test.id
|
||||
description = "ID of the created monitor status"
|
||||
}
|
||||
|
||||
output "monitor_status_name" {
|
||||
value = oneuptime_monitor_status.test.name
|
||||
description = "Name of the created monitor status"
|
||||
}
|
||||
|
||||
output "monitor_status_description" {
|
||||
value = oneuptime_monitor_status.test.description
|
||||
description = "Description of the created monitor status"
|
||||
}
|
||||
|
||||
output "monitor_status_color" {
|
||||
value = oneuptime_monitor_status.test.color
|
||||
description = "Color of the created monitor status"
|
||||
}
|
||||
|
||||
output "monitor_status_priority" {
|
||||
value = oneuptime_monitor_status.test.priority
|
||||
description = "Priority of the created monitor status"
|
||||
}
|
||||
|
||||
output "monitor_status_is_operational_state" {
|
||||
value = oneuptime_monitor_status.test.is_operational_state
|
||||
description = "Whether this status indicates an operational state"
|
||||
}
|
||||
15
E2E/Terraform/e2e-tests/tests/02-monitor-status/variables.tf
Normal file
15
E2E/Terraform/e2e-tests/tests/02-monitor-status/variables.tf
Normal file
@@ -0,0 +1,15 @@
|
||||
variable "oneuptime_url" {
|
||||
type = string
|
||||
description = "OneUptime API URL"
|
||||
}
|
||||
|
||||
variable "api_key" {
|
||||
type = string
|
||||
description = "OneUptime API Key"
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "project_id" {
|
||||
type = string
|
||||
description = "OneUptime Project ID"
|
||||
}
|
||||
74
E2E/Terraform/e2e-tests/tests/02-monitor-status/verify.sh
Executable file
74
E2E/Terraform/e2e-tests/tests/02-monitor-status/verify.sh
Executable file
@@ -0,0 +1,74 @@
|
||||
#!/bin/bash
|
||||
# Verify script for 02-monitor-status test
|
||||
# Validates that the monitor status resource was created correctly via API
|
||||
|
||||
set -e
|
||||
|
||||
# Get terraform outputs
|
||||
RESOURCE_ID=$(terraform output -raw monitor_status_id)
|
||||
EXPECTED_NAME=$(terraform output -raw monitor_status_name)
|
||||
EXPECTED_DESCRIPTION=$(terraform output -raw monitor_status_description)
|
||||
EXPECTED_COLOR=$(terraform output -raw monitor_status_color)
|
||||
EXPECTED_PRIORITY=$(terraform output -raw monitor_status_priority)
|
||||
EXPECTED_IS_OPERATIONAL=$(terraform output -raw monitor_status_is_operational_state)
|
||||
|
||||
echo " Verifying monitor status resource via API..."
|
||||
echo " Resource ID: $RESOURCE_ID"
|
||||
|
||||
# Call API to get the resource
|
||||
RESPONSE=$(curl -s -X POST "${ONEUPTIME_URL}/api/monitor-status/${RESOURCE_ID}/get-item" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Apikey: $TF_VAR_api_key" \
|
||||
-H "projectid: $TF_VAR_project_id" \
|
||||
-d '{"select": {"_id": true, "name": true, "description": true, "color": true, "priority": true, "isOperationalState": true}}')
|
||||
|
||||
# Check if response contains the resource
|
||||
API_ID=$(echo "$RESPONSE" | jq -r '._id // empty')
|
||||
if [ -z "$API_ID" ] || [ "$API_ID" = "null" ]; then
|
||||
echo " ✗ FAILED: Monitor status not found in API response"
|
||||
echo " Response: $RESPONSE"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Monitor status exists in API"
|
||||
|
||||
# Validate name
|
||||
API_NAME=$(echo "$RESPONSE" | jq -r '.name // empty')
|
||||
if [ "$API_NAME" != "$EXPECTED_NAME" ]; then
|
||||
echo " ✗ FAILED: Name mismatch - Expected: '$EXPECTED_NAME', Got: '$API_NAME'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Name matches: $API_NAME"
|
||||
|
||||
# Validate description
|
||||
API_DESCRIPTION=$(echo "$RESPONSE" | jq -r '.description // empty')
|
||||
if [ "$API_DESCRIPTION" != "$EXPECTED_DESCRIPTION" ]; then
|
||||
echo " ✗ FAILED: Description mismatch - Expected: '$EXPECTED_DESCRIPTION', Got: '$API_DESCRIPTION'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Description matches: $API_DESCRIPTION"
|
||||
|
||||
# Validate color
|
||||
API_COLOR=$(echo "$RESPONSE" | jq -r '.color // empty')
|
||||
if [ "$API_COLOR" != "$EXPECTED_COLOR" ]; then
|
||||
echo " ✗ FAILED: Color mismatch - Expected: '$EXPECTED_COLOR', Got: '$API_COLOR'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Color matches: $API_COLOR"
|
||||
|
||||
# Validate priority
|
||||
API_PRIORITY=$(echo "$RESPONSE" | jq -r '.priority // empty')
|
||||
if [ "$API_PRIORITY" != "$EXPECTED_PRIORITY" ]; then
|
||||
echo " ✗ FAILED: Priority mismatch - Expected: '$EXPECTED_PRIORITY', Got: '$API_PRIORITY'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Priority matches: $API_PRIORITY"
|
||||
|
||||
# Validate isOperationalState
|
||||
API_IS_OPERATIONAL=$(echo "$RESPONSE" | jq -r '.isOperationalState // empty')
|
||||
if [ "$API_IS_OPERATIONAL" != "$EXPECTED_IS_OPERATIONAL" ]; then
|
||||
echo " ✗ FAILED: isOperationalState mismatch - Expected: '$EXPECTED_IS_OPERATIONAL', Got: '$API_IS_OPERATIONAL'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ isOperationalState matches: $API_IS_OPERATIONAL"
|
||||
|
||||
echo " ✓ All monitor status validations passed"
|
||||
46
E2E/Terraform/e2e-tests/tests/03-incident-severity/main.tf
Normal file
46
E2E/Terraform/e2e-tests/tests/03-incident-severity/main.tf
Normal file
@@ -0,0 +1,46 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
oneuptime = {
|
||||
source = "oneuptime/oneuptime"
|
||||
version = "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "oneuptime" {
|
||||
oneuptime_url = var.oneuptime_url
|
||||
api_key = var.api_key
|
||||
}
|
||||
|
||||
resource "oneuptime_incident_severity" "test" {
|
||||
project_id = var.project_id
|
||||
name = "terraform-e2e-severity-${formatdate("YYYYMMDDhhmmss", timestamp())}"
|
||||
description = "Incident severity created by Terraform E2E tests"
|
||||
color = "#FFA500"
|
||||
order = 99
|
||||
}
|
||||
|
||||
output "incident_severity_id" {
|
||||
value = oneuptime_incident_severity.test.id
|
||||
description = "ID of the created incident severity"
|
||||
}
|
||||
|
||||
output "incident_severity_name" {
|
||||
value = oneuptime_incident_severity.test.name
|
||||
description = "Name of the created incident severity"
|
||||
}
|
||||
|
||||
output "incident_severity_description" {
|
||||
value = oneuptime_incident_severity.test.description
|
||||
description = "Description of the created incident severity"
|
||||
}
|
||||
|
||||
output "incident_severity_color" {
|
||||
value = oneuptime_incident_severity.test.color
|
||||
description = "Color of the created incident severity"
|
||||
}
|
||||
|
||||
output "incident_severity_order" {
|
||||
value = oneuptime_incident_severity.test.order
|
||||
description = "Order of the created incident severity"
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
variable "oneuptime_url" {
|
||||
type = string
|
||||
description = "OneUptime API URL"
|
||||
}
|
||||
|
||||
variable "api_key" {
|
||||
type = string
|
||||
description = "OneUptime API Key"
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "project_id" {
|
||||
type = string
|
||||
description = "OneUptime Project ID"
|
||||
}
|
||||
65
E2E/Terraform/e2e-tests/tests/03-incident-severity/verify.sh
Executable file
65
E2E/Terraform/e2e-tests/tests/03-incident-severity/verify.sh
Executable file
@@ -0,0 +1,65 @@
|
||||
#!/bin/bash
|
||||
# Verify script for 03-incident-severity test
|
||||
# Validates that the incident severity resource was created correctly via API
|
||||
|
||||
set -e
|
||||
|
||||
# Get terraform outputs
|
||||
RESOURCE_ID=$(terraform output -raw incident_severity_id)
|
||||
EXPECTED_NAME=$(terraform output -raw incident_severity_name)
|
||||
EXPECTED_DESCRIPTION=$(terraform output -raw incident_severity_description)
|
||||
EXPECTED_COLOR=$(terraform output -raw incident_severity_color)
|
||||
EXPECTED_ORDER=$(terraform output -raw incident_severity_order)
|
||||
|
||||
echo " Verifying incident severity resource via API..."
|
||||
echo " Resource ID: $RESOURCE_ID"
|
||||
|
||||
# Call API to get the resource
|
||||
RESPONSE=$(curl -s -X POST "${ONEUPTIME_URL}/api/incident-severity/${RESOURCE_ID}/get-item" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Apikey: $TF_VAR_api_key" \
|
||||
-H "projectid: $TF_VAR_project_id" \
|
||||
-d '{"select": {"_id": true, "name": true, "description": true, "color": true, "order": true}}')
|
||||
|
||||
# Check if response contains the resource
|
||||
API_ID=$(echo "$RESPONSE" | jq -r '._id // empty')
|
||||
if [ -z "$API_ID" ] || [ "$API_ID" = "null" ]; then
|
||||
echo " ✗ FAILED: Incident severity not found in API response"
|
||||
echo " Response: $RESPONSE"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Incident severity exists in API"
|
||||
|
||||
# Validate name
|
||||
API_NAME=$(echo "$RESPONSE" | jq -r '.name // empty')
|
||||
if [ "$API_NAME" != "$EXPECTED_NAME" ]; then
|
||||
echo " ✗ FAILED: Name mismatch - Expected: '$EXPECTED_NAME', Got: '$API_NAME'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Name matches: $API_NAME"
|
||||
|
||||
# Validate description
|
||||
API_DESCRIPTION=$(echo "$RESPONSE" | jq -r '.description // empty')
|
||||
if [ "$API_DESCRIPTION" != "$EXPECTED_DESCRIPTION" ]; then
|
||||
echo " ✗ FAILED: Description mismatch - Expected: '$EXPECTED_DESCRIPTION', Got: '$API_DESCRIPTION'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Description matches: $API_DESCRIPTION"
|
||||
|
||||
# Validate color
|
||||
API_COLOR=$(echo "$RESPONSE" | jq -r '.color // empty')
|
||||
if [ "$API_COLOR" != "$EXPECTED_COLOR" ]; then
|
||||
echo " ✗ FAILED: Color mismatch - Expected: '$EXPECTED_COLOR', Got: '$API_COLOR'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Color matches: $API_COLOR"
|
||||
|
||||
# Validate order
|
||||
API_ORDER=$(echo "$RESPONSE" | jq -r '.order // empty')
|
||||
if [ "$API_ORDER" != "$EXPECTED_ORDER" ]; then
|
||||
echo " ✗ FAILED: Order mismatch - Expected: '$EXPECTED_ORDER', Got: '$API_ORDER'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Order matches: $API_ORDER"
|
||||
|
||||
echo " ✓ All incident severity validations passed"
|
||||
46
E2E/Terraform/e2e-tests/tests/04-incident-state/main.tf
Normal file
46
E2E/Terraform/e2e-tests/tests/04-incident-state/main.tf
Normal file
@@ -0,0 +1,46 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
oneuptime = {
|
||||
source = "oneuptime/oneuptime"
|
||||
version = "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "oneuptime" {
|
||||
oneuptime_url = var.oneuptime_url
|
||||
api_key = var.api_key
|
||||
}
|
||||
|
||||
resource "oneuptime_incident_state" "test" {
|
||||
project_id = var.project_id
|
||||
name = "terraform-e2e-state-${formatdate("YYYYMMDDhhmmss", timestamp())}"
|
||||
description = "Incident state created by Terraform E2E tests"
|
||||
color = "#0000FF"
|
||||
order = 99
|
||||
}
|
||||
|
||||
output "incident_state_id" {
|
||||
value = oneuptime_incident_state.test.id
|
||||
description = "ID of the created incident state"
|
||||
}
|
||||
|
||||
output "incident_state_name" {
|
||||
value = oneuptime_incident_state.test.name
|
||||
description = "Name of the created incident state"
|
||||
}
|
||||
|
||||
output "incident_state_description" {
|
||||
value = oneuptime_incident_state.test.description
|
||||
description = "Description of the created incident state"
|
||||
}
|
||||
|
||||
output "incident_state_color" {
|
||||
value = oneuptime_incident_state.test.color
|
||||
description = "Color of the created incident state"
|
||||
}
|
||||
|
||||
output "incident_state_order" {
|
||||
value = oneuptime_incident_state.test.order
|
||||
description = "Order of the created incident state"
|
||||
}
|
||||
15
E2E/Terraform/e2e-tests/tests/04-incident-state/variables.tf
Normal file
15
E2E/Terraform/e2e-tests/tests/04-incident-state/variables.tf
Normal file
@@ -0,0 +1,15 @@
|
||||
variable "oneuptime_url" {
|
||||
type = string
|
||||
description = "OneUptime API URL"
|
||||
}
|
||||
|
||||
variable "api_key" {
|
||||
type = string
|
||||
description = "OneUptime API Key"
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "project_id" {
|
||||
type = string
|
||||
description = "OneUptime Project ID"
|
||||
}
|
||||
65
E2E/Terraform/e2e-tests/tests/04-incident-state/verify.sh
Executable file
65
E2E/Terraform/e2e-tests/tests/04-incident-state/verify.sh
Executable file
@@ -0,0 +1,65 @@
|
||||
#!/bin/bash
|
||||
# Verify script for 04-incident-state test
|
||||
# Validates that the incident state resource was created correctly via API
|
||||
|
||||
set -e
|
||||
|
||||
# Get terraform outputs
|
||||
RESOURCE_ID=$(terraform output -raw incident_state_id)
|
||||
EXPECTED_NAME=$(terraform output -raw incident_state_name)
|
||||
EXPECTED_DESCRIPTION=$(terraform output -raw incident_state_description)
|
||||
EXPECTED_COLOR=$(terraform output -raw incident_state_color)
|
||||
EXPECTED_ORDER=$(terraform output -raw incident_state_order)
|
||||
|
||||
echo " Verifying incident state resource via API..."
|
||||
echo " Resource ID: $RESOURCE_ID"
|
||||
|
||||
# Call API to get the resource
|
||||
RESPONSE=$(curl -s -X POST "${ONEUPTIME_URL}/api/incident-state/${RESOURCE_ID}/get-item" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Apikey: $TF_VAR_api_key" \
|
||||
-H "projectid: $TF_VAR_project_id" \
|
||||
-d '{"select": {"_id": true, "name": true, "description": true, "color": true, "order": true}}')
|
||||
|
||||
# Check if response contains the resource
|
||||
API_ID=$(echo "$RESPONSE" | jq -r '._id // empty')
|
||||
if [ -z "$API_ID" ] || [ "$API_ID" = "null" ]; then
|
||||
echo " ✗ FAILED: Incident state not found in API response"
|
||||
echo " Response: $RESPONSE"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Incident state exists in API"
|
||||
|
||||
# Validate name
|
||||
API_NAME=$(echo "$RESPONSE" | jq -r '.name // empty')
|
||||
if [ "$API_NAME" != "$EXPECTED_NAME" ]; then
|
||||
echo " ✗ FAILED: Name mismatch - Expected: '$EXPECTED_NAME', Got: '$API_NAME'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Name matches: $API_NAME"
|
||||
|
||||
# Validate description
|
||||
API_DESCRIPTION=$(echo "$RESPONSE" | jq -r '.description // empty')
|
||||
if [ "$API_DESCRIPTION" != "$EXPECTED_DESCRIPTION" ]; then
|
||||
echo " ✗ FAILED: Description mismatch - Expected: '$EXPECTED_DESCRIPTION', Got: '$API_DESCRIPTION'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Description matches: $API_DESCRIPTION"
|
||||
|
||||
# Validate color
|
||||
API_COLOR=$(echo "$RESPONSE" | jq -r '.color // empty')
|
||||
if [ "$API_COLOR" != "$EXPECTED_COLOR" ]; then
|
||||
echo " ✗ FAILED: Color mismatch - Expected: '$EXPECTED_COLOR', Got: '$API_COLOR'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Color matches: $API_COLOR"
|
||||
|
||||
# Validate order
|
||||
API_ORDER=$(echo "$RESPONSE" | jq -r '.order // empty')
|
||||
if [ "$API_ORDER" != "$EXPECTED_ORDER" ]; then
|
||||
echo " ✗ FAILED: Order mismatch - Expected: '$EXPECTED_ORDER', Got: '$API_ORDER'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Order matches: $API_ORDER"
|
||||
|
||||
echo " ✓ All incident state validations passed"
|
||||
64
E2E/Terraform/e2e-tests/tests/05-status-page/main.tf
Normal file
64
E2E/Terraform/e2e-tests/tests/05-status-page/main.tf
Normal file
@@ -0,0 +1,64 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
oneuptime = {
|
||||
source = "oneuptime/oneuptime"
|
||||
version = "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "oneuptime" {
|
||||
oneuptime_url = var.oneuptime_url
|
||||
api_key = var.api_key
|
||||
}
|
||||
|
||||
resource "oneuptime_status_page" "test" {
|
||||
project_id = var.project_id
|
||||
name = "terraform-e2e-statuspage-${formatdate("YYYYMMDDhhmmss", timestamp())}"
|
||||
description = "Status page created by Terraform E2E tests"
|
||||
page_title = "Terraform Test Status"
|
||||
page_description = "This is a test status page"
|
||||
is_public_status_page = false
|
||||
enable_email_subscribers = false
|
||||
enable_sms_subscribers = false
|
||||
}
|
||||
|
||||
output "status_page_id" {
|
||||
value = oneuptime_status_page.test.id
|
||||
description = "ID of the created status page"
|
||||
}
|
||||
|
||||
output "status_page_name" {
|
||||
value = oneuptime_status_page.test.name
|
||||
description = "Name of the created status page"
|
||||
}
|
||||
|
||||
output "status_page_description" {
|
||||
value = oneuptime_status_page.test.description
|
||||
description = "Description of the created status page"
|
||||
}
|
||||
|
||||
output "status_page_page_title" {
|
||||
value = oneuptime_status_page.test.page_title
|
||||
description = "Page title of the created status page"
|
||||
}
|
||||
|
||||
output "status_page_page_description" {
|
||||
value = oneuptime_status_page.test.page_description
|
||||
description = "Page description of the created status page"
|
||||
}
|
||||
|
||||
output "status_page_is_public_status_page" {
|
||||
value = oneuptime_status_page.test.is_public_status_page
|
||||
description = "Whether the status page is public"
|
||||
}
|
||||
|
||||
output "status_page_enable_email_subscribers" {
|
||||
value = oneuptime_status_page.test.enable_email_subscribers
|
||||
description = "Whether email subscribers are enabled"
|
||||
}
|
||||
|
||||
output "status_page_enable_sms_subscribers" {
|
||||
value = oneuptime_status_page.test.enable_sms_subscribers
|
||||
description = "Whether SMS subscribers are enabled"
|
||||
}
|
||||
15
E2E/Terraform/e2e-tests/tests/05-status-page/variables.tf
Normal file
15
E2E/Terraform/e2e-tests/tests/05-status-page/variables.tf
Normal file
@@ -0,0 +1,15 @@
|
||||
variable "oneuptime_url" {
|
||||
type = string
|
||||
description = "OneUptime API URL"
|
||||
}
|
||||
|
||||
variable "api_key" {
|
||||
type = string
|
||||
description = "OneUptime API Key"
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "project_id" {
|
||||
type = string
|
||||
description = "OneUptime Project ID"
|
||||
}
|
||||
92
E2E/Terraform/e2e-tests/tests/05-status-page/verify.sh
Executable file
92
E2E/Terraform/e2e-tests/tests/05-status-page/verify.sh
Executable file
@@ -0,0 +1,92 @@
|
||||
#!/bin/bash
|
||||
# Verify script for 05-status-page test
|
||||
# Validates that the status page resource was created correctly via API
|
||||
|
||||
set -e
|
||||
|
||||
# Get terraform outputs
|
||||
RESOURCE_ID=$(terraform output -raw status_page_id)
|
||||
EXPECTED_NAME=$(terraform output -raw status_page_name)
|
||||
EXPECTED_DESCRIPTION=$(terraform output -raw status_page_description)
|
||||
EXPECTED_PAGE_TITLE=$(terraform output -raw status_page_page_title)
|
||||
EXPECTED_PAGE_DESCRIPTION=$(terraform output -raw status_page_page_description)
|
||||
EXPECTED_IS_PUBLIC=$(terraform output -raw status_page_is_public_status_page)
|
||||
EXPECTED_EMAIL_SUBSCRIBERS=$(terraform output -raw status_page_enable_email_subscribers)
|
||||
EXPECTED_SMS_SUBSCRIBERS=$(terraform output -raw status_page_enable_sms_subscribers)
|
||||
|
||||
echo " Verifying status page resource via API..."
|
||||
echo " Resource ID: $RESOURCE_ID"
|
||||
|
||||
# Call API to get the resource
|
||||
RESPONSE=$(curl -s -X POST "${ONEUPTIME_URL}/api/status-page/${RESOURCE_ID}/get-item" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Apikey: $TF_VAR_api_key" \
|
||||
-H "projectid: $TF_VAR_project_id" \
|
||||
-d '{"select": {"_id": true, "name": true, "description": true, "pageTitle": true, "pageDescription": true, "isPublicStatusPage": true, "enableEmailSubscribers": true, "enableSmsSubscribers": true}}')
|
||||
|
||||
# Check if response contains the resource
|
||||
API_ID=$(echo "$RESPONSE" | jq -r '._id // empty')
|
||||
if [ -z "$API_ID" ] || [ "$API_ID" = "null" ]; then
|
||||
echo " ✗ FAILED: Status page not found in API response"
|
||||
echo " Response: $RESPONSE"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Status page exists in API"
|
||||
|
||||
# Validate name
|
||||
API_NAME=$(echo "$RESPONSE" | jq -r '.name // empty')
|
||||
if [ "$API_NAME" != "$EXPECTED_NAME" ]; then
|
||||
echo " ✗ FAILED: Name mismatch - Expected: '$EXPECTED_NAME', Got: '$API_NAME'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Name matches: $API_NAME"
|
||||
|
||||
# Validate description
|
||||
API_DESCRIPTION=$(echo "$RESPONSE" | jq -r '.description // empty')
|
||||
if [ "$API_DESCRIPTION" != "$EXPECTED_DESCRIPTION" ]; then
|
||||
echo " ✗ FAILED: Description mismatch - Expected: '$EXPECTED_DESCRIPTION', Got: '$API_DESCRIPTION'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Description matches: $API_DESCRIPTION"
|
||||
|
||||
# Validate pageTitle
|
||||
API_PAGE_TITLE=$(echo "$RESPONSE" | jq -r '.pageTitle // empty')
|
||||
if [ "$API_PAGE_TITLE" != "$EXPECTED_PAGE_TITLE" ]; then
|
||||
echo " ✗ FAILED: Page title mismatch - Expected: '$EXPECTED_PAGE_TITLE', Got: '$API_PAGE_TITLE'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Page title matches: $API_PAGE_TITLE"
|
||||
|
||||
# Validate pageDescription
|
||||
API_PAGE_DESCRIPTION=$(echo "$RESPONSE" | jq -r '.pageDescription // empty')
|
||||
if [ "$API_PAGE_DESCRIPTION" != "$EXPECTED_PAGE_DESCRIPTION" ]; then
|
||||
echo " ✗ FAILED: Page description mismatch - Expected: '$EXPECTED_PAGE_DESCRIPTION', Got: '$API_PAGE_DESCRIPTION'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Page description matches: $API_PAGE_DESCRIPTION"
|
||||
|
||||
# Validate isPublicStatusPage
|
||||
API_IS_PUBLIC=$(echo "$RESPONSE" | jq -r '.isPublicStatusPage // empty')
|
||||
if [ "$API_IS_PUBLIC" != "$EXPECTED_IS_PUBLIC" ]; then
|
||||
echo " ✗ FAILED: isPublicStatusPage mismatch - Expected: '$EXPECTED_IS_PUBLIC', Got: '$API_IS_PUBLIC'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ isPublicStatusPage matches: $API_IS_PUBLIC"
|
||||
|
||||
# Validate enableEmailSubscribers
|
||||
API_EMAIL_SUBSCRIBERS=$(echo "$RESPONSE" | jq -r '.enableEmailSubscribers // empty')
|
||||
if [ "$API_EMAIL_SUBSCRIBERS" != "$EXPECTED_EMAIL_SUBSCRIBERS" ]; then
|
||||
echo " ✗ FAILED: enableEmailSubscribers mismatch - Expected: '$EXPECTED_EMAIL_SUBSCRIBERS', Got: '$API_EMAIL_SUBSCRIBERS'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ enableEmailSubscribers matches: $API_EMAIL_SUBSCRIBERS"
|
||||
|
||||
# Validate enableSmsSubscribers
|
||||
API_SMS_SUBSCRIBERS=$(echo "$RESPONSE" | jq -r '.enableSmsSubscribers // empty')
|
||||
if [ "$API_SMS_SUBSCRIBERS" != "$EXPECTED_SMS_SUBSCRIBERS" ]; then
|
||||
echo " ✗ FAILED: enableSmsSubscribers mismatch - Expected: '$EXPECTED_SMS_SUBSCRIBERS', Got: '$API_SMS_SUBSCRIBERS'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ enableSmsSubscribers matches: $API_SMS_SUBSCRIBERS"
|
||||
|
||||
echo " ✓ All status page validations passed"
|
||||
46
E2E/Terraform/e2e-tests/tests/06-alert-severity/main.tf
Normal file
46
E2E/Terraform/e2e-tests/tests/06-alert-severity/main.tf
Normal file
@@ -0,0 +1,46 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
oneuptime = {
|
||||
source = "oneuptime/oneuptime"
|
||||
version = "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "oneuptime" {
|
||||
oneuptime_url = var.oneuptime_url
|
||||
api_key = var.api_key
|
||||
}
|
||||
|
||||
resource "oneuptime_alert_severity" "test" {
|
||||
project_id = var.project_id
|
||||
name = "terraform-e2e-alert-sev-${formatdate("YYYYMMDDhhmmss", timestamp())}"
|
||||
description = "Alert severity created by Terraform E2E tests"
|
||||
color = "#FF0000"
|
||||
order = 99
|
||||
}
|
||||
|
||||
output "alert_severity_id" {
|
||||
value = oneuptime_alert_severity.test.id
|
||||
description = "ID of the created alert severity"
|
||||
}
|
||||
|
||||
output "alert_severity_name" {
|
||||
value = oneuptime_alert_severity.test.name
|
||||
description = "Name of the created alert severity"
|
||||
}
|
||||
|
||||
output "alert_severity_description" {
|
||||
value = oneuptime_alert_severity.test.description
|
||||
description = "Description of the created alert severity"
|
||||
}
|
||||
|
||||
output "alert_severity_color" {
|
||||
value = oneuptime_alert_severity.test.color
|
||||
description = "Color of the created alert severity"
|
||||
}
|
||||
|
||||
output "alert_severity_order" {
|
||||
value = oneuptime_alert_severity.test.order
|
||||
description = "Order of the created alert severity"
|
||||
}
|
||||
15
E2E/Terraform/e2e-tests/tests/06-alert-severity/variables.tf
Normal file
15
E2E/Terraform/e2e-tests/tests/06-alert-severity/variables.tf
Normal file
@@ -0,0 +1,15 @@
|
||||
variable "oneuptime_url" {
|
||||
type = string
|
||||
description = "OneUptime API URL"
|
||||
}
|
||||
|
||||
variable "api_key" {
|
||||
type = string
|
||||
description = "OneUptime API Key"
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "project_id" {
|
||||
type = string
|
||||
description = "OneUptime Project ID"
|
||||
}
|
||||
65
E2E/Terraform/e2e-tests/tests/06-alert-severity/verify.sh
Executable file
65
E2E/Terraform/e2e-tests/tests/06-alert-severity/verify.sh
Executable file
@@ -0,0 +1,65 @@
|
||||
#!/bin/bash
|
||||
# Verify script for 06-alert-severity test
|
||||
# Validates that the alert severity resource was created correctly via API
|
||||
|
||||
set -e
|
||||
|
||||
# Get terraform outputs
|
||||
RESOURCE_ID=$(terraform output -raw alert_severity_id)
|
||||
EXPECTED_NAME=$(terraform output -raw alert_severity_name)
|
||||
EXPECTED_DESCRIPTION=$(terraform output -raw alert_severity_description)
|
||||
EXPECTED_COLOR=$(terraform output -raw alert_severity_color)
|
||||
EXPECTED_ORDER=$(terraform output -raw alert_severity_order)
|
||||
|
||||
echo " Verifying alert severity resource via API..."
|
||||
echo " Resource ID: $RESOURCE_ID"
|
||||
|
||||
# Call API to get the resource
|
||||
RESPONSE=$(curl -s -X POST "${ONEUPTIME_URL}/api/alert-severity/${RESOURCE_ID}/get-item" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Apikey: $TF_VAR_api_key" \
|
||||
-H "projectid: $TF_VAR_project_id" \
|
||||
-d '{"select": {"_id": true, "name": true, "description": true, "color": true, "order": true}}')
|
||||
|
||||
# Check if response contains the resource
|
||||
API_ID=$(echo "$RESPONSE" | jq -r '._id // empty')
|
||||
if [ -z "$API_ID" ] || [ "$API_ID" = "null" ]; then
|
||||
echo " ✗ FAILED: Alert severity not found in API response"
|
||||
echo " Response: $RESPONSE"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Alert severity exists in API"
|
||||
|
||||
# Validate name
|
||||
API_NAME=$(echo "$RESPONSE" | jq -r '.name // empty')
|
||||
if [ "$API_NAME" != "$EXPECTED_NAME" ]; then
|
||||
echo " ✗ FAILED: Name mismatch - Expected: '$EXPECTED_NAME', Got: '$API_NAME'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Name matches: $API_NAME"
|
||||
|
||||
# Validate description
|
||||
API_DESCRIPTION=$(echo "$RESPONSE" | jq -r '.description // empty')
|
||||
if [ "$API_DESCRIPTION" != "$EXPECTED_DESCRIPTION" ]; then
|
||||
echo " ✗ FAILED: Description mismatch - Expected: '$EXPECTED_DESCRIPTION', Got: '$API_DESCRIPTION'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Description matches: $API_DESCRIPTION"
|
||||
|
||||
# Validate color
|
||||
API_COLOR=$(echo "$RESPONSE" | jq -r '.color // empty')
|
||||
if [ "$API_COLOR" != "$EXPECTED_COLOR" ]; then
|
||||
echo " ✗ FAILED: Color mismatch - Expected: '$EXPECTED_COLOR', Got: '$API_COLOR'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Color matches: $API_COLOR"
|
||||
|
||||
# Validate order
|
||||
API_ORDER=$(echo "$RESPONSE" | jq -r '.order // empty')
|
||||
if [ "$API_ORDER" != "$EXPECTED_ORDER" ]; then
|
||||
echo " ✗ FAILED: Order mismatch - Expected: '$EXPECTED_ORDER', Got: '$API_ORDER'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Order matches: $API_ORDER"
|
||||
|
||||
echo " ✓ All alert severity validations passed"
|
||||
46
E2E/Terraform/e2e-tests/tests/07-alert-state/main.tf
Normal file
46
E2E/Terraform/e2e-tests/tests/07-alert-state/main.tf
Normal file
@@ -0,0 +1,46 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
oneuptime = {
|
||||
source = "oneuptime/oneuptime"
|
||||
version = "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "oneuptime" {
|
||||
oneuptime_url = var.oneuptime_url
|
||||
api_key = var.api_key
|
||||
}
|
||||
|
||||
resource "oneuptime_alert_state" "test" {
|
||||
project_id = var.project_id
|
||||
name = "terraform-e2e-alert-state-${formatdate("YYYYMMDDhhmmss", timestamp())}"
|
||||
description = "Alert state created by Terraform E2E tests"
|
||||
color = "#800080"
|
||||
order = 99
|
||||
}
|
||||
|
||||
output "alert_state_id" {
|
||||
value = oneuptime_alert_state.test.id
|
||||
description = "ID of the created alert state"
|
||||
}
|
||||
|
||||
output "alert_state_name" {
|
||||
value = oneuptime_alert_state.test.name
|
||||
description = "Name of the created alert state"
|
||||
}
|
||||
|
||||
output "alert_state_description" {
|
||||
value = oneuptime_alert_state.test.description
|
||||
description = "Description of the created alert state"
|
||||
}
|
||||
|
||||
output "alert_state_color" {
|
||||
value = oneuptime_alert_state.test.color
|
||||
description = "Color of the created alert state"
|
||||
}
|
||||
|
||||
output "alert_state_order" {
|
||||
value = oneuptime_alert_state.test.order
|
||||
description = "Order of the created alert state"
|
||||
}
|
||||
15
E2E/Terraform/e2e-tests/tests/07-alert-state/variables.tf
Normal file
15
E2E/Terraform/e2e-tests/tests/07-alert-state/variables.tf
Normal file
@@ -0,0 +1,15 @@
|
||||
variable "oneuptime_url" {
|
||||
type = string
|
||||
description = "OneUptime API URL"
|
||||
}
|
||||
|
||||
variable "api_key" {
|
||||
type = string
|
||||
description = "OneUptime API Key"
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "project_id" {
|
||||
type = string
|
||||
description = "OneUptime Project ID"
|
||||
}
|
||||
65
E2E/Terraform/e2e-tests/tests/07-alert-state/verify.sh
Executable file
65
E2E/Terraform/e2e-tests/tests/07-alert-state/verify.sh
Executable file
@@ -0,0 +1,65 @@
|
||||
#!/bin/bash
|
||||
# Verify script for 07-alert-state test
|
||||
# Validates that the alert state resource was created correctly via API
|
||||
|
||||
set -e
|
||||
|
||||
# Get terraform outputs
|
||||
RESOURCE_ID=$(terraform output -raw alert_state_id)
|
||||
EXPECTED_NAME=$(terraform output -raw alert_state_name)
|
||||
EXPECTED_DESCRIPTION=$(terraform output -raw alert_state_description)
|
||||
EXPECTED_COLOR=$(terraform output -raw alert_state_color)
|
||||
EXPECTED_ORDER=$(terraform output -raw alert_state_order)
|
||||
|
||||
echo " Verifying alert state resource via API..."
|
||||
echo " Resource ID: $RESOURCE_ID"
|
||||
|
||||
# Call API to get the resource
|
||||
RESPONSE=$(curl -s -X POST "${ONEUPTIME_URL}/api/alert-state/${RESOURCE_ID}/get-item" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Apikey: $TF_VAR_api_key" \
|
||||
-H "projectid: $TF_VAR_project_id" \
|
||||
-d '{"select": {"_id": true, "name": true, "description": true, "color": true, "order": true}}')
|
||||
|
||||
# Check if response contains the resource
|
||||
API_ID=$(echo "$RESPONSE" | jq -r '._id // empty')
|
||||
if [ -z "$API_ID" ] || [ "$API_ID" = "null" ]; then
|
||||
echo " ✗ FAILED: Alert state not found in API response"
|
||||
echo " Response: $RESPONSE"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Alert state exists in API"
|
||||
|
||||
# Validate name
|
||||
API_NAME=$(echo "$RESPONSE" | jq -r '.name // empty')
|
||||
if [ "$API_NAME" != "$EXPECTED_NAME" ]; then
|
||||
echo " ✗ FAILED: Name mismatch - Expected: '$EXPECTED_NAME', Got: '$API_NAME'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Name matches: $API_NAME"
|
||||
|
||||
# Validate description
|
||||
API_DESCRIPTION=$(echo "$RESPONSE" | jq -r '.description // empty')
|
||||
if [ "$API_DESCRIPTION" != "$EXPECTED_DESCRIPTION" ]; then
|
||||
echo " ✗ FAILED: Description mismatch - Expected: '$EXPECTED_DESCRIPTION', Got: '$API_DESCRIPTION'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Description matches: $API_DESCRIPTION"
|
||||
|
||||
# Validate color
|
||||
API_COLOR=$(echo "$RESPONSE" | jq -r '.color // empty')
|
||||
if [ "$API_COLOR" != "$EXPECTED_COLOR" ]; then
|
||||
echo " ✗ FAILED: Color mismatch - Expected: '$EXPECTED_COLOR', Got: '$API_COLOR'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Color matches: $API_COLOR"
|
||||
|
||||
# Validate order
|
||||
API_ORDER=$(echo "$RESPONSE" | jq -r '.order // empty')
|
||||
if [ "$API_ORDER" != "$EXPECTED_ORDER" ]; then
|
||||
echo " ✗ FAILED: Order mismatch - Expected: '$EXPECTED_ORDER', Got: '$API_ORDER'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Order matches: $API_ORDER"
|
||||
|
||||
echo " ✓ All alert state validations passed"
|
||||
42
E2E/Terraform/e2e-tests/tests/08-probe/main.tf
Normal file
42
E2E/Terraform/e2e-tests/tests/08-probe/main.tf
Normal file
@@ -0,0 +1,42 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
oneuptime = {
|
||||
source = "oneuptime/oneuptime"
|
||||
version = "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "oneuptime" {
|
||||
oneuptime_url = var.oneuptime_url
|
||||
api_key = var.api_key
|
||||
}
|
||||
|
||||
# Test for GitHub Issue #2228: probe_version field produces inconsistent result after apply
|
||||
# The probe_version should remain as "1.0.0" and not be converted to JSON like {"_type":"Version","value":"1.0.0"}
|
||||
resource "oneuptime_probe" "test" {
|
||||
project_id = var.project_id
|
||||
key = "terraform-e2e-probe-key-${formatdate("YYYYMMDDhhmmss", timestamp())}"
|
||||
name = "terraform-e2e-probe-${formatdate("YYYYMMDDhhmmss", timestamp())}"
|
||||
probe_version = "1.0.0"
|
||||
}
|
||||
|
||||
output "probe_id" {
|
||||
value = oneuptime_probe.test.id
|
||||
description = "ID of the created probe"
|
||||
}
|
||||
|
||||
output "probe_key" {
|
||||
value = oneuptime_probe.test.key
|
||||
description = "Key of the created probe"
|
||||
}
|
||||
|
||||
output "probe_name" {
|
||||
value = oneuptime_probe.test.name
|
||||
description = "Name of the created probe"
|
||||
}
|
||||
|
||||
output "probe_version" {
|
||||
value = oneuptime_probe.test.probe_version
|
||||
description = "Version of the created probe"
|
||||
}
|
||||
15
E2E/Terraform/e2e-tests/tests/08-probe/variables.tf
Normal file
15
E2E/Terraform/e2e-tests/tests/08-probe/variables.tf
Normal file
@@ -0,0 +1,15 @@
|
||||
variable "oneuptime_url" {
|
||||
type = string
|
||||
description = "OneUptime API URL"
|
||||
}
|
||||
|
||||
variable "api_key" {
|
||||
type = string
|
||||
description = "OneUptime API Key"
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "project_id" {
|
||||
type = string
|
||||
description = "OneUptime Project ID"
|
||||
}
|
||||
63
E2E/Terraform/e2e-tests/tests/08-probe/verify.sh
Executable file
63
E2E/Terraform/e2e-tests/tests/08-probe/verify.sh
Executable file
@@ -0,0 +1,63 @@
|
||||
#!/bin/bash
|
||||
# Verify script for 08-probe test
|
||||
# Validates that the probe resource was created correctly via API
|
||||
# Also validates GitHub Issue #2228: probe_version field consistency
|
||||
|
||||
set -e
|
||||
|
||||
# Get terraform outputs
|
||||
RESOURCE_ID=$(terraform output -raw probe_id)
|
||||
EXPECTED_KEY=$(terraform output -raw probe_key)
|
||||
EXPECTED_NAME=$(terraform output -raw probe_name)
|
||||
EXPECTED_VERSION=$(terraform output -raw probe_version)
|
||||
|
||||
echo " Verifying probe resource via API..."
|
||||
echo " Resource ID: $RESOURCE_ID"
|
||||
|
||||
# Call API to get the resource
|
||||
RESPONSE=$(curl -s -X POST "${ONEUPTIME_URL}/api/probe/${RESOURCE_ID}/get-item" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Apikey: $TF_VAR_api_key" \
|
||||
-H "projectid: $TF_VAR_project_id" \
|
||||
-d '{"select": {"_id": true, "key": true, "name": true, "probeVersion": true}}')
|
||||
|
||||
# Check if response contains the resource
|
||||
API_ID=$(echo "$RESPONSE" | jq -r '._id // empty')
|
||||
if [ -z "$API_ID" ] || [ "$API_ID" = "null" ]; then
|
||||
echo " ✗ FAILED: Probe not found in API response"
|
||||
echo " Response: $RESPONSE"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Probe exists in API"
|
||||
|
||||
# Validate key
|
||||
API_KEY=$(echo "$RESPONSE" | jq -r '.key // empty')
|
||||
if [ "$API_KEY" != "$EXPECTED_KEY" ]; then
|
||||
echo " ✗ FAILED: Key mismatch - Expected: '$EXPECTED_KEY', Got: '$API_KEY'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Key matches: $API_KEY"
|
||||
|
||||
# Validate name
|
||||
API_NAME=$(echo "$RESPONSE" | jq -r '.name // empty')
|
||||
if [ "$API_NAME" != "$EXPECTED_NAME" ]; then
|
||||
echo " ✗ FAILED: Name mismatch - Expected: '$EXPECTED_NAME', Got: '$API_NAME'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Name matches: $API_NAME"
|
||||
|
||||
# Validate probeVersion - handle wrapper object format {"_type":"Version","value":"1.0.0"}
|
||||
API_VERSION_RAW=$(echo "$RESPONSE" | jq '.probeVersion')
|
||||
if echo "$API_VERSION_RAW" | jq -e '.value' > /dev/null 2>&1; then
|
||||
API_VERSION=$(echo "$API_VERSION_RAW" | jq -r '.value')
|
||||
else
|
||||
API_VERSION=$(echo "$API_VERSION_RAW" | jq -r '.')
|
||||
fi
|
||||
|
||||
if [ "$API_VERSION" != "$EXPECTED_VERSION" ]; then
|
||||
echo " ✗ FAILED: Probe version mismatch - Expected: '$EXPECTED_VERSION', Got: '$API_VERSION'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Probe version matches: $API_VERSION (Issue #2228 validated)"
|
||||
|
||||
echo " ✓ All probe validations passed"
|
||||
38
E2E/Terraform/e2e-tests/tests/09-label-crud/main.tf
Normal file
38
E2E/Terraform/e2e-tests/tests/09-label-crud/main.tf
Normal file
@@ -0,0 +1,38 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
oneuptime = {
|
||||
source = "oneuptime/oneuptime"
|
||||
version = "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "oneuptime" {
|
||||
oneuptime_url = var.oneuptime_url
|
||||
api_key = var.api_key
|
||||
}
|
||||
|
||||
# Comprehensive CRUD test for label resource
|
||||
# This test creates a label, then updates can be applied via variable changes
|
||||
resource "oneuptime_label" "test" {
|
||||
project_id = var.project_id
|
||||
name = var.label_name
|
||||
description = var.label_description
|
||||
color = var.label_color
|
||||
}
|
||||
|
||||
output "label_id" {
|
||||
value = oneuptime_label.test.id
|
||||
}
|
||||
|
||||
output "label_name" {
|
||||
value = oneuptime_label.test.name
|
||||
}
|
||||
|
||||
output "label_description" {
|
||||
value = oneuptime_label.test.description
|
||||
}
|
||||
|
||||
output "label_color" {
|
||||
value = oneuptime_label.test.color
|
||||
}
|
||||
33
E2E/Terraform/e2e-tests/tests/09-label-crud/variables.tf
Normal file
33
E2E/Terraform/e2e-tests/tests/09-label-crud/variables.tf
Normal file
@@ -0,0 +1,33 @@
|
||||
variable "oneuptime_url" {
|
||||
type = string
|
||||
description = "OneUptime API URL"
|
||||
}
|
||||
|
||||
variable "api_key" {
|
||||
type = string
|
||||
description = "OneUptime API Key"
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "project_id" {
|
||||
type = string
|
||||
description = "OneUptime Project ID"
|
||||
}
|
||||
|
||||
variable "label_name" {
|
||||
type = string
|
||||
description = "Label name"
|
||||
default = "terraform-crud-test-label"
|
||||
}
|
||||
|
||||
variable "label_description" {
|
||||
type = string
|
||||
description = "Label description"
|
||||
default = "Initial description for CRUD test"
|
||||
}
|
||||
|
||||
variable "label_color" {
|
||||
type = string
|
||||
description = "Label color"
|
||||
default = "#FF0000"
|
||||
}
|
||||
56
E2E/Terraform/e2e-tests/tests/09-label-crud/verify.sh
Executable file
56
E2E/Terraform/e2e-tests/tests/09-label-crud/verify.sh
Executable file
@@ -0,0 +1,56 @@
|
||||
#!/bin/bash
|
||||
# Verify script for 09-label-crud test
|
||||
# Validates that the label CRUD operations work correctly via API
|
||||
|
||||
set -e
|
||||
|
||||
# Get terraform outputs
|
||||
RESOURCE_ID=$(terraform output -raw label_id)
|
||||
EXPECTED_NAME=$(terraform output -raw label_name)
|
||||
EXPECTED_DESCRIPTION=$(terraform output -raw label_description)
|
||||
EXPECTED_COLOR=$(terraform output -raw label_color)
|
||||
|
||||
echo " Verifying label CRUD resource via API..."
|
||||
echo " Resource ID: $RESOURCE_ID"
|
||||
|
||||
# Call API to get the resource
|
||||
RESPONSE=$(curl -s -X POST "${ONEUPTIME_URL}/api/label/${RESOURCE_ID}/get-item" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Apikey: $TF_VAR_api_key" \
|
||||
-H "projectid: $TF_VAR_project_id" \
|
||||
-d '{"select": {"_id": true, "name": true, "description": true, "color": true}}')
|
||||
|
||||
# Check if response contains the resource
|
||||
API_ID=$(echo "$RESPONSE" | jq -r '._id // empty')
|
||||
if [ -z "$API_ID" ] || [ "$API_ID" = "null" ]; then
|
||||
echo " ✗ FAILED: Label not found in API response"
|
||||
echo " Response: $RESPONSE"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Label exists in API"
|
||||
|
||||
# Validate name
|
||||
API_NAME=$(echo "$RESPONSE" | jq -r '.name // empty')
|
||||
if [ "$API_NAME" != "$EXPECTED_NAME" ]; then
|
||||
echo " ✗ FAILED: Name mismatch - Expected: '$EXPECTED_NAME', Got: '$API_NAME'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Name matches: $API_NAME"
|
||||
|
||||
# Validate description
|
||||
API_DESCRIPTION=$(echo "$RESPONSE" | jq -r '.description // empty')
|
||||
if [ "$API_DESCRIPTION" != "$EXPECTED_DESCRIPTION" ]; then
|
||||
echo " ✗ FAILED: Description mismatch - Expected: '$EXPECTED_DESCRIPTION', Got: '$API_DESCRIPTION'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Description matches: $API_DESCRIPTION"
|
||||
|
||||
# Validate color
|
||||
API_COLOR=$(echo "$RESPONSE" | jq -r '.color // empty')
|
||||
if [ "$API_COLOR" != "$EXPECTED_COLOR" ]; then
|
||||
echo " ✗ FAILED: Color mismatch - Expected: '$EXPECTED_COLOR', Got: '$API_COLOR'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Color matches: $API_COLOR"
|
||||
|
||||
echo " ✓ All label CRUD validations passed"
|
||||
47
E2E/Terraform/e2e-tests/tests/10-monitor-status-crud/main.tf
Normal file
47
E2E/Terraform/e2e-tests/tests/10-monitor-status-crud/main.tf
Normal file
@@ -0,0 +1,47 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
oneuptime = {
|
||||
source = "oneuptime/oneuptime"
|
||||
version = "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "oneuptime" {
|
||||
oneuptime_url = var.oneuptime_url
|
||||
api_key = var.api_key
|
||||
}
|
||||
|
||||
# Comprehensive CRUD test for monitor_status resource
|
||||
resource "oneuptime_monitor_status" "test" {
|
||||
project_id = var.project_id
|
||||
name = var.status_name
|
||||
description = var.status_description
|
||||
color = var.status_color
|
||||
priority = var.status_priority
|
||||
}
|
||||
|
||||
output "monitor_status_id" {
|
||||
value = oneuptime_monitor_status.test.id
|
||||
description = "ID of the created monitor status"
|
||||
}
|
||||
|
||||
output "monitor_status_name" {
|
||||
value = oneuptime_monitor_status.test.name
|
||||
description = "Name of the created monitor status"
|
||||
}
|
||||
|
||||
output "monitor_status_description" {
|
||||
value = oneuptime_monitor_status.test.description
|
||||
description = "Description of the created monitor status"
|
||||
}
|
||||
|
||||
output "monitor_status_color" {
|
||||
value = oneuptime_monitor_status.test.color
|
||||
description = "Color of the created monitor status"
|
||||
}
|
||||
|
||||
output "monitor_status_priority" {
|
||||
value = oneuptime_monitor_status.test.priority
|
||||
description = "Priority of the created monitor status"
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
variable "oneuptime_url" {
|
||||
type = string
|
||||
description = "OneUptime API URL"
|
||||
}
|
||||
|
||||
variable "api_key" {
|
||||
type = string
|
||||
description = "OneUptime API Key"
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "project_id" {
|
||||
type = string
|
||||
description = "OneUptime Project ID"
|
||||
}
|
||||
|
||||
variable "status_name" {
|
||||
type = string
|
||||
description = "Monitor status name"
|
||||
default = "terraform-crud-test-status"
|
||||
}
|
||||
|
||||
variable "status_description" {
|
||||
type = string
|
||||
description = "Monitor status description"
|
||||
default = "Initial description for CRUD test"
|
||||
}
|
||||
|
||||
variable "status_color" {
|
||||
type = string
|
||||
description = "Monitor status color"
|
||||
default = "#00FF00"
|
||||
}
|
||||
|
||||
variable "status_priority" {
|
||||
type = number
|
||||
description = "Monitor status priority"
|
||||
default = 100
|
||||
}
|
||||
65
E2E/Terraform/e2e-tests/tests/10-monitor-status-crud/verify.sh
Executable file
65
E2E/Terraform/e2e-tests/tests/10-monitor-status-crud/verify.sh
Executable file
@@ -0,0 +1,65 @@
|
||||
#!/bin/bash
|
||||
# Verify script for 10-monitor-status-crud test
|
||||
# Validates that the monitor status CRUD operations work correctly via API
|
||||
|
||||
set -e
|
||||
|
||||
# Get terraform outputs
|
||||
RESOURCE_ID=$(terraform output -raw monitor_status_id)
|
||||
EXPECTED_NAME=$(terraform output -raw monitor_status_name)
|
||||
EXPECTED_DESCRIPTION=$(terraform output -raw monitor_status_description)
|
||||
EXPECTED_COLOR=$(terraform output -raw monitor_status_color)
|
||||
EXPECTED_PRIORITY=$(terraform output -raw monitor_status_priority)
|
||||
|
||||
echo " Verifying monitor status CRUD resource via API..."
|
||||
echo " Resource ID: $RESOURCE_ID"
|
||||
|
||||
# Call API to get the resource
|
||||
RESPONSE=$(curl -s -X POST "${ONEUPTIME_URL}/api/monitor-status/${RESOURCE_ID}/get-item" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Apikey: $TF_VAR_api_key" \
|
||||
-H "projectid: $TF_VAR_project_id" \
|
||||
-d '{"select": {"_id": true, "name": true, "description": true, "color": true, "priority": true}}')
|
||||
|
||||
# Check if response contains the resource
|
||||
API_ID=$(echo "$RESPONSE" | jq -r '._id // empty')
|
||||
if [ -z "$API_ID" ] || [ "$API_ID" = "null" ]; then
|
||||
echo " ✗ FAILED: Monitor status not found in API response"
|
||||
echo " Response: $RESPONSE"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Monitor status exists in API"
|
||||
|
||||
# Validate name
|
||||
API_NAME=$(echo "$RESPONSE" | jq -r '.name // empty')
|
||||
if [ "$API_NAME" != "$EXPECTED_NAME" ]; then
|
||||
echo " ✗ FAILED: Name mismatch - Expected: '$EXPECTED_NAME', Got: '$API_NAME'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Name matches: $API_NAME"
|
||||
|
||||
# Validate description
|
||||
API_DESCRIPTION=$(echo "$RESPONSE" | jq -r '.description // empty')
|
||||
if [ "$API_DESCRIPTION" != "$EXPECTED_DESCRIPTION" ]; then
|
||||
echo " ✗ FAILED: Description mismatch - Expected: '$EXPECTED_DESCRIPTION', Got: '$API_DESCRIPTION'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Description matches: $API_DESCRIPTION"
|
||||
|
||||
# Validate color
|
||||
API_COLOR=$(echo "$RESPONSE" | jq -r '.color // empty')
|
||||
if [ "$API_COLOR" != "$EXPECTED_COLOR" ]; then
|
||||
echo " ✗ FAILED: Color mismatch - Expected: '$EXPECTED_COLOR', Got: '$API_COLOR'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Color matches: $API_COLOR"
|
||||
|
||||
# Validate priority
|
||||
API_PRIORITY=$(echo "$RESPONSE" | jq -r '.priority // empty')
|
||||
if [ "$API_PRIORITY" != "$EXPECTED_PRIORITY" ]; then
|
||||
echo " ✗ FAILED: Priority mismatch - Expected: '$EXPECTED_PRIORITY', Got: '$API_PRIORITY'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Priority matches: $API_PRIORITY"
|
||||
|
||||
echo " ✓ All monitor status CRUD validations passed"
|
||||
@@ -0,0 +1,47 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
oneuptime = {
|
||||
source = "oneuptime/oneuptime"
|
||||
version = "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "oneuptime" {
|
||||
oneuptime_url = var.oneuptime_url
|
||||
api_key = var.api_key
|
||||
}
|
||||
|
||||
# Comprehensive CRUD test for incident_severity resource
|
||||
resource "oneuptime_incident_severity" "test" {
|
||||
project_id = var.project_id
|
||||
name = var.severity_name
|
||||
description = var.severity_description
|
||||
color = var.severity_color
|
||||
order = var.severity_order
|
||||
}
|
||||
|
||||
output "incident_severity_id" {
|
||||
value = oneuptime_incident_severity.test.id
|
||||
description = "ID of the created incident severity"
|
||||
}
|
||||
|
||||
output "incident_severity_name" {
|
||||
value = oneuptime_incident_severity.test.name
|
||||
description = "Name of the created incident severity"
|
||||
}
|
||||
|
||||
output "incident_severity_description" {
|
||||
value = oneuptime_incident_severity.test.description
|
||||
description = "Description of the created incident severity"
|
||||
}
|
||||
|
||||
output "incident_severity_color" {
|
||||
value = oneuptime_incident_severity.test.color
|
||||
description = "Color of the created incident severity"
|
||||
}
|
||||
|
||||
output "incident_severity_order" {
|
||||
value = oneuptime_incident_severity.test.order
|
||||
description = "Order of the created incident severity"
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
variable "oneuptime_url" {
|
||||
type = string
|
||||
description = "OneUptime API URL"
|
||||
}
|
||||
|
||||
variable "api_key" {
|
||||
type = string
|
||||
description = "OneUptime API Key"
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "project_id" {
|
||||
type = string
|
||||
description = "OneUptime Project ID"
|
||||
}
|
||||
|
||||
variable "severity_name" {
|
||||
type = string
|
||||
description = "Incident severity name"
|
||||
default = "terraform-crud-test-severity"
|
||||
}
|
||||
|
||||
variable "severity_description" {
|
||||
type = string
|
||||
description = "Incident severity description"
|
||||
default = "Initial description for CRUD test"
|
||||
}
|
||||
|
||||
variable "severity_color" {
|
||||
type = string
|
||||
description = "Incident severity color"
|
||||
default = "#FFA500"
|
||||
}
|
||||
|
||||
variable "severity_order" {
|
||||
type = number
|
||||
description = "Incident severity order"
|
||||
default = 100
|
||||
}
|
||||
65
E2E/Terraform/e2e-tests/tests/11-incident-severity-crud/verify.sh
Executable file
65
E2E/Terraform/e2e-tests/tests/11-incident-severity-crud/verify.sh
Executable file
@@ -0,0 +1,65 @@
|
||||
#!/bin/bash
|
||||
# Verify script for 11-incident-severity-crud test
|
||||
# Validates that the incident severity CRUD operations work correctly via API
|
||||
|
||||
set -e
|
||||
|
||||
# Get terraform outputs
|
||||
RESOURCE_ID=$(terraform output -raw incident_severity_id)
|
||||
EXPECTED_NAME=$(terraform output -raw incident_severity_name)
|
||||
EXPECTED_DESCRIPTION=$(terraform output -raw incident_severity_description)
|
||||
EXPECTED_COLOR=$(terraform output -raw incident_severity_color)
|
||||
EXPECTED_ORDER=$(terraform output -raw incident_severity_order)
|
||||
|
||||
echo " Verifying incident severity CRUD resource via API..."
|
||||
echo " Resource ID: $RESOURCE_ID"
|
||||
|
||||
# Call API to get the resource
|
||||
RESPONSE=$(curl -s -X POST "${ONEUPTIME_URL}/api/incident-severity/${RESOURCE_ID}/get-item" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Apikey: $TF_VAR_api_key" \
|
||||
-H "projectid: $TF_VAR_project_id" \
|
||||
-d '{"select": {"_id": true, "name": true, "description": true, "color": true, "order": true}}')
|
||||
|
||||
# Check if response contains the resource
|
||||
API_ID=$(echo "$RESPONSE" | jq -r '._id // empty')
|
||||
if [ -z "$API_ID" ] || [ "$API_ID" = "null" ]; then
|
||||
echo " ✗ FAILED: Incident severity not found in API response"
|
||||
echo " Response: $RESPONSE"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Incident severity exists in API"
|
||||
|
||||
# Validate name
|
||||
API_NAME=$(echo "$RESPONSE" | jq -r '.name // empty')
|
||||
if [ "$API_NAME" != "$EXPECTED_NAME" ]; then
|
||||
echo " ✗ FAILED: Name mismatch - Expected: '$EXPECTED_NAME', Got: '$API_NAME'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Name matches: $API_NAME"
|
||||
|
||||
# Validate description
|
||||
API_DESCRIPTION=$(echo "$RESPONSE" | jq -r '.description // empty')
|
||||
if [ "$API_DESCRIPTION" != "$EXPECTED_DESCRIPTION" ]; then
|
||||
echo " ✗ FAILED: Description mismatch - Expected: '$EXPECTED_DESCRIPTION', Got: '$API_DESCRIPTION'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Description matches: $API_DESCRIPTION"
|
||||
|
||||
# Validate color
|
||||
API_COLOR=$(echo "$RESPONSE" | jq -r '.color // empty')
|
||||
if [ "$API_COLOR" != "$EXPECTED_COLOR" ]; then
|
||||
echo " ✗ FAILED: Color mismatch - Expected: '$EXPECTED_COLOR', Got: '$API_COLOR'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Color matches: $API_COLOR"
|
||||
|
||||
# Validate order
|
||||
API_ORDER=$(echo "$RESPONSE" | jq -r '.order // empty')
|
||||
if [ "$API_ORDER" != "$EXPECTED_ORDER" ]; then
|
||||
echo " ✗ FAILED: Order mismatch - Expected: '$EXPECTED_ORDER', Got: '$API_ORDER'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Order matches: $API_ORDER"
|
||||
|
||||
echo " ✓ All incident severity CRUD validations passed"
|
||||
96
E2E/Terraform/e2e-tests/tests/12-status-page-domain/main.tf
Normal file
96
E2E/Terraform/e2e-tests/tests/12-status-page-domain/main.tf
Normal file
@@ -0,0 +1,96 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
oneuptime = {
|
||||
source = "oneuptime/oneuptime"
|
||||
version = "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "oneuptime" {
|
||||
oneuptime_url = var.oneuptime_url
|
||||
api_key = var.api_key
|
||||
}
|
||||
|
||||
# First, create a domain (required for status_page_domain)
|
||||
# The domain must be verified before it can be used with status_page_domain
|
||||
# For test domains (.example.com), DNS verification is bypassed
|
||||
resource "oneuptime_domain" "test" {
|
||||
project_id = var.project_id
|
||||
domain = "status-page-domain-e2e-test.example.com"
|
||||
is_verified = true
|
||||
}
|
||||
|
||||
# Then, create a status page (required for status_page_domain)
|
||||
resource "oneuptime_status_page" "test" {
|
||||
project_id = var.project_id
|
||||
name = "Status Page Domain E2E Test"
|
||||
description = "Status page created by Terraform E2E tests"
|
||||
page_title = "Terraform Test Status"
|
||||
page_description = "This is a test status page"
|
||||
is_public_status_page = false
|
||||
enable_email_subscribers = false
|
||||
enable_sms_subscribers = false
|
||||
}
|
||||
|
||||
# Test status_page_domain resource
|
||||
# After fix for issue #2236:
|
||||
# - full_domain is computed (server generates from subdomain + domain)
|
||||
# - cname_verification_token is computed (server generates a UUID)
|
||||
resource "oneuptime_status_page_domain" "test" {
|
||||
project_id = var.project_id
|
||||
domain_id = oneuptime_domain.test.id
|
||||
status_page_id = oneuptime_status_page.test.id
|
||||
subdomain = "status"
|
||||
|
||||
# full_domain and cname_verification_token are NOT specified here
|
||||
# because they are server-generated computed fields
|
||||
}
|
||||
|
||||
output "status_page_domain_id" {
|
||||
value = oneuptime_status_page_domain.test.id
|
||||
description = "ID of the created status page domain"
|
||||
}
|
||||
|
||||
output "domain_id" {
|
||||
value = oneuptime_domain.test.id
|
||||
description = "ID of the created domain"
|
||||
}
|
||||
|
||||
output "status_page_id" {
|
||||
value = oneuptime_status_page.test.id
|
||||
description = "ID of the created status page"
|
||||
}
|
||||
|
||||
# Output the computed full_domain to verify it's returned by the API
|
||||
output "full_domain" {
|
||||
value = oneuptime_status_page_domain.test.full_domain
|
||||
description = "Full domain computed by the server (should be subdomain.domain)"
|
||||
}
|
||||
|
||||
output "subdomain" {
|
||||
value = oneuptime_status_page_domain.test.subdomain
|
||||
description = "Subdomain of the status page domain"
|
||||
}
|
||||
|
||||
# Domain resource outputs for API validation
|
||||
output "domain_name" {
|
||||
value = oneuptime_domain.test.domain
|
||||
description = "Domain name"
|
||||
}
|
||||
|
||||
output "domain_is_verified" {
|
||||
value = oneuptime_domain.test.is_verified
|
||||
description = "Whether the domain is verified"
|
||||
}
|
||||
|
||||
# Status page outputs for API validation
|
||||
output "status_page_name" {
|
||||
value = oneuptime_status_page.test.name
|
||||
description = "Name of the status page"
|
||||
}
|
||||
|
||||
output "status_page_description" {
|
||||
value = oneuptime_status_page.test.description
|
||||
description = "Description of the status page"
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
variable "oneuptime_url" {
|
||||
type = string
|
||||
description = "OneUptime API URL"
|
||||
}
|
||||
|
||||
variable "api_key" {
|
||||
type = string
|
||||
description = "OneUptime API Key"
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "project_id" {
|
||||
type = string
|
||||
description = "OneUptime Project ID"
|
||||
}
|
||||
109
E2E/Terraform/e2e-tests/tests/12-status-page-domain/verify.sh
Executable file
109
E2E/Terraform/e2e-tests/tests/12-status-page-domain/verify.sh
Executable file
@@ -0,0 +1,109 @@
|
||||
#!/bin/bash
|
||||
# Verify script for 12-status-page-domain test
|
||||
# Validates that domain, status page, and status page domain resources were created correctly via API
|
||||
|
||||
set -e
|
||||
|
||||
# Get terraform outputs
|
||||
DOMAIN_ID=$(terraform output -raw domain_id)
|
||||
STATUS_PAGE_ID=$(terraform output -raw status_page_id)
|
||||
STATUS_PAGE_DOMAIN_ID=$(terraform output -raw status_page_domain_id)
|
||||
EXPECTED_SUBDOMAIN=$(terraform output -raw subdomain)
|
||||
EXPECTED_FULL_DOMAIN=$(terraform output -raw full_domain)
|
||||
EXPECTED_DOMAIN_NAME=$(terraform output -raw domain_name)
|
||||
EXPECTED_IS_VERIFIED=$(terraform output -raw domain_is_verified)
|
||||
EXPECTED_SP_NAME=$(terraform output -raw status_page_name)
|
||||
EXPECTED_SP_DESCRIPTION=$(terraform output -raw status_page_description)
|
||||
|
||||
echo " Verifying domain resource via API..."
|
||||
echo " Domain ID: $DOMAIN_ID"
|
||||
|
||||
# Validate Domain
|
||||
RESPONSE=$(curl -s -X POST "${ONEUPTIME_URL}/api/domain/${DOMAIN_ID}/get-item" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Apikey: $TF_VAR_api_key" \
|
||||
-H "projectid: $TF_VAR_project_id" \
|
||||
-d '{"select": {"_id": true, "domain": true, "isVerified": true}}')
|
||||
|
||||
API_ID=$(echo "$RESPONSE" | jq -r '._id // empty')
|
||||
if [ -z "$API_ID" ] || [ "$API_ID" = "null" ]; then
|
||||
echo " ✗ FAILED: Domain not found in API response"
|
||||
echo " Response: $RESPONSE"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Domain exists in API"
|
||||
|
||||
API_DOMAIN=$(echo "$RESPONSE" | jq -r '.domain // empty')
|
||||
if [ "$API_DOMAIN" != "$EXPECTED_DOMAIN_NAME" ]; then
|
||||
echo " ✗ FAILED: Domain name mismatch - Expected: '$EXPECTED_DOMAIN_NAME', Got: '$API_DOMAIN'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Domain name matches: $API_DOMAIN"
|
||||
|
||||
API_IS_VERIFIED=$(echo "$RESPONSE" | jq -r '.isVerified // empty')
|
||||
if [ "$API_IS_VERIFIED" != "$EXPECTED_IS_VERIFIED" ]; then
|
||||
echo " ✗ FAILED: isVerified mismatch - Expected: '$EXPECTED_IS_VERIFIED', Got: '$API_IS_VERIFIED'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ isVerified matches: $API_IS_VERIFIED"
|
||||
|
||||
# Validate Status Page
|
||||
echo ""
|
||||
echo " Verifying status page resource via API..."
|
||||
echo " Status Page ID: $STATUS_PAGE_ID"
|
||||
|
||||
RESPONSE=$(curl -s -X POST "${ONEUPTIME_URL}/api/status-page/${STATUS_PAGE_ID}/get-item" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Apikey: $TF_VAR_api_key" \
|
||||
-H "projectid: $TF_VAR_project_id" \
|
||||
-d '{"select": {"_id": true, "name": true, "description": true}}')
|
||||
|
||||
API_ID=$(echo "$RESPONSE" | jq -r '._id // empty')
|
||||
if [ -z "$API_ID" ] || [ "$API_ID" = "null" ]; then
|
||||
echo " ✗ FAILED: Status page not found in API response"
|
||||
echo " Response: $RESPONSE"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Status page exists in API"
|
||||
|
||||
API_NAME=$(echo "$RESPONSE" | jq -r '.name // empty')
|
||||
if [ "$API_NAME" != "$EXPECTED_SP_NAME" ]; then
|
||||
echo " ✗ FAILED: Name mismatch - Expected: '$EXPECTED_SP_NAME', Got: '$API_NAME'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Name matches: $API_NAME"
|
||||
|
||||
# Validate Status Page Domain
|
||||
echo ""
|
||||
echo " Verifying status page domain resource via API..."
|
||||
echo " Status Page Domain ID: $STATUS_PAGE_DOMAIN_ID"
|
||||
|
||||
RESPONSE=$(curl -s -X POST "${ONEUPTIME_URL}/api/status-page-domain/${STATUS_PAGE_DOMAIN_ID}/get-item" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Apikey: $TF_VAR_api_key" \
|
||||
-H "projectid: $TF_VAR_project_id" \
|
||||
-d '{"select": {"_id": true, "subdomain": true, "fullDomain": true}}')
|
||||
|
||||
API_ID=$(echo "$RESPONSE" | jq -r '._id // empty')
|
||||
if [ -z "$API_ID" ] || [ "$API_ID" = "null" ]; then
|
||||
echo " ✗ FAILED: Status page domain not found in API response"
|
||||
echo " Response: $RESPONSE"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Status page domain exists in API"
|
||||
|
||||
API_SUBDOMAIN=$(echo "$RESPONSE" | jq -r '.subdomain // empty')
|
||||
if [ "$API_SUBDOMAIN" != "$EXPECTED_SUBDOMAIN" ]; then
|
||||
echo " ✗ FAILED: Subdomain mismatch - Expected: '$EXPECTED_SUBDOMAIN', Got: '$API_SUBDOMAIN'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Subdomain matches: $API_SUBDOMAIN"
|
||||
|
||||
API_FULL_DOMAIN=$(echo "$RESPONSE" | jq -r '.fullDomain // empty')
|
||||
if [ "$API_FULL_DOMAIN" != "$EXPECTED_FULL_DOMAIN" ]; then
|
||||
echo " ✗ FAILED: Full domain mismatch - Expected: '$EXPECTED_FULL_DOMAIN', Got: '$API_FULL_DOMAIN'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Full domain matches: $API_FULL_DOMAIN"
|
||||
|
||||
echo " ✓ All status page domain validations passed"
|
||||
@@ -0,0 +1,106 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
oneuptime = {
|
||||
source = "oneuptime/oneuptime"
|
||||
version = "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "oneuptime" {
|
||||
oneuptime_url = var.oneuptime_url
|
||||
api_key = var.api_key
|
||||
}
|
||||
|
||||
# First, create a domain (required for status_page_domain)
|
||||
# The domain must be verified before it can be used with status_page_domain
|
||||
# For test domains (.example.com), DNS verification is bypassed
|
||||
resource "oneuptime_domain" "test" {
|
||||
project_id = var.project_id
|
||||
domain = var.domain_name
|
||||
is_verified = true
|
||||
}
|
||||
|
||||
# Then, create a status page (required for status_page_domain)
|
||||
resource "oneuptime_status_page" "test" {
|
||||
project_id = var.project_id
|
||||
name = var.status_page_name
|
||||
description = "Status page created by Terraform E2E tests for computed fields test"
|
||||
page_title = "Computed Fields Test Status"
|
||||
page_description = "This tests computed field handling"
|
||||
is_public_status_page = false
|
||||
enable_email_subscribers = false
|
||||
enable_sms_subscribers = false
|
||||
}
|
||||
|
||||
# Test: status_page_domain - Validates Issue #2236 fix
|
||||
#
|
||||
# This test verifies that computed fields work correctly:
|
||||
#
|
||||
# 1. full_domain:
|
||||
# - Should be computed by server from subdomain + domain
|
||||
# - User should NOT need to provide this value
|
||||
#
|
||||
# 2. cname_verification_token:
|
||||
# - Should be computed by server (generates UUID)
|
||||
# - Has no read permission (security - not readable via API)
|
||||
# - User should NOT need to provide this value
|
||||
#
|
||||
resource "oneuptime_status_page_domain" "test" {
|
||||
project_id = var.project_id
|
||||
domain_id = oneuptime_domain.test.id
|
||||
status_page_id = oneuptime_status_page.test.id
|
||||
subdomain = var.subdomain
|
||||
|
||||
# full_domain and cname_verification_token are NOT specified
|
||||
# They are server-generated computed fields
|
||||
}
|
||||
|
||||
output "status_page_domain_id" {
|
||||
value = oneuptime_status_page_domain.test.id
|
||||
description = "ID of the created status page domain"
|
||||
}
|
||||
|
||||
output "domain_id" {
|
||||
value = oneuptime_domain.test.id
|
||||
description = "ID of the created domain"
|
||||
}
|
||||
|
||||
output "status_page_id" {
|
||||
value = oneuptime_status_page.test.id
|
||||
description = "ID of the created status page"
|
||||
}
|
||||
|
||||
# Output the computed full_domain - this should be server-generated
|
||||
output "computed_full_domain" {
|
||||
value = oneuptime_status_page_domain.test.full_domain
|
||||
description = "Full domain computed by the server (should match subdomain.domain)"
|
||||
}
|
||||
|
||||
# Output subdomain for verification
|
||||
output "subdomain" {
|
||||
value = oneuptime_status_page_domain.test.subdomain
|
||||
description = "Subdomain used"
|
||||
}
|
||||
|
||||
# Domain resource outputs for API validation
|
||||
output "domain_name" {
|
||||
value = oneuptime_domain.test.domain
|
||||
description = "Domain name"
|
||||
}
|
||||
|
||||
output "domain_is_verified" {
|
||||
value = oneuptime_domain.test.is_verified
|
||||
description = "Whether the domain is verified"
|
||||
}
|
||||
|
||||
# Status page outputs for API validation
|
||||
output "status_page_name" {
|
||||
value = oneuptime_status_page.test.name
|
||||
description = "Name of the status page"
|
||||
}
|
||||
|
||||
output "status_page_description" {
|
||||
value = oneuptime_status_page.test.description
|
||||
description = "Description of the status page"
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
variable "oneuptime_url" {
|
||||
type = string
|
||||
description = "OneUptime API URL"
|
||||
}
|
||||
|
||||
variable "api_key" {
|
||||
type = string
|
||||
description = "OneUptime API Key"
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "project_id" {
|
||||
type = string
|
||||
description = "OneUptime Project ID"
|
||||
}
|
||||
|
||||
variable "domain_name" {
|
||||
type = string
|
||||
description = "Domain name for testing"
|
||||
default = "computed-fields-test.example.com"
|
||||
}
|
||||
|
||||
variable "status_page_name" {
|
||||
type = string
|
||||
description = "Status page name for testing"
|
||||
default = "Computed Fields Test Status Page"
|
||||
}
|
||||
|
||||
variable "subdomain" {
|
||||
type = string
|
||||
description = "Subdomain for the status page domain"
|
||||
default = "status"
|
||||
}
|
||||
104
E2E/Terraform/e2e-tests/tests/13-status-page-domain-computed-fields/verify.sh
Executable file
104
E2E/Terraform/e2e-tests/tests/13-status-page-domain-computed-fields/verify.sh
Executable file
@@ -0,0 +1,104 @@
|
||||
#!/bin/bash
|
||||
# Verify script for 13-status-page-domain-computed-fields test
|
||||
# Validates GitHub Issue #2236: computed fields (full_domain, cname_verification_token) work correctly
|
||||
|
||||
set -e
|
||||
|
||||
# Get terraform outputs
|
||||
DOMAIN_ID=$(terraform output -raw domain_id)
|
||||
STATUS_PAGE_ID=$(terraform output -raw status_page_id)
|
||||
STATUS_PAGE_DOMAIN_ID=$(terraform output -raw status_page_domain_id)
|
||||
EXPECTED_SUBDOMAIN=$(terraform output -raw subdomain)
|
||||
EXPECTED_FULL_DOMAIN=$(terraform output -raw computed_full_domain)
|
||||
EXPECTED_DOMAIN_NAME=$(terraform output -raw domain_name)
|
||||
EXPECTED_IS_VERIFIED=$(terraform output -raw domain_is_verified)
|
||||
EXPECTED_SP_NAME=$(terraform output -raw status_page_name)
|
||||
|
||||
echo " Verifying computed fields test via API (Issue #2236)..."
|
||||
|
||||
# Validate Domain
|
||||
echo " Verifying domain resource..."
|
||||
echo " Domain ID: $DOMAIN_ID"
|
||||
|
||||
RESPONSE=$(curl -s -X POST "${ONEUPTIME_URL}/api/domain/${DOMAIN_ID}/get-item" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Apikey: $TF_VAR_api_key" \
|
||||
-H "projectid: $TF_VAR_project_id" \
|
||||
-d '{"select": {"_id": true, "domain": true, "isVerified": true}}')
|
||||
|
||||
API_ID=$(echo "$RESPONSE" | jq -r '._id // empty')
|
||||
if [ -z "$API_ID" ] || [ "$API_ID" = "null" ]; then
|
||||
echo " ✗ FAILED: Domain not found in API response"
|
||||
echo " Response: $RESPONSE"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Domain exists in API"
|
||||
|
||||
API_DOMAIN=$(echo "$RESPONSE" | jq -r '.domain // empty')
|
||||
if [ "$API_DOMAIN" != "$EXPECTED_DOMAIN_NAME" ]; then
|
||||
echo " ✗ FAILED: Domain name mismatch - Expected: '$EXPECTED_DOMAIN_NAME', Got: '$API_DOMAIN'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Domain name matches: $API_DOMAIN"
|
||||
|
||||
# Validate Status Page
|
||||
echo ""
|
||||
echo " Verifying status page resource..."
|
||||
echo " Status Page ID: $STATUS_PAGE_ID"
|
||||
|
||||
RESPONSE=$(curl -s -X POST "${ONEUPTIME_URL}/api/status-page/${STATUS_PAGE_ID}/get-item" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Apikey: $TF_VAR_api_key" \
|
||||
-H "projectid: $TF_VAR_project_id" \
|
||||
-d '{"select": {"_id": true, "name": true}}')
|
||||
|
||||
API_ID=$(echo "$RESPONSE" | jq -r '._id // empty')
|
||||
if [ -z "$API_ID" ] || [ "$API_ID" = "null" ]; then
|
||||
echo " ✗ FAILED: Status page not found in API response"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Status page exists in API"
|
||||
|
||||
# Validate Status Page Domain - Key test for Issue #2236
|
||||
echo ""
|
||||
echo " Verifying status page domain computed fields (Issue #2236)..."
|
||||
echo " Status Page Domain ID: $STATUS_PAGE_DOMAIN_ID"
|
||||
|
||||
RESPONSE=$(curl -s -X POST "${ONEUPTIME_URL}/api/status-page-domain/${STATUS_PAGE_DOMAIN_ID}/get-item" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Apikey: $TF_VAR_api_key" \
|
||||
-H "projectid: $TF_VAR_project_id" \
|
||||
-d '{"select": {"_id": true, "subdomain": true, "fullDomain": true, "cnameVerificationToken": true}}')
|
||||
|
||||
API_ID=$(echo "$RESPONSE" | jq -r '._id // empty')
|
||||
if [ -z "$API_ID" ] || [ "$API_ID" = "null" ]; then
|
||||
echo " ✗ FAILED: Status page domain not found in API response"
|
||||
echo " Response: $RESPONSE"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Status page domain exists in API"
|
||||
|
||||
# Validate subdomain
|
||||
API_SUBDOMAIN=$(echo "$RESPONSE" | jq -r '.subdomain // empty')
|
||||
if [ "$API_SUBDOMAIN" != "$EXPECTED_SUBDOMAIN" ]; then
|
||||
echo " ✗ FAILED: Subdomain mismatch - Expected: '$EXPECTED_SUBDOMAIN', Got: '$API_SUBDOMAIN'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Subdomain matches: $API_SUBDOMAIN"
|
||||
|
||||
# Validate computed full_domain (Issue #2236 key validation)
|
||||
API_FULL_DOMAIN=$(echo "$RESPONSE" | jq -r '.fullDomain // empty')
|
||||
if [ -z "$API_FULL_DOMAIN" ] || [ "$API_FULL_DOMAIN" = "null" ]; then
|
||||
echo " ✗ FAILED: fullDomain is empty - server should compute this value"
|
||||
exit 1
|
||||
fi
|
||||
if [ "$API_FULL_DOMAIN" != "$EXPECTED_FULL_DOMAIN" ]; then
|
||||
echo " ✗ FAILED: Full domain mismatch - Expected: '$EXPECTED_FULL_DOMAIN', Got: '$API_FULL_DOMAIN'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Computed fullDomain matches: $API_FULL_DOMAIN (Issue #2236 validated)"
|
||||
|
||||
# Note: cnameVerificationToken has no read permission, so we just verify the field exists in terraform output
|
||||
echo " ✓ cnameVerificationToken is computed by server (no read permission)"
|
||||
|
||||
echo " ✓ All computed field validations passed (Issue #2236)"
|
||||
@@ -0,0 +1,103 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
oneuptime = {
|
||||
source = "oneuptime/oneuptime"
|
||||
version = "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "oneuptime" {
|
||||
oneuptime_url = var.oneuptime_url
|
||||
api_key = var.api_key
|
||||
}
|
||||
|
||||
# Test: Status Page with Server-Provided Defaults (Issue #2232)
|
||||
#
|
||||
# This test verifies that the fix for GitHub issue #2232 works correctly.
|
||||
# The issue was: "Provider produced inconsistent result after apply" error
|
||||
# when creating a status page without specifying downtime_monitor_statuses.
|
||||
#
|
||||
# The fix adds UseStateForUnknown() plan modifier to Optional+Computed fields,
|
||||
# which tells Terraform to accept server-provided default values.
|
||||
#
|
||||
# Test cases:
|
||||
# 1. Create status page WITHOUT specifying downtime_monitor_statuses
|
||||
# 2. Verify no "inconsistent result" error occurs
|
||||
# 3. Verify server provides default values for the field
|
||||
|
||||
resource "oneuptime_status_page" "test_server_defaults" {
|
||||
project_id = var.project_id
|
||||
name = "Server Defaults Test Status Page"
|
||||
description = "Tests that server-provided defaults work correctly (Issue #2232)"
|
||||
page_title = "Server Defaults Test"
|
||||
page_description = "This status page tests UseStateForUnknown plan modifier"
|
||||
is_public_status_page = true
|
||||
enable_email_subscribers = false
|
||||
enable_sms_subscribers = false
|
||||
|
||||
# IMPORTANT: We intentionally DO NOT specify downtime_monitor_statuses here
|
||||
# The server will inject default values (all non-operational monitor statuses)
|
||||
# With the fix, Terraform should accept these server-provided defaults
|
||||
# without throwing "inconsistent result after apply" error
|
||||
}
|
||||
|
||||
# Output the ID to verify creation succeeded
|
||||
output "status_page_id" {
|
||||
value = oneuptime_status_page.test_server_defaults.id
|
||||
description = "ID of the created status page"
|
||||
}
|
||||
|
||||
# Status page fields for API validation
|
||||
output "status_page_name" {
|
||||
value = oneuptime_status_page.test_server_defaults.name
|
||||
description = "Name of the created status page"
|
||||
}
|
||||
|
||||
output "status_page_description" {
|
||||
value = oneuptime_status_page.test_server_defaults.description
|
||||
description = "Description of the created status page"
|
||||
}
|
||||
|
||||
output "status_page_page_title" {
|
||||
value = oneuptime_status_page.test_server_defaults.page_title
|
||||
description = "Page title of the created status page"
|
||||
}
|
||||
|
||||
output "status_page_page_description" {
|
||||
value = oneuptime_status_page.test_server_defaults.page_description
|
||||
description = "Page description of the created status page"
|
||||
}
|
||||
|
||||
output "status_page_is_public_status_page" {
|
||||
value = oneuptime_status_page.test_server_defaults.is_public_status_page
|
||||
description = "Whether the status page is public"
|
||||
}
|
||||
|
||||
output "status_page_enable_email_subscribers" {
|
||||
value = oneuptime_status_page.test_server_defaults.enable_email_subscribers
|
||||
description = "Whether email subscribers are enabled"
|
||||
}
|
||||
|
||||
output "status_page_enable_sms_subscribers" {
|
||||
value = oneuptime_status_page.test_server_defaults.enable_sms_subscribers
|
||||
description = "Whether SMS subscribers are enabled"
|
||||
}
|
||||
|
||||
# Output the server-provided downtime_monitor_statuses
|
||||
# This should contain the default non-operational monitor statuses
|
||||
output "downtime_monitor_statuses" {
|
||||
value = oneuptime_status_page.test_server_defaults.downtime_monitor_statuses
|
||||
description = "Server-provided default downtime monitor statuses (should not be empty)"
|
||||
}
|
||||
|
||||
# Output other server-computed fields to verify they work too
|
||||
output "slug" {
|
||||
value = oneuptime_status_page.test_server_defaults.slug
|
||||
description = "Server-generated slug"
|
||||
}
|
||||
|
||||
output "created_at" {
|
||||
value = oneuptime_status_page.test_server_defaults.created_at
|
||||
description = "Server-generated creation timestamp"
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
variable "oneuptime_url" {
|
||||
type = string
|
||||
description = "OneUptime API URL"
|
||||
}
|
||||
|
||||
variable "api_key" {
|
||||
type = string
|
||||
description = "OneUptime API Key"
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "project_id" {
|
||||
type = string
|
||||
description = "OneUptime Project ID"
|
||||
}
|
||||
83
E2E/Terraform/e2e-tests/tests/14-status-page-server-defaults/verify.sh
Executable file
83
E2E/Terraform/e2e-tests/tests/14-status-page-server-defaults/verify.sh
Executable file
@@ -0,0 +1,83 @@
|
||||
#!/bin/bash
|
||||
# Verify script for 14-status-page-server-defaults test
|
||||
# Validates GitHub Issue #2232: server-provided defaults for status page work correctly
|
||||
|
||||
set -e
|
||||
|
||||
# Get terraform outputs
|
||||
RESOURCE_ID=$(terraform output -raw status_page_id)
|
||||
EXPECTED_NAME=$(terraform output -raw status_page_name)
|
||||
EXPECTED_DESCRIPTION=$(terraform output -raw status_page_description)
|
||||
EXPECTED_PAGE_TITLE=$(terraform output -raw status_page_page_title)
|
||||
EXPECTED_PAGE_DESCRIPTION=$(terraform output -raw status_page_page_description)
|
||||
EXPECTED_IS_PUBLIC=$(terraform output -raw status_page_is_public_status_page)
|
||||
EXPECTED_EMAIL_SUBSCRIBERS=$(terraform output -raw status_page_enable_email_subscribers)
|
||||
EXPECTED_SMS_SUBSCRIBERS=$(terraform output -raw status_page_enable_sms_subscribers)
|
||||
|
||||
echo " Verifying status page with server defaults via API (Issue #2232)..."
|
||||
echo " Resource ID: $RESOURCE_ID"
|
||||
|
||||
# Call API to get the resource
|
||||
RESPONSE=$(curl -s -X POST "${ONEUPTIME_URL}/api/status-page/${RESOURCE_ID}/get-item" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Apikey: $TF_VAR_api_key" \
|
||||
-H "projectid: $TF_VAR_project_id" \
|
||||
-d '{"select": {"_id": true, "name": true, "description": true, "pageTitle": true, "pageDescription": true, "isPublicStatusPage": true, "enableEmailSubscribers": true, "enableSmsSubscribers": true, "downtimeMonitorStatuses": true, "slug": true}}')
|
||||
|
||||
# Check if response contains the resource
|
||||
API_ID=$(echo "$RESPONSE" | jq -r '._id // empty')
|
||||
if [ -z "$API_ID" ] || [ "$API_ID" = "null" ]; then
|
||||
echo " ✗ FAILED: Status page not found in API response"
|
||||
echo " Response: $RESPONSE"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Status page exists in API"
|
||||
|
||||
# Validate name
|
||||
API_NAME=$(echo "$RESPONSE" | jq -r '.name // empty')
|
||||
if [ "$API_NAME" != "$EXPECTED_NAME" ]; then
|
||||
echo " ✗ FAILED: Name mismatch - Expected: '$EXPECTED_NAME', Got: '$API_NAME'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Name matches: $API_NAME"
|
||||
|
||||
# Validate description
|
||||
API_DESCRIPTION=$(echo "$RESPONSE" | jq -r '.description // empty')
|
||||
if [ "$API_DESCRIPTION" != "$EXPECTED_DESCRIPTION" ]; then
|
||||
echo " ✗ FAILED: Description mismatch - Expected: '$EXPECTED_DESCRIPTION', Got: '$API_DESCRIPTION'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Description matches: $API_DESCRIPTION"
|
||||
|
||||
# Validate pageTitle
|
||||
API_PAGE_TITLE=$(echo "$RESPONSE" | jq -r '.pageTitle // empty')
|
||||
if [ "$API_PAGE_TITLE" != "$EXPECTED_PAGE_TITLE" ]; then
|
||||
echo " ✗ FAILED: Page title mismatch - Expected: '$EXPECTED_PAGE_TITLE', Got: '$API_PAGE_TITLE'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Page title matches: $API_PAGE_TITLE"
|
||||
|
||||
# Validate isPublicStatusPage
|
||||
API_IS_PUBLIC=$(echo "$RESPONSE" | jq -r '.isPublicStatusPage // empty')
|
||||
if [ "$API_IS_PUBLIC" != "$EXPECTED_IS_PUBLIC" ]; then
|
||||
echo " ✗ FAILED: isPublicStatusPage mismatch - Expected: '$EXPECTED_IS_PUBLIC', Got: '$API_IS_PUBLIC'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ isPublicStatusPage matches: $API_IS_PUBLIC"
|
||||
|
||||
# Validate server-provided downtimeMonitorStatuses (Issue #2232 key validation)
|
||||
DOWNTIME_STATUSES=$(echo "$RESPONSE" | jq '.downtimeMonitorStatuses')
|
||||
if [ "$DOWNTIME_STATUSES" = "null" ] || [ "$DOWNTIME_STATUSES" = "[]" ]; then
|
||||
echo " ⚠ Warning: downtimeMonitorStatuses is empty (server may not have provided defaults)"
|
||||
else
|
||||
STATUSES_COUNT=$(echo "$DOWNTIME_STATUSES" | jq 'length')
|
||||
echo " ✓ Server-provided downtimeMonitorStatuses exists with $STATUSES_COUNT items (Issue #2232 validated)"
|
||||
fi
|
||||
|
||||
# Validate slug was computed by server
|
||||
API_SLUG=$(echo "$RESPONSE" | jq -r '.slug // empty')
|
||||
if [ -n "$API_SLUG" ] && [ "$API_SLUG" != "null" ]; then
|
||||
echo " ✓ Server-computed slug: $API_SLUG"
|
||||
fi
|
||||
|
||||
echo " ✓ All status page server defaults validations passed (Issue #2232)"
|
||||
@@ -0,0 +1,85 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
oneuptime = {
|
||||
source = "oneuptime/oneuptime"
|
||||
version = "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "oneuptime" {
|
||||
oneuptime_url = var.oneuptime_url
|
||||
api_key = var.api_key
|
||||
}
|
||||
|
||||
# Test: Monitor with Server-Provided Defaults (Issue #2226)
|
||||
#
|
||||
# This test verifies that the fix for GitHub issue #2226 works correctly.
|
||||
# The issue was: "Provider produced inconsistent result after apply" error
|
||||
# when creating a monitor - the server injects exceptionMonitor defaults
|
||||
# into monitor_steps that weren't in the original request.
|
||||
#
|
||||
# The fix adds UseStateForUnknown() plan modifier to Optional+Computed fields,
|
||||
# which tells Terraform to accept server-provided default values.
|
||||
#
|
||||
# Test cases:
|
||||
# 1. Create monitor with minimal monitor_steps (no exceptionMonitor)
|
||||
# 2. Verify no "inconsistent result" error occurs
|
||||
# 3. Verify server can inject defaults into monitor_steps
|
||||
|
||||
resource "oneuptime_monitor" "test_server_defaults" {
|
||||
project_id = var.project_id
|
||||
name = "Monitor Server Defaults Test"
|
||||
description = "Tests that server-provided defaults work correctly (Issue #2226)"
|
||||
monitor_type = "Manual"
|
||||
|
||||
# IMPORTANT: We provide minimal monitor_steps without exceptionMonitor
|
||||
# The server will inject default exceptionMonitor values
|
||||
# With the fix, Terraform should accept these server-provided defaults
|
||||
# without throwing "inconsistent result after apply" error
|
||||
}
|
||||
|
||||
# Output the ID to verify creation succeeded
|
||||
output "monitor_id" {
|
||||
value = oneuptime_monitor.test_server_defaults.id
|
||||
description = "ID of the created monitor"
|
||||
}
|
||||
|
||||
# Monitor fields for API validation
|
||||
output "monitor_name" {
|
||||
value = oneuptime_monitor.test_server_defaults.name
|
||||
description = "Name of the created monitor"
|
||||
}
|
||||
|
||||
output "monitor_description" {
|
||||
value = oneuptime_monitor.test_server_defaults.description
|
||||
description = "Description of the created monitor"
|
||||
}
|
||||
|
||||
output "monitor_monitor_type" {
|
||||
value = oneuptime_monitor.test_server_defaults.monitor_type
|
||||
description = "Type of the created monitor"
|
||||
}
|
||||
|
||||
# Output the server-modified monitor_steps
|
||||
# This should contain the server-injected exceptionMonitor defaults
|
||||
output "monitor_steps" {
|
||||
value = oneuptime_monitor.test_server_defaults.monitor_steps
|
||||
description = "Server-modified monitor_steps (may contain injected exceptionMonitor)"
|
||||
}
|
||||
|
||||
# Output other server-computed fields
|
||||
output "slug" {
|
||||
value = oneuptime_monitor.test_server_defaults.slug
|
||||
description = "Server-generated slug"
|
||||
}
|
||||
|
||||
output "created_at" {
|
||||
value = oneuptime_monitor.test_server_defaults.created_at
|
||||
description = "Server-generated creation timestamp"
|
||||
}
|
||||
|
||||
output "current_monitor_status_id" {
|
||||
value = oneuptime_monitor.test_server_defaults.current_monitor_status_id
|
||||
description = "Server-assigned default monitor status"
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
variable "oneuptime_url" {
|
||||
type = string
|
||||
description = "OneUptime API URL"
|
||||
}
|
||||
|
||||
variable "api_key" {
|
||||
type = string
|
||||
description = "OneUptime API Key"
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "project_id" {
|
||||
type = string
|
||||
description = "OneUptime Project ID"
|
||||
}
|
||||
74
E2E/Terraform/e2e-tests/tests/15-monitor-server-defaults/verify.sh
Executable file
74
E2E/Terraform/e2e-tests/tests/15-monitor-server-defaults/verify.sh
Executable file
@@ -0,0 +1,74 @@
|
||||
#!/bin/bash
|
||||
# Verify script for 15-monitor-server-defaults test
|
||||
# Validates GitHub Issue #2226: server-provided defaults for monitor work correctly
|
||||
|
||||
set -e
|
||||
|
||||
# Get terraform outputs
|
||||
RESOURCE_ID=$(terraform output -raw monitor_id)
|
||||
EXPECTED_NAME=$(terraform output -raw monitor_name)
|
||||
EXPECTED_DESCRIPTION=$(terraform output -raw monitor_description)
|
||||
EXPECTED_MONITOR_TYPE=$(terraform output -raw monitor_monitor_type)
|
||||
|
||||
echo " Verifying monitor with server defaults via API (Issue #2226)..."
|
||||
echo " Resource ID: $RESOURCE_ID"
|
||||
|
||||
# Call API to get the resource
|
||||
RESPONSE=$(curl -s -X POST "${ONEUPTIME_URL}/api/monitor/${RESOURCE_ID}/get-item" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Apikey: $TF_VAR_api_key" \
|
||||
-H "projectid: $TF_VAR_project_id" \
|
||||
-d '{"select": {"_id": true, "name": true, "description": true, "monitorType": true, "monitorSteps": true, "slug": true, "currentMonitorStatusId": true}}')
|
||||
|
||||
# Check if response contains the resource
|
||||
API_ID=$(echo "$RESPONSE" | jq -r '._id // empty')
|
||||
if [ -z "$API_ID" ] || [ "$API_ID" = "null" ]; then
|
||||
echo " ✗ FAILED: Monitor not found in API response"
|
||||
echo " Response: $RESPONSE"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Monitor exists in API"
|
||||
|
||||
# Validate name
|
||||
API_NAME=$(echo "$RESPONSE" | jq -r '.name // empty')
|
||||
if [ "$API_NAME" != "$EXPECTED_NAME" ]; then
|
||||
echo " ✗ FAILED: Name mismatch - Expected: '$EXPECTED_NAME', Got: '$API_NAME'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Name matches: $API_NAME"
|
||||
|
||||
# Validate description
|
||||
API_DESCRIPTION=$(echo "$RESPONSE" | jq -r '.description // empty')
|
||||
if [ "$API_DESCRIPTION" != "$EXPECTED_DESCRIPTION" ]; then
|
||||
echo " ✗ FAILED: Description mismatch - Expected: '$EXPECTED_DESCRIPTION', Got: '$API_DESCRIPTION'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Description matches: $API_DESCRIPTION"
|
||||
|
||||
# Validate monitorType
|
||||
API_MONITOR_TYPE=$(echo "$RESPONSE" | jq -r '.monitorType // empty')
|
||||
if [ "$API_MONITOR_TYPE" != "$EXPECTED_MONITOR_TYPE" ]; then
|
||||
echo " ✗ FAILED: Monitor type mismatch - Expected: '$EXPECTED_MONITOR_TYPE', Got: '$API_MONITOR_TYPE'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Monitor type matches: $API_MONITOR_TYPE"
|
||||
|
||||
# Validate server-provided monitorSteps (Issue #2226 key validation)
|
||||
MONITOR_STEPS=$(echo "$RESPONSE" | jq '.monitorSteps')
|
||||
if [ "$MONITOR_STEPS" != "null" ]; then
|
||||
echo " ✓ Server-provided monitorSteps exists (Issue #2226 validated)"
|
||||
fi
|
||||
|
||||
# Validate server-assigned currentMonitorStatusId
|
||||
CURRENT_STATUS_ID=$(echo "$RESPONSE" | jq -r '.currentMonitorStatusId // empty')
|
||||
if [ -n "$CURRENT_STATUS_ID" ] && [ "$CURRENT_STATUS_ID" != "null" ]; then
|
||||
echo " ✓ Server-assigned currentMonitorStatusId: $CURRENT_STATUS_ID"
|
||||
fi
|
||||
|
||||
# Validate slug was computed by server
|
||||
API_SLUG=$(echo "$RESPONSE" | jq -r '.slug // empty')
|
||||
if [ -n "$API_SLUG" ] && [ "$API_SLUG" != "null" ]; then
|
||||
echo " ✓ Server-computed slug: $API_SLUG"
|
||||
fi
|
||||
|
||||
echo " ✓ All monitor server defaults validations passed (Issue #2226)"
|
||||
@@ -0,0 +1,111 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
oneuptime = {
|
||||
source = "oneuptime/oneuptime"
|
||||
version = "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "oneuptime" {
|
||||
oneuptime_url = var.oneuptime_url
|
||||
api_key = var.api_key
|
||||
}
|
||||
|
||||
# Test: Incident with Server-Provided Defaults
|
||||
#
|
||||
# This test verifies UseStateForUnknown() works for various column types:
|
||||
# - String fields: current_incident_state_id, description, etc.
|
||||
# - Bool fields: should_status_page_subscribers_be_notified_on_incident_created
|
||||
# - List fields: monitors, labels, on_call_duty_policies
|
||||
#
|
||||
# The server injects defaults for many fields that aren't specified.
|
||||
|
||||
# First create an incident severity (required dependency)
|
||||
resource "oneuptime_incident_severity" "test" {
|
||||
project_id = var.project_id
|
||||
name = "Incident Test Severity"
|
||||
description = "Severity for incident server defaults test"
|
||||
color = "#FF0000"
|
||||
order = 99
|
||||
}
|
||||
|
||||
# Create incident with minimal fields - let server provide defaults
|
||||
resource "oneuptime_incident" "test_server_defaults" {
|
||||
project_id = var.project_id
|
||||
title = "Incident Server Defaults Test"
|
||||
incident_severity_id = oneuptime_incident_severity.test.id
|
||||
|
||||
# IMPORTANT: We intentionally DO NOT specify these Optional+Computed fields:
|
||||
# - description (string)
|
||||
# - monitors (list)
|
||||
# - labels (list)
|
||||
# - on_call_duty_policies (list)
|
||||
# - current_incident_state_id (string - server sets to default "created" state)
|
||||
# - should_status_page_subscribers_be_notified_on_incident_created (bool)
|
||||
#
|
||||
# The server will provide default values for these fields.
|
||||
# With UseStateForUnknown(), Terraform accepts server-provided defaults.
|
||||
}
|
||||
|
||||
# Output to verify creation succeeded
|
||||
output "incident_id" {
|
||||
value = oneuptime_incident.test_server_defaults.id
|
||||
description = "ID of the created incident"
|
||||
}
|
||||
|
||||
# Incident severity outputs for API validation
|
||||
output "incident_severity_id" {
|
||||
value = oneuptime_incident_severity.test.id
|
||||
description = "ID of the created incident severity"
|
||||
}
|
||||
|
||||
output "incident_severity_name" {
|
||||
value = oneuptime_incident_severity.test.name
|
||||
description = "Name of the incident severity"
|
||||
}
|
||||
|
||||
output "incident_severity_color" {
|
||||
value = oneuptime_incident_severity.test.color
|
||||
description = "Color of the incident severity"
|
||||
}
|
||||
|
||||
# Incident title for API validation
|
||||
output "incident_title" {
|
||||
value = oneuptime_incident.test_server_defaults.title
|
||||
description = "Title of the created incident"
|
||||
}
|
||||
|
||||
# String field - server provides default incident state
|
||||
output "current_incident_state_id" {
|
||||
value = oneuptime_incident.test_server_defaults.current_incident_state_id
|
||||
description = "Server-assigned default incident state (should be 'created' state)"
|
||||
}
|
||||
|
||||
# List field - server may provide empty list or defaults
|
||||
output "monitors" {
|
||||
value = oneuptime_incident.test_server_defaults.monitors
|
||||
description = "Server-provided monitors list"
|
||||
}
|
||||
|
||||
output "labels" {
|
||||
value = oneuptime_incident.test_server_defaults.labels
|
||||
description = "Server-provided labels list"
|
||||
}
|
||||
|
||||
# Bool field - server provides default
|
||||
output "should_notify_subscribers" {
|
||||
value = oneuptime_incident.test_server_defaults.should_status_page_subscribers_be_notified_on_incident_created
|
||||
description = "Server-provided default for subscriber notification"
|
||||
}
|
||||
|
||||
# Other server-computed fields
|
||||
output "slug" {
|
||||
value = oneuptime_incident.test_server_defaults.slug
|
||||
description = "Server-generated slug"
|
||||
}
|
||||
|
||||
output "created_at" {
|
||||
value = oneuptime_incident.test_server_defaults.created_at
|
||||
description = "Server-generated creation timestamp"
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
variable "oneuptime_url" {
|
||||
type = string
|
||||
description = "OneUptime API URL"
|
||||
}
|
||||
|
||||
variable "api_key" {
|
||||
type = string
|
||||
description = "OneUptime API Key"
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "project_id" {
|
||||
type = string
|
||||
description = "OneUptime Project ID"
|
||||
}
|
||||
87
E2E/Terraform/e2e-tests/tests/16-incident-server-defaults/verify.sh
Executable file
87
E2E/Terraform/e2e-tests/tests/16-incident-server-defaults/verify.sh
Executable file
@@ -0,0 +1,87 @@
|
||||
#!/bin/bash
|
||||
# Verify script for 16-incident-server-defaults test
|
||||
# Validates server-provided defaults for incident resource
|
||||
|
||||
set -e
|
||||
|
||||
# Get terraform outputs
|
||||
INCIDENT_ID=$(terraform output -raw incident_id)
|
||||
INCIDENT_SEVERITY_ID=$(terraform output -raw incident_severity_id)
|
||||
EXPECTED_SEVERITY_NAME=$(terraform output -raw incident_severity_name)
|
||||
EXPECTED_SEVERITY_COLOR=$(terraform output -raw incident_severity_color)
|
||||
EXPECTED_TITLE=$(terraform output -raw incident_title)
|
||||
|
||||
echo " Verifying incident with server defaults via API..."
|
||||
|
||||
# First validate the incident severity dependency
|
||||
echo " Verifying incident severity..."
|
||||
echo " Incident Severity ID: $INCIDENT_SEVERITY_ID"
|
||||
|
||||
RESPONSE=$(curl -s -X POST "${ONEUPTIME_URL}/api/incident-severity/${INCIDENT_SEVERITY_ID}/get-item" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Apikey: $TF_VAR_api_key" \
|
||||
-H "projectid: $TF_VAR_project_id" \
|
||||
-d '{"select": {"_id": true, "name": true, "color": true}}')
|
||||
|
||||
API_ID=$(echo "$RESPONSE" | jq -r '._id // empty')
|
||||
if [ -z "$API_ID" ] || [ "$API_ID" = "null" ]; then
|
||||
echo " ✗ FAILED: Incident severity not found in API response"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Incident severity exists in API"
|
||||
|
||||
API_NAME=$(echo "$RESPONSE" | jq -r '.name // empty')
|
||||
if [ "$API_NAME" != "$EXPECTED_SEVERITY_NAME" ]; then
|
||||
echo " ✗ FAILED: Severity name mismatch - Expected: '$EXPECTED_SEVERITY_NAME', Got: '$API_NAME'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Severity name matches: $API_NAME"
|
||||
|
||||
# Now validate the incident
|
||||
echo ""
|
||||
echo " Verifying incident resource..."
|
||||
echo " Incident ID: $INCIDENT_ID"
|
||||
|
||||
RESPONSE=$(curl -s -X POST "${ONEUPTIME_URL}/api/incident/${INCIDENT_ID}/get-item" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Apikey: $TF_VAR_api_key" \
|
||||
-H "projectid: $TF_VAR_project_id" \
|
||||
-d '{"select": {"_id": true, "title": true, "incidentSeverityId": true, "currentIncidentStateId": true, "monitors": true, "labels": true, "slug": true}}')
|
||||
|
||||
API_ID=$(echo "$RESPONSE" | jq -r '._id // empty')
|
||||
if [ -z "$API_ID" ] || [ "$API_ID" = "null" ]; then
|
||||
echo " ✗ FAILED: Incident not found in API response"
|
||||
echo " Response: $RESPONSE"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Incident exists in API"
|
||||
|
||||
# Validate title
|
||||
API_TITLE=$(echo "$RESPONSE" | jq -r '.title // empty')
|
||||
if [ "$API_TITLE" != "$EXPECTED_TITLE" ]; then
|
||||
echo " ✗ FAILED: Title mismatch - Expected: '$EXPECTED_TITLE', Got: '$API_TITLE'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Title matches: $API_TITLE"
|
||||
|
||||
# Validate incident severity relationship
|
||||
API_SEVERITY_ID=$(echo "$RESPONSE" | jq -r '.incidentSeverityId // empty')
|
||||
if [ "$API_SEVERITY_ID" != "$INCIDENT_SEVERITY_ID" ]; then
|
||||
echo " ✗ FAILED: Incident severity ID mismatch - Expected: '$INCIDENT_SEVERITY_ID', Got: '$API_SEVERITY_ID'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Incident severity ID matches"
|
||||
|
||||
# Validate server-provided currentIncidentStateId
|
||||
CURRENT_STATE_ID=$(echo "$RESPONSE" | jq -r '.currentIncidentStateId // empty')
|
||||
if [ -n "$CURRENT_STATE_ID" ] && [ "$CURRENT_STATE_ID" != "null" ]; then
|
||||
echo " ✓ Server-assigned currentIncidentStateId: $CURRENT_STATE_ID"
|
||||
fi
|
||||
|
||||
# Validate slug was computed by server
|
||||
API_SLUG=$(echo "$RESPONSE" | jq -r '.slug // empty')
|
||||
if [ -n "$API_SLUG" ] && [ "$API_SLUG" != "null" ]; then
|
||||
echo " ✓ Server-computed slug: $API_SLUG"
|
||||
fi
|
||||
|
||||
echo " ✓ All incident server defaults validations passed"
|
||||
@@ -0,0 +1,97 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
oneuptime = {
|
||||
source = "oneuptime/oneuptime"
|
||||
version = "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "oneuptime" {
|
||||
oneuptime_url = var.oneuptime_url
|
||||
api_key = var.api_key
|
||||
}
|
||||
|
||||
# Test: Alert with Server-Provided Defaults
|
||||
#
|
||||
# This test verifies UseStateForUnknown() works for alert resource:
|
||||
# - String fields: current_alert_state_id, description
|
||||
# - Bool fields: is_owner_notified_of_alert_creation
|
||||
# - List fields: labels, on_call_duty_policies
|
||||
#
|
||||
# Similar to incident but for the alert resource type.
|
||||
|
||||
# First create an alert severity (required dependency)
|
||||
resource "oneuptime_alert_severity" "test" {
|
||||
project_id = var.project_id
|
||||
name = "Alert Test Severity"
|
||||
description = "Severity for alert server defaults test"
|
||||
color = "#FFA500"
|
||||
order = 98
|
||||
}
|
||||
|
||||
# Create alert with minimal fields - let server provide defaults
|
||||
resource "oneuptime_alert" "test_server_defaults" {
|
||||
project_id = var.project_id
|
||||
title = "Alert Server Defaults Test"
|
||||
alert_severity_id = oneuptime_alert_severity.test.id
|
||||
|
||||
# IMPORTANT: We intentionally DO NOT specify these Optional+Computed fields:
|
||||
# - description (string)
|
||||
# - labels (list)
|
||||
# - on_call_duty_policies (list)
|
||||
# - current_alert_state_id (string - server sets to default state)
|
||||
#
|
||||
# The server will provide default values for these fields.
|
||||
}
|
||||
|
||||
# Output to verify creation succeeded
|
||||
output "alert_id" {
|
||||
value = oneuptime_alert.test_server_defaults.id
|
||||
description = "ID of the created alert"
|
||||
}
|
||||
|
||||
# Alert severity outputs for API validation
|
||||
output "alert_severity_id" {
|
||||
value = oneuptime_alert_severity.test.id
|
||||
description = "ID of the created alert severity"
|
||||
}
|
||||
|
||||
output "alert_severity_name" {
|
||||
value = oneuptime_alert_severity.test.name
|
||||
description = "Name of the alert severity"
|
||||
}
|
||||
|
||||
output "alert_severity_color" {
|
||||
value = oneuptime_alert_severity.test.color
|
||||
description = "Color of the alert severity"
|
||||
}
|
||||
|
||||
# Alert title for API validation
|
||||
output "alert_title" {
|
||||
value = oneuptime_alert.test_server_defaults.title
|
||||
description = "Title of the created alert"
|
||||
}
|
||||
|
||||
# String field - server provides default alert state
|
||||
output "current_alert_state_id" {
|
||||
value = oneuptime_alert.test_server_defaults.current_alert_state_id
|
||||
description = "Server-assigned default alert state"
|
||||
}
|
||||
|
||||
# List fields - server may provide empty list or defaults
|
||||
output "labels" {
|
||||
value = oneuptime_alert.test_server_defaults.labels
|
||||
description = "Server-provided labels list"
|
||||
}
|
||||
|
||||
output "on_call_duty_policies" {
|
||||
value = oneuptime_alert.test_server_defaults.on_call_duty_policies
|
||||
description = "Server-provided on-call duty policies list"
|
||||
}
|
||||
|
||||
# Other server-computed fields
|
||||
output "created_at" {
|
||||
value = oneuptime_alert.test_server_defaults.created_at
|
||||
description = "Server-generated creation timestamp"
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
variable "oneuptime_url" {
|
||||
type = string
|
||||
description = "OneUptime API URL"
|
||||
}
|
||||
|
||||
variable "api_key" {
|
||||
type = string
|
||||
description = "OneUptime API Key"
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "project_id" {
|
||||
type = string
|
||||
description = "OneUptime Project ID"
|
||||
}
|
||||
81
E2E/Terraform/e2e-tests/tests/17-alert-server-defaults/verify.sh
Executable file
81
E2E/Terraform/e2e-tests/tests/17-alert-server-defaults/verify.sh
Executable file
@@ -0,0 +1,81 @@
|
||||
#!/bin/bash
|
||||
# Verify script for 17-alert-server-defaults test
|
||||
# Validates server-provided defaults for alert resource
|
||||
|
||||
set -e
|
||||
|
||||
# Get terraform outputs
|
||||
ALERT_ID=$(terraform output -raw alert_id)
|
||||
ALERT_SEVERITY_ID=$(terraform output -raw alert_severity_id)
|
||||
EXPECTED_SEVERITY_NAME=$(terraform output -raw alert_severity_name)
|
||||
EXPECTED_SEVERITY_COLOR=$(terraform output -raw alert_severity_color)
|
||||
EXPECTED_TITLE=$(terraform output -raw alert_title)
|
||||
|
||||
echo " Verifying alert with server defaults via API..."
|
||||
|
||||
# First validate the alert severity dependency
|
||||
echo " Verifying alert severity..."
|
||||
echo " Alert Severity ID: $ALERT_SEVERITY_ID"
|
||||
|
||||
RESPONSE=$(curl -s -X POST "${ONEUPTIME_URL}/api/alert-severity/${ALERT_SEVERITY_ID}/get-item" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Apikey: $TF_VAR_api_key" \
|
||||
-H "projectid: $TF_VAR_project_id" \
|
||||
-d '{"select": {"_id": true, "name": true, "color": true}}')
|
||||
|
||||
API_ID=$(echo "$RESPONSE" | jq -r '._id // empty')
|
||||
if [ -z "$API_ID" ] || [ "$API_ID" = "null" ]; then
|
||||
echo " ✗ FAILED: Alert severity not found in API response"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Alert severity exists in API"
|
||||
|
||||
API_NAME=$(echo "$RESPONSE" | jq -r '.name // empty')
|
||||
if [ "$API_NAME" != "$EXPECTED_SEVERITY_NAME" ]; then
|
||||
echo " ✗ FAILED: Severity name mismatch - Expected: '$EXPECTED_SEVERITY_NAME', Got: '$API_NAME'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Severity name matches: $API_NAME"
|
||||
|
||||
# Now validate the alert
|
||||
echo ""
|
||||
echo " Verifying alert resource..."
|
||||
echo " Alert ID: $ALERT_ID"
|
||||
|
||||
RESPONSE=$(curl -s -X POST "${ONEUPTIME_URL}/api/alert/${ALERT_ID}/get-item" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Apikey: $TF_VAR_api_key" \
|
||||
-H "projectid: $TF_VAR_project_id" \
|
||||
-d '{"select": {"_id": true, "title": true, "alertSeverityId": true, "currentAlertStateId": true, "labels": true}}')
|
||||
|
||||
API_ID=$(echo "$RESPONSE" | jq -r '._id // empty')
|
||||
if [ -z "$API_ID" ] || [ "$API_ID" = "null" ]; then
|
||||
echo " ✗ FAILED: Alert not found in API response"
|
||||
echo " Response: $RESPONSE"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Alert exists in API"
|
||||
|
||||
# Validate title
|
||||
API_TITLE=$(echo "$RESPONSE" | jq -r '.title // empty')
|
||||
if [ "$API_TITLE" != "$EXPECTED_TITLE" ]; then
|
||||
echo " ✗ FAILED: Title mismatch - Expected: '$EXPECTED_TITLE', Got: '$API_TITLE'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Title matches: $API_TITLE"
|
||||
|
||||
# Validate alert severity relationship
|
||||
API_SEVERITY_ID=$(echo "$RESPONSE" | jq -r '.alertSeverityId // empty')
|
||||
if [ "$API_SEVERITY_ID" != "$ALERT_SEVERITY_ID" ]; then
|
||||
echo " ✗ FAILED: Alert severity ID mismatch - Expected: '$ALERT_SEVERITY_ID', Got: '$API_SEVERITY_ID'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Alert severity ID matches"
|
||||
|
||||
# Validate server-provided currentAlertStateId
|
||||
CURRENT_STATE_ID=$(echo "$RESPONSE" | jq -r '.currentAlertStateId // empty')
|
||||
if [ -n "$CURRENT_STATE_ID" ] && [ "$CURRENT_STATE_ID" != "null" ]; then
|
||||
echo " ✓ Server-assigned currentAlertStateId: $CURRENT_STATE_ID"
|
||||
fi
|
||||
|
||||
echo " ✓ All alert server defaults validations passed"
|
||||
@@ -0,0 +1,106 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
oneuptime = {
|
||||
source = "oneuptime/oneuptime"
|
||||
version = "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "oneuptime" {
|
||||
oneuptime_url = var.oneuptime_url
|
||||
api_key = var.api_key
|
||||
}
|
||||
|
||||
# Test: Scheduled Maintenance Event with Server-Provided Defaults
|
||||
#
|
||||
# This test verifies UseStateForUnknown() works for scheduled maintenance:
|
||||
# - String fields: description, current_scheduled_maintenance_state_id
|
||||
# - Bool fields: should_status_page_subscribers_be_notified_on_event_created
|
||||
# - List fields: monitors, labels, status_pages
|
||||
#
|
||||
# Tests datetime fields and various Optional+Computed field types.
|
||||
|
||||
# Create scheduled maintenance event with minimal fields
|
||||
resource "oneuptime_scheduled_maintenance_event" "test_server_defaults" {
|
||||
project_id = var.project_id
|
||||
title = "Scheduled Maintenance Server Defaults Test"
|
||||
|
||||
# Required datetime fields - use future dates
|
||||
starts_at = "2030-01-01T00:00:00.000Z"
|
||||
ends_at = "2030-01-01T02:00:00.000Z"
|
||||
|
||||
# IMPORTANT: We intentionally DO NOT specify these Optional+Computed fields:
|
||||
# - description (string)
|
||||
# - monitors (list)
|
||||
# - labels (list)
|
||||
# - status_pages (list)
|
||||
# - current_scheduled_maintenance_state_id (string - server sets default)
|
||||
# - should_status_page_subscribers_be_notified_on_event_created (bool)
|
||||
# - should_status_page_subscribers_be_notified_when_event_changes_to_ongoing (bool)
|
||||
# - should_status_page_subscribers_be_notified_when_event_changes_to_ended (bool)
|
||||
#
|
||||
# The server will provide default values for these fields.
|
||||
}
|
||||
|
||||
# Output to verify creation succeeded
|
||||
output "scheduled_maintenance_event_id" {
|
||||
value = oneuptime_scheduled_maintenance_event.test_server_defaults.id
|
||||
description = "ID of the created scheduled maintenance event"
|
||||
}
|
||||
|
||||
# Scheduled maintenance title for API validation
|
||||
output "scheduled_maintenance_event_title" {
|
||||
value = oneuptime_scheduled_maintenance_event.test_server_defaults.title
|
||||
description = "Title of the scheduled maintenance event"
|
||||
}
|
||||
|
||||
# DateTime fields for API validation
|
||||
output "scheduled_maintenance_event_starts_at" {
|
||||
value = oneuptime_scheduled_maintenance_event.test_server_defaults.starts_at
|
||||
description = "Start time of the scheduled maintenance"
|
||||
}
|
||||
|
||||
output "scheduled_maintenance_event_ends_at" {
|
||||
value = oneuptime_scheduled_maintenance_event.test_server_defaults.ends_at
|
||||
description = "End time of the scheduled maintenance"
|
||||
}
|
||||
|
||||
# String field - server provides default state
|
||||
output "current_state_id" {
|
||||
value = oneuptime_scheduled_maintenance_event.test_server_defaults.current_scheduled_maintenance_state_id
|
||||
description = "Server-assigned default scheduled maintenance state"
|
||||
}
|
||||
|
||||
# List fields - server may provide empty list or defaults
|
||||
output "monitors" {
|
||||
value = oneuptime_scheduled_maintenance_event.test_server_defaults.monitors
|
||||
description = "Server-provided monitors list"
|
||||
}
|
||||
|
||||
output "labels" {
|
||||
value = oneuptime_scheduled_maintenance_event.test_server_defaults.labels
|
||||
description = "Server-provided labels list"
|
||||
}
|
||||
|
||||
output "status_pages" {
|
||||
value = oneuptime_scheduled_maintenance_event.test_server_defaults.status_pages
|
||||
description = "Server-provided status pages list"
|
||||
}
|
||||
|
||||
# Bool fields - server provides defaults
|
||||
output "notify_on_created" {
|
||||
value = oneuptime_scheduled_maintenance_event.test_server_defaults.should_status_page_subscribers_be_notified_on_event_created
|
||||
description = "Server-provided default for notification on create"
|
||||
}
|
||||
|
||||
# Other server-computed fields
|
||||
output "slug" {
|
||||
value = oneuptime_scheduled_maintenance_event.test_server_defaults.slug
|
||||
description = "Server-generated slug"
|
||||
}
|
||||
|
||||
output "created_at" {
|
||||
value = oneuptime_scheduled_maintenance_event.test_server_defaults.created_at
|
||||
description = "Server-generated creation timestamp"
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
variable "oneuptime_url" {
|
||||
type = string
|
||||
description = "OneUptime API URL"
|
||||
}
|
||||
|
||||
variable "api_key" {
|
||||
type = string
|
||||
description = "OneUptime API Key"
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "project_id" {
|
||||
type = string
|
||||
description = "OneUptime Project ID"
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
#!/bin/bash
|
||||
# Verify script for 18-scheduled-maintenance-server-defaults test
|
||||
# Validates server-provided defaults for scheduled maintenance event resource
|
||||
|
||||
set -e
|
||||
|
||||
# Get terraform outputs
|
||||
RESOURCE_ID=$(terraform output -raw scheduled_maintenance_event_id)
|
||||
EXPECTED_TITLE=$(terraform output -raw scheduled_maintenance_event_title)
|
||||
EXPECTED_STARTS_AT=$(terraform output -raw scheduled_maintenance_event_starts_at)
|
||||
EXPECTED_ENDS_AT=$(terraform output -raw scheduled_maintenance_event_ends_at)
|
||||
|
||||
echo " Verifying scheduled maintenance event with server defaults via API..."
|
||||
echo " Resource ID: $RESOURCE_ID"
|
||||
|
||||
# Call API to get the resource
|
||||
RESPONSE=$(curl -s -X POST "${ONEUPTIME_URL}/api/scheduled-maintenance-event/${RESOURCE_ID}/get-item" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Apikey: $TF_VAR_api_key" \
|
||||
-H "projectid: $TF_VAR_project_id" \
|
||||
-d '{"select": {"_id": true, "title": true, "startsAt": true, "endsAt": true, "currentScheduledMaintenanceStateId": true, "monitors": true, "labels": true, "statusPages": true, "slug": true}}')
|
||||
|
||||
# Check if response contains the resource
|
||||
API_ID=$(echo "$RESPONSE" | jq -r '._id // empty')
|
||||
if [ -z "$API_ID" ] || [ "$API_ID" = "null" ]; then
|
||||
echo " ✗ FAILED: Scheduled maintenance event not found in API response"
|
||||
echo " Response: $RESPONSE"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Scheduled maintenance event exists in API"
|
||||
|
||||
# Validate title
|
||||
API_TITLE=$(echo "$RESPONSE" | jq -r '.title // empty')
|
||||
if [ "$API_TITLE" != "$EXPECTED_TITLE" ]; then
|
||||
echo " ✗ FAILED: Title mismatch - Expected: '$EXPECTED_TITLE', Got: '$API_TITLE'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Title matches: $API_TITLE"
|
||||
|
||||
# Validate startsAt
|
||||
API_STARTS_AT=$(echo "$RESPONSE" | jq -r '.startsAt // empty')
|
||||
if [ -n "$API_STARTS_AT" ] && [ "$API_STARTS_AT" != "null" ]; then
|
||||
echo " ✓ startsAt is set: $API_STARTS_AT"
|
||||
fi
|
||||
|
||||
# Validate endsAt
|
||||
API_ENDS_AT=$(echo "$RESPONSE" | jq -r '.endsAt // empty')
|
||||
if [ -n "$API_ENDS_AT" ] && [ "$API_ENDS_AT" != "null" ]; then
|
||||
echo " ✓ endsAt is set: $API_ENDS_AT"
|
||||
fi
|
||||
|
||||
# Validate server-provided currentScheduledMaintenanceStateId
|
||||
CURRENT_STATE_ID=$(echo "$RESPONSE" | jq -r '.currentScheduledMaintenanceStateId // empty')
|
||||
if [ -n "$CURRENT_STATE_ID" ] && [ "$CURRENT_STATE_ID" != "null" ]; then
|
||||
echo " ✓ Server-assigned currentScheduledMaintenanceStateId: $CURRENT_STATE_ID"
|
||||
fi
|
||||
|
||||
# Validate slug was computed by server
|
||||
API_SLUG=$(echo "$RESPONSE" | jq -r '.slug // empty')
|
||||
if [ -n "$API_SLUG" ] && [ "$API_SLUG" != "null" ]; then
|
||||
echo " ✓ Server-computed slug: $API_SLUG"
|
||||
fi
|
||||
|
||||
echo " ✓ All scheduled maintenance server defaults validations passed"
|
||||
@@ -0,0 +1,66 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
oneuptime = {
|
||||
source = "oneuptime/oneuptime"
|
||||
version = "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "oneuptime" {
|
||||
oneuptime_url = var.oneuptime_url
|
||||
api_key = var.api_key
|
||||
}
|
||||
|
||||
# Test: On-Call Policy with Server-Provided Defaults
|
||||
#
|
||||
# This test verifies UseStateForUnknown() works for on-call policy:
|
||||
# - String fields: description
|
||||
# - Bool fields: send_incidnet_created_notification_to_all_on_call_layers
|
||||
# - List fields: labels
|
||||
# - Number fields: repeat_policy_if_no_one_acknowledges_no_of_times
|
||||
#
|
||||
# Tests various Optional+Computed field types.
|
||||
|
||||
# Create on-call policy with minimal fields
|
||||
resource "oneuptime_on_call_policy" "test_server_defaults" {
|
||||
project_id = var.project_id
|
||||
name = "On-Call Policy Server Defaults Test"
|
||||
|
||||
# IMPORTANT: We intentionally DO NOT specify these Optional+Computed fields:
|
||||
# - description (string)
|
||||
# - labels (list)
|
||||
# - send_incidnet_created_notification_to_all_on_call_layers (bool) [note: typo in API]
|
||||
# - repeat_policy_if_no_one_acknowledges_no_of_times (number)
|
||||
#
|
||||
# The server will provide default values for these fields.
|
||||
}
|
||||
|
||||
# Output to verify creation succeeded
|
||||
output "on_call_duty_policy_id" {
|
||||
value = oneuptime_on_call_policy.test_server_defaults.id
|
||||
description = "ID of the created on-call policy"
|
||||
}
|
||||
|
||||
# On-call policy name for API validation
|
||||
output "on_call_duty_policy_name" {
|
||||
value = oneuptime_on_call_policy.test_server_defaults.name
|
||||
description = "Name of the on-call policy"
|
||||
}
|
||||
|
||||
# List field - server may provide empty list or defaults
|
||||
output "labels" {
|
||||
value = oneuptime_on_call_policy.test_server_defaults.labels
|
||||
description = "Server-provided labels list"
|
||||
}
|
||||
|
||||
# Other server-computed fields
|
||||
output "slug" {
|
||||
value = oneuptime_on_call_policy.test_server_defaults.slug
|
||||
description = "Server-generated slug"
|
||||
}
|
||||
|
||||
output "created_at" {
|
||||
value = oneuptime_on_call_policy.test_server_defaults.created_at
|
||||
description = "Server-generated creation timestamp"
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
variable "oneuptime_url" {
|
||||
type = string
|
||||
description = "OneUptime API URL"
|
||||
}
|
||||
|
||||
variable "api_key" {
|
||||
type = string
|
||||
description = "OneUptime API Key"
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "project_id" {
|
||||
type = string
|
||||
description = "OneUptime Project ID"
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
#!/bin/bash
|
||||
# Verify script for 19-on-call-duty-policy-server-defaults test
|
||||
# Validates server-provided defaults for on-call duty policy resource
|
||||
|
||||
set -e
|
||||
|
||||
# Get terraform outputs
|
||||
RESOURCE_ID=$(terraform output -raw on_call_duty_policy_id)
|
||||
EXPECTED_NAME=$(terraform output -raw on_call_duty_policy_name)
|
||||
|
||||
echo " Verifying on-call duty policy with server defaults via API..."
|
||||
echo " Resource ID: $RESOURCE_ID"
|
||||
|
||||
# Call API to get the resource
|
||||
RESPONSE=$(curl -s -X POST "${ONEUPTIME_URL}/api/on-call-duty-policy/${RESOURCE_ID}/get-item" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Apikey: $TF_VAR_api_key" \
|
||||
-H "projectid: $TF_VAR_project_id" \
|
||||
-d '{"select": {"_id": true, "name": true, "description": true, "labels": true, "slug": true}}')
|
||||
|
||||
# Check if response contains the resource
|
||||
API_ID=$(echo "$RESPONSE" | jq -r '._id // empty')
|
||||
if [ -z "$API_ID" ] || [ "$API_ID" = "null" ]; then
|
||||
echo " ✗ FAILED: On-call duty policy not found in API response"
|
||||
echo " Response: $RESPONSE"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ On-call duty policy exists in API"
|
||||
|
||||
# Validate name
|
||||
API_NAME=$(echo "$RESPONSE" | jq -r '.name // empty')
|
||||
if [ "$API_NAME" != "$EXPECTED_NAME" ]; then
|
||||
echo " ✗ FAILED: Name mismatch - Expected: '$EXPECTED_NAME', Got: '$API_NAME'"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Name matches: $API_NAME"
|
||||
|
||||
# Validate slug was computed by server
|
||||
API_SLUG=$(echo "$RESPONSE" | jq -r '.slug // empty')
|
||||
if [ -n "$API_SLUG" ] && [ "$API_SLUG" != "null" ]; then
|
||||
echo " ✓ Server-computed slug: $API_SLUG"
|
||||
fi
|
||||
|
||||
echo " ✓ All on-call duty policy server defaults validations passed"
|
||||
@@ -19,7 +19,6 @@ import Express, {
|
||||
ExpressResponse,
|
||||
ExpressRouter,
|
||||
NextFunction,
|
||||
OneUptimeRequest,
|
||||
} from "Common/Server/Utils/Express";
|
||||
import logger from "Common/Server/Utils/Logger";
|
||||
import Response from "Common/Server/Utils/Response";
|
||||
@@ -30,7 +29,6 @@ import ProjectService from "Common/Server/Services/ProjectService";
|
||||
import MonitorType from "Common/Types/Monitor/MonitorType";
|
||||
import MonitorTest from "Common/Models/DatabaseModels/MonitorTest";
|
||||
import MonitorTestService from "Common/Server/Services/MonitorTestService";
|
||||
import NumberUtil from "Common/Utils/Number";
|
||||
|
||||
const router: ExpressRouter = Express.getRouter();
|
||||
|
||||
@@ -385,45 +383,36 @@ router.post(
|
||||
logger.debug("Fetching monitor list for probes");
|
||||
|
||||
/*
|
||||
* we do this to distribute the load among the probes.
|
||||
* so every request will get a different set of monitors to monitor
|
||||
* const moduloBy: number = 10;
|
||||
* const reminder: number = NumberUtil.getRandomNumber(0, 100) % moduloBy;
|
||||
* Atomically claim monitors for this probe instance using FOR UPDATE SKIP LOCKED
|
||||
* This prevents multiple instances of the same probe from picking up the same monitors
|
||||
*/
|
||||
const claimedMonitorProbeIds: Array<ObjectID> =
|
||||
await MonitorProbeService.claimMonitorProbesForProbing({
|
||||
probeId: probeId,
|
||||
limit: limit,
|
||||
});
|
||||
|
||||
const count: PositiveNumber = await MonitorProbeService.countBy({
|
||||
query: {
|
||||
...getMonitorFetchQuery((req as OneUptimeRequest).probe!.id!),
|
||||
// version: QueryHelper.modulo(moduloBy, reminder), // distribute the load among the probes
|
||||
},
|
||||
skip: 0,
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
logger.debug(
|
||||
`Claimed ${claimedMonitorProbeIds.length} monitor probes for probing`,
|
||||
);
|
||||
|
||||
/*
|
||||
* we do this to distribute the load among the probes.
|
||||
* so every request will get a different set of monitors to monitor
|
||||
*/
|
||||
const countNumber: number = count.toNumber();
|
||||
let skip: number = 0;
|
||||
|
||||
if (countNumber > limit) {
|
||||
skip = NumberUtil.getRandomNumber(0, countNumber - limit);
|
||||
if (claimedMonitorProbeIds.length === 0) {
|
||||
logger.debug("No monitors to probe");
|
||||
return Response.sendEntityArrayResponse(
|
||||
req,
|
||||
res,
|
||||
[],
|
||||
new PositiveNumber(0),
|
||||
Monitor,
|
||||
);
|
||||
}
|
||||
|
||||
// Fetch the full monitor details for the claimed monitors
|
||||
const monitorProbes: Array<MonitorProbe> =
|
||||
await MonitorProbeService.findBy({
|
||||
query: {
|
||||
...getMonitorFetchQuery((req as OneUptimeRequest).probe!.id!),
|
||||
// version: QueryHelper.modulo(moduloBy, reminder), // distribute the load among the probes
|
||||
_id: QueryHelper.any(claimedMonitorProbeIds),
|
||||
},
|
||||
sort: {
|
||||
nextPingAt: SortOrder.Ascending,
|
||||
},
|
||||
skip: skip,
|
||||
limit: limit,
|
||||
select: {
|
||||
nextPingAt: true,
|
||||
probeId: true,
|
||||
@@ -435,6 +424,8 @@ router.post(
|
||||
projectId: true,
|
||||
},
|
||||
},
|
||||
limit: limit,
|
||||
skip: 0,
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
@@ -443,8 +434,7 @@ router.post(
|
||||
logger.debug("Fetched monitor list");
|
||||
logger.debug(monitorProbes);
|
||||
|
||||
// update the lastMonitoredAt field of the monitors
|
||||
|
||||
// Update the nextPingAt based on the actual monitoring interval
|
||||
const updatePromises: Array<Promise<void>> = [];
|
||||
|
||||
for (const monitorProbe of monitorProbes) {
|
||||
@@ -469,7 +459,6 @@ router.post(
|
||||
MonitorProbeService.updateOneById({
|
||||
id: monitorProbe.id!,
|
||||
data: {
|
||||
lastPingAt: OneUptimeDate.getCurrentDate(),
|
||||
nextPingAt: nextPing,
|
||||
},
|
||||
props: {
|
||||
@@ -479,6 +468,7 @@ router.post(
|
||||
);
|
||||
}
|
||||
|
||||
// Update nextPingAt in parallel - this refines the temporary value set during claiming
|
||||
await Promise.all(updatePromises);
|
||||
|
||||
const monitors: Array<Monitor> = monitorProbes
|
||||
|
||||
@@ -59,11 +59,6 @@ export class ResourceGenerator {
|
||||
];
|
||||
|
||||
// Add conditional imports only if they're actually used
|
||||
const hasNumberFields: boolean = Object.values(resource.schema).some(
|
||||
(attr: any) => {
|
||||
return attr.type === "number";
|
||||
},
|
||||
);
|
||||
const hasReadOperation: boolean = Boolean(resource.operations.read);
|
||||
const hasDefaultValues: boolean = Object.values(resource.schema).some(
|
||||
(attr: any) => {
|
||||
@@ -71,9 +66,8 @@ export class ResourceGenerator {
|
||||
},
|
||||
);
|
||||
|
||||
if (hasNumberFields) {
|
||||
imports.push("math/big");
|
||||
}
|
||||
// Always add math/big since the bigFloatToFloat64 helper method uses it
|
||||
imports.push("math/big");
|
||||
|
||||
if (hasReadOperation) {
|
||||
imports.push("net/http");
|
||||
@@ -218,12 +212,47 @@ export class ResourceGenerator {
|
||||
}
|
||||
|
||||
if (resource.operations.create || resource.operations.update) {
|
||||
// Check which plan modifier imports are needed based on Optional+Computed fields
|
||||
const hasOptionalComputedBools: boolean = Object.values(
|
||||
resource.schema,
|
||||
).some((attr: any) => {
|
||||
return attr.optional && attr.computed && attr.type === "bool";
|
||||
});
|
||||
const hasOptionalComputedNumbers: boolean = Object.values(
|
||||
resource.schema,
|
||||
).some((attr: any) => {
|
||||
return attr.optional && attr.computed && attr.type === "number";
|
||||
});
|
||||
const hasOptionalComputedLists: boolean = Object.values(
|
||||
resource.schema,
|
||||
).some((attr: any) => {
|
||||
return attr.optional && attr.computed && attr.type === "list";
|
||||
});
|
||||
|
||||
// Always need planmodifier and stringplanmodifier for the id field and Optional+Computed strings
|
||||
imports.push(
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier",
|
||||
);
|
||||
imports.push(
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier",
|
||||
);
|
||||
|
||||
// Only add other plan modifier imports if needed
|
||||
if (hasOptionalComputedBools) {
|
||||
imports.push(
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/boolplanmodifier",
|
||||
);
|
||||
}
|
||||
if (hasOptionalComputedNumbers) {
|
||||
imports.push(
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/numberplanmodifier",
|
||||
);
|
||||
}
|
||||
if (hasOptionalComputedLists) {
|
||||
imports.push(
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const importStatements: string = imports
|
||||
@@ -340,15 +369,24 @@ func (r *${resourceTypeName}Resource) parseJSONField(terraformString types.Strin
|
||||
if terraformString.IsNull() || terraformString.IsUnknown() || terraformString.ValueString() == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
var result interface{}
|
||||
if err := json.Unmarshal([]byte(terraformString.ValueString()), &result); err != nil {
|
||||
// If JSON parsing fails, return the raw string
|
||||
return terraformString.ValueString()
|
||||
}
|
||||
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// Helper method to convert *big.Float to float64 for JSON serialization
|
||||
func (r *${resourceTypeName}Resource) bigFloatToFloat64(bf *big.Float) interface{} {
|
||||
if bf == nil {
|
||||
return nil
|
||||
}
|
||||
f, _ := bf.Float64()
|
||||
return f
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -531,6 +569,32 @@ func (r *${resourceTypeName}Resource) parseJSONField(terraformString types.Strin
|
||||
PlanModifiers: []planmodifier.String{
|
||||
stringplanmodifier.UseStateForUnknown(),
|
||||
}`;
|
||||
} else if (attr.optional && attr.computed) {
|
||||
/*
|
||||
* Add UseStateForUnknown() for Optional+Computed fields
|
||||
* This prevents "inconsistent result after apply" errors when server provides defaults
|
||||
*/
|
||||
if (attr.type === "string") {
|
||||
planModifiers = `,
|
||||
PlanModifiers: []planmodifier.String{
|
||||
stringplanmodifier.UseStateForUnknown(),
|
||||
}`;
|
||||
} else if (attr.type === "bool") {
|
||||
planModifiers = `,
|
||||
PlanModifiers: []planmodifier.Bool{
|
||||
boolplanmodifier.UseStateForUnknown(),
|
||||
}`;
|
||||
} else if (attr.type === "number") {
|
||||
planModifiers = `,
|
||||
PlanModifiers: []planmodifier.Number{
|
||||
numberplanmodifier.UseStateForUnknown(),
|
||||
}`;
|
||||
} else if (attr.type === "list") {
|
||||
planModifiers = `,
|
||||
PlanModifiers: []planmodifier.List{
|
||||
listplanmodifier.UseStateForUnknown(),
|
||||
}`;
|
||||
}
|
||||
}
|
||||
|
||||
return `schema.${attrType}Attribute{
|
||||
@@ -1070,9 +1134,15 @@ func (r *${resourceTypeName}Resource) Delete(ctx context.Context, req resource.D
|
||||
terraformAttr.type === "string" &&
|
||||
terraformAttr.isComplexObject
|
||||
) {
|
||||
/*
|
||||
* Try to parse as JSON first, but if it fails (e.g., for simple strings like "#FF0000"),
|
||||
* fall back to sending the raw string value
|
||||
*/
|
||||
return `var ${fieldName.toLowerCase()}Data interface{}
|
||||
if err := json.Unmarshal([]byte(data.${fieldName}.ValueString()), &${fieldName.toLowerCase()}Data); err == nil {
|
||||
requestDataMap["${apiFieldName}"] = ${fieldName.toLowerCase()}Data
|
||||
} else {
|
||||
requestDataMap["${apiFieldName}"] = data.${fieldName}.ValueString()
|
||||
}`;
|
||||
}
|
||||
return `requestDataMap["${apiFieldName}"] = ${value}`;
|
||||
@@ -1276,9 +1346,16 @@ func (r *${resourceTypeName}Resource) Delete(ctx context.Context, req resource.D
|
||||
// ${fieldName} value is already set from the existing state
|
||||
}`;
|
||||
} else if (isComplexObject) {
|
||||
// For complex object strings, convert API object response to JSON string
|
||||
/*
|
||||
* For complex object strings, check if it's a wrapper object with _type and value fields
|
||||
* (e.g., {"_type":"Version","value":"1.0.0"} or {"_type":"DateTime","value":"..."})
|
||||
* If so, extract the value; otherwise convert the entire object to JSON string
|
||||
*/
|
||||
return `if val, ok := ${responseValue}.(map[string]interface{}); ok {
|
||||
if jsonBytes, err := json.Marshal(val); err == nil {
|
||||
// Check if it's a wrapper object with value field (e.g., Version, DateTime types)
|
||||
if innerVal, ok := val["value"].(string); ok {
|
||||
${fieldName} = types.StringValue(innerVal)
|
||||
} else if jsonBytes, err := json.Marshal(val); err == nil {
|
||||
${fieldName} = types.StringValue(string(jsonBytes))
|
||||
} else {
|
||||
${fieldName} = types.StringNull()
|
||||
@@ -1417,7 +1494,8 @@ func (r *${resourceTypeName}Resource) Delete(ctx context.Context, req resource.D
|
||||
case "string":
|
||||
return `${fieldRef}.ValueString()`;
|
||||
case "number":
|
||||
return `${fieldRef}.ValueBigFloat()`;
|
||||
// Use helper to convert *big.Float to float64 for proper JSON serialization
|
||||
return `r.bigFloatToFloat64(${fieldRef}.ValueBigFloat())`;
|
||||
case "bool":
|
||||
return `${fieldRef}.ValueBool()`;
|
||||
case "map":
|
||||
|
||||
16
Scripts/package-lock.json
generated
16
Scripts/package-lock.json
generated
@@ -287,6 +287,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.5.tgz",
|
||||
"integrity": "sha512-UdOWmk4pNWTm/4DlPUl/Pt4Gz4rcEMb7CY0Y3eJl5Yz1vI8ZJGmHWaVE55LoxRjdpx0z259GE9U5STA9atUinQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@ampproject/remapping": "^2.1.0",
|
||||
"@babel/code-frame": "^7.18.6",
|
||||
@@ -1274,6 +1275,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.5.2.tgz",
|
||||
"integrity": "sha512-mpT8LJJ4CMeeahobofYWIjFo0xonRS/HfxnVEPMPFSQdGUt1uHCnoPT7Zhb+sjDU2wz0oKV0OLUR0WzrHNgfeA==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"jest-matcher-utils": "^27.0.0",
|
||||
"pretty-format": "^27.0.0"
|
||||
@@ -1294,7 +1296,8 @@
|
||||
"node_modules/@types/node": {
|
||||
"version": "17.0.45",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz",
|
||||
"integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw=="
|
||||
"integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/@types/prettier": {
|
||||
"version": "2.7.1",
|
||||
@@ -1388,6 +1391,7 @@
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
|
||||
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"fast-uri": "^3.0.1",
|
||||
@@ -1627,6 +1631,7 @@
|
||||
"url": "https://tidelift.com/funding/github/npm/browserslist"
|
||||
}
|
||||
],
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"caniuse-lite": "^1.0.30001400",
|
||||
"electron-to-chromium": "^1.4.251",
|
||||
@@ -2808,6 +2813,7 @@
|
||||
"resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz",
|
||||
"integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@jest/core": "^27.5.1",
|
||||
"import-local": "^3.0.2",
|
||||
@@ -4874,6 +4880,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.5.tgz",
|
||||
"integrity": "sha512-UdOWmk4pNWTm/4DlPUl/Pt4Gz4rcEMb7CY0Y3eJl5Yz1vI8ZJGmHWaVE55LoxRjdpx0z259GE9U5STA9atUinQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"@ampproject/remapping": "^2.1.0",
|
||||
"@babel/code-frame": "^7.18.6",
|
||||
@@ -5641,6 +5648,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.5.2.tgz",
|
||||
"integrity": "sha512-mpT8LJJ4CMeeahobofYWIjFo0xonRS/HfxnVEPMPFSQdGUt1uHCnoPT7Zhb+sjDU2wz0oKV0OLUR0WzrHNgfeA==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"jest-matcher-utils": "^27.0.0",
|
||||
"pretty-format": "^27.0.0"
|
||||
@@ -5659,7 +5667,8 @@
|
||||
"@types/node": {
|
||||
"version": "17.0.45",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz",
|
||||
"integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw=="
|
||||
"integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==",
|
||||
"peer": true
|
||||
},
|
||||
"@types/prettier": {
|
||||
"version": "2.7.1",
|
||||
@@ -5736,6 +5745,7 @@
|
||||
"version": "8.17.1",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
|
||||
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"fast-uri": "^3.0.1",
|
||||
@@ -5908,6 +5918,7 @@
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz",
|
||||
"integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"caniuse-lite": "^1.0.30001400",
|
||||
"electron-to-chromium": "^1.4.251",
|
||||
@@ -6894,6 +6905,7 @@
|
||||
"resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz",
|
||||
"integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"@jest/core": "^27.5.1",
|
||||
"import-local": "^3.0.2",
|
||||
|
||||
13
package-lock.json
generated
13
package-lock.json
generated
@@ -82,6 +82,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.4.tgz",
|
||||
"integrity": "sha512-bXYxrXFubeYdvB0NhD/NBB3Qi6aZeV20GOWVI47t2dkecCEoneR4NPVcb7abpXDEvejgrUfFtG6vG/zxAKmg+g==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@ampproject/remapping": "^2.2.0",
|
||||
"@babel/code-frame": "^7.27.1",
|
||||
@@ -1570,7 +1571,8 @@
|
||||
"node_modules/@types/node": {
|
||||
"version": "18.11.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.15.tgz",
|
||||
"integrity": "sha512-VkhBbVo2+2oozlkdHXLrb3zjsRkpdnaU2bXmX8Wgle3PUi569eLRaHGlgETQHR7lLL1w7GiG3h9SnePhxNDecw=="
|
||||
"integrity": "sha512-VkhBbVo2+2oozlkdHXLrb3zjsRkpdnaU2bXmX8Wgle3PUi569eLRaHGlgETQHR7lLL1w7GiG3h9SnePhxNDecw==",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/@types/stack-utils": {
|
||||
"version": "2.0.3",
|
||||
@@ -1599,6 +1601,7 @@
|
||||
"integrity": "sha512-molgphGqOBT7t4YKCSkbasmu1tb1MgrZ2szGzHbclF7PNmOkSTQVHy+2jXOSnxvR3+Xe1yySHFZoqMpz3TfQsw==",
|
||||
"devOptional": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/regexpp": "^4.10.0",
|
||||
"@typescript-eslint/scope-manager": "8.44.1",
|
||||
@@ -1639,6 +1642,7 @@
|
||||
"integrity": "sha512-EHrrEsyhOhxYt8MTg4zTF+DJMuNBzWwgvvOYNj/zm1vnaD/IC5zCXFehZv94Piqa2cRFfXrTFxIvO95L7Qc/cw==",
|
||||
"devOptional": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "8.44.1",
|
||||
"@typescript-eslint/types": "8.44.1",
|
||||
@@ -2155,6 +2159,7 @@
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
|
||||
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
@@ -2650,6 +2655,7 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"caniuse-lite": "^1.0.30001718",
|
||||
"electron-to-chromium": "^1.5.160",
|
||||
@@ -3569,6 +3575,7 @@
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.36.0.tgz",
|
||||
"integrity": "sha512-hB4FIzXovouYzwzECDcUkJ4OcfOEkXTv2zRY6B9bkwjx/cprAq0uvm1nl7zvQ0/TsUk0zQiN4uPfJpB9m+rPMQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.8.0",
|
||||
"@eslint-community/regexpp": "^4.12.1",
|
||||
@@ -3629,6 +3636,7 @@
|
||||
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz",
|
||||
"integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"eslint-config-prettier": "bin/cli.js"
|
||||
},
|
||||
@@ -7179,6 +7187,7 @@
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz",
|
||||
"integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"prettier": "bin/prettier.cjs"
|
||||
},
|
||||
@@ -8276,6 +8285,7 @@
|
||||
"version": "10.9.2",
|
||||
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
|
||||
"integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@cspotcode/source-map-support": "^0.8.0",
|
||||
"@tsconfig/node10": "^1.0.7",
|
||||
@@ -8610,6 +8620,7 @@
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz",
|
||||
"integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
|
||||
@@ -78,7 +78,8 @@
|
||||
"generate-terraform-provider": "export $(grep -v '^#' config.env | xargs) && node --require ts-node/register ./Scripts/TerraformProvider/GenerateProvider.ts",
|
||||
"install-terraform-provider-locally": "bash ./Scripts/TerraformProvider/install-terraform-provider-locally.sh --force",
|
||||
"generate-and-install-terraform-provider-locally": "npm run install-terraform-provider-locally",
|
||||
"publish-terraform-provider": "bash ./Scripts/TerraformProvider/publish-terraform-provider.sh"
|
||||
"publish-terraform-provider": "bash ./Scripts/TerraformProvider/publish-terraform-provider.sh",
|
||||
"run-terraform-tests": "bash ./E2E/Terraform/e2e-tests/scripts/index.sh"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
Reference in New Issue
Block a user