feat: adding taints, labels and annotations to terraform provider and ui all implementing the SDK

This commit is contained in:
allanice001
2025-11-05 21:31:13 +00:00
parent c41af60b26
commit b09c3179c7
46 changed files with 1021 additions and 271 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -848,7 +848,7 @@ paths:
consumes:
- application/json
description: 'Returns annotations for the organization in X-Org-ID. Filters:
`name`, `value`, and `q` (name contains). Add `include=node_pools` to include
`key`, `value`, and `q` (key contains). Add `include=node_pools` to include
linked node pools.'
operationId: ListAnnotations
parameters:
@@ -856,15 +856,15 @@ paths:
in: header
name: X-Org-ID
type: string
- description: Exact name
- description: Exact key
in: query
name: name
name: key
type: string
- description: Exact value
in: query
name: value
type: string
- description: name contains (case-insensitive)
- description: key contains (case-insensitive)
in: query
name: q
type: string

View File

@@ -19,14 +19,14 @@ import (
// ListAnnotations godoc
// @ID ListAnnotations
// @Summary List annotations (org scoped)
// @Description Returns annotations for the organization in X-Org-ID. Filters: `name`, `value`, and `q` (name contains). Add `include=node_pools` to include linked node pools.
// @Description Returns annotations for the organization in X-Org-ID. Filters: `key`, `value`, and `q` (key contains). Add `include=node_pools` to include linked node pools.
// @Tags Annotations
// @Accept json
// @Produce json
// @Param X-Org-ID header string false "Organization UUID"
// @Param name query string false "Exact name"
// @Param key query string false "Exact key"
// @Param value query string false "Exact value"
// @Param q query string false "name contains (case-insensitive)"
// @Param q query string false "key contains (case-insensitive)"
// @Success 200 {array} dto.AnnotationResponse
// @Failure 401 {string} string "Unauthorized"
// @Failure 403 {string} string "organization required"
@@ -60,6 +60,10 @@ func ListAnnotations(db *gorm.DB) http.HandlerFunc {
utils.WriteError(w, http.StatusInternalServerError, "db_error", "db error")
return
}
if out == nil {
out = []dto.AnnotationResponse{}
}
utils.WriteJSON(w, http.StatusOK, out)
}
}

View File

@@ -59,6 +59,9 @@ func ListLabels(db *gorm.DB) http.HandlerFunc {
utils.WriteError(w, http.StatusInternalServerError, "db_error", "db error")
return
}
if out == nil {
out = []dto.LabelResponse{}
}
utils.WriteJSON(w, http.StatusOK, out)
}

View File

@@ -278,7 +278,7 @@ paths:
/annotations:
get:
description: "Returns annotations for the organization in X-Org-ID. Filters:\
\ `name`, `value`, and `q` (name contains). Add `include=node_pools` to include\
\ `key`, `value`, and `q` (key contains). Add `include=node_pools` to include\
\ linked node pools."
operationId: ListAnnotations
parameters:
@@ -287,9 +287,9 @@ paths:
name: X-Org-ID
schema:
type: string
- description: Exact name
- description: Exact key
in: query
name: name
name: key
schema:
type: string
- description: Exact value
@@ -297,7 +297,7 @@ paths:
name: value
schema:
type: string
- description: name contains (case-insensitive)
- description: key contains (case-insensitive)
in: query
name: q
schema:
@@ -2446,54 +2446,51 @@ components:
type: object
dto.Job:
example:
updated_at: updated_at
updated_at: 2025-11-04T09:30:00Z
payload: "{}"
max_attempts: 6
created_at: created_at
id: id
last_error: last_error
run_at: run_at
type: type
queue: queue
max_attempts: 3
created_at: 2025-11-04T09:30:00Z
id: 01HF7SZK8Z8WG1M3J7S2Z8M2N6
last_error: error message
run_at: 2025-11-04T09:30:00Z
type: email.send
queue: default
attempts: 0
status: "{}"
status: queued
properties:
attempts:
description: "example: 0"
example: 0
type: integer
created_at:
description: "example: 2025-11-04T09:30:00Z"
example: 2025-11-04T09:30:00Z
type: string
id:
description: "example: 01HF7SZK8Z8WG1M3J7S2Z8M2N6"
example: 01HF7SZK8Z8WG1M3J7S2Z8M2N6
type: string
last_error:
description: "example: dial tcp: i/o timeout"
example: error message
type: string
max_attempts:
description: "example: 3"
example: 3
type: integer
payload:
description: arbitrary JSON payload
type: object
queue:
description: "example: default"
example: default
type: string
run_at:
description: "example: 2025-11-05T08:00:00Z"
example: 2025-11-04T09:30:00Z
type: string
status:
allOf:
- $ref: "#/components/schemas/dto.JobStatus"
description: |-
enum: queued,running,succeeded,failed,canceled,retrying,scheduled
example: queued
type: object
type:
description: "example: email.send"
example: email.send
type: string
updated_at:
description: "example: 2025-11-04T09:31:00Z"
example: 2025-11-04T09:30:00Z
type: string
type: object
dto.JobStatus:
@@ -2544,69 +2541,69 @@ components:
type: object
dto.PageJob:
example:
total: 5
total: 120
page: 1
items:
- updated_at: updated_at
- updated_at: 2025-11-04T09:30:00Z
payload: "{}"
max_attempts: 6
created_at: created_at
id: id
last_error: last_error
run_at: run_at
type: type
queue: queue
max_attempts: 3
created_at: 2025-11-04T09:30:00Z
id: 01HF7SZK8Z8WG1M3J7S2Z8M2N6
last_error: error message
run_at: 2025-11-04T09:30:00Z
type: email.send
queue: default
attempts: 0
status: "{}"
- updated_at: updated_at
status: queued
- updated_at: 2025-11-04T09:30:00Z
payload: "{}"
max_attempts: 6
created_at: created_at
id: id
last_error: last_error
run_at: run_at
type: type
queue: queue
max_attempts: 3
created_at: 2025-11-04T09:30:00Z
id: 01HF7SZK8Z8WG1M3J7S2Z8M2N6
last_error: error message
run_at: 2025-11-04T09:30:00Z
type: email.send
queue: default
attempts: 0
status: "{}"
page_size: 5
status: queued
page_size: 25
properties:
items:
items:
$ref: "#/components/schemas/dto.Job"
type: array
page:
description: "example: 1"
example: 1
type: integer
page_size:
description: "example: 25"
example: 25
type: integer
total:
description: "example: 120"
example: 120
type: integer
type: object
dto.QueueInfo:
example:
running: 1
scheduled: 5
pending: 6
name: name
failed: 0
running: 3
scheduled: 7
pending: 42
name: default
failed: 5
properties:
failed:
description: "example: 5"
example: 5
type: integer
name:
description: "example: default"
example: default
type: string
pending:
description: "example: 42"
example: 42
type: integer
running:
description: "example: 3"
example: 3
type: integer
scheduled:
description: "example: 7"
example: 7
type: integer
type: object
dto.RefreshRequest:

View File

