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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docusaurus/docs/extensions/resources-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,4 @@ const customResources = await resources.cluster.findFiltered('mycompany.io.custo
| :--- | :--- |
| [Cluster API](./resources-api/interfaces/ClusterApi) | Interact with cluster-scoped Kubernetes resources (Pods, Deployments, Services, etc.) |
| [Management API](./resources-api/interfaces/MgmtApi) | Interact with global Rancher resources (Users, Clusters, Settings, etc.) |
| [Resource Instance API](./resources-api/interfaces/ResourceInstanceApi) | Interact any given Kubernetes resource instance |
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i don't think we need to surface this as a major api, it's more a facet of the above two

19 changes: 19 additions & 0 deletions shell/apis/intf/resources-api/resource-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,25 @@ import {
*/
export type ResourceType = K8SResourceType | string;

/**
* @interface
* Data object for creating a new resource. Must include a `type` property.
*
* @example
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably worth creating an instance of CreateResourceData first and then using it for it's indented purpose. this makes it nice and clear

* ```ts
* import { useResources, K8S } from '@shell/apis';
*
* const resources = useResources();
*
* await resources.cluster.create({
* type: K8S.CONFIG_MAP,
* metadata: { name: 'my-config', namespace: 'default' },
* data: { key: 'value' }
* });
* ```
*/
export type CreateResourceData = { type: ResourceType } & Record<string, any>;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this might be more of a preference thing, but why not just... ?

export type CreateResourceData = {
  [key: string]: any,
  type: ResourceType,
};


/**
* @interface
* Resources API "findAll" options
Expand Down
96 changes: 96 additions & 0 deletions shell/apis/intf/resources-api/resource-instance.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { SteveGetResponse } from '@shell/types/rancher/steve.api';

/**
* Instance-level operations available on resources returned by the Resources API.
*
* These methods operate on a specific resource that has already been fetched.
*/
export interface ResourceInstanceApi {
/**
* Applies a partial update to a resource using HTTP PATCH (merge-patch).
*
* Only the fields provided in `data` are sent to the server — the rest of the resource
* remains unchanged. The server response is merged back into this instance.
*
* Requires edit permissions (`canEdit`).
*
* @param data - An object containing only the fields to update.
* @returns a resource instance, updated with the server response.
*
* @example
* ```ts
* import { useResources, K8S } from '@shell/apis';
*
* const resources = useResources();
* const configMap = await resources.cluster.find(K8S.CONFIG_MAP, 'default/my-config');
*
* await configMap.patch({ newKey: 'newValue' });
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* await configMap.patch({ newKey: 'newValue' });
* await configMap.patch({ newKey: 'newValue' });
*
* const result = configMap.newKey === 'newValue' // true

* ```
*/
patch(data: Record<string, any>): Promise<ResourceInstanceApi>;

/**
* Performs a full replacement update of a resource using HTTP PUT.
*
* Sends the entire current state of the resource to the server.
*
* Requires edit permissions (`canEdit`).
*
* @returns a resource instance, updated with the server response.
*
* @example
* ```ts
* import { useResources, K8S } from '@shell/apis';
*
* const resources = useResources();
* const configMap = await resources.cluster.find(K8S.CONFIG_MAP, 'default/my-config');
*
* configMap.data.myKey = 'updatedValue';
* await configMap.update();
* ```
*/
update(): Promise<ResourceInstanceApi>;

/**
* Deletes a resource instance.
*
* Requires delete permissions (`canDelete`).
*
* @returns A promise that resolves when the resource has been deleted.
*
* @example
* ```ts
* import { useResources, K8S } from '@shell/apis';
*
* const resources = useResources();
* const pod = await resources.cluster.find(K8S.POD, 'default/my-pod-123');
*
* await pod.delete();
* ```
*/
delete(): Promise<void>;
}

/**
* Represents a single resource instance returned from the Resources API.
*
* Provides instance-level operations such as deleting or updating a resource instance.
* The resource data (metadata, spec, status, etc.) is accessible directly on the instance.
*
* @template T - The shape of the underlying resource data (defaults to SteveGetResponse)
*
* @example
* ```ts
* import { useResources, K8S } from '@shell/apis';
*
* const resources = useResources();
* const pod = await resources.cluster.find(K8S.POD, 'my-pod-123');
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* const pod = await resources.cluster.find(K8S.POD, 'my-pod-123');
* const pod = await resources.cluster.find(K8S.POD, 'default/my-pod-123');

*
* // Access resource data directly
* console.log(pod.metadata.name);
*
* // Use instance operations
* await pod.delete();
* ```
*/
export type ResourceInstance<T = SteveGetResponse> = T & ResourceInstanceApi;
120 changes: 115 additions & 5 deletions shell/apis/intf/resources-api/resources-api.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import {
ResourceType, FindMethodOptions, FindAllMethodOptions, FindFilteredPageOptions, FindFilteredLabelSelectorOptions,
ResourceType, CreateResourceData, FindMethodOptions, FindAllMethodOptions, FindFilteredPageOptions, FindFilteredLabelSelectorOptions,
FindFilteredPageResponse, FindFilteredLabelSelectorResponse
} from './resource-base';
import { SteveListResponse, SteveGetResponse } from '@shell/types/rancher/steve.api';
import { ResourceInstance } from './resource-instance';
import { SteveListResponse } from '@shell/types/rancher/steve.api';

/**
* Base interface for all resource API operations.
Expand All @@ -24,7 +25,7 @@ export interface ResourcesApi {
/**
* Finds a specific resource by its type and ID.
*
* @template T - The type of the resource (defaults to SteveGetResponse)
* @template T - The type of the resource (defaults to ResourceInstance)
* @param resourceType - The type of the resource to find (use **{@link K8S}** constant). See also {@link ResourceType}.
* @param resourceId - The unique identifier of the resource to find. If the resource is namespaced, this should be in the format `namespace/name`.
* @param options - Optional find arguments
Expand All @@ -43,7 +44,7 @@ export interface ResourcesApi {
* const node = await resources.cluster.find(K8S.NODE, 'worker-1');
* ```
*/
find<T = SteveGetResponse>(
find<T = ResourceInstance>(
resourceType: ResourceType,
resourceId: string,
options?: FindMethodOptions
Expand All @@ -54,7 +55,7 @@ export interface ResourcesApi {
*
* Requires `ui-sql-cache` to be enabled.
*
* @template T - The type of the resources (defaults to SteveListResponse)
* @template T - The type of the resources (defaults to ResourceInstance)
* @param resourceType - The type of the resources to find (use **{@link K8S}** constant). See also {@link ResourceType}.
* @param options - Pagination options with server-side filtering and sorting via the Steve API's pagination cache. See {@link FindFilteredPageOptions}.
* @returns Response containing resource items (may be transient if requested, otherwise cached array).
Expand Down Expand Up @@ -140,4 +141,113 @@ export interface ResourcesApi {
resourceType: ResourceType,
options?: FindAllMethodOptions
): Promise<T[]>;

/**
* Creates a new resource.
*
* The `data` object must include a `type` property identifying the resource type.
* Checks `canCreate` permissions before saving.
*
* @template T - The type of the resource (defaults to ResourceInstance)
* @param data - The resource data to create. Must include a `type` property (use **{@link K8S}** constant). See also {@link CreateResourceData}.
* @returns The created resource instance.
*
* @example
* ```ts
* import { useResources, K8S } from '@shell/apis';
*
* const resources = useResources();
*
* const configMap = await resources.cluster.create({
* type: K8S.CONFIG_MAP,
* metadata: { name: 'my-config', namespace: 'default' },
* data: { key: 'value' }
* });
* ```
*/
create<T = ResourceInstance>(
data: CreateResourceData
): Promise<T>;

/**
* Applies a partial update to a resource using HTTP PATCH (merge-patch).
*
* Only the fields provided in `data` are sent to the server.
* This is a raw HTTP operation — it does not check permissions or update the store cache.
*
* @template T - The type of the response (defaults to ResourceInstance)
* @param resourceType - The type of the resource (use **{@link K8S}** constant). See also {@link ResourceType}.
* @param resourceId - The unique identifier. If namespaced, use `namespace/name` format.
* @param data - An object containing only the fields to update.
* @returns The server response.
*
* @example
* ```ts
* import { useResources, K8S } from '@shell/apis';
*
* const resources = useResources();
*
* const result = await resources.cluster.patch(K8S.CONFIG_MAP, 'default/my-config', {
* data: { newKey: 'newValue' }
* });
* ```
*/
patch<T = ResourceInstance>(
resourceType: ResourceType,
resourceId: string,
data: Record<string, any>
): Promise<T>;

/**
* Performs a full replacement update of a resource using HTTP PUT.
*
* Runs `cleanForSave` on the data before sending.
* This is a raw HTTP operation — it does not check permissions or update the store cache.
*
* @template T - The type of the response (defaults to ResourceInstance)
* @param resourceType - The type of the resource (use **{@link K8S}** constant). See also {@link ResourceType}.
* @param resourceId - The unique identifier. If namespaced, use `namespace/name` format.
* @param data - The complete resource data to send as the replacement.
* @returns The server response.
*
* @example
* ```ts
* import { useResources, K8S } from '@shell/apis';
*
* const resources = useResources();
*
* const result = await resources.cluster.update(K8S.CONFIG_MAP, 'default/my-config', {
* type: 'configmap',
* metadata: { name: 'my-config', namespace: 'default', resourceVersion: '12345' },
* data: { key: 'replacedValue' }
* });
* ```
*/
update<T = ResourceInstance>(
resourceType: ResourceType,
resourceId: string,
data: Record<string, any>
): Promise<T>;

/**
* Deletes a resource by type and ID using HTTP DELETE.
*
* This is a raw HTTP operation — it does not check permissions or update the store cache.
*
* @param resourceType - The type of the resource (use **{@link K8S}** constant). See also {@link ResourceType}.
* @param resourceId - The unique identifier. If namespaced, use `namespace/name` format.
*
* @example
* ```ts
* import { useResources, K8S } from '@shell/apis';
*
* const resources = useResources();
*
* await resources.cluster.delete(K8S.CONFIG_MAP, 'default/my-config');
* ```
*/
delete(
resourceType: ResourceType,
resourceId: string
): Promise<void>;
}
4 changes: 3 additions & 1 deletion shell/apis/intf/resources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ export * from '@shell/apis/intf/resources-api/resources-api';
export * from '@shell/apis/intf/resources-api/cluster-api';
export * from '@shell/apis/intf/resources-api/mgmt-api';
export {
ResourceType, FindMethodOptions, FindAllMethodOptions, FindFilteredPageOptions, FindFilteredLabelSelectorOptions,
ResourceType, CreateResourceData, FindMethodOptions, FindAllMethodOptions, FindFilteredPageOptions, FindFilteredLabelSelectorOptions,
FindFilteredPageResponse, FindFilteredLabelSelectorResponse
} from '@shell/apis/intf/resources-api/resource-base';
export * from '@shell/apis/intf/resources-api/resource-constants';

export * from '@shell/apis/intf/resources-api/resource-instance';

export { SteveGetResponse, SteveListResponse } from '@shell/types/rancher/steve.api';
export { KubeLabelSelector, KubeLabelSelectorExpression } from '@shell/types/kube/kube-api';
export {
Expand Down
Loading
Loading