Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
fdfc760
Added new common.ts within API folder to store generic types against …
Redtigercod4 Jun 30, 2026
ea7eeb7
Updated types within common.ts and created a new RPM Repository type …
Redtigercod4 Jul 1, 2026
41f5e58
Updated ansible repository to new interface, mapped out shared types …
Redtigercod4 Jul 1, 2026
1e81ca6
Updated file repository to new interface adding in new fields from re…
Redtigercod4 Jul 1, 2026
f1221fb
Fixed issue with Ansible types. Removed incorrect comment due to plug…
Redtigercod4 Jul 1, 2026
63086c4
Defined new distribution generic from pulpcore and built out ansible …
Redtigercod4 Jul 2, 2026
762de1e
Defined new distribution and publication generic for file distributio…
Redtigercod4 Jul 2, 2026
ee63c10
Defined new Remote generic and updated ansible remote type
Redtigercod4 Jul 2, 2026
4e164e3
Updated File Remote definition along with commit pinning references.
Redtigercod4 Jul 2, 2026
8ccab40
Updated Container distributions to have new interface against plugin
Redtigercod4 Jul 2, 2026
8f80c3d
Built out RPM Repository API Client with Typed List endpoint
Redtigercod4 Jul 3, 2026
eb4b326
Added integration testing against RPM Repository API Client using nod…
Redtigercod4 Jul 3, 2026
dfa58c6
Refined test suite to using Axios instead of node:fetch, Fixed minor …
Redtigercod4 Jul 9, 2026
c92abff
Added create & update on RPM repositories with associated testing
Redtigercod4 Jul 9, 2026
a094275
Added repository delete with testing helpers to handle dispatch task …
Redtigercod4 Jul 10, 2026
e6524b1
Updated types for task dispatch response, updated error messaging on …
Redtigercod4 Jul 10, 2026
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
6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,12 @@
"sort-exports": "perl -i -pe 's/^export/import/' src/**/index.ts ; npm run prettier ; perl -i -pe 's/^import/export/' src/**/index.ts",
"start": "NODE_ENV=development webpack serve --config config/start.config.js",
"test": "true",
"test:check-ts": "node -e \"process.versions.node.localeCompare('22.10.0',undefined,{numeric:true})>=0||(console.error('Testing uses feature flags requiring Node >= 22.10.0, but is using '+process.versions.node),process.exit(1))\"",
"test:check-api-status": "curl -sf \"${PULP_BASE_URL:-http://localhost:8080/pulp/api/v3/}status/\" -o /dev/null || (echo 'Integration tests require the Pulp API, is it running?' >&2; exit 1)",
"test:check": "npm run test:check-ts && npm run test:check-api-status",
"test:unit": "npm run test:check && node --test --experimental-strip-types --test-name-pattern '^Unit: '",
"test:integration": "npm run test:check && node --test --experimental-strip-types --test-name-pattern '^Integration: '",
"test:coverage": "npm run test:check && node --test --experimental-strip-types --experimental-test-coverage --test-coverage-exclude '**/*.test.ts' --test-coverage-exclude 'src/api/test-utils/**'",
"upgrade": "npx npm-check-updates -u -t minor"
},
"engines": {
Expand Down
16 changes: 16 additions & 0 deletions src/api/ansible-distribution.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
import type { GenericDistribution } from './common';
import { PulpAPI } from './pulp';

/**
* Ansible Distribution Type.
*
* @see https://github.com/pulp/pulp_ansible/blob/0043923641fc7fd3893f8489fd29ff04addc9d71/pulp_ansible/app/serializers.py#L356
*/
interface AnsibleDistributionType extends Omit<
GenericDistribution,
'base_url'
> {
readonly client_url: string;
repository_version?: string | null;
}

const base = new PulpAPI();

export const AnsibleDistributionAPI = {
Expand All @@ -11,3 +25,5 @@ export const AnsibleDistributionAPI = {

url: (distro_data) => distro_data.client_url,
};

export type { AnsibleDistributionType };
48 changes: 18 additions & 30 deletions src/api/ansible-remote.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,22 @@
import type { AnsibleLastSyncType, GenericRemote } from './common';
import { PulpAPI } from './pulp';

export class AnsibleRemoteType {
auth_url: string;
ca_cert: string;
client_cert: string;
download_concurrency: number;
name: string;
proxy_url: string;
pulp_href?: string;
rate_limit: number;
requirements_file: string;
tls_validation: boolean;
url: string;
signed_only: boolean;
/**
* Ansible Remote Type.
*
* @see https://github.com/pulp/pulp_ansible/blob/0043923641fc7fd3893f8489fd29ff04addc9d71/pulp_ansible/app/serializers.py#L213
*/
interface AnsibleRemoteType extends GenericRemote {
requirements_file?: string | null;
auth_url?: string | null;
token?: string | null;
sync_dependencies?: boolean;

// connect_timeout
// headers
// max_retries
// policy
// pulp_created
// pulp_labels
// pulp_last_updated
// sock_connect_timeout
// sock_read_timeout
// total_timeout

hidden_fields: {
is_set: boolean;
name: string;
}[];

signed_only?: boolean;
readonly last_sync_task?: AnsibleLastSyncType | null;
/**
* NOTE: Not part of the Ansible serializer, populated separately.
* This should be broken out into its own type and extend the interface.
*/
my_permissions?: string[];
}

Expand Down Expand Up @@ -90,3 +76,5 @@ export const AnsibleRemoteAPI = {
smartUpdate(newValue, oldValue),
),
};

export type { AnsibleRemoteType };
32 changes: 16 additions & 16 deletions src/api/ansible-repository.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
import type { AnsibleLastSyncType, GenericRepository } from './common';
import { PulpAPI } from './pulp';
import { type LastSyncType } from './response-types/remote';

export class AnsibleRepositoryType {
description: string;
last_sync_task?: LastSyncType;
latest_version_href?: string;
name: string;
/**
* Ansible Repository Type.
*
* @see https://github.com/pulp/pulp_ansible/blob/0043923641fc7fd3893f8489fd29ff04addc9d71/pulp_ansible/app/serializers.py#L148
*/
interface AnsibleRepositoryType extends GenericRepository {
last_synced_metadata_time?: string | null;
gpgkey?: string | null;
readonly last_sync_task?: AnsibleLastSyncType | null;
private?: boolean;
pulp_created?: string;
pulp_href?: string;
pulp_labels?: Record<string, string>;
remote?: string;
retain_repo_versions: number;

// gpgkey
// last_synced_metadata_time
// versions_href

/**
* NOTE: Not part of the Ansible serializer, populated separately.
* This should be broken out into its own type and extend the interface.
*/
my_permissions?: string[];
}

Expand Down Expand Up @@ -91,3 +89,5 @@ export const AnsibleRepositoryAPI = {
update: (id: string, data) =>
base.http.put(`repositories/ansible/ansible/${id}/`, data),
};

export type { AnsibleRepositoryType };
223 changes: 223 additions & 0 deletions src/api/common.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
import type { PulpStatus } from './response-types/pulp';

/**
* Generic PulpCore Exceptions based on dictionary representation.
* @see https://github.com/pulp/pulpcore/blob/934c752dae916857b2005e1fe0ef75496accc082/pulpcore/exceptions/base.py#L37
*/
interface TaskErrorType {
description: string;
traceback: string | null;
error_code?: string;
}

/**
* Generic Resource shared across every Pulp resource.
*
* @see https://github.com/pulp/pulpcore/blob/934c752dae916857b2005e1fe0ef75496accc082/pulpcore/app/serializers/base.py#L448
*/
interface GenericResource {
readonly pulp_href?: string;
readonly prn?: string;
readonly pulp_created?: string;
readonly pulp_last_updated?: string;
}

/**
* Generic Repository shared across Pulp Repository plugins.
*
* @see https://github.com/pulp/pulpcore/blob/934c752dae916857b2005e1fe0ef75496accc082/pulpcore/app/serializers/repository.py#L26
*/
interface GenericRepository extends GenericResource {
pulp_labels?: Record<string, string>;
readonly versions_href?: string;
readonly latest_version_href?: string;
name: string;
description?: string | null;
retain_repo_versions?: number | null;
retain_checkpoints?: number | null;
remote?: string | null;
}

/**
* Generic Distribution shared across Pulp Distribution plugins.
*
* @see https://github.com/pulp/pulpcore/blob/934c752dae916857b2005e1fe0ef75496accc082/pulpcore/app/serializers/publication.py
*/
interface GenericDistribution extends GenericResource {
base_path: string;
readonly base_url?: string;
content_guard?: string | null;
readonly content_guard_prn?: string | null;
readonly no_content_change_since?: string | null;
hidden?: boolean;
pulp_labels?: Record<string, string>;
name: string;
repository?: string;
repository_version?: string;
}

/**
* Generic Publication shared across Pulp Publication plugins.
*
* @see https://github.com/pulp/pulpcore/blob/934c752dae916857b2005e1fe0ef75496accc082/pulpcore/app/serializers/publication.py#L23
*/
interface GenericPublication extends GenericResource {
repository_version?: string;
repository?: string;
}

/**
* Generic Remote shared across Pulp Remote plugins.
*
* @see https://github.com/pulp/pulpcore/blob/934c752dae916857b2005e1fe0ef75496accc082/pulpcore/app/serializers/repository.py#L85
* @see https://github.com/pulp/pulpcore/blob/934c752dae916857b2005e1fe0ef75496accc082/pulpcore/app/serializers/base.py#L612
* @see https://github.com/pulp/pulpcore/blob/934c752dae916857b2005e1fe0ef75496accc082/pulpcore/app/serializers/base.py#L367
*/
interface GenericRemote extends GenericResource {
pulp_labels?: Record<string, string>;
name: string;
url: string;
policy?: string;
readonly hidden_fields?: { name: string; is_set: boolean }[];
ca_cert?: string | null;
client_cert?: string | null;
client_key?: string | null;
tls_validation?: boolean;
proxy_url?: string | null;
proxy_username?: string | null;
proxy_password?: string | null;
username?: string | null;
password?: string | null;
max_retries?: number | null;
total_timeout?: number | null;
connect_timeout?: number | null;
sock_connect_timeout?: number | null;
sock_read_timeout?: number | null;
headers?: unknown[];
download_concurrency?: number | null;
rate_limit?: number | null;
}

/**
* Generic Filters shared across PulpCore & Plugin Endpoints.
*
* @see https://github.com/pulp/pulpcore/blob/934c752dae916857b2005e1fe0ef75496accc082/pulpcore/filters.py#L290
*/
interface GenericFilterParams {
pulp_id__in?: string;
pulp_href__in?: string;
prn__in?: string;
q?: string;
exclude_fields?: string;
fields?: string;
limit?: number;
minimal?: boolean;
offset?: number;
page_size?: number;
ordering?: string;
format?: string;
}

type LookupFilterParams<
Field extends string,
Lookup extends string,
Value,
> = Partial<Record<Field | `${Field}__${Lookup}`, Value>>;
type NameFilterOptions =
| 'iexact'
| 'in'
| 'contains'
| 'icontains'
| 'startswith'
| 'istartswith'
| 'regex'
| 'iregex';
type NullableNumericFilterOptions =
| 'ne'
| 'lt'
| 'lte'
| 'gt'
| 'gte'
| 'range'
| 'isnull';
type NameFilterParams = LookupFilterParams<'name', NameFilterOptions, string>;
type RetainRepoVersionsFilterParams = LookupFilterParams<
'retain_repo_versions',
NullableNumericFilterOptions,
number | string
>;
type RetainCheckpointsFilterParams = LookupFilterParams<
'retain_checkpoints',
NullableNumericFilterOptions,
number | string
>;

/**
* Generic Repository Filters shared across PulpCore & Plugin Endpoints.
*
* @see https://github.com/pulp/pulpcore/blob/934c752dae916857b2005e1fe0ef75496accc082/pulpcore/app/viewsets/repository.py#L88
*/
interface GenericRepositoryFilterParams
extends
GenericFilterParams,
NameFilterParams,
RetainRepoVersionsFilterParams,
RetainCheckpointsFilterParams {
pulp_label_select?: string;
remote?: string | null;
with_content?: string;
latest_with_content?: string;
}

/**
* Paginated Response shared across PulpCore & Plugin Endpoints.
*
* @see https://github.com/pulp/pulpcore/blob/934c752dae916857b2005e1fe0ef75496accc082/pulpcore/app/settings.py#L186
* @see https://github.com/encode/django-rest-framework/blob/6f0b74def3fcc81e126b87b08e59abdb6c2ad056/rest_framework/pagination.py#L364
*/
interface PaginatedResponse<TResult> {
count: number;
next: string | null;
previous: string | null;
results: TResult[];
}

/**
* Async Task Dispatch Response shared across PulpCore & Plugin Endpoints.
*
* @see https://github.com/pulp/pulpcore/blob/dea04fa79a6ca590f2943a0a7754c219061be10c/pulpcore/app/response.py#L6
*/
interface DispatchedTaskResponse {
task: string;
}

/**
* --------------------
* These are shared Plugin Types outside the PulpCore Generics.
* --------------------
*/

/**
* Last Sync Task Type.
*
* @see https://github.com/pulp/pulp_ansible/blob/0043923641fc7fd3893f8489fd29ff04addc9d71/pulp_ansible/app/utils.py#L47
*/
interface AnsibleLastSyncType {
pk: string;
state: PulpStatus;
pulp_created: string;
finished_at: string | null;
error: TaskErrorType | null;
}

export type {
TaskErrorType,
GenericRepository,
GenericDistribution,
GenericPublication,
GenericRemote,
GenericRepositoryFilterParams,
PaginatedResponse,
DispatchedTaskResponse,
AnsibleLastSyncType,
};
Loading