@@ -642,7 +642,7 @@ type ApiListAnnotationsRequest struct {
ctx context.Context
ApiService *AnnotationsAPIService
xOrgID *string
name *string
key *string
value *string
q *string
}
@@ -653,9 +653,9 @@ func (r ApiListAnnotationsRequest) XOrgID(xOrgID string) ApiListAnnotationsReque
return r
}
// Exact name
func (r ApiListAnnotationsRequest) Name(name string) ApiListAnnotationsRequest {
r.name = &name
// Exact key
func (r ApiListAnnotationsRequest) Key(key string) ApiListAnnotationsRequest {
r.key = &key
return r
}
@@ -665,7 +665,7 @@ func (r ApiListAnnotationsRequest) Value(value string) ApiListAnnotationsRequest
return r
}
// name contains (case-insensitive)
// key contains (case-insensitive)
func (r ApiListAnnotationsRequest) Q(q string) ApiListAnnotationsRequest {
r.q = &q
return r
@@ -678,7 +678,7 @@ func (r ApiListAnnotationsRequest) Execute() ([]DtoAnnotationResponse, *http.Res
/*
ListAnnotations List annotations (org scoped)
Returns annotations for the organization in X-Org-ID. Filters: `name`, `value`, and `q` (name contains). Add `include=node_pools` to include linked node pools.
Returns annotations for the organization in X-Org-ID. Filters: `key`, `value`, and `q` (key contains). Add `include=node_pools` to include linked node pools.
@param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background().
@return ApiListAnnotationsRequest
@@ -712,8 +712,8 @@ func (a *AnnotationsAPIService) ListAnnotationsExecute(r ApiListAnnotationsReque
localVarQueryParams := url.Values{}
localVarFormParams := url.Values{}
if r.name != nil {
parameterAddToHeaderOrQuery(localVarQueryParams, "name", r.name, "", "")
if r.key != nil {
parameterAddToHeaderOrQuery(localVarQueryParams, "key", r.key, "", "")
}
if r.value != nil {
parameterAddToHeaderOrQuery(localVarQueryParams, "value", r.value, "", "")

View File

@@ -226,7 +226,7 @@ Name | Type | Description | Notes
## ListAnnotations
> []DtoAnnotationResponse ListAnnotations(ctx).XOrgID(xOrgID).Name(name).Value(value).Q(q).Execute()
> []DtoAnnotationResponse ListAnnotations(ctx).XOrgID(xOrgID).Key(key).Value(value).Q(q).Execute()
List annotations (org scoped)
@@ -246,13 +246,13 @@ import (
func main() {
xOrgID := "xOrgID_example" // string | Organization UUID (optional)
name := "name_example" // string | Exact name (optional)
key := "key_example" // string | Exact key (optional)
value := "value_example" // string | Exact value (optional)
q := "q_example" // string | name contains (case-insensitive) (optional)
q := "q_example" // string | key contains (case-insensitive) (optional)
configuration := openapiclient.NewConfiguration()
apiClient := openapiclient.NewAPIClient(configuration)
resp, r, err := apiClient.AnnotationsAPI.ListAnnotations(context.Background()).XOrgID(xOrgID).Name(name).Value(value).Q(q).Execute()
resp, r, err := apiClient.AnnotationsAPI.ListAnnotations(context.Background()).XOrgID(xOrgID).Key(key).Value(value).Q(q).Execute()
if err != nil {
fmt.Fprintf(os.Stderr, "Error when calling `AnnotationsAPI.ListAnnotations``: %v\n", err)
fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r)
@@ -274,9 +274,9 @@ Other parameters are passed through a pointer to a apiListAnnotationsRequest str
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**xOrgID** | **string** | Organization UUID |
**name** | **string** | Exact name |
**key** | **string** | Exact key |
**value** | **string** | Exact value |
**q** | **string** | name contains (case-insensitive) |
**q** | **string** | key contains (case-insensitive) |
### Return type

View File

@@ -4,17 +4,17 @@
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**Attempts** | Pointer to **int32** | example: 0 | [optional]
**CreatedAt** | Pointer to **string** | example: 2025-11-04T09:30:00Z | [optional]
**Id** | Pointer to **string** | example: 01HF7SZK8Z8WG1M3J7S2Z8M2N6 | [optional]
**LastError** | Pointer to **string** | example: dial tcp: i/o timeout | [optional]
**MaxAttempts** | Pointer to **int32** | example: 3 | [optional]
**Payload** | Pointer to **map[string]interface{}** | arbitrary JSON payload | [optional]
**Queue** | Pointer to **string** | example: default | [optional]
**RunAt** | Pointer to **string** | example: 2025-11-05T08:00:00Z | [optional]
**Status** | Pointer to [**DtoJobStatus**](DtoJobStatus.md) | enum: queued,running,succeeded,failed,canceled,retrying,scheduled example: queued | [optional]
**Type** | Pointer to **string** | example: email.send | [optional]
**UpdatedAt** | Pointer to **string** | example: 2025-11-04T09:31:00Z | [optional]
**Attempts** | Pointer to **int32** | | [optional]
**CreatedAt** | Pointer to **string** | | [optional]
**Id** | Pointer to **string** | | [optional]
**LastError** | Pointer to **string** | | [optional]
**MaxAttempts** | Pointer to **int32** | | [optional]
**Payload** | Pointer to **map[string]interface{}** | | [optional]
**Queue** | Pointer to **string** | | [optional]
**RunAt** | Pointer to **string** | | [optional]
**Status** | Pointer to [**DtoJobStatus**](DtoJobStatus.md) | | [optional]
**Type** | Pointer to **string** | | [optional]
**UpdatedAt** | Pointer to **string** | | [optional]
## Methods

View File

@@ -5,9 +5,9 @@
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**Items** | Pointer to [**[]DtoJob**](DtoJob.md) | | [optional]
**Page** | Pointer to **int32** | example: 1 | [optional]
**PageSize** | Pointer to **int32** | example: 25 | [optional]
**Total** | Pointer to **int32** | example: 120 | [optional]
**Page** | Pointer to **int32** | | [optional]
**PageSize** | Pointer to **int32** | | [optional]
**Total** | Pointer to **int32** | | [optional]
## Methods

View File

@@ -4,11 +4,11 @@
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**Failed** | Pointer to **int32** | example: 5 | [optional]
**Name** | Pointer to **string** | example: default | [optional]
**Pending** | Pointer to **int32** | example: 42 | [optional]
**Running** | Pointer to **int32** | example: 3 | [optional]
**Scheduled** | Pointer to **int32** | example: 7 | [optional]
**Failed** | Pointer to **int32** | | [optional]
**Name** | Pointer to **string** | | [optional]
**Pending** | Pointer to **int32** | | [optional]
**Running** | Pointer to **int32** | | [optional]
**Scheduled** | Pointer to **int32** | | [optional]
## Methods

View File

@@ -19,27 +19,16 @@ var _ MappedNullable = &DtoJob{}
// DtoJob struct for DtoJob
type DtoJob struct {
// example: 0
Attempts *int32 `json:"attempts,omitempty"`
// example: 2025-11-04T09:30:00Z
CreatedAt *string `json:"created_at,omitempty"`
// example: 01HF7SZK8Z8WG1M3J7S2Z8M2N6
Id *string `json:"id,omitempty"`
// example: dial tcp: i/o timeout
LastError *string `json:"last_error,omitempty"`
// example: 3
MaxAttempts *int32 `json:"max_attempts,omitempty"`
// arbitrary JSON payload
Payload map[string]interface{} `json:"payload,omitempty"`
// example: default
Queue *string `json:"queue,omitempty"`
// example: 2025-11-05T08:00:00Z
RunAt *string `json:"run_at,omitempty"`
// enum: queued,running,succeeded,failed,canceled,retrying,scheduled example: queued
Status *DtoJobStatus `json:"status,omitempty"`
// example: email.send
Type *string `json:"type,omitempty"`
// example: 2025-11-04T09:31:00Z
UpdatedAt *string `json:"updated_at,omitempty"`
}

View File

@@ -20,11 +20,8 @@ var _ MappedNullable = &DtoPageJob{}
// DtoPageJob struct for DtoPageJob
type DtoPageJob struct {
Items []DtoJob `json:"items,omitempty"`
// example: 1
Page *int32 `json:"page,omitempty"`
// example: 25
PageSize *int32 `json:"page_size,omitempty"`
// example: 120
Total *int32 `json:"total,omitempty"`
}

View File

@@ -19,15 +19,10 @@ var _ MappedNullable = &DtoQueueInfo{}
// DtoQueueInfo struct for DtoQueueInfo
type DtoQueueInfo struct {
// example: 5
Failed *int32 `json:"failed,omitempty"`
// example: default
Name *string `json:"name,omitempty"`
// example: 42
Pending *int32 `json:"pending,omitempty"`
// example: 3
Running *int32 `json:"running,omitempty"`
// example: 7
Scheduled *int32 `json:"scheduled,omitempty"`
}

View File

@@ -247,11 +247,11 @@ example().catch(console.error);
## listAnnotations
> Array<DtoAnnotationResponse> listAnnotations(xOrgID, name, value, q)
> Array<DtoAnnotationResponse> listAnnotations(xOrgID, key, value, q)
List annotations (org scoped)
Returns annotations for the organization in X-Org-ID. Filters: `name`, `value`, and `q` (name contains). Add `include=node_pools` to include linked node pools.
Returns annotations for the organization in X-Org-ID. Filters: `key`, `value`, and `q` (key contains). Add `include=node_pools` to include linked node pools.
### Example
@@ -274,11 +274,11 @@ async function example() {
const body = {
// string | Organization UUID (optional)
xOrgID: xOrgID_example,
// string | Exact name (optional)
name: name_example,
// string | Exact key (optional)
key: key_example,
// string | Exact value (optional)
value: value_example,
// string | name contains (case-insensitive) (optional)
// string | key contains (case-insensitive) (optional)
q: q_example,
} satisfies ListAnnotationsRequest;
@@ -297,11 +297,11 @@ example().catch(console.error);
### Parameters
| Name | Type | Description | Notes |
| ---------- | -------- | -------------------------------- | ------------------------------------ |
| ---------- | -------- | ------------------------------- | ------------------------------------ |
| **xOrgID** | `string` | Organization UUID | [Optional] [Defaults to `undefined`] |
| **name** | `string` | Exact name | [Optional] [Defaults to `undefined`] |
| **key** | `string` | Exact key | [Optional] [Defaults to `undefined`] |
| **value** | `string` | Exact value | [Optional] [Defaults to `undefined`] |
| **q** | `string` | name contains (case-insensitive) | [Optional] [Defaults to `undefined`] |
| **q** | `string` | key contains (case-insensitive) | [Optional] [Defaults to `undefined`] |
### Return type

View File

@@ -19,32 +19,32 @@
## Example
```typescript
import type { DtoJob } from "@glueops/autoglue-sdk-go";
import type { DtoJob } from '@glueops/autoglue-sdk-go'
// TODO: Update the object below with actual values
const example = {
attempts: null,
created_at: null,
id: null,
last_error: null,
max_attempts: null,
payload: null,
queue: null,
run_at: null,
status: null,
type: null,
updated_at: null,
} satisfies DtoJob;
"attempts": 0,
"created_at": 2025-11-04T09:30:00Z,
"id": 01HF7SZK8Z8WG1M3J7S2Z8M2N6,
"last_error": error message,
"max_attempts": 3,
"payload": null,
"queue": default,
"run_at": 2025-11-04T09:30:00Z,
"status": null,
"type": email.send,
"updated_at": 2025-11-04T09:30:00Z,
} satisfies DtoJob
console.log(example);
console.log(example)
// Convert the instance to a JSON string
const exampleJSON: string = JSON.stringify(example);
console.log(exampleJSON);
const exampleJSON: string = JSON.stringify(example)
console.log(exampleJSON)
// Parse the JSON string back to an object
const exampleParsed = JSON.parse(exampleJSON) as DtoJob;
console.log(exampleParsed);
const exampleParsed = JSON.parse(exampleJSON) as DtoJob
console.log(exampleParsed)
```
[[Back to top]](#) [[Back to API list]](../README.md#api-endpoints) [[Back to Model list]](../README.md#models) [[Back to README]](../README.md)

View File

@@ -17,9 +17,9 @@ import type { DtoPageJob } from "@glueops/autoglue-sdk-go";
// TODO: Update the object below with actual values
const example = {
items: null,
page: null,
page_size: null,
total: null,
page: 1,
page_size: 25,
total: 120,
} satisfies DtoPageJob;
console.log(example);

View File

@@ -13,26 +13,26 @@
## Example
```typescript
import type { DtoQueueInfo } from "@glueops/autoglue-sdk-go";
import type { DtoQueueInfo } from '@glueops/autoglue-sdk-go'
// TODO: Update the object below with actual values
const example = {
failed: null,
name: null,
pending: null,
running: null,
scheduled: null,
} satisfies DtoQueueInfo;
"failed": 5,
"name": default,
"pending": 42,
"running": 3,
"scheduled": 7,
} satisfies DtoQueueInfo
console.log(example);
console.log(example)
// Convert the instance to a JSON string
const exampleJSON: string = JSON.stringify(example);
console.log(exampleJSON);
const exampleJSON: string = JSON.stringify(example)
console.log(exampleJSON)
// Parse the JSON string back to an object
const exampleParsed = JSON.parse(exampleJSON) as DtoQueueInfo;
console.log(exampleParsed);
const exampleParsed = JSON.parse(exampleJSON) as DtoQueueInfo
console.log(exampleParsed)
```
[[Back to top]](#) [[Back to API list]](../README.md#api-endpoints) [[Back to Model list]](../README.md#models) [[Back to README]](../README.md)

View File

@@ -44,7 +44,7 @@ export interface GetAnnotationRequest {
export interface ListAnnotationsRequest {
xOrgID?: string;
name?: string;
key?: string;
value?: string;
q?: string;
}
@@ -283,7 +283,7 @@ export class AnnotationsApi extends runtime.BaseAPI {
}
/**
* Returns annotations for the organization in X-Org-ID. Filters: `name`, `value`, and `q` (name contains). Add `include=node_pools` to include linked node pools.
* Returns annotations for the organization in X-Org-ID. Filters: `key`, `value`, and `q` (key contains). Add `include=node_pools` to include linked node pools.
* List annotations (org scoped)
*/
async listAnnotationsRaw(
@@ -292,8 +292,8 @@ export class AnnotationsApi extends runtime.BaseAPI {
): Promise<runtime.ApiResponse<Array<DtoAnnotationResponse>>> {
const queryParameters: any = {};
if (requestParameters["name"] != null) {
queryParameters["name"] = requestParameters["name"];
if (requestParameters["key"] != null) {
queryParameters["key"] = requestParameters["key"];
}
if (requestParameters["value"] != null) {
@@ -343,7 +343,7 @@ export class AnnotationsApi extends runtime.BaseAPI {
}
/**
* Returns annotations for the organization in X-Org-ID. Filters: `name`, `value`, and `q` (name contains). Add `include=node_pools` to include linked node pools.
* Returns annotations for the organization in X-Org-ID. Filters: `key`, `value`, and `q` (key contains). Add `include=node_pools` to include linked node pools.
* List annotations (org scoped)
*/
async listAnnotations(

View File

@@ -28,68 +28,67 @@ import {
*/
export interface DtoJob {
/**
* example: 0
*
* @type {number}
* @memberof DtoJob
*/
attempts?: number;
/**
* example: 2025-11-04T09:30:00Z
*
* @type {string}
* @memberof DtoJob
*/
created_at?: string;
/**
* example: 01HF7SZK8Z8WG1M3J7S2Z8M2N6
*
* @type {string}
* @memberof DtoJob
*/
id?: string;
/**
* example: dial tcp: i/o timeout
*
* @type {string}
* @memberof DtoJob
*/
last_error?: string;
/**
* example: 3
*
* @type {number}
* @memberof DtoJob
*/
max_attempts?: number;
/**
* arbitrary JSON payload
*
* @type {object}
* @memberof DtoJob
*/
payload?: object;
/**
* example: default
*
* @type {string}
* @memberof DtoJob
*/
queue?: string;
/**
* example: 2025-11-05T08:00:00Z
*
* @type {string}
* @memberof DtoJob
*/
run_at?: string;
/**
* enum: queued,running,succeeded,failed,canceled,retrying,scheduled
* example: queued
*
* @type {DtoJobStatus}
* @memberof DtoJob
*/
status?: DtoJobStatus;
/**
* example: email.send
*
* @type {string}
* @memberof DtoJob
*/
type?: string;
/**
* example: 2025-11-04T09:31:00Z
*
* @type {string}
* @memberof DtoJob
*/

View File

@@ -34,19 +34,19 @@ export interface DtoPageJob {
*/
items?: Array<DtoJob>;
/**
* example: 1
*
* @type {number}
* @memberof DtoPageJob
*/
page?: number;
/**
* example: 25
*
* @type {number}
* @memberof DtoPageJob
*/
page_size?: number;
/**
* example: 120
*
* @type {number}
* @memberof DtoPageJob
*/

View File

@@ -20,31 +20,31 @@ import { mapValues } from "../runtime";
*/
export interface DtoQueueInfo {
/**
* example: 5
*
* @type {number}
* @memberof DtoQueueInfo
*/
failed?: number;
/**
* example: default
*
* @type {string}
* @memberof DtoQueueInfo
*/
name?: string;
/**
* example: 42
*
* @type {number}
* @memberof DtoQueueInfo
*/
pending?: number;
/**
* example: 3
*
* @type {number}
* @memberof DtoQueueInfo
*/
running?: number;
/**
* example: 7
*
* @type {number}
* @memberof DtoQueueInfo
*/

View File

@@ -0,0 +1,104 @@
package provider
import (
"context"
"encoding/json"
"fmt"
"github.com/hashicorp/terraform-plugin-framework/datasource"
dschema "github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/types"
)
var _ datasource.DataSource = &AnnotationsDataSource{}
var _ datasource.DataSourceWithConfigure = &AnnotationsDataSource{}
type AnnotationsDataSource struct{ client *Client }
func NewAnnotationsDataSource() datasource.DataSource { return &AnnotationsDataSource{} }
type annotationsDSModel struct {
Items []annotationItem `tfsdk:"items"`
}
type annotationItem struct {
ID types.String `tfsdk:"id"`
OrganizationID types.String `tfsdk:"organization_id"`
CreatedAt types.String `tfsdk:"created_at"`
UpdatedAt types.String `tfsdk:"updated_at"`
Key types.String `tfsdk:"key"`
Value types.String `tfsdk:"value"`
Raw types.String `tfsdk:"raw"`
}
func (d *AnnotationsDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_annotations"
}
func (d *AnnotationsDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = dschema.Schema{
Description: "List annotations for the organization (org-scoped).",
Attributes: map[string]dschema.Attribute{
"items": dschema.ListNestedAttribute{
Computed: true,
Description: "Annotations returned by the API.",
NestedObject: dschema.NestedAttributeObject{
Attributes: map[string]dschema.Attribute{
"id": dschema.StringAttribute{Computed: true, Description: "Taint ID (UUID)."},
"organization_id": dschema.StringAttribute{Computed: true},
"key": dschema.StringAttribute{Computed: true},
"value": dschema.StringAttribute{Computed: true},
"created_at": dschema.StringAttribute{Computed: true, Description: "RFC3339, UTC."},
"updated_at": dschema.StringAttribute{Computed: true, Description: "RFC3339, UTC."},
"raw": dschema.StringAttribute{Computed: true, Description: "Full JSON for the item."},
},
},
},
},
}
}
func (d *AnnotationsDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, _ *datasource.ConfigureResponse) {
if req.ProviderData == nil {
return
}
d.client = req.ProviderData.(*Client)
}
func (d *AnnotationsDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
if d.client == nil || d.client.SDK == nil {
resp.Diagnostics.AddError("Client not configured", "Provider configuration missing")
return
}
var conf annotationsDSModel
resp.Diagnostics.Append(req.Config.Get(ctx, &conf)...)
if resp.Diagnostics.HasError() {
return
}
call := d.client.SDK.AnnotationsAPI.ListAnnotations(ctx)
items, httpResp, err := call.Execute()
if err != nil {
resp.Diagnostics.AddError("List annotations failed", fmt.Sprintf("%v", httpErr(err, httpResp)))
return
}
out := annotationsDSModel{
Items: make([]annotationItem, 0, len(items)),
}
for _, item := range items {
raw, _ := json.Marshal(item)
out.Items = append(out.Items, annotationItem{
ID: types.StringPointerValue(item.Id),
OrganizationID: types.StringPointerValue(item.OrganizationId),
Key: types.StringPointerValue(item.Key),
Value: types.StringPointerValue(item.Value),
CreatedAt: types.StringPointerValue(item.CreatedAt),
UpdatedAt: types.StringPointerValue(item.UpdatedAt),
Raw: types.StringValue(string(raw)),
})
}
resp.Diagnostics.Append(resp.State.Set(ctx, &out)...)
}

View File

@@ -77,7 +77,7 @@ func (d *LabelsDataSource) Read(ctx context.Context, req datasource.ReadRequest,
return
}
call := d.client.SDK.TaintsAPI.ListTaints(ctx)
call := d.client.SDK.LabelsAPI.ListLabels(ctx)
items, httpResp, err := call.Execute()
if err != nil {
resp.Diagnostics.AddError("List labels failed", fmt.Sprintf("%v", httpErr(err, httpResp)))

View File

@@ -51,6 +51,7 @@ func (p *AutoglueProvider) DataSources(_ context.Context) []func() datasource.Da
NewServersDataSource,
NewTaintsDataSource,
NewLabelsDataSource,
NewAnnotationsDataSource,
}
}
@@ -60,5 +61,6 @@ func (p *AutoglueProvider) Resources(_ context.Context) []func() resource.Resour
NewServerResource,
NewTaintResource,
NewLabelResource,
NewAnnotationResource,
}
}

View File

@@ -0,0 +1,235 @@
package provider
import (
"context"
"encoding/json"
"fmt"
"net/http"
"github.com/glueops/autoglue-sdk-go"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/resource"
rschema "github.com/hashicorp/terraform-plugin-framework/resource/schema"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/types"
)
var _ resource.Resource = &AnnotationResource{}
var _ resource.ResourceWithConfigure = &AnnotationResource{}
var _ resource.ResourceWithImportState = &AnnotationResource{}
type AnnotationResource struct{ client *Client }
func NewAnnotationResource() resource.Resource { return &AnnotationResource{} }
type annotationResModel struct {
ID types.String `tfsdk:"id"`
OrganizationID types.String `tfsdk:"organization_id"`
CreatedAt types.String `tfsdk:"created_at"`
UpdatedAt types.String `tfsdk:"updated_at"`
Key types.String `tfsdk:"key"`
Value types.String `tfsdk:"value"`
Raw types.String `tfsdk:"raw"`
}
func (r *AnnotationResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_annotation"
}
func (r *AnnotationResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = rschema.Schema{
Description: "Create and manage a annotation (org-scoped).",
Attributes: map[string]rschema.Attribute{
"id": rschema.StringAttribute{
Computed: true,
Description: "ID (UUID).",
PlanModifiers: []planmodifier.String{
stringplanmodifier.UseStateForUnknown(),
},
},
"organization_id": rschema.StringAttribute{Computed: true},
"created_at": rschema.StringAttribute{Computed: true},
"updated_at": rschema.StringAttribute{Computed: true},
"key": rschema.StringAttribute{
Required: true,
Description: "Key.",
},
"value": rschema.StringAttribute{
Required: true,
Description: "Value.",
},
"raw": rschema.StringAttribute{
Computed: true,
Description: "Full server JSON from API.",
},
},
}
}
func (r *AnnotationResource) Configure(_ context.Context, req resource.ConfigureRequest, _ *resource.ConfigureResponse) {
if req.ProviderData == nil {
return
}
r.client = req.ProviderData.(*Client)
}
func (r *AnnotationResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
if r.client == nil || r.client.SDK == nil {
resp.Diagnostics.AddError("Client not configured", "Provider configuration missing")
return
}
var plan annotationResModel
resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...)
if resp.Diagnostics.HasError() {
return
}
payload := autoglue.NewDtoCreateAnnotationRequest()
if !plan.Key.IsNull() {
k := plan.Key.ValueString()
payload.SetKey(k)
}
if !plan.Value.IsNull() {
v := plan.Value.ValueString()
payload.SetValue(v)
}
call := r.client.SDK.AnnotationsAPI.CreateAnnotation(ctx).Body(*payload)
out, httpResp, err := call.Execute()
if err != nil {
resp.Diagnostics.AddError("Create label failed", fmt.Sprintf("%v", httpErr(err, httpResp)))
return
}
raw, _ := json.Marshal(out)
var state annotationResModel
r.mapRespToState(out, &state)
state.Raw = types.StringValue(string(raw))
resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
}
func (r *AnnotationResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
if r.client == nil || r.client.SDK == nil {
resp.Diagnostics.AddError("Client not configured", "Provider configuration missing")
return
}
var state annotationResModel
resp.Diagnostics.Append(req.State.Get(ctx, &state)...)
if resp.Diagnostics.HasError() {
return
}
if state.ID.IsNull() || state.ID.ValueString() == "" {
// Nothing to read; treat as gone
resp.State.RemoveResource(ctx)
return
}
call := r.client.SDK.AnnotationsAPI.GetAnnotation(ctx, state.ID.ValueString())
out, httpResp, err := call.Execute()
if err != nil {
if httpResp != nil && httpResp.StatusCode == http.StatusNotFound {
resp.State.RemoveResource(ctx)
return
}
resp.Diagnostics.AddError("Read label failed", fmt.Sprintf("%v", httpErr(err, httpResp)))
return
}
raw, _ := json.Marshal(out)
r.mapRespToState(out, &state)
state.Raw = types.StringValue(string(raw))
resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
}
func (r *AnnotationResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
if r.client == nil || r.client.SDK == nil {
resp.Diagnostics.AddError("Client not configured", "Provider configuration missing")
return
}
var plan annotationResModel
var prior annotationResModel
resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...)
resp.Diagnostics.Append(req.State.Get(ctx, &prior)...)
if resp.Diagnostics.HasError() {
return
}
body := autoglue.NewDtoUpdateAnnotationRequest()
if !plan.Key.IsNull() {
k := plan.Key.ValueString()
body.SetKey(k)
}
if !plan.Value.IsNull() {
v := plan.Value.ValueString()
body.SetValue(v)
}
call := r.client.SDK.AnnotationsAPI.UpdateAnnotation(ctx, prior.ID.ValueString()).Body(*body)
out, httpResp, err := call.Execute()
if err != nil {
// If 404 on update, treat as gone
if httpResp != nil && httpResp.StatusCode == http.StatusNotFound {
resp.State.RemoveResource(ctx)
return
}
resp.Diagnostics.AddError("Update label failed", fmt.Sprintf("%v", httpErr(err, httpResp)))
return
}
raw, _ := json.Marshal(out)
var newState annotationResModel
r.mapRespToState(out, &newState)
newState.Raw = types.StringValue(string(raw))
resp.Diagnostics.Append(resp.State.Set(ctx, &newState)...)
}
func (r *AnnotationResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
if r.client == nil || r.client.SDK == nil {
resp.Diagnostics.AddError("Client not configured", "Provider configuration missing")
return
}
var state annotationResModel
resp.Diagnostics.Append(req.State.Get(ctx, &state)...)
if resp.Diagnostics.HasError() {
return
}
call := r.client.SDK.AnnotationsAPI.DeleteAnnotation(ctx, state.ID.ValueString())
_, httpResp, err := call.Execute()
if err != nil {
// If already gone, that's fine
if httpResp != nil && httpResp.StatusCode == http.StatusNotFound {
return
}
resp.Diagnostics.AddError("Delete label failed", fmt.Sprintf("%v", httpErr(err, httpResp)))
return
}
}
func (r *AnnotationResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("id"), req.ID)...)
}
func (r *AnnotationResource) mapRespToState(s *autoglue.DtoAnnotationResponse, out *annotationResModel) {
out.ID = types.StringPointerValue(s.Id)
out.OrganizationID = types.StringPointerValue(s.OrganizationId)
out.Key = types.StringPointerValue(s.Key)
out.Value = types.StringPointerValue(s.Value)
out.CreatedAt = types.StringPointerValue(s.CreatedAt)
out.UpdatedAt = types.StringPointerValue(s.UpdatedAt)
}

View File

@@ -2,6 +2,7 @@ import { AppShell } from "@/layouts/app-shell.tsx"
import { Route, Routes } from "react-router-dom"
import { ProtectedRoute } from "@/components/protected-route.tsx"
import { AnnotationPage } from "@/pages/annotations/annotation-page.tsx"
import { Login } from "@/pages/auth/login.tsx"
import { JobsPage } from "@/pages/jobs/jobs-page.tsx"
import { LabelsPage } from "@/pages/labels/labels-page.tsx"
@@ -29,6 +30,7 @@ export default function App() {
<Route path="/servers" element={<ServerPage />} />
<Route path="/taints" element={<TaintsPage />} />
<Route path="/labels" element={<LabelsPage />} />
<Route path="/annotations" element={<AnnotationPage />} />
<Route path="/admin/jobs" element={<JobsPage />} />
</Route>

27
ui/src/api/annotations.ts Normal file
View File

@@ -0,0 +1,27 @@
import { withRefresh } from "@/api/with-refresh.ts"
import type { DtoCreateAnnotationRequest, DtoUpdateAnnotationRequest } from "@/sdk"
import { makeAnnotationsApi } from "@/sdkClient.ts"
const annotations = makeAnnotationsApi()
export const annotationsApi = {
listAnnotations: () =>
withRefresh(async () => {
return await annotations.listAnnotations()
}),
createAnnotation: (body: DtoCreateAnnotationRequest) =>
withRefresh(async () => {
return await annotations.createAnnotation({ body })
}),
getAnnotation: (id: string) =>
withRefresh(async () => {
return await annotations.getAnnotation({ id })
}),
deleteAnnotation: (id: string) =>
withRefresh(async () => {
await annotations.deleteAnnotation({ id })
}),
updateAnnotation: (id: string, body: DtoUpdateAnnotationRequest) =>
withRefresh(async () => {
return await annotations.updateAnnotation({ id, body })
}),
}

View File

@@ -1,4 +1,5 @@
import { withRefresh } from "@/api/with-refresh.ts"
import type { AdminListArcherJobsRequest } from "@/sdk"
import { makeArcherAdminApi } from "@/sdkClient.ts"
const archerAdmin = makeArcherAdminApi()
@@ -12,7 +13,7 @@ type ListParams = {
}
export const archerAdminApi = {
listJobs: (params: ListParams = {}) => {
listJobs: (params: AdminListArcherJobsRequest = {}) => {
return withRefresh(async () => {
return await archerAdmin.adminListArcherJobs(params)
})

View File

@@ -24,7 +24,7 @@ export const mainNav: NavItem[] = [
{ to: "/clusters", label: "Clusters", icon: AiOutlineCluster },
{ to: "/node-pools", label: "Node Pools", icon: BoxesIcon },
{ to: "/annotations", label: "Annotations", icon: ComponentIcon },
{ to: "/Labels", label: "Labels", icon: TagsIcon },
{ to: "/labels", label: "Labels", icon: TagsIcon },
{ to: "/taints", label: "Taints", icon: SprayCanIcon },
{ to: "/servers", label: "Servers", icon: ServerIcon },
{ to: "/ssh", label: "SSH Keys", icon: FileKey2Icon },

View File

@@ -0,0 +1,372 @@
import { useMemo, useState } from "react"
import { annotationsApi } from "@/api/annotations.ts"
import { labelsApi } from "@/api/labels.ts"
import type { DtoLabelResponse } from "@/sdk"
import { zodResolver } from "@hookform/resolvers/zod"
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"
import { CircleSlash2, Pencil, Plus, Search, Tags } from "lucide-react"
import { useForm } from "react-hook-form"
import { toast } from "sonner"
import { z } from "zod"
import { truncateMiddle } from "@/lib/utils.ts"
import { Badge } from "@/components/ui/badge.tsx"
import { Button } from "@/components/ui/button.tsx"
import {
Dialog,
DialogContent,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog.tsx"
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form.tsx"
import { Input } from "@/components/ui/input.tsx"
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table.tsx"
const createAnnotationSchema = z.object({
key: z.string().trim().min(1, "Key is required").max(120, "Max 120 chars"),
value: z.string().trim().optional(),
})
type CreateAnnotationInput = z.input<typeof createAnnotationSchema>
const updateAnnotationSchema = createAnnotationSchema.partial()
type UpdateAnnotationValues = z.infer<typeof updateAnnotationSchema>
function AnnotationBadge({ t }: { t: Pick<DtoLabelResponse, "key" | "value"> }) {
const label = `${t.key}${t.value ? `=${t.value}` : ""}`
return (
<Badge variant="secondary" className="font-mono text-xs">
<Tags className="mr-1 h-3 w-3" />
{label}
</Badge>
)
}
export const AnnotationPage = () => {
const [filter, setFilter] = useState<string>("")
const [createOpen, setCreateOpen] = useState<boolean>(false)
const [updateOpen, setUpdateOpen] = useState<boolean>(false)
const [deleteId, setDeleteId] = useState<string | null>(null)
const [editingId, setEditingId] = useState<string | null>(null)
const qc = useQueryClient()
const annotationQ = useQuery({
queryKey: ["annotations"],
queryFn: () => annotationsApi.listAnnotations(),
})
// --- Create
const createForm = useForm<CreateAnnotationInput>({
resolver: zodResolver(createAnnotationSchema),
defaultValues: {
key: "",
value: "",
},
})
const createMut = useMutation({
mutationFn: (values: CreateAnnotationInput) => annotationsApi.createAnnotation(values),
onSuccess: async () => {
await qc.invalidateQueries({ queryKey: ["annotations"] })
createForm.reset()
setCreateOpen(false)
toast.success("Annotation Created Successfully.")
},
onError: (err) => {
toast.error(err.message ?? "There was an error while creating Annotation")
},
})
const onCreateSubmit = (values: CreateAnnotationInput) => {
createMut.mutate(values)
}
// --- Update
const updateForm = useForm<UpdateAnnotationValues>({
resolver: zodResolver(updateAnnotationSchema),
defaultValues: {},
})
const updateMut = useMutation({
mutationFn: ({ id, values }: { id: string; values: UpdateAnnotationValues }) =>
annotationsApi.updateAnnotation(id, values),
onSuccess: async () => {
await qc.invalidateQueries({ queryKey: ["annotations"] })
updateForm.reset()
setUpdateOpen(false)
toast.success("Annotation Updated Successfully.")
},
onError: (err) => {
toast.error(err.message ?? "There was an error while updating Annotation")
},
})
const openEdit = (label: any) => {
setEditingId(label.id)
updateForm.reset({
key: label.key,
value: label.value,
})
setUpdateOpen(true)
}
// --- Delete ---
const deleteMut = useMutation({
mutationFn: (id: string) => annotationsApi.deleteAnnotation(id),
onSuccess: async () => {
await qc.invalidateQueries({ queryKey: ["annotations"] })
setDeleteId(null)
toast.success("Annotation Deleted Successfully.")
},
onError: (err) => {
toast.error(err.message ?? "There was an error while deleting Annotation")
},
})
// --- Filter ---
const filtered = useMemo(() => {
const data = annotationQ.data ?? []
const q = filter.trim().toLowerCase()
return q
? data.filter((k: any) => {
return k.key?.toLowerCase().includes(q) || k.value?.toLowerCase().includes(q)
})
: data
}, [filter, annotationQ.data])
if (annotationQ.isLoading) return <div className="p-6">Loading annotations</div>
if (annotationQ.error)
return (
<div className="p-6 text-red-500">
Error loading annotations.<pre>{JSON.stringify(annotationQ, null, 2)}</pre>
</div>
)
return (
<div className="space-y-4 p-6">
<div className="flex flex-col gap-3 md:flex-row md:items-center md:justify-between">
<h1 className="mb-4 text-2xl font-bold">Annotations</h1>
<div className="flex flex-wrap items-center gap-2">
<div className="relative">
<Search className="absolute top-2.5 left-2 h-4 w-4 opacity-60" />
<Input
value={filter}
onChange={(e) => setFilter(e.target.value)}
placeholder="Search annotations"
className="w-64 pl-8"
/>
</div>
<Dialog open={createOpen} onOpenChange={setCreateOpen}>
<DialogTrigger asChild>
<Button onClick={() => setCreateOpen(true)}>
<Plus className="mr-2 h-4 w-4" />
Create Annotation
</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-lg">
<DialogHeader>
<DialogTitle>Create Label</DialogTitle>
</DialogHeader>
<Form {...createForm}>
<form className="space-y-4" onSubmit={createForm.handleSubmit(onCreateSubmit)}>
<FormField
control={createForm.control}
name="key"
render={({ field }) => (
<FormItem>
<FormLabel>Key</FormLabel>
<FormControl>
<Input placeholder="environment" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={createForm.control}
name="value"
render={({ field }) => (
<FormItem>
<FormLabel>Value</FormLabel>
<FormControl>
<Input placeholder="dev" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<DialogFooter className="gap-2">
<Button type="button" variant="outline" onClick={() => setCreateOpen(false)}>
Cancel
</Button>
<Button type="submit" disabled={createForm.formState.isSubmitting}>
{createForm.formState.isSubmitting ? "Creating…" : "Create"}
</Button>
</DialogFooter>
</form>
</Form>
</DialogContent>
</Dialog>
</div>
</div>
<div className="bg-background overflow-hidden rounded-2xl border shadow-sm">
<div className="overflow-x-auto">
<Table>
<TableHeader>
<TableRow>
<TableHead>Key</TableHead>
<TableHead>Value</TableHead>
<TableHead>Annotation</TableHead>
<TableHead className="w-[180px] text-right">Actions</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{filtered.map((t) => (
<TableRow key={t.id}>
<TableCell>{t.key}</TableCell>
<TableCell>{t.value}</TableCell>
<TableCell>
<div className="flex items-center gap-2">
<AnnotationBadge t={t} />
<code className="text-muted-foreground text-xs">
{truncateMiddle(t.id!, 6)}
</code>
</div>
</TableCell>
<TableCell>
<div className="flex justify-end gap-2">
<Button variant="outline" size="sm" onClick={() => openEdit(t)}>
<Pencil className="mr-2 h-4 w-4" /> Edit
</Button>
<Button
variant="destructive"
size="sm"
onClick={() => setDeleteId(t.id!)}
disabled={deleteMut.isPending && deleteId === t.id}
>
{deleteMut.isPending && deleteId === t.id ? "Deleting…" : "Delete"}
</Button>
</div>
</TableCell>
</TableRow>
))}
{filtered.length === 0 && (
<TableRow>
<TableCell colSpan={4} className="text-muted-foreground py-10 text-center">
<CircleSlash2 className="mx-auto mb-2 h-6 w-6 opacity-60" />
No labels match your search.
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</div>
</div>
{/* Update dialog */}
<Dialog open={updateOpen} onOpenChange={setUpdateOpen}>
<DialogContent className="sm:max-w-lg">
<DialogHeader>
<DialogTitle>Edit Annotation</DialogTitle>
</DialogHeader>
<Form {...updateForm}>
<form
className="space-y-4"
onSubmit={updateForm.handleSubmit((values) => {
if (!editingId) return
updateMut.mutate({ id: editingId, values })
})}
>
<FormField
control={updateForm.control}
name="key"
render={({ field }) => (
<FormItem>
<FormLabel>Key</FormLabel>
<FormControl>
<Input placeholder="dedicated" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={updateForm.control}
name="value"
render={({ field }) => (
<FormItem>
<FormLabel>Value (optional)</FormLabel>
<FormControl>
<Input placeholder="gpu" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<DialogFooter className="gap-2">
<Button type="button" variant="outline" onClick={() => setUpdateOpen(false)}>
Cancel
</Button>
<Button type="submit" disabled={updateMut.isPending}>
{updateMut.isPending ? "Saving…" : "Save changes"}
</Button>
</DialogFooter>
</form>
</Form>
</DialogContent>
</Dialog>
{/* Delete confirm dialog */}
<Dialog open={!!deleteId} onOpenChange={(open) => !open && setDeleteId(null)}>
<DialogContent className="sm:max-w-md">
<DialogHeader>
<DialogTitle>Delete annotation</DialogTitle>
</DialogHeader>
<p className="text-muted-foreground text-sm">
This action cannot be undone. Are you sure you want to delete this annotation?
</p>
<DialogFooter className="gap-2">
<Button variant="outline" onClick={() => setDeleteId(null)}>
Cancel
</Button>
<Button
variant="destructive"
onClick={() => deleteId && deleteMut.mutate(deleteId)}
disabled={deleteMut.isPending}
>
{deleteMut.isPending ? "Deleting…" : "Delete"}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</div>
)
}

View File

@@ -1,5 +1,6 @@
import { useEffect, useState, type FC } from "react"
import { archerAdminApi } from "@/api/archer_admin"
import type { AdminListArcherJobsRequest } from "@/sdk"
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"
import { Loader2, Plus, RefreshCw, Search, X } from "lucide-react"
@@ -125,13 +126,13 @@ export const JobsPage: FC = () => {
queryKey: key,
queryFn: () =>
archerAdminApi.listJobs({
status: status || undefined,
status: status,
queue: queue || undefined,
q: debouncedQ || undefined,
page,
pageSize,
}) as Promise<DtoPageJob>,
keepPreviousData: true,
} as AdminListArcherJobsRequest) as Promise<DtoPageJob>,
placeholderData: (prev) => prev,
staleTime: 10_000,
})
@@ -159,7 +160,7 @@ export const JobsPage: FC = () => {
const busy = jobsQ.isFetching
const data = jobsQ.data
const data = jobsQ.data as DtoPageJob
const totalPages = data ? Math.max(1, Math.ceil(data.total / data.pageSize)) : 1
return (

View File

@@ -287,7 +287,7 @@ export const LabelsPage = () => {
<Dialog open={updateOpen} onOpenChange={setUpdateOpen}>
<DialogContent className="sm:max-w-lg">
<DialogHeader>
<DialogTitle>Edit taint</DialogTitle>
<DialogTitle>Edit Label</DialogTitle>
</DialogHeader>
<Form {...updateForm}>
<form
@@ -337,7 +337,30 @@ export const LabelsPage = () => {
</Form>
</DialogContent>
</Dialog>
<pre>{JSON.stringify(labelsQ.data, null, 2)}</pre>
{/* Delete confirm dialog */}
<Dialog open={!!deleteId} onOpenChange={(open) => !open && setDeleteId(null)}>
<DialogContent className="sm:max-w-md">
<DialogHeader>
<DialogTitle>Delete label</DialogTitle>
</DialogHeader>
<p className="text-muted-foreground text-sm">
This action cannot be undone. Are you sure you want to delete this label?
</p>
<DialogFooter className="gap-2">
<Button variant="outline" onClick={() => setDeleteId(null)}>
Cancel
</Button>
<Button
variant="destructive"
onClick={() => deleteId && deleteMut.mutate(deleteId)}
disabled={deleteMut.isPending}
>
{deleteMut.isPending ? "Deleting…" : "Delete"}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</div>
)
}

View File

@@ -500,7 +500,6 @@ export const MePage = () => {
</div>
</DialogContent>
</Dialog>
<pre>{JSON.stringify(meQ.data, null, 2)}</pre>
</div>
)
}

View File

@@ -819,7 +819,6 @@ export const ServerPage = () => {
</DialogFooter>
</DialogContent>
</Dialog>
<pre>{JSON.stringify(serverQ.data, null, 2)}</pre>
</TooltipProvider>
)
}

View File

@@ -470,7 +470,6 @@ export const SshPage = () => {
</DialogContent>
</Dialog>
</div>
<pre>{JSON.stringify(sshQ.data, null, 2)}</pre>
</TooltipProvider>
)
}

View File

@@ -422,7 +422,6 @@ export const TaintsPage = () => {
</DialogFooter>
</DialogContent>
</Dialog>
<pre>{JSON.stringify(taintsQ.data, null, 2)}</pre>
</div>
)
}

View File

@@ -45,7 +45,7 @@ export interface GetAnnotationRequest {
export interface ListAnnotationsRequest {
xOrgID?: string;
name?: string;
key?: string;
value?: string;
q?: string;
}
@@ -233,14 +233,14 @@ export class AnnotationsApi extends runtime.BaseAPI {
}
/**
* Returns annotations for the organization in X-Org-ID. Filters: `name`, `value`, and `q` (name contains). Add `include=node_pools` to include linked node pools.
* Returns annotations for the organization in X-Org-ID. Filters: `key`, `value`, and `q` (key contains). Add `include=node_pools` to include linked node pools.
* List annotations (org scoped)
*/
async listAnnotationsRaw(requestParameters: ListAnnotationsRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<Array<DtoAnnotationResponse>>> {
const queryParameters: any = {};
if (requestParameters['name'] != null) {
queryParameters['name'] = requestParameters['name'];
if (requestParameters['key'] != null) {
queryParameters['key'] = requestParameters['key'];
}
if (requestParameters['value'] != null) {
@@ -283,7 +283,7 @@ export class AnnotationsApi extends runtime.BaseAPI {
}
/**
* Returns annotations for the organization in X-Org-ID. Filters: `name`, `value`, and `q` (name contains). Add `include=node_pools` to include linked node pools.
* Returns annotations for the organization in X-Org-ID. Filters: `key`, `value`, and `q` (key contains). Add `include=node_pools` to include linked node pools.
* List annotations (org scoped)
*/
async listAnnotations(requestParameters: ListAnnotationsRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<Array<DtoAnnotationResponse>> {

View File

@@ -261,11 +261,11 @@ example().catch(console.error);
## listAnnotations
> Array&lt;DtoAnnotationResponse&gt; listAnnotations(xOrgID, name, value, q)
> Array&lt;DtoAnnotationResponse&gt; listAnnotations(xOrgID, key, value, q)
List annotations (org scoped)
Returns annotations for the organization in X-Org-ID. Filters: &#x60;name&#x60;, &#x60;value&#x60;, and &#x60;q&#x60; (name contains). Add &#x60;include&#x3D;node_pools&#x60; to include linked node pools.
Returns annotations for the organization in X-Org-ID. Filters: &#x60;key&#x60;, &#x60;value&#x60;, and &#x60;q&#x60; (key contains). Add &#x60;include&#x3D;node_pools&#x60; to include linked node pools.
### Example
@@ -291,11 +291,11 @@ async function example() {
const body = {
// string | Organization UUID (optional)
xOrgID: xOrgID_example,
// string | Exact name (optional)
name: name_example,
// string | Exact key (optional)
key: key_example,
// string | Exact value (optional)
value: value_example,
// string | name contains (case-insensitive) (optional)
// string | key contains (case-insensitive) (optional)
q: q_example,
} satisfies ListAnnotationsRequest;
@@ -317,9 +317,9 @@ example().catch(console.error);
| Name | Type | Description | Notes |
|------------- | ------------- | ------------- | -------------|
| **xOrgID** | `string` | Organization UUID | [Optional] [Defaults to `undefined`] |
| **name** | `string` | Exact name | [Optional] [Defaults to `undefined`] |
| **key** | `string` | Exact key | [Optional] [Defaults to `undefined`] |
| **value** | `string` | Exact value | [Optional] [Defaults to `undefined`] |
| **q** | `string` | name contains (case-insensitive) | [Optional] [Defaults to `undefined`] |
| **q** | `string` | key contains (case-insensitive) | [Optional] [Defaults to `undefined`] |
### Return type

View File

@@ -25,17 +25,17 @@ import type { DtoJob } from '@glueops/autoglue-sdk-go'
// TODO: Update the object below with actual values
const example = {
"attempts": null,
"created_at": null,
"id": null,
"last_error": null,
"max_attempts": null,
"attempts": 0,
"created_at": 2025-11-04T09:30:00Z,
"id": 01HF7SZK8Z8WG1M3J7S2Z8M2N6,
"last_error": error message,
"max_attempts": 3,
"payload": null,
"queue": null,
"run_at": null,
"queue": default,
"run_at": 2025-11-04T09:30:00Z,
"status": null,
"type": null,
"updated_at": null,
"type": email.send,
"updated_at": 2025-11-04T09:30:00Z,
} satisfies DtoJob
console.log(example)

View File

@@ -19,9 +19,9 @@ import type { DtoPageJob } from '@glueops/autoglue-sdk-go'
// TODO: Update the object below with actual values
const example = {
"items": null,
"page": null,
"page_size": null,
"total": null,
"page": 1,
"page_size": 25,
"total": 120,
} satisfies DtoPageJob
console.log(example)

View File

@@ -19,11 +19,11 @@ import type { DtoQueueInfo } from '@glueops/autoglue-sdk-go'
// TODO: Update the object below with actual values
const example = {
"failed": null,
"name": null,
"pending": null,
"running": null,
"scheduled": null,
"failed": 5,
"name": default,
"pending": 42,
"running": 3,
"scheduled": 7,
} satisfies DtoQueueInfo
console.log(example)

View File

@@ -28,68 +28,67 @@ import {
*/
export interface DtoJob {
/**
* example: 0
*
* @type {number}
* @memberof DtoJob
*/
attempts?: number;
/**
* example: 2025-11-04T09:30:00Z
*
* @type {string}
* @memberof DtoJob
*/
created_at?: string;
/**
* example: 01HF7SZK8Z8WG1M3J7S2Z8M2N6
*
* @type {string}
* @memberof DtoJob
*/
id?: string;
/**
* example: dial tcp: i/o timeout
*
* @type {string}
* @memberof DtoJob
*/
last_error?: string;
/**
* example: 3
*
* @type {number}
* @memberof DtoJob
*/
max_attempts?: number;
/**
* arbitrary JSON payload
*
* @type {object}
* @memberof DtoJob
*/
payload?: object;
/**
* example: default
*
* @type {string}
* @memberof DtoJob
*/
queue?: string;
/**
* example: 2025-11-05T08:00:00Z
*
* @type {string}
* @memberof DtoJob
*/
run_at?: string;
/**
* enum: queued,running,succeeded,failed,canceled,retrying,scheduled
* example: queued
*
* @type {DtoJobStatus}
* @memberof DtoJob
*/
status?: DtoJobStatus;
/**
* example: email.send
*
* @type {string}
* @memberof DtoJob
*/
type?: string;
/**
* example: 2025-11-04T09:31:00Z
*
* @type {string}
* @memberof DtoJob
*/

View File

@@ -34,19 +34,19 @@ export interface DtoPageJob {
*/
items?: Array<DtoJob>;
/**
* example: 1
*
* @type {number}
* @memberof DtoPageJob
*/
page?: number;
/**
* example: 25
*
* @type {number}
* @memberof DtoPageJob
*/
page_size?: number;
/**
* example: 120
*
* @type {number}
* @memberof DtoPageJob
*/

View File

@@ -20,31 +20,31 @@ import { mapValues } from '../runtime';
*/
export interface DtoQueueInfo {
/**
* example: 5
*
* @type {number}
* @memberof DtoQueueInfo
*/
failed?: number;
/**
* example: default
*
* @type {string}
* @memberof DtoQueueInfo
*/
name?: string;
/**
* example: 42
*
* @type {number}
* @memberof DtoQueueInfo
*/
pending?: number;
/**
* example: 3
*
* @type {number}
* @memberof DtoQueueInfo
*/
running?: number;
/**
* example: 7
*
* @type {number}
* @memberof DtoQueueInfo
*/

View File

@@ -1,6 +1,7 @@
import { orgStore } from "@/auth/org.ts"
import { authStore } from "@/auth/store.ts"
import {
AnnotationsApi,
ArcherAdminApi,
AuthApi,
Configuration,
@@ -95,6 +96,9 @@ export function makeLabelsApi() {
return makeApiClient(LabelsApi)
}
export function makeAnnotationsApi() {
return makeApiClient(AnnotationsApi)
}
export function makeArcherAdminApi() {
return makeApiClient(ArcherAdminApi)
}