POC/Provisioning: update generator (#98027)
* Add source * Update filters * Exclude all namespace endpoints * Remove watch endpoints * Exclude collection endpoint * Update arg names * Add parser script * Update spec * Update @rtk-query/codegen-openapi * Update params for list endpoints * Use new hooks and types in hooks * alternative operation ID * alternative operation ID * alt operation * alt operation * Move some transformations to BE * Update endpoints * Update types after generation * Remove spec and generated endpoints * Add tags automatically * Update pkg/services/apiserver/builder/helper.go Co-authored-by: Ryan McKinley <ryantxu@gmail.com> * add static openapi * Use generated spec --------- Co-authored-by: Ryan McKinley <ryantxu@gmail.com>
This commit is contained in:
co-authored by
Ryan McKinley
parent
2f4f727758
commit
dfb7d5110e
+2
-2
@@ -63,7 +63,7 @@
|
||||
"plugin:build:commit": "nx run-many -t build:commit --projects='tag:scope:plugin'",
|
||||
"plugin:build:dev": "nx run-many -t dev --projects='tag:scope:plugin' --maxParallel=100",
|
||||
"generate-icons": "nx run grafana-icons:generate",
|
||||
"generate-apis": "rtk-query-codegen-openapi ./scripts/generate-rtk-apis.ts"
|
||||
"generate-apis": "rtk-query-codegen-openapi ./scripts/generate-rtk-apis.ts && ts-node scripts/parse-generated-api.ts"
|
||||
},
|
||||
"grafana": {
|
||||
"whatsNewUrl": "https://grafana.com/docs/grafana/next/whatsnew/whats-new-in-v11-4/",
|
||||
@@ -90,7 +90,7 @@
|
||||
"@react-types/overlays": "3.8.11",
|
||||
"@react-types/shared": "3.26.0",
|
||||
"@rsdoctor/webpack-plugin": "^0.4.6",
|
||||
"@rtk-query/codegen-openapi": "^1.2.0",
|
||||
"@rtk-query/codegen-openapi": "^2.0.0",
|
||||
"@rtsao/plugin-proposal-class-properties": "7.0.1-patch.1",
|
||||
"@stylistic/eslint-plugin-ts": "^2.9.0",
|
||||
"@swc/core": "1.10.1",
|
||||
|
||||
@@ -2,9 +2,14 @@ package builder
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/csv"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
@@ -117,15 +122,104 @@ func SetupConfig(
|
||||
// Add the custom routes to service discovery
|
||||
serverConfig.OpenAPIV3Config.PostProcessSpec = getOpenAPIPostProcessor(buildVersion, builders)
|
||||
serverConfig.OpenAPIV3Config.GetOperationIDAndTagsFromRoute = func(r common.Route) (string, []string, error) {
|
||||
meta := r.Metadata()
|
||||
kind := ""
|
||||
action := ""
|
||||
sub := ""
|
||||
|
||||
tags := []string{}
|
||||
prop, ok := r.Metadata()["x-kubernetes-group-version-kind"]
|
||||
prop, ok := meta["x-kubernetes-group-version-kind"]
|
||||
if ok {
|
||||
gvk, ok := prop.(metav1.GroupVersionKind)
|
||||
if ok && gvk.Kind != "" {
|
||||
kind = gvk.Kind
|
||||
tags = append(tags, gvk.Kind)
|
||||
}
|
||||
}
|
||||
return r.OperationName(), tags, nil
|
||||
prop, ok = meta["x-kubernetes-action"]
|
||||
if ok {
|
||||
action = fmt.Sprintf("%v", prop)
|
||||
}
|
||||
|
||||
isNew := false
|
||||
if _, err := os.Stat("test.csv"); errors.Is(err, os.ErrNotExist) {
|
||||
isNew = true
|
||||
}
|
||||
|
||||
if action == "connect" {
|
||||
idx := strings.LastIndex(r.Path(), "/{name}/")
|
||||
if idx > 0 {
|
||||
sub = r.Path()[(idx + len("/{name}/")):]
|
||||
}
|
||||
}
|
||||
|
||||
operationAlt := r.OperationName()
|
||||
if action != "" {
|
||||
if action == "connect" {
|
||||
idx := strings.Index(r.OperationName(), "Namespaced")
|
||||
if idx > 0 {
|
||||
operationAlt = strings.ToLower(r.Method()) +
|
||||
r.OperationName()[idx:]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
operationAlt = strings.ReplaceAll(operationAlt, "Namespaced", "")
|
||||
if strings.HasPrefix(operationAlt, "post") {
|
||||
operationAlt = "create" + operationAlt[len("post"):]
|
||||
} else if strings.HasPrefix(operationAlt, "read") {
|
||||
operationAlt = "get" + operationAlt[len("read"):]
|
||||
} else if strings.HasPrefix(operationAlt, "patch") {
|
||||
operationAlt = "update" + operationAlt[len("patch"):]
|
||||
}
|
||||
|
||||
// Audit our options here
|
||||
if false {
|
||||
// Safe to ignore G304 -- this will be removed before merging to main, and just helps audit the conversion
|
||||
// nolint:gosec
|
||||
f, err := os.OpenFile("test.csv", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: %s\n", err)
|
||||
} else {
|
||||
metastr, _ := json.Marshal(meta)
|
||||
|
||||
prop, ok = meta["x-kubernetes-group-version-kind"]
|
||||
if ok {
|
||||
gvk, ok := prop.(metav1.GroupVersionKind)
|
||||
if ok {
|
||||
kind = gvk.Kind
|
||||
}
|
||||
}
|
||||
|
||||
w := csv.NewWriter(f)
|
||||
if isNew {
|
||||
w.Write([]string{
|
||||
"#Path",
|
||||
"Method",
|
||||
"action",
|
||||
"kind",
|
||||
"sub",
|
||||
"OperationName",
|
||||
"OperationNameAlt",
|
||||
"Description",
|
||||
"metadata",
|
||||
})
|
||||
}
|
||||
w.Write([]string{
|
||||
r.Path(),
|
||||
r.Method(),
|
||||
action,
|
||||
kind,
|
||||
sub,
|
||||
r.OperationName(),
|
||||
operationAlt,
|
||||
r.Description(),
|
||||
string(metastr),
|
||||
})
|
||||
w.Flush()
|
||||
}
|
||||
}
|
||||
return operationAlt, tags, nil
|
||||
}
|
||||
|
||||
// Set the swagger build versions
|
||||
|
||||
@@ -8,10 +8,12 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/stretchr/testify/require"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@@ -168,6 +170,45 @@ func (c *K8sTestHelper) AsStatusError(err error) *errors.StatusError {
|
||||
return statusError
|
||||
}
|
||||
|
||||
func (c *K8sTestHelper) VerifyStaticOpenAPISpec(gv schema.GroupVersion, fpath string) {
|
||||
c.t.Helper()
|
||||
|
||||
path := fmt.Sprintf("/openapi/v3/apis/%s/%s", gv.Group, gv.Version)
|
||||
rsp := DoRequest(c, RequestParams{
|
||||
Method: http.MethodGet,
|
||||
Path: path,
|
||||
User: c.Org1.Admin,
|
||||
}, &AnyResource{})
|
||||
|
||||
require.NotNil(c.t, rsp.Response)
|
||||
require.Equal(c.t, 200, rsp.Response.StatusCode)
|
||||
|
||||
var prettyJSON bytes.Buffer
|
||||
err := json.Indent(&prettyJSON, rsp.Body, "", " ")
|
||||
require.NoError(c.t, err)
|
||||
pretty := prettyJSON.String()
|
||||
|
||||
// nolint:gosec
|
||||
// We can ignore the gosec G304 warning since this is a test and the function is only called with explicit paths
|
||||
body, err := os.ReadFile(fpath)
|
||||
if err == nil {
|
||||
if diff := cmp.Diff(pretty, string(body)); diff != "" {
|
||||
str := fmt.Sprintf("body mismatch (-want +got):\n%s\n", diff)
|
||||
err = fmt.Errorf(str)
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
e2 := os.WriteFile(fpath, []byte(pretty), 0644)
|
||||
if e2 != nil {
|
||||
c.t.Errorf("error writing file: %s", e2.Error())
|
||||
}
|
||||
abs, _ := filepath.Abs(fpath)
|
||||
c.t.Errorf("openapi spec has changed: %s (%s)", err.Error(), abs)
|
||||
c.t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func (c *K8sResourceClient) SanitizeJSONList(v *unstructured.UnstructuredList, replaceMeta ...string) string {
|
||||
c.t.Helper()
|
||||
|
||||
|
||||
@@ -202,6 +202,11 @@ func TestIntegrationProvisioning(t *testing.T) {
|
||||
}
|
||||
]
|
||||
}`, string(v1Disco))
|
||||
|
||||
// also verify the openapi
|
||||
helper.VerifyStaticOpenAPISpec(schema.GroupVersion{
|
||||
Group: "provisioning.grafana.app", Version: "v0alpha1",
|
||||
}, "testdata/openapi.json")
|
||||
})
|
||||
|
||||
t.Run("Check basic create and get", func(t *testing.T) {
|
||||
|
||||
+5388
File diff suppressed because it is too large
Load Diff
@@ -20,8 +20,7 @@ import { AnnoKeyRepoName, AnnoKeyRepoPath } from 'app/features/apiserver/types';
|
||||
import { DashboardMeta } from 'app/types';
|
||||
|
||||
import { RepositorySelect } from '../../provisioning/RepositorySelect';
|
||||
import { useGetRepositoryQuery } from '../../provisioning/api';
|
||||
import { RepositorySpec } from '../../provisioning/api/types';
|
||||
import { useGetRepositoryQuery, RepositorySpec } from '../../provisioning/api';
|
||||
import { PROVISIONING_URL } from '../../provisioning/constants';
|
||||
import { useCreateOrUpdateRepositoryFile, usePullRequestParam } from '../../provisioning/hooks';
|
||||
import { WorkflowOption } from '../../provisioning/types';
|
||||
|
||||
@@ -23,7 +23,10 @@ const injectedRtkApi = api.injectEndpoints({
|
||||
getSnapshot: build.query<GetSnapshotApiResponse, GetSnapshotApiArg>({
|
||||
query: (queryArg) => ({
|
||||
url: `/cloudmigration/migration/${queryArg.uid}/snapshot/${queryArg.snapshotUid}`,
|
||||
params: { resultPage: queryArg.resultPage, resultLimit: queryArg.resultLimit },
|
||||
params: {
|
||||
resultPage: queryArg.resultPage,
|
||||
resultLimit: queryArg.resultLimit,
|
||||
},
|
||||
}),
|
||||
}),
|
||||
cancelSnapshot: build.mutation<CancelSnapshotApiResponse, CancelSnapshotApiArg>({
|
||||
@@ -41,7 +44,11 @@ const injectedRtkApi = api.injectEndpoints({
|
||||
getShapshotList: build.query<GetShapshotListApiResponse, GetShapshotListApiArg>({
|
||||
query: (queryArg) => ({
|
||||
url: `/cloudmigration/migration/${queryArg.uid}/snapshots`,
|
||||
params: { page: queryArg.page, limit: queryArg.limit, sort: queryArg.sort },
|
||||
params: {
|
||||
page: queryArg.page,
|
||||
limit: queryArg.limit,
|
||||
sort: queryArg.sort,
|
||||
},
|
||||
}),
|
||||
}),
|
||||
getCloudMigrationToken: build.query<GetCloudMigrationTokenApiResponse, GetCloudMigrationTokenApiArg>({
|
||||
@@ -95,14 +102,14 @@ export type GetSnapshotApiArg = {
|
||||
/** UID of a snapshot */
|
||||
snapshotUid: string;
|
||||
};
|
||||
export type CancelSnapshotApiResponse = /** status 200 (empty) */ void;
|
||||
export type CancelSnapshotApiResponse = unknown;
|
||||
export type CancelSnapshotApiArg = {
|
||||
/** Session UID of a session */
|
||||
uid: string;
|
||||
/** UID of a snapshot */
|
||||
snapshotUid: string;
|
||||
};
|
||||
export type UploadSnapshotApiResponse = /** status 200 (empty) */ void;
|
||||
export type UploadSnapshotApiResponse = unknown;
|
||||
export type UploadSnapshotApiArg = {
|
||||
/** Session UID of a session */
|
||||
uid: string;
|
||||
@@ -124,7 +131,7 @@ export type GetCloudMigrationTokenApiResponse = /** status 200 (empty) */ GetAcc
|
||||
export type GetCloudMigrationTokenApiArg = void;
|
||||
export type CreateCloudMigrationTokenApiResponse = /** status 200 (empty) */ CreateAccessTokenResponseDto;
|
||||
export type CreateCloudMigrationTokenApiArg = void;
|
||||
export type DeleteCloudMigrationTokenApiResponse = /** status 204 (empty) */ void;
|
||||
export type DeleteCloudMigrationTokenApiResponse = unknown;
|
||||
export type DeleteCloudMigrationTokenApiArg = {
|
||||
/** UID of a cloud migration token */
|
||||
uid: string;
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
import { FormPrompt } from 'app/core/components/FormPrompt/FormPrompt';
|
||||
import { FolderPicker } from 'app/core/components/Select/FolderPicker';
|
||||
|
||||
import { RepositoryResource, RepositorySpec } from './api/types';
|
||||
import { Repository, RepositorySpec } from './api';
|
||||
import { useCreateOrUpdateRepository } from './hooks';
|
||||
import { RepositoryFormData } from './types';
|
||||
import { dataToSpec, specToData } from './utils/data';
|
||||
@@ -52,10 +52,10 @@ function getDefaultValues(repository?: RepositorySpec): RepositoryFormData {
|
||||
}
|
||||
|
||||
export interface ConfigFormProps {
|
||||
data?: RepositoryResource;
|
||||
data?: Repository;
|
||||
}
|
||||
export function ConfigForm({ data }: ConfigFormProps) {
|
||||
const [submitData, request] = useCreateOrUpdateRepository(data?.metadata.name);
|
||||
const [submitData, request] = useCreateOrUpdateRepository(data?.metadata?.name);
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
|
||||
@@ -21,7 +21,7 @@ export function DeleteRepositoryButton({ name }: { name: string }) {
|
||||
}, [request.isSuccess]);
|
||||
|
||||
const onConfirm = useCallback(() => {
|
||||
deleteRepository({ name });
|
||||
deleteRepository({ name, body: {} });
|
||||
}, [deleteRepository, name]);
|
||||
|
||||
return (
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useParams } from 'react-router-dom-v5-compat';
|
||||
import { Card, EmptyState, Spinner, Text, TextLink } from '@grafana/ui';
|
||||
import { Page } from 'app/core/components/Page/Page';
|
||||
|
||||
import { useListRepositoryFileHistoryQuery, useGetRepositoryStatusQuery } from './api';
|
||||
import { useGetRepositoryHistoryWithPathQuery, useGetRepositoryStatusQuery } from './api';
|
||||
import { HistoryListResponse } from './api/types';
|
||||
import { PROVISIONING_URL } from './constants';
|
||||
|
||||
@@ -12,7 +12,7 @@ export default function FileHistoryPage() {
|
||||
const name = params['name'] ?? '';
|
||||
const path = params['*'] ?? '';
|
||||
const query = useGetRepositoryStatusQuery({ name });
|
||||
const history = useListRepositoryFileHistoryQuery({ name, path });
|
||||
const history = useGetRepositoryHistoryWithPathQuery({ name, path });
|
||||
|
||||
//@ts-expect-error TODO add error types
|
||||
const notFound = query.isError && query.error?.status === 404;
|
||||
@@ -21,7 +21,7 @@ export default function FileHistoryPage() {
|
||||
navId="provisioning"
|
||||
pageNav={{
|
||||
text: `History: ${path}`, //,
|
||||
subTitle: query.data?.spec.title ?? 'Repository',
|
||||
subTitle: query.data?.spec?.title ?? 'Repository',
|
||||
}}
|
||||
>
|
||||
<Page.Contents isLoading={false}>
|
||||
@@ -31,6 +31,7 @@ export default function FileHistoryPage() {
|
||||
<TextLink href={PROVISIONING_URL}>Back to repositories</TextLink>
|
||||
</EmptyState>
|
||||
) : (
|
||||
//@ts-expect-error TODO fix history response types
|
||||
<div>{history.data ? <HistoryView history={history.data} path={path} repo={name} /> : <Spinner />}</div>
|
||||
)}
|
||||
</Page.Contents>
|
||||
|
||||
@@ -19,8 +19,7 @@ import {
|
||||
import { Page } from 'app/core/components/Page/Page';
|
||||
import { useQueryParams } from 'app/core/hooks/useQueryParams';
|
||||
|
||||
import { useGetRepositoryFilesQuery, useGetRepositoryStatusQuery } from './api';
|
||||
import { ResourceWrapper } from './api/types';
|
||||
import { useGetRepositoryFilesWithPathQuery, useGetRepositoryStatusQuery, ResourceWrapper } from './api';
|
||||
import { PROVISIONING_URL } from './constants';
|
||||
|
||||
export default function FileStatusPage() {
|
||||
@@ -31,7 +30,7 @@ export default function FileStatusPage() {
|
||||
const name = params['name'] ?? '';
|
||||
const path = params['*'] ?? '';
|
||||
const query = useGetRepositoryStatusQuery({ name });
|
||||
const file = useGetRepositoryFilesQuery({ name, path, ref });
|
||||
const file = useGetRepositoryFilesWithPathQuery({ name, path, ref });
|
||||
|
||||
//@ts-expect-error TODO add error types
|
||||
const notFound = query.isError && query.error?.status === 404;
|
||||
@@ -40,7 +39,7 @@ export default function FileStatusPage() {
|
||||
navId="provisioning"
|
||||
pageNav={{
|
||||
text: `File: ${path} ${ref ? `(@${ref})` : ''}`,
|
||||
subTitle: query.data?.spec.title ?? 'Repository',
|
||||
subTitle: query.data?.spec?.title ?? 'Repository',
|
||||
}}
|
||||
>
|
||||
<Page.Contents isLoading={false}>
|
||||
@@ -141,11 +140,14 @@ function ResourceView({ wrap, repo, repoRef, tab }: Props) {
|
||||
{tab === TabSelection.Lint && (
|
||||
<div>
|
||||
{wrap.lint ? (
|
||||
wrap.lint.map((r, idx) => (
|
||||
<Alert title={r.rule} severity={r.severity} key={`${r.rule}/${idx}`}>
|
||||
{r.message}
|
||||
</Alert>
|
||||
))
|
||||
wrap.lint.map((r, idx) => {
|
||||
return (
|
||||
//@ts-expect-error TODO fix lint response types
|
||||
<Alert title={r.rule} severity={r.severity} key={`${r.rule}/${idx}`}>
|
||||
{r.message}
|
||||
</Alert>
|
||||
);
|
||||
})
|
||||
) : (
|
||||
<div>
|
||||
<h3>No lint issues</h3>
|
||||
|
||||
@@ -4,11 +4,9 @@ import { useState } from 'react';
|
||||
import { Card, EmptySearchResult, EmptyState, FilterInput, LinkButton, Stack, TextLink } from '@grafana/ui';
|
||||
import { Page } from 'app/core/components/Page/Page';
|
||||
|
||||
import { Resource } from '../apiserver/types';
|
||||
|
||||
import { DeleteRepositoryButton } from './DeleteRepositoryButton';
|
||||
import { SyncRepository } from './SyncRepository';
|
||||
import { RepositorySpec } from './api/types';
|
||||
import { Repository } from './api';
|
||||
import { NEW_URL, PROVISIONING_URL } from './constants';
|
||||
import { useRepositoryList } from './hooks';
|
||||
|
||||
@@ -23,7 +21,7 @@ export default function RepositoryListPage() {
|
||||
);
|
||||
}
|
||||
|
||||
function RepositoryListPageContent({ items }: { items?: Array<Resource<RepositorySpec>> }) {
|
||||
function RepositoryListPageContent({ items }: { items?: Repository[] }) {
|
||||
const [query, setQuery] = useState('');
|
||||
if (!items?.length) {
|
||||
return (
|
||||
@@ -39,7 +37,7 @@ function RepositoryListPageContent({ items }: { items?: Array<Resource<Repositor
|
||||
);
|
||||
}
|
||||
|
||||
const filteredItems = items.filter((item) => item.metadata.name.includes(query));
|
||||
const filteredItems = items.filter((item) => item.metadata?.name?.includes(query));
|
||||
|
||||
return (
|
||||
<Stack direction={'column'} gap={3}>
|
||||
@@ -52,20 +50,21 @@ function RepositoryListPageContent({ items }: { items?: Array<Resource<Repositor
|
||||
<Stack direction={'column'}>
|
||||
{!!filteredItems.length ? (
|
||||
filteredItems.map((item) => {
|
||||
const name = item.metadata?.name ?? '';
|
||||
return (
|
||||
<Card key={item.metadata.name} className={css({ alignItems: 'center' })}>
|
||||
<Card key={item.metadata?.name} className={css({ alignItems: 'center' })}>
|
||||
<Stack direction={'column'}>
|
||||
<Card.Heading>
|
||||
<TextLink href={`${PROVISIONING_URL}/${item.metadata.name}`}>{item.spec.title}</TextLink>
|
||||
<TextLink href={`${PROVISIONING_URL}/${name}`}>{item.spec?.title}</TextLink>
|
||||
</Card.Heading>
|
||||
<Card.Meta>{item.spec.type}</Card.Meta>
|
||||
<Card.Meta>{item.spec?.type}</Card.Meta>
|
||||
</Stack>
|
||||
<Stack>
|
||||
<LinkButton variant="secondary" href={`${PROVISIONING_URL}/${item.metadata.name}/edit`}>
|
||||
<LinkButton variant="secondary" href={`${PROVISIONING_URL}/${name}/edit`}>
|
||||
Edit
|
||||
</LinkButton>
|
||||
<SyncRepository repository={item} />
|
||||
<DeleteRepositoryButton name={item.metadata.name} />
|
||||
<DeleteRepositoryButton name={name} />
|
||||
</Stack>
|
||||
</Card>
|
||||
);
|
||||
|
||||
@@ -16,8 +16,8 @@ export function RepositorySelect(props: Pick<ComboboxBaseProps<string>, 'value'
|
||||
placeholder={'Select a repository'}
|
||||
options={
|
||||
listQuery.data?.items?.map((repo) => ({
|
||||
label: repo.spec.title,
|
||||
value: repo.metadata.name,
|
||||
label: repo.spec?.title,
|
||||
value: repo.metadata?.name ?? '',
|
||||
})) || []
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -4,7 +4,6 @@ import { useParams } from 'react-router-dom-v5-compat';
|
||||
|
||||
import { SelectableValue, urlUtil } from '@grafana/data';
|
||||
import {
|
||||
List,
|
||||
Alert,
|
||||
Card,
|
||||
CellProps,
|
||||
@@ -24,13 +23,8 @@ import {
|
||||
import { Page } from 'app/core/components/Page/Page';
|
||||
import { useQueryParams } from 'app/core/hooks/useQueryParams';
|
||||
|
||||
import {
|
||||
useGetRepositoryStatusQuery,
|
||||
useListJobsQuery,
|
||||
useListRepositoryFilesQuery,
|
||||
useTestRepositoryQuery,
|
||||
} from './api';
|
||||
import { RepositoryResource, FileDetails, TestResponse } from './api/types';
|
||||
import { useGetRepositoryStatusQuery, useListJobQuery, useGetRepositoryFilesQuery, Repository } from './api';
|
||||
import { FileDetails } from './api/types';
|
||||
import { PROVISIONING_URL } from './constants';
|
||||
|
||||
enum TabSelection {
|
||||
@@ -60,7 +54,7 @@ export default function RepositoryStatusPage() {
|
||||
<Page
|
||||
navId="provisioning"
|
||||
pageNav={{
|
||||
text: query.data?.spec.title ?? 'Repository Status',
|
||||
text: query.data?.spec?.title ?? 'Repository Status',
|
||||
subTitle: 'Check the status of configured repository.',
|
||||
}}
|
||||
>
|
||||
@@ -74,7 +68,7 @@ export default function RepositoryStatusPage() {
|
||||
<>
|
||||
{query.data ? (
|
||||
<>
|
||||
<ErrorView repo={query.data} />
|
||||
{/*<ErrorView repo={query.data} />*/}
|
||||
<TabsBar>
|
||||
{tabInfo.map((t: SelectableValue) => (
|
||||
<Tab
|
||||
@@ -102,39 +96,39 @@ export default function RepositoryStatusPage() {
|
||||
);
|
||||
}
|
||||
interface RepoProps {
|
||||
repo: RepositoryResource;
|
||||
repo: Repository;
|
||||
}
|
||||
|
||||
function ErrorView({ repo }: RepoProps) {
|
||||
const name = repo.metadata.name;
|
||||
const status = useTestRepositoryQuery({ name });
|
||||
if (status.isLoading) {
|
||||
return (
|
||||
<div>
|
||||
<Spinner /> Testing configuration...
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (status.isError) {
|
||||
let response = (status.error as any)?.data as TestResponse;
|
||||
if (!response || !response.errors) {
|
||||
return <Alert title="Error testing configuration" severity="error" />;
|
||||
}
|
||||
|
||||
return (
|
||||
<Alert title="Error testing configuration" severity="error">
|
||||
<List items={response.errors} renderItem={(error) => <div>{error}</div>} />
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
return null; // don't show anything when it is OK?
|
||||
}
|
||||
// function ErrorView({ repo }: RepoProps) {
|
||||
// const name = repo.metadata.name;
|
||||
// const status = useTestRepositoryQuery({ name });
|
||||
// if (status.isLoading) {
|
||||
// return (
|
||||
// <div>
|
||||
// <Spinner /> Testing configuration...
|
||||
// </div>
|
||||
// );
|
||||
// }
|
||||
// if (status.isError) {
|
||||
// let response = (status.error as any)?.data as TestResponse;
|
||||
// if (!response || !response.errors) {
|
||||
// return <Alert title="Error testing configuration" severity="error" />;
|
||||
// }
|
||||
//
|
||||
// return (
|
||||
// <Alert title="Error testing configuration" severity="error">
|
||||
// <List items={response.errors} renderItem={(error) => <div>{error}</div>} />
|
||||
// </Alert>
|
||||
// );
|
||||
// }
|
||||
// return null; // don't show anything when it is OK?
|
||||
// }
|
||||
|
||||
type Cell<T extends keyof FileDetails = keyof FileDetails> = CellProps<FileDetails, FileDetails[T]>;
|
||||
|
||||
function FilesView({ repo }: RepoProps) {
|
||||
const name = repo.metadata.name;
|
||||
const query = useListRepositoryFilesQuery({ name });
|
||||
const name = repo.metadata?.name ?? '';
|
||||
const query = useGetRepositoryFilesQuery({ name });
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
const data = [...(query.data?.files ?? [])].filter((file) =>
|
||||
file.path.toLowerCase().includes(searchQuery.toLowerCase())
|
||||
@@ -205,8 +199,8 @@ function FilesView({ repo }: RepoProps) {
|
||||
}
|
||||
|
||||
function JobsView({ repo }: RepoProps) {
|
||||
const name = repo.metadata.name;
|
||||
const query = useListJobsQuery({
|
||||
const name = repo.metadata?.name;
|
||||
const query = useListJobQuery({
|
||||
labelSelector: [
|
||||
{
|
||||
key: 'repository',
|
||||
@@ -241,9 +235,9 @@ function JobsView({ repo }: RepoProps) {
|
||||
<div>
|
||||
{items.map((item) => {
|
||||
return (
|
||||
<Card key={item.metadata.resourceVersion}>
|
||||
<Card key={item.metadata?.resourceVersion}>
|
||||
<Card.Heading>
|
||||
{item.spec.action} / {item.status?.state}
|
||||
{item.spec?.action} / {item.status?.state}
|
||||
</Card.Heading>
|
||||
<Card.Description>
|
||||
<span>{JSON.stringify(item.spec)}</span>
|
||||
@@ -259,9 +253,9 @@ function JobsView({ repo }: RepoProps) {
|
||||
function FolderView({ repo }: RepoProps) {
|
||||
return (
|
||||
<div>
|
||||
<h2>TODO, show folder: {repo.metadata.name}</h2>
|
||||
<h2>TODO, show folder: {repo.metadata?.name}</h2>
|
||||
<br />
|
||||
<a href={`/dashboards/f/${repo.spec.folder} /`}>{repo.spec.folder} </a>
|
||||
<a href={`/dashboards/f/${repo.spec?.folder} /`}>{repo.spec?.folder} </a>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -269,9 +263,9 @@ function FolderView({ repo }: RepoProps) {
|
||||
function SettingsView({ repo }: RepoProps) {
|
||||
return (
|
||||
<div>
|
||||
<h2>TODO, show settings inline???: {repo.metadata.name}</h2>
|
||||
<h2>TODO, show settings inline???: {repo.metadata?.name}</h2>
|
||||
|
||||
<LinkButton href={`${PROVISIONING_URL}/${repo.metadata.name}/edit`}>Edit</LinkButton>
|
||||
<LinkButton href={`${PROVISIONING_URL}/${repo.metadata?.name}/edit`}>Edit</LinkButton>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,14 +6,12 @@ import { AppEvents } from '@grafana/data';
|
||||
import { config, getAppEvents, getBackendSrv } from '@grafana/runtime';
|
||||
import { Button, ConfirmModal } from '@grafana/ui';
|
||||
|
||||
import { Resource } from '../apiserver/types';
|
||||
import { Loader } from '../plugins/admin/components/Loader';
|
||||
|
||||
import { useCreateRepositorySyncMutation, useListRepositoryQuery } from './api';
|
||||
import { RepositorySpec } from './api/types';
|
||||
import { Repository, useCreateRepositorySyncMutation, useListRepositoryQuery } from './api';
|
||||
|
||||
interface Props {
|
||||
repository: Resource<RepositorySpec>;
|
||||
repository: Repository;
|
||||
}
|
||||
|
||||
export function SyncRepository({ repository }: Props) {
|
||||
|
||||
@@ -39,5 +39,4 @@ export const baseAPI = createApi({
|
||||
baseURL: BASE_URL,
|
||||
}),
|
||||
endpoints: () => ({}),
|
||||
tagTypes: ['RepositoryList', 'JobList'],
|
||||
});
|
||||
|
||||
@@ -1,238 +1,658 @@
|
||||
import { Resource } from 'app/features/apiserver/types';
|
||||
|
||||
import { parseListOptionsSelector } from '../../apiserver/client';
|
||||
|
||||
import { baseAPI as api } from './baseAPI';
|
||||
import {
|
||||
RepositoryList,
|
||||
RepositoryResource,
|
||||
RequestArg,
|
||||
UpdateRequestArg,
|
||||
RepositoryForCreate,
|
||||
ResourceWrapper,
|
||||
FileOperationArg,
|
||||
GetFileArg,
|
||||
ListFilesApiResponse,
|
||||
HistoryListResponse,
|
||||
TestResponse,
|
||||
RepositorySpec,
|
||||
JobList,
|
||||
JobResource,
|
||||
ListApiArg,
|
||||
WebhookResponse,
|
||||
HistoryItem,
|
||||
GetRequestArg,
|
||||
} from './types';
|
||||
|
||||
const BASE_PATH = '/repositories';
|
||||
|
||||
const injectedRtkApi = api.injectEndpoints({
|
||||
endpoints: (build) => ({
|
||||
listJobs: build.query<JobList, ListApiArg | void>({
|
||||
query: (queryArg) => {
|
||||
return {
|
||||
export const addTagTypes = ['Job', 'Repository'] as const;
|
||||
const injectedRtkApi = api
|
||||
.enhanceEndpoints({
|
||||
addTagTypes,
|
||||
})
|
||||
.injectEndpoints({
|
||||
endpoints: (build) => ({
|
||||
listJob: build.query<ListJobResponse, ListJobArg | void>({
|
||||
query: (queryArg) => ({
|
||||
url: `/jobs`,
|
||||
params: getListParams(queryArg),
|
||||
};
|
||||
},
|
||||
providesTags: ['JobList'],
|
||||
}),
|
||||
getJob: build.query<JobResource, RequestArg>({
|
||||
query: (queryArg) => ({
|
||||
url: `/jobs/${queryArg.name}`,
|
||||
}),
|
||||
providesTags: ['Job'],
|
||||
}),
|
||||
getJob: build.query<GetJobResponse, GetJobArg>({
|
||||
query: (queryArg) => ({
|
||||
url: `/jobs/${queryArg.name}`,
|
||||
params: {
|
||||
pretty: queryArg.pretty,
|
||||
},
|
||||
}),
|
||||
providesTags: ['Job'],
|
||||
}),
|
||||
listRepository: build.query<ListRepositoryResponse, ListRepositoryArg | void>({
|
||||
query: (queryArg) => ({
|
||||
url: `/repositories`,
|
||||
}),
|
||||
providesTags: ['Repository'],
|
||||
}),
|
||||
createRepository: build.mutation<CreateRepositoryResponse, CreateRepositoryArg>({
|
||||
query: (queryArg) => ({
|
||||
url: `/repositories`,
|
||||
method: 'POST',
|
||||
body: queryArg.body,
|
||||
params: {
|
||||
pretty: queryArg.pretty,
|
||||
dryRun: queryArg.dryRun,
|
||||
fieldManager: queryArg.fieldManager,
|
||||
fieldValidation: queryArg.fieldValidation,
|
||||
},
|
||||
}),
|
||||
invalidatesTags: ['Repository'],
|
||||
}),
|
||||
getRepository: build.query<GetRepositoryResponse, GetRepositoryArg>({
|
||||
query: (queryArg) => ({
|
||||
url: `/repositories/${queryArg.name}`,
|
||||
params: {
|
||||
pretty: queryArg.pretty,
|
||||
},
|
||||
}),
|
||||
providesTags: ['Repository'],
|
||||
}),
|
||||
replaceRepository: build.mutation<ReplaceRepositoryResponse, ReplaceRepositoryArg>({
|
||||
query: (queryArg) => ({
|
||||
url: `/repositories/${queryArg.name}`,
|
||||
method: 'PUT',
|
||||
body: queryArg.body,
|
||||
params: {
|
||||
pretty: queryArg.pretty,
|
||||
dryRun: queryArg.dryRun,
|
||||
fieldManager: queryArg.fieldManager,
|
||||
fieldValidation: queryArg.fieldValidation,
|
||||
},
|
||||
}),
|
||||
invalidatesTags: ['Repository'],
|
||||
}),
|
||||
deleteRepository: build.mutation<DeleteRepositoryResponse, DeleteRepositoryArg>({
|
||||
query: (queryArg) => ({
|
||||
url: `/repositories/${queryArg.name}`,
|
||||
method: 'DELETE',
|
||||
body: queryArg.body,
|
||||
params: {
|
||||
pretty: queryArg.pretty,
|
||||
dryRun: queryArg.dryRun,
|
||||
gracePeriodSeconds: queryArg.gracePeriodSeconds,
|
||||
orphanDependents: queryArg.orphanDependents,
|
||||
propagationPolicy: queryArg.propagationPolicy,
|
||||
},
|
||||
}),
|
||||
invalidatesTags: ['Repository'],
|
||||
}),
|
||||
updateRepository: build.mutation<UpdateRepositoryResponse, UpdateRepositoryArg>({
|
||||
query: (queryArg) => ({
|
||||
url: `/repositories/${queryArg.name}`,
|
||||
method: 'PATCH',
|
||||
headers: { 'Content-Type': 'application/merge-patch+json' },
|
||||
body: queryArg.body,
|
||||
params: {
|
||||
pretty: queryArg.pretty,
|
||||
dryRun: queryArg.dryRun,
|
||||
fieldManager: queryArg.fieldManager,
|
||||
fieldValidation: queryArg.fieldValidation,
|
||||
force: queryArg.force,
|
||||
},
|
||||
}),
|
||||
invalidatesTags: ['Repository'],
|
||||
}),
|
||||
createRepositoryExport: build.mutation<CreateRepositoryExportResponse, CreateRepositoryExportArg>({
|
||||
query: (queryArg) => ({
|
||||
url: `/repositories/${queryArg.name}/export`,
|
||||
method: 'POST',
|
||||
}),
|
||||
invalidatesTags: ['Repository'],
|
||||
}),
|
||||
getRepositoryFiles: build.query<GetRepositoryFilesResponse, GetRepositoryFilesArg>({
|
||||
query: (queryArg) => ({
|
||||
url: `/repositories/${queryArg.name}/files/`,
|
||||
params: {
|
||||
ref: queryArg.ref,
|
||||
},
|
||||
}),
|
||||
providesTags: ['Repository'],
|
||||
}),
|
||||
getRepositoryFilesWithPath: build.query<GetRepositoryFilesWithPathResponse, GetRepositoryFilesWithPathArg>({
|
||||
query: (queryArg) => ({
|
||||
url: `/repositories/${queryArg.name}/files/${queryArg.path}`,
|
||||
params: {
|
||||
ref: queryArg.ref,
|
||||
},
|
||||
}),
|
||||
providesTags: ['Repository'],
|
||||
}),
|
||||
putRepositoryFilesWithPath: build.mutation<PutRepositoryFilesWithPathResponse, PutRepositoryFilesWithPathArg>({
|
||||
query: (queryArg) => ({
|
||||
url: `/repositories/${queryArg.name}/files/${queryArg.path}`,
|
||||
method: 'PUT',
|
||||
body: queryArg.body,
|
||||
params: {
|
||||
ref: queryArg.ref,
|
||||
message: queryArg.message,
|
||||
},
|
||||
}),
|
||||
invalidatesTags: ['Repository'],
|
||||
}),
|
||||
createRepositoryFilesWithPath: build.mutation<
|
||||
CreateRepositoryFilesWithPathResponse,
|
||||
CreateRepositoryFilesWithPathArg
|
||||
>({
|
||||
query: (queryArg) => ({
|
||||
url: `/repositories/${queryArg.name}/files/${queryArg.path}`,
|
||||
method: 'POST',
|
||||
body: queryArg.body,
|
||||
params: {
|
||||
ref: queryArg.ref,
|
||||
message: queryArg.message,
|
||||
},
|
||||
}),
|
||||
invalidatesTags: ['Repository'],
|
||||
}),
|
||||
deleteRepositoryFilesWithPath: build.mutation<
|
||||
DeleteRepositoryFilesWithPathResponse,
|
||||
DeleteRepositoryFilesWithPathArg
|
||||
>({
|
||||
query: (queryArg) => ({
|
||||
url: `/repositories/${queryArg.name}/files/${queryArg.path}`,
|
||||
method: 'DELETE',
|
||||
params: {
|
||||
ref: queryArg.ref,
|
||||
message: queryArg.message,
|
||||
},
|
||||
}),
|
||||
invalidatesTags: ['Repository'],
|
||||
}),
|
||||
getRepositoryHistory: build.query<GetRepositoryHistoryResponse, GetRepositoryHistoryArg>({
|
||||
query: (queryArg) => ({
|
||||
url: `/repositories/${queryArg.name}/history`,
|
||||
params: {
|
||||
ref: queryArg.ref,
|
||||
},
|
||||
}),
|
||||
providesTags: ['Repository'],
|
||||
}),
|
||||
getRepositoryHistoryWithPath: build.query<GetRepositoryHistoryWithPathResponse, GetRepositoryHistoryWithPathArg>({
|
||||
query: (queryArg) => ({
|
||||
url: `/repositories/${queryArg.name}/history/${queryArg.path}`,
|
||||
params: {
|
||||
ref: queryArg.ref,
|
||||
},
|
||||
}),
|
||||
providesTags: ['Repository'],
|
||||
}),
|
||||
getRepositoryStatus: build.query<GetRepositoryStatusResponse, GetRepositoryStatusArg>({
|
||||
query: (queryArg) => ({
|
||||
url: `/repositories/${queryArg.name}/status`,
|
||||
params: {
|
||||
pretty: queryArg.pretty,
|
||||
},
|
||||
}),
|
||||
providesTags: ['Repository'],
|
||||
}),
|
||||
replaceRepositoryStatus: build.mutation<ReplaceRepositoryStatusResponse, ReplaceRepositoryStatusArg>({
|
||||
query: (queryArg) => ({
|
||||
url: `/repositories/${queryArg.name}/status`,
|
||||
method: 'PUT',
|
||||
body: queryArg.body,
|
||||
params: {
|
||||
pretty: queryArg.pretty,
|
||||
dryRun: queryArg.dryRun,
|
||||
fieldManager: queryArg.fieldManager,
|
||||
fieldValidation: queryArg.fieldValidation,
|
||||
},
|
||||
}),
|
||||
invalidatesTags: ['Repository'],
|
||||
}),
|
||||
updateRepositoryStatus: build.mutation<UpdateRepositoryStatusResponse, UpdateRepositoryStatusArg>({
|
||||
query: (queryArg) => ({
|
||||
url: `/repositories/${queryArg.name}/status`,
|
||||
method: 'PATCH',
|
||||
headers: { 'Content-Type': 'application/merge-patch+json' },
|
||||
body: queryArg.body,
|
||||
params: {
|
||||
pretty: queryArg.pretty,
|
||||
dryRun: queryArg.dryRun,
|
||||
fieldManager: queryArg.fieldManager,
|
||||
fieldValidation: queryArg.fieldValidation,
|
||||
force: queryArg.force,
|
||||
},
|
||||
}),
|
||||
invalidatesTags: ['Repository'],
|
||||
}),
|
||||
createRepositorySync: build.mutation<CreateRepositorySyncResponse, CreateRepositorySyncArg>({
|
||||
query: (queryArg) => ({
|
||||
url: `/repositories/${queryArg.name}/sync`,
|
||||
method: 'POST',
|
||||
}),
|
||||
invalidatesTags: ['Repository'],
|
||||
}),
|
||||
createRepositoryTest: build.mutation<CreateRepositoryTestResponse, CreateRepositoryTestArg>({
|
||||
query: (queryArg) => ({
|
||||
url: `/repositories/${queryArg.name}/test`,
|
||||
method: 'POST',
|
||||
body: queryArg.body,
|
||||
}),
|
||||
invalidatesTags: ['Repository'],
|
||||
}),
|
||||
getRepositoryWebhook: build.query<GetRepositoryWebhookResponse, GetRepositoryWebhookArg>({
|
||||
query: (queryArg) => ({
|
||||
url: `/repositories/${queryArg.name}/webhook`,
|
||||
}),
|
||||
providesTags: ['Repository'],
|
||||
}),
|
||||
createRepositoryWebhook: build.mutation<CreateRepositoryWebhookResponse, CreateRepositoryWebhookArg>({
|
||||
query: (queryArg) => ({
|
||||
url: `/repositories/${queryArg.name}/webhook`,
|
||||
method: 'POST',
|
||||
}),
|
||||
invalidatesTags: ['Repository'],
|
||||
}),
|
||||
}),
|
||||
listRepository: build.query<RepositoryList, ListApiArg | void>({
|
||||
query: (params) => ({
|
||||
url: `${BASE_PATH}`,
|
||||
params: getListParams(params),
|
||||
}),
|
||||
providesTags: ['RepositoryList'],
|
||||
}),
|
||||
createRepository: build.mutation<void, RepositoryForCreate>({
|
||||
query: (body) => ({
|
||||
url: BASE_PATH,
|
||||
method: 'POST',
|
||||
body,
|
||||
}),
|
||||
invalidatesTags: ['RepositoryList'],
|
||||
}),
|
||||
updateRepository: build.mutation<void, UpdateRequestArg>({
|
||||
query: ({ name, body }) => ({
|
||||
url: `${BASE_PATH}/${name}`,
|
||||
method: 'PUT',
|
||||
body,
|
||||
}),
|
||||
}),
|
||||
deleteRepository: build.mutation<void, RequestArg>({
|
||||
query: ({ name }) => ({
|
||||
url: `${BASE_PATH}/${name}`,
|
||||
method: 'DELETE',
|
||||
}),
|
||||
invalidatesTags: ['RepositoryList'],
|
||||
}),
|
||||
patchRepository: build.mutation<void, UpdateRequestArg>({
|
||||
query: ({ name, body }) => ({
|
||||
url: `${BASE_PATH}/${name}`,
|
||||
method: 'PATCH',
|
||||
headers: { 'Content-Type': 'application/merge-patch+json' },
|
||||
body,
|
||||
}),
|
||||
invalidatesTags: ['RepositoryList'],
|
||||
}),
|
||||
getRepository: build.query<RepositoryResource, RequestArg>({
|
||||
query: (queryArg) => ({
|
||||
url: `${BASE_PATH}/${queryArg.name}`,
|
||||
}),
|
||||
}),
|
||||
createRepositoryExport: build.mutation<ResourceWrapper, RequestArg>({
|
||||
query: ({ name }) => ({
|
||||
url: `${BASE_PATH}/${name}/export`,
|
||||
method: 'POST',
|
||||
}),
|
||||
}),
|
||||
getRepositoryFiles: build.query<ResourceWrapper, GetFileArg>({
|
||||
query: ({ name, path, ref }) => ({
|
||||
url: `${BASE_PATH}/${name}/files/${path}`,
|
||||
params: { ref },
|
||||
}),
|
||||
}),
|
||||
listRepositoryFiles: build.query<ListFilesApiResponse, { name: string; ref?: string }>({
|
||||
query: ({ name, ref }) => ({
|
||||
url: `${BASE_PATH}/${name}/files/`,
|
||||
params: { ref },
|
||||
}),
|
||||
}),
|
||||
listRepositoryFileHistory: build.query<HistoryListResponse, { name: string; path: string; ref?: string }>({
|
||||
query: ({ name, ref, path }) => ({
|
||||
url: `${BASE_PATH}/${name}/history/${path}`,
|
||||
params: { ref },
|
||||
}),
|
||||
}),
|
||||
updateRepositoryFiles: build.mutation<ResourceWrapper, FileOperationArg>({
|
||||
query: ({ name, path, body, ref, message }) => ({
|
||||
url: `${BASE_PATH}/${name}/files/${path}`,
|
||||
method: 'PUT',
|
||||
body,
|
||||
params: { ref, message },
|
||||
}),
|
||||
}),
|
||||
createRepositoryFiles: build.mutation<ResourceWrapper, FileOperationArg>({
|
||||
query: ({ name, path, body, ref, message }) => ({
|
||||
url: `${BASE_PATH}/${name}/files/${path}`,
|
||||
method: 'POST',
|
||||
body,
|
||||
params: { ref, message },
|
||||
}),
|
||||
}),
|
||||
deleteRepositoryFiles: build.mutation<
|
||||
ResourceWrapper,
|
||||
{ name: string; path: string; ref?: string; message?: string }
|
||||
>({
|
||||
query: ({ name, path, ref, message }) => ({
|
||||
url: `${BASE_PATH}/${name}/files/${path}`,
|
||||
method: 'DELETE',
|
||||
params: { ref, message },
|
||||
}),
|
||||
}),
|
||||
listRepositoryHistory: build.query<HistoryListResponse, RequestArg>({
|
||||
query: (queryArg) => ({
|
||||
url: `${BASE_PATH}/${queryArg.name}/history`,
|
||||
params: { ref: queryArg.ref },
|
||||
}),
|
||||
}),
|
||||
getRepositoryHistory: build.query<HistoryItem, GetRequestArg>({
|
||||
query: (queryArg) => ({
|
||||
url: `${BASE_PATH}/${queryArg.name}/history/${queryArg.path}`,
|
||||
params: { ref: queryArg.ref },
|
||||
}),
|
||||
}),
|
||||
createRepositorySync: build.mutation<ResourceWrapper, { name: string }>({
|
||||
query: ({ name }) => ({
|
||||
url: `${BASE_PATH}/${name}/sync`,
|
||||
method: 'POST',
|
||||
}),
|
||||
}),
|
||||
getRepositoryStatus: build.query<RepositoryResource, RequestArg>({
|
||||
query: ({ name }) => ({
|
||||
url: `${BASE_PATH}/${name}/status`,
|
||||
}),
|
||||
}),
|
||||
updateRepositoryStatus: build.mutation<RepositoryResource, UpdateRequestArg>({
|
||||
query: ({ name, body }) => ({
|
||||
url: `${BASE_PATH}/${name}/status`,
|
||||
method: 'PUT',
|
||||
body,
|
||||
}),
|
||||
}),
|
||||
patchRepositoryStatus: build.mutation<RepositoryResource, UpdateRequestArg>({
|
||||
query: ({ name, body }) => ({
|
||||
url: `${BASE_PATH}/${name}/status`,
|
||||
method: 'PATCH',
|
||||
headers: { 'Content-Type': 'application/merge-patch+json' },
|
||||
body,
|
||||
}),
|
||||
}),
|
||||
testRepository: build.query<TestResponse, { name: string }>({
|
||||
query: ({ name }) => ({
|
||||
url: `${BASE_PATH}/${name}/test`,
|
||||
method: 'POST', // tests the existing configuration
|
||||
}),
|
||||
}),
|
||||
testRepositoryConfig: build.mutation<TestResponse, Resource<RepositorySpec>>({
|
||||
query: ({ metadata }) => ({
|
||||
url: `${BASE_PATH}/${metadata.name ?? 'new'}/test`,
|
||||
method: 'POST',
|
||||
}),
|
||||
}),
|
||||
getRepositoryWebhook: build.query<WebhookResponse, RequestArg>({
|
||||
query: (queryArg) => ({
|
||||
url: `${BASE_PATH}/${queryArg.name}/webhook`,
|
||||
}),
|
||||
}),
|
||||
postRepositoryWebhook: build.mutation<WebhookResponse, RequestArg>({
|
||||
query: (queryArg) => ({
|
||||
url: `${BASE_PATH}/${queryArg.name}/webhook`,
|
||||
method: 'POST',
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
overrideExisting: false,
|
||||
});
|
||||
|
||||
overrideExisting: false,
|
||||
});
|
||||
export { injectedRtkApi as generatedAPI };
|
||||
export type ListJobResponse = JobList;
|
||||
export type ListJobArg = {};
|
||||
export type GetJobResponse = Job;
|
||||
export type GetJobArg = {
|
||||
name: string;
|
||||
pretty?: string;
|
||||
};
|
||||
export type ListRepositoryResponse = RepositoryList;
|
||||
export type ListRepositoryArg = {};
|
||||
export type CreateRepositoryResponse = Repository;
|
||||
export type CreateRepositoryArg = {
|
||||
pretty?: string;
|
||||
dryRun?: string;
|
||||
fieldManager?: string;
|
||||
fieldValidation?: string;
|
||||
body: Repository;
|
||||
};
|
||||
export type GetRepositoryResponse = Repository;
|
||||
export type GetRepositoryArg = {
|
||||
name: string;
|
||||
pretty?: string;
|
||||
};
|
||||
export type ReplaceRepositoryResponse = Repository;
|
||||
export type ReplaceRepositoryArg = {
|
||||
name: string;
|
||||
pretty?: string;
|
||||
dryRun?: string;
|
||||
fieldManager?: string;
|
||||
fieldValidation?: string;
|
||||
body: Repository;
|
||||
};
|
||||
export type DeleteRepositoryResponse = Status;
|
||||
export type DeleteRepositoryArg = {
|
||||
name: string;
|
||||
pretty?: string;
|
||||
dryRun?: string;
|
||||
gracePeriodSeconds?: number;
|
||||
orphanDependents?: boolean;
|
||||
propagationPolicy?: string;
|
||||
body: DeleteOptions;
|
||||
};
|
||||
export type UpdateRepositoryResponse = Repository;
|
||||
export type UpdateRepositoryArg = {
|
||||
name: string;
|
||||
pretty?: string;
|
||||
dryRun?: string;
|
||||
fieldManager?: string;
|
||||
fieldValidation?: string;
|
||||
force?: boolean;
|
||||
body: Patch;
|
||||
};
|
||||
export type CreateRepositoryExportResponse = Job;
|
||||
export type CreateRepositoryExportArg = {
|
||||
name: string;
|
||||
};
|
||||
export type GetRepositoryFilesResponse = {
|
||||
apiVersion?: string;
|
||||
files?: any[];
|
||||
kind?: string;
|
||||
metadata?: any;
|
||||
};
|
||||
export type GetRepositoryFilesArg = {
|
||||
name: string;
|
||||
ref?: string;
|
||||
};
|
||||
export type GetRepositoryFilesWithPathResponse = ResourceWrapper;
|
||||
export type GetRepositoryFilesWithPathArg = {
|
||||
name: string;
|
||||
path: string;
|
||||
ref?: string;
|
||||
};
|
||||
export type PutRepositoryFilesWithPathResponse = ResourceWrapper;
|
||||
export type PutRepositoryFilesWithPathArg = {
|
||||
name: string;
|
||||
path: string;
|
||||
ref?: string;
|
||||
message?: string;
|
||||
body: {
|
||||
[key: string]: any;
|
||||
};
|
||||
};
|
||||
export type CreateRepositoryFilesWithPathResponse = ResourceWrapper;
|
||||
export type CreateRepositoryFilesWithPathArg = {
|
||||
name: string;
|
||||
path: string;
|
||||
ref?: string;
|
||||
message?: string;
|
||||
body: {
|
||||
[key: string]: any;
|
||||
};
|
||||
};
|
||||
export type DeleteRepositoryFilesWithPathResponse = ResourceWrapper;
|
||||
export type DeleteRepositoryFilesWithPathArg = {
|
||||
name: string;
|
||||
path: string;
|
||||
ref?: string;
|
||||
message?: string;
|
||||
};
|
||||
export type GetRepositoryHistoryResponse = string;
|
||||
export type GetRepositoryHistoryArg = {
|
||||
name: string;
|
||||
ref?: string;
|
||||
};
|
||||
export type GetRepositoryHistoryWithPathResponse = string;
|
||||
export type GetRepositoryHistoryWithPathArg = {
|
||||
name: string;
|
||||
path: string;
|
||||
ref?: string;
|
||||
};
|
||||
export type GetRepositoryStatusResponse = Repository;
|
||||
export type GetRepositoryStatusArg = {
|
||||
name: string;
|
||||
pretty?: string;
|
||||
};
|
||||
export type ReplaceRepositoryStatusResponse = Repository;
|
||||
export type ReplaceRepositoryStatusArg = {
|
||||
name: string;
|
||||
pretty?: string;
|
||||
dryRun?: string;
|
||||
fieldManager?: string;
|
||||
fieldValidation?: string;
|
||||
body: Repository;
|
||||
};
|
||||
export type UpdateRepositoryStatusResponse = Repository;
|
||||
export type UpdateRepositoryStatusArg = {
|
||||
name: string;
|
||||
pretty?: string;
|
||||
dryRun?: string;
|
||||
fieldManager?: string;
|
||||
fieldValidation?: string;
|
||||
force?: boolean;
|
||||
body: Patch;
|
||||
};
|
||||
export type CreateRepositorySyncResponse = Job;
|
||||
export type CreateRepositorySyncArg = {
|
||||
name: string;
|
||||
};
|
||||
|
||||
export type CreateRepositoryTestResponse = TestResults;
|
||||
export type CreateRepositoryTestArg = {
|
||||
name: string;
|
||||
body: {
|
||||
apiVersion?: string;
|
||||
kind?: string;
|
||||
metadata?: any;
|
||||
spec?: any;
|
||||
status?: any;
|
||||
};
|
||||
};
|
||||
export type GetRepositoryWebhookResponse = WebhookResponse;
|
||||
export type GetRepositoryWebhookArg = {
|
||||
name: string;
|
||||
};
|
||||
export type CreateRepositoryWebhookResponse = WebhookResponse;
|
||||
export type CreateRepositoryWebhookArg = {
|
||||
name: string;
|
||||
};
|
||||
export type Time = string;
|
||||
export type FieldsV1 = object;
|
||||
export type ManagedFieldsEntry = {
|
||||
apiVersion?: string;
|
||||
fieldsType?: string;
|
||||
fieldsV1?: FieldsV1;
|
||||
manager?: string;
|
||||
operation?: string;
|
||||
subresource?: string;
|
||||
time?: Time;
|
||||
};
|
||||
export type OwnerReference = {
|
||||
apiVersion: string;
|
||||
blockOwnerDeletion?: boolean;
|
||||
controller?: boolean;
|
||||
kind: string;
|
||||
name: string;
|
||||
uid: string;
|
||||
};
|
||||
export type ObjectMeta = {
|
||||
annotations?: {
|
||||
[key: string]: string;
|
||||
};
|
||||
creationTimestamp?: Time;
|
||||
deletionGracePeriodSeconds?: number;
|
||||
deletionTimestamp?: Time;
|
||||
finalizers?: string[];
|
||||
generateName?: string;
|
||||
generation?: number;
|
||||
labels?: {
|
||||
[key: string]: string;
|
||||
};
|
||||
managedFields?: ManagedFieldsEntry[];
|
||||
name?: string;
|
||||
namespace?: string;
|
||||
ownerReferences?: OwnerReference[];
|
||||
resourceVersion?: string;
|
||||
selfLink?: string;
|
||||
uid?: string;
|
||||
};
|
||||
export type JobSpec = {
|
||||
action: 'export' | 'pr' | 'sync';
|
||||
hash?: string;
|
||||
pr?: number;
|
||||
ref?: string;
|
||||
url?: string;
|
||||
};
|
||||
export type JobStatus = {
|
||||
errors?: string[];
|
||||
finished?: number;
|
||||
message?: string;
|
||||
started?: number;
|
||||
state?: 'error' | 'pending' | 'success' | 'working';
|
||||
};
|
||||
export type Job = {
|
||||
apiVersion?: string;
|
||||
kind?: string;
|
||||
metadata?: ObjectMeta;
|
||||
spec?: JobSpec;
|
||||
status?: JobStatus;
|
||||
};
|
||||
export type ListMeta = {
|
||||
continue?: string;
|
||||
remainingItemCount?: number;
|
||||
resourceVersion?: string;
|
||||
selfLink?: string;
|
||||
};
|
||||
export type JobList = {
|
||||
apiVersion?: string;
|
||||
items?: Job[];
|
||||
kind?: string;
|
||||
metadata?: ListMeta;
|
||||
};
|
||||
export type EditingOptions = {
|
||||
create: boolean;
|
||||
delete: boolean;
|
||||
update: boolean;
|
||||
};
|
||||
export type GitHubRepositoryConfig = {
|
||||
branch?: string;
|
||||
branchWorkflow?: boolean;
|
||||
generateDashboardPreviews?: boolean;
|
||||
owner?: string;
|
||||
pullRequestLinter?: boolean;
|
||||
repository?: string;
|
||||
token?: string;
|
||||
webhookSecret?: string;
|
||||
webhookURL?: string;
|
||||
};
|
||||
export type LocalRepositoryConfig = {
|
||||
path?: string;
|
||||
};
|
||||
export type S3RepositoryConfig = {
|
||||
bucket?: string;
|
||||
region?: string;
|
||||
};
|
||||
export type RepositorySpec = {
|
||||
description?: string;
|
||||
editing: EditingOptions;
|
||||
folder?: string;
|
||||
github?: GitHubRepositoryConfig;
|
||||
linting?: boolean;
|
||||
local?: LocalRepositoryConfig;
|
||||
preferYaml?: boolean;
|
||||
s3?: S3RepositoryConfig;
|
||||
title: string;
|
||||
type: 'github' | 'local' | 's3';
|
||||
};
|
||||
export type HealthStatus = {
|
||||
checked?: number;
|
||||
healthy: boolean;
|
||||
message?: string[];
|
||||
};
|
||||
export type SyncStatus = {
|
||||
finished?: number;
|
||||
hash?: string;
|
||||
job?: string;
|
||||
message?: string[];
|
||||
scheduled?: number;
|
||||
started?: number;
|
||||
state: 'error' | 'pending' | 'success' | 'working';
|
||||
};
|
||||
export type RepositoryStatus = {
|
||||
health: HealthStatus;
|
||||
sync: SyncStatus;
|
||||
};
|
||||
export type Repository = {
|
||||
apiVersion?: string;
|
||||
kind?: string;
|
||||
metadata?: ObjectMeta;
|
||||
spec?: RepositorySpec;
|
||||
status?: RepositoryStatus;
|
||||
};
|
||||
export type RepositoryList = {
|
||||
apiVersion?: string;
|
||||
items?: Repository[];
|
||||
kind?: string;
|
||||
metadata?: ListMeta;
|
||||
};
|
||||
export type StatusCause = {
|
||||
field?: string;
|
||||
message?: string;
|
||||
reason?: string;
|
||||
};
|
||||
export type StatusDetails = {
|
||||
causes?: StatusCause[];
|
||||
group?: string;
|
||||
kind?: string;
|
||||
name?: string;
|
||||
retryAfterSeconds?: number;
|
||||
uid?: string;
|
||||
};
|
||||
export type Status = {
|
||||
apiVersion?: string;
|
||||
code?: number;
|
||||
details?: StatusDetails;
|
||||
kind?: string;
|
||||
message?: string;
|
||||
metadata?: ListMeta;
|
||||
reason?: string;
|
||||
status?: string;
|
||||
};
|
||||
export type Preconditions = {
|
||||
resourceVersion?: string;
|
||||
uid?: string;
|
||||
};
|
||||
export type DeleteOptions = {
|
||||
apiVersion?: string;
|
||||
dryRun?: string[];
|
||||
gracePeriodSeconds?: number;
|
||||
kind?: string;
|
||||
orphanDependents?: boolean;
|
||||
preconditions?: Preconditions;
|
||||
propagationPolicy?: string;
|
||||
};
|
||||
export type Patch = object;
|
||||
export type LintIssue = {
|
||||
message: string;
|
||||
rule: string;
|
||||
severity: 'error' | 'exclude' | 'fixed' | 'quiet' | 'warning';
|
||||
};
|
||||
export type Unstructured = {
|
||||
[key: string]: any;
|
||||
};
|
||||
export type ResourceType = {
|
||||
classic?: 'access-control' | 'alerting' | 'dashboard' | 'datasources';
|
||||
group?: string;
|
||||
kind?: string;
|
||||
resource?: string;
|
||||
version?: string;
|
||||
};
|
||||
export type ResourceObjects = {
|
||||
action?: 'create' | 'delete' | 'update';
|
||||
dryRun?: Unstructured;
|
||||
existing?: Unstructured;
|
||||
file?: Unstructured;
|
||||
type: ResourceType;
|
||||
};
|
||||
export type ResourceWrapper = {
|
||||
apiVersion?: string;
|
||||
errors?: string[];
|
||||
hash?: string;
|
||||
kind?: string;
|
||||
lint?: LintIssue[];
|
||||
path?: string;
|
||||
ref?: string;
|
||||
resource: ResourceObjects;
|
||||
timestamp?: Time;
|
||||
};
|
||||
export type TestResults = {
|
||||
apiVersion?: string;
|
||||
code: number;
|
||||
details?: Unstructured;
|
||||
errors?: string[];
|
||||
kind?: string;
|
||||
success: boolean;
|
||||
};
|
||||
export type WebhookResponse = {
|
||||
added?: string;
|
||||
apiVersion?: string;
|
||||
code?: number;
|
||||
job?: JobSpec;
|
||||
kind?: string;
|
||||
};
|
||||
export const {
|
||||
useListJobQuery,
|
||||
useGetJobQuery,
|
||||
useListRepositoryQuery,
|
||||
useListJobsQuery,
|
||||
useCreateRepositoryMutation,
|
||||
useGetRepositoryQuery,
|
||||
useUpdateRepositoryMutation,
|
||||
useReplaceRepositoryMutation,
|
||||
useDeleteRepositoryMutation,
|
||||
usePatchRepositoryMutation,
|
||||
useUpdateRepositoryMutation,
|
||||
useCreateRepositoryExportMutation,
|
||||
useGetRepositoryFilesQuery,
|
||||
useListRepositoryFilesQuery,
|
||||
useListRepositoryFileHistoryQuery,
|
||||
useUpdateRepositoryFilesMutation,
|
||||
useCreateRepositoryFilesMutation,
|
||||
useDeleteRepositoryFilesMutation,
|
||||
useCreateRepositorySyncMutation,
|
||||
useGetRepositoryFilesWithPathQuery,
|
||||
usePutRepositoryFilesWithPathMutation,
|
||||
useCreateRepositoryFilesWithPathMutation,
|
||||
useDeleteRepositoryFilesWithPathMutation,
|
||||
useGetRepositoryHistoryQuery,
|
||||
useGetRepositoryHistoryWithPathQuery,
|
||||
useGetRepositoryStatusQuery,
|
||||
useReplaceRepositoryStatusMutation,
|
||||
useUpdateRepositoryStatusMutation,
|
||||
usePatchRepositoryStatusMutation,
|
||||
useTestRepositoryQuery,
|
||||
useTestRepositoryConfigMutation,
|
||||
useCreateRepositorySyncMutation,
|
||||
useCreateRepositoryTestMutation,
|
||||
useGetRepositoryWebhookQuery,
|
||||
useCreateRepositoryWebhookMutation,
|
||||
} = injectedRtkApi;
|
||||
|
||||
function getListParams(queryArg: ListApiArg | void) {
|
||||
if (!queryArg) {
|
||||
return undefined;
|
||||
}
|
||||
const { fieldSelector, labelSelector, ...params } = queryArg;
|
||||
return {
|
||||
fieldSelector: fieldSelector ? parseListOptionsSelector(fieldSelector) : undefined,
|
||||
labelSelector: labelSelector ? parseListOptionsSelector(labelSelector) : undefined,
|
||||
...params,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,4 +1,34 @@
|
||||
import { parseListOptionsSelector } from '../../apiserver/client';
|
||||
import { ListOptions } from '../../apiserver/types';
|
||||
export * from './endpoints';
|
||||
|
||||
import { generatedAPI } from './endpoints';
|
||||
|
||||
export const provisioningAPI = generatedAPI.enhanceEndpoints({});
|
||||
export const provisioningAPI = generatedAPI.enhanceEndpoints({
|
||||
endpoints: {
|
||||
listJob(endpoint) {
|
||||
endpoint.query = (queryArg) => ({
|
||||
url: `/jobs`,
|
||||
params: getListParams(queryArg),
|
||||
});
|
||||
},
|
||||
listRepository(endpoint) {
|
||||
endpoint.query = (queryArg) => ({
|
||||
url: `/repositories`,
|
||||
params: getListParams(queryArg),
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
function getListParams<T extends ListOptions>(queryArg: T | void) {
|
||||
if (!queryArg) {
|
||||
return undefined;
|
||||
}
|
||||
const { fieldSelector, labelSelector, ...params } = queryArg;
|
||||
return {
|
||||
fieldSelector: fieldSelector ? parseListOptionsSelector(fieldSelector) : undefined,
|
||||
labelSelector: labelSelector ? parseListOptionsSelector(labelSelector) : undefined,
|
||||
...params,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3,13 +3,15 @@ import { useCallback } from 'react';
|
||||
import { useUrlParams } from 'app/core/navigation/hooks';
|
||||
|
||||
import {
|
||||
useCreateRepositoryFilesMutation,
|
||||
Repository,
|
||||
useCreateRepositoryFilesWithPathMutation,
|
||||
useCreateRepositoryMutation,
|
||||
useListRepositoryQuery,
|
||||
useUpdateRepositoryFilesMutation,
|
||||
usePutRepositoryFilesWithPathMutation,
|
||||
useUpdateRepositoryMutation,
|
||||
RepositorySpec,
|
||||
PutRepositoryFilesWithPathArg,
|
||||
} from './api';
|
||||
import { FileOperationArg, RepositoryResource, RepositorySpec } from './api/types';
|
||||
|
||||
export function useCreateOrUpdateRepository(name?: string) {
|
||||
const [create, createRequest] = useCreateRepositoryMutation();
|
||||
@@ -20,7 +22,7 @@ export function useCreateOrUpdateRepository(name?: string) {
|
||||
if (name) {
|
||||
return update({ name, body: { metadata: { name }, spec: data } });
|
||||
}
|
||||
return create({ metadata: { generateName: 'repository' }, spec: data });
|
||||
return create({ body: { metadata: { generateName: 'repository' }, spec: data } });
|
||||
},
|
||||
[create, name, update]
|
||||
);
|
||||
@@ -29,22 +31,22 @@ export function useCreateOrUpdateRepository(name?: string) {
|
||||
}
|
||||
|
||||
// Sort repositories by resourceVersion to show the last modified
|
||||
export function useRepositoryList(): [RepositoryResource[] | undefined, boolean] {
|
||||
export function useRepositoryList(): [Repository[] | undefined, boolean] {
|
||||
const query = useListRepositoryQuery();
|
||||
|
||||
const sortedItems = query.data?.items?.slice().sort((a, b) => {
|
||||
return Number(b.metadata.resourceVersion) - Number(a.metadata.resourceVersion);
|
||||
return Number(b.metadata?.resourceVersion) - Number(a.metadata?.resourceVersion);
|
||||
});
|
||||
|
||||
return [sortedItems, query.isLoading];
|
||||
}
|
||||
|
||||
export function useCreateOrUpdateRepositoryFile(name?: string) {
|
||||
const [create, createRequest] = useCreateRepositoryFilesMutation();
|
||||
const [update, updateRequest] = useUpdateRepositoryFilesMutation();
|
||||
const [create, createRequest] = useCreateRepositoryFilesWithPathMutation();
|
||||
const [update, updateRequest] = usePutRepositoryFilesWithPathMutation();
|
||||
|
||||
const updateOrCreate = useCallback(
|
||||
(data: FileOperationArg) => {
|
||||
(data: PutRepositoryFilesWithPathArg) => {
|
||||
const actions = name ? update : create;
|
||||
return actions(data);
|
||||
},
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { RepositorySpec } from '../api/types';
|
||||
import { RepositorySpec } from '../api';
|
||||
import { RepositoryFormData } from '../types';
|
||||
|
||||
export const dataToSpec = (data: RepositoryFormData): RepositorySpec => {
|
||||
const spec: RepositorySpec = {
|
||||
type: data.type,
|
||||
folder: data.folder,
|
||||
title: data.title,
|
||||
title: data.title || '',
|
||||
editing: data.editing,
|
||||
linting: data.linting,
|
||||
preferYaml: data.preferYaml,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { RepositorySpec } from '../api/types';
|
||||
import { RepositorySpec } from '../api';
|
||||
|
||||
export function createPRLink(spec?: RepositorySpec, dashboardName?: string, ref?: string) {
|
||||
if (!spec || spec.type !== 'github' || !ref) {
|
||||
|
||||
@@ -38,10 +38,29 @@ const config: ConfigFile = {
|
||||
},
|
||||
'../public/app/features/provisioning/api/endpoints.gen.ts': {
|
||||
apiFile: '../public/app/features/provisioning/api/baseAPI.ts',
|
||||
schemaFile: '../public/app/features/provisioning/api/spec.json',
|
||||
schemaFile: '../pkg/tests/apis/provisioning/testdata/openapi.json',
|
||||
apiImport: 'baseAPI',
|
||||
filterEndpoints,
|
||||
argSuffix: 'Arg',
|
||||
responseSuffix: 'Response',
|
||||
tag: true,
|
||||
endpointOverrides: [
|
||||
{
|
||||
pattern: /^list/,
|
||||
parameterFilter: () => false,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
function filterEndpoints(name: string) {
|
||||
return (
|
||||
!name.toLowerCase().includes('forallnamespaces') &&
|
||||
!name.toLowerCase().includes('getapiresources') &&
|
||||
!name.toLowerCase().includes('watch') &&
|
||||
!name.toLowerCase().includes('collection')
|
||||
);
|
||||
}
|
||||
|
||||
export default config;
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
// Read the content of the file
|
||||
const filePath = path.resolve(__dirname, '../public/app/features/provisioning/api/endpoints.gen.ts');
|
||||
const outputFilePath = path.resolve(__dirname, '../public/app/features/provisioning/api/endpoints.ts');
|
||||
const content = fs.readFileSync(filePath, 'utf-8');
|
||||
|
||||
// Define the prefixes to remove
|
||||
const prefixes = [
|
||||
'ComGithubGrafanaGrafanaPkgApisProvisioningV0Alpha1',
|
||||
'ComGithubGrafanaGrafanaPkgApimachineryApisCommonV0Alpha1',
|
||||
'IoK8SApimachineryPkgApisMetaV1',
|
||||
'IoK8SApimachineryPkgRuntimeRaw',
|
||||
];
|
||||
|
||||
// Function to create a regex for each prefix
|
||||
const createPrefixRegex = (prefixes: string[]): RegExp => {
|
||||
return new RegExp(prefixes.join('|'), 'g');
|
||||
};
|
||||
|
||||
// Function to remove duplicate types from union type definitions
|
||||
const removeDuplicateTypes = (typeDef: string): string => {
|
||||
const typeSet = new Set(typeDef.split('|').map((type) => type.trim()));
|
||||
return Array.from(typeSet).join(' | ');
|
||||
};
|
||||
|
||||
// Perform transformations
|
||||
const transformedContent = content
|
||||
// Remove comments (block comments and line comments)
|
||||
.replace(/(?:\/\*\*[\s\S]*?\*\/)|(?:\/\/.*)/g, '')
|
||||
|
||||
// Remove namespace property from all types
|
||||
.replace(/namespace: string;/g, '')
|
||||
|
||||
// Remove any lines that are now just whitespace or empty
|
||||
.replace(/^\s*[\r\n]/gm, '')
|
||||
|
||||
// Remove specified prefixes
|
||||
.replace(createPrefixRegex(prefixes), '')
|
||||
|
||||
// Remove the specific URL segment
|
||||
.replace(/\/apis\/provisioning\.grafana\.app\/v0alpha1\/namespaces\/\$\{queryArg\['namespace']}/g, '')
|
||||
|
||||
// Replace lowercase 'com' prefix specific match with 'body'
|
||||
.replace(/\bcomGithubGrafanaGrafanaPkgApisProvisioningV0Alpha1[A-Za-z0-9_]*/g, 'body')
|
||||
|
||||
// Replace ioK8SApimachineryPkgApisMetaV1 prefix specific match with 'body'
|
||||
.replace(/\bioK8SApimachineryPkgApisMetaV1[A-Za-z0-9_]*/g, 'body')
|
||||
|
||||
// Remove duplicate types in union type definitions
|
||||
.replace(/(export type [A-Za-z0-9]+ = [^;]+);/g, (match: string, typeDef: string) => {
|
||||
return `${removeDuplicateTypes(typeDef)};`;
|
||||
})
|
||||
|
||||
// Modify any 'List...Arg>' to 'List...Arg | void>'
|
||||
.replace(/(List[A-Za-z0-9]+Arg)>/g, '$1 | void>')
|
||||
|
||||
// Add headers for content-type in patch endpoints
|
||||
.replace(/(method: 'PATCH',)/g, "$1\n\t\t\t\theaders: { 'Content-Type': 'application/merge-patch+json' },");
|
||||
|
||||
// Write the transformed content back to a new file
|
||||
fs.writeFileSync(outputFilePath, transformedContent);
|
||||
|
||||
console.log('Transformation complete! Check the transformed file at:', outputFilePath);
|
||||
@@ -6909,20 +6909,21 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@rtk-query/codegen-openapi@npm:^1.2.0":
|
||||
version: 1.2.0
|
||||
resolution: "@rtk-query/codegen-openapi@npm:1.2.0"
|
||||
"@rtk-query/codegen-openapi@npm:^2.0.0":
|
||||
version: 2.0.0
|
||||
resolution: "@rtk-query/codegen-openapi@npm:2.0.0"
|
||||
dependencies:
|
||||
"@apidevtools/swagger-parser": "npm:^10.0.2"
|
||||
commander: "npm:^6.2.0"
|
||||
oazapfts: "npm:^4.8.0"
|
||||
prettier: "npm:^2.2.1"
|
||||
lodash.camelcase: "npm:^4.3.0"
|
||||
oazapfts: "npm:^6.1.0"
|
||||
prettier: "npm:^3.2.5"
|
||||
semver: "npm:^7.3.5"
|
||||
swagger2openapi: "npm:^7.0.4"
|
||||
typescript: "npm:^5.0.0"
|
||||
typescript: "npm:^5.5.4"
|
||||
bin:
|
||||
rtk-query-codegen-openapi: lib/bin/cli.js
|
||||
checksum: 10/74b5d68b40322e6f30fff3f0250bccf378e5408e24bb47c109ad31e3c45a53c99d67b0ea0685ab0abcfc2e598eec9bdfc94aee241b61049ac862b77bd9780518
|
||||
rtk-query-codegen-openapi: lib/bin/cli.mjs
|
||||
checksum: 10/c1dbab43e950c4defc1246034506c770a6a742aaf86a991c1cdbac0ac63cd2232c14bbe05d8c29421339b5e3aeb75740de3d709c5503f2af0b746e71b46caa87
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -17607,7 +17608,7 @@ __metadata:
|
||||
"@react-types/shared": "npm:3.26.0"
|
||||
"@reduxjs/toolkit": "npm:2.5.0"
|
||||
"@rsdoctor/webpack-plugin": "npm:^0.4.6"
|
||||
"@rtk-query/codegen-openapi": "npm:^1.2.0"
|
||||
"@rtk-query/codegen-openapi": "npm:^2.0.0"
|
||||
"@rtsao/plugin-proposal-class-properties": "npm:7.0.1-patch.1"
|
||||
"@stylistic/eslint-plugin-ts": "npm:^2.9.0"
|
||||
"@swc/core": "npm:1.10.1"
|
||||
@@ -21169,6 +21170,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lodash.camelcase@npm:^4.3.0":
|
||||
version: 4.3.0
|
||||
resolution: "lodash.camelcase@npm:4.3.0"
|
||||
checksum: 10/c301cc379310441dc73cd6cebeb91fb254bea74e6ad3027f9346fc43b4174385153df420ffa521654e502fd34c40ef69ca4e7d40ee7129a99e06f306032bfc65
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lodash.debounce@npm:^4, lodash.debounce@npm:^4.0.8":
|
||||
version: 4.0.8
|
||||
resolution: "lodash.debounce@npm:4.0.8"
|
||||
@@ -22957,18 +22965,21 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"oazapfts@npm:^4.8.0":
|
||||
version: 4.12.0
|
||||
resolution: "oazapfts@npm:4.12.0"
|
||||
"oazapfts@npm:^6.1.0":
|
||||
version: 6.1.0
|
||||
resolution: "oazapfts@npm:6.1.0"
|
||||
dependencies:
|
||||
"@apidevtools/swagger-parser": "npm:^10.1.0"
|
||||
lodash: "npm:^4.17.21"
|
||||
minimist: "npm:^1.2.8"
|
||||
swagger2openapi: "npm:^7.0.8"
|
||||
typescript: "npm:^5.2.2"
|
||||
tapable: "npm:^2.2.1"
|
||||
typescript: "npm:^5.4.5"
|
||||
peerDependencies:
|
||||
"@oazapfts/runtime": "*"
|
||||
bin:
|
||||
oazapfts: lib/codegen/cli.js
|
||||
checksum: 10/993d2cebfb2aab6178893e63039eda5968248684e02cf7e3df41e8fbc57d3a551c1c4a7b8bc3f1384f9a10557e9fd71717eeef8b1a38948a412ba46c5271f411
|
||||
oazapfts: cli.js
|
||||
checksum: 10/804c3936702acf66bb9bcff6bdcdce2708783b31c83262d7097fb04a53d3720d96114cec345408cbf3f933f9c5d198815457853a07362796c6a6d5db7a31d150
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -24447,7 +24458,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"prettier@npm:^2.2.1, prettier@npm:^2.3.2, prettier@npm:^2.8.7":
|
||||
"prettier@npm:^2.3.2, prettier@npm:^2.8.7":
|
||||
version: 2.8.8
|
||||
resolution: "prettier@npm:2.8.8"
|
||||
bin:
|
||||
@@ -24456,6 +24467,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"prettier@npm:^3.2.5":
|
||||
version: 3.4.2
|
||||
resolution: "prettier@npm:3.4.2"
|
||||
bin:
|
||||
prettier: bin/prettier.cjs
|
||||
checksum: 10/a3e806fb0b635818964d472d35d27e21a4e17150c679047f5501e1f23bd4aa806adf660f0c0d35214a210d5d440da6896c2e86156da55f221a57938278dc326e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"pretty-bytes@npm:^5.6.0":
|
||||
version: 5.6.0
|
||||
resolution: "pretty-bytes@npm:5.6.0"
|
||||
@@ -29733,7 +29753,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"typescript@npm:5.5.4, typescript@npm:>=2.7, typescript@npm:>=3 < 6, typescript@npm:^5.0.0, typescript@npm:^5.0.4, typescript@npm:^5.2.2":
|
||||
"typescript@npm:5.5.4, typescript@npm:>=2.7, typescript@npm:>=3 < 6, typescript@npm:^5.0.4":
|
||||
version: 5.5.4
|
||||
resolution: "typescript@npm:5.5.4"
|
||||
bin:
|
||||
@@ -29743,7 +29763,17 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"typescript@patch:typescript@npm%3A5.5.4#optional!builtin<compat/typescript>, typescript@patch:typescript@npm%3A>=2.7#optional!builtin<compat/typescript>, typescript@patch:typescript@npm%3A>=3 < 6#optional!builtin<compat/typescript>, typescript@patch:typescript@npm%3A^5.0.0#optional!builtin<compat/typescript>, typescript@patch:typescript@npm%3A^5.0.4#optional!builtin<compat/typescript>, typescript@patch:typescript@npm%3A^5.2.2#optional!builtin<compat/typescript>":
|
||||
"typescript@npm:^5.4.5, typescript@npm:^5.5.4":
|
||||
version: 5.7.2
|
||||
resolution: "typescript@npm:5.7.2"
|
||||
bin:
|
||||
tsc: bin/tsc
|
||||
tsserver: bin/tsserver
|
||||
checksum: 10/4caa3904df69db9d4a8bedc31bafc1e19ffb7b24fbde2997a1633ae1398d0de5bdbf8daf602ccf3b23faddf1aeeb9b795223a2ed9c9a4fdcaf07bfde114a401a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"typescript@patch:typescript@npm%3A5.5.4#optional!builtin<compat/typescript>, typescript@patch:typescript@npm%3A>=2.7#optional!builtin<compat/typescript>, typescript@patch:typescript@npm%3A>=3 < 6#optional!builtin<compat/typescript>, typescript@patch:typescript@npm%3A^5.0.4#optional!builtin<compat/typescript>":
|
||||
version: 5.5.4
|
||||
resolution: "typescript@patch:typescript@npm%3A5.5.4#optional!builtin<compat/typescript>::version=5.5.4&hash=379a07"
|
||||
bin:
|
||||
@@ -29753,6 +29783,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"typescript@patch:typescript@npm%3A^5.4.5#optional!builtin<compat/typescript>, typescript@patch:typescript@npm%3A^5.5.4#optional!builtin<compat/typescript>":
|
||||
version: 5.7.2
|
||||
resolution: "typescript@patch:typescript@npm%3A5.7.2#optional!builtin<compat/typescript>::version=5.7.2&hash=5786d5"
|
||||
bin:
|
||||
tsc: bin/tsc
|
||||
tsserver: bin/tsserver
|
||||
checksum: 10/d75ca10141afc64fd3474b41a8b082b640555bed388d237558aed64e5827ddadb48f90932c7f4205883f18f5bcab8b6a739a2cfac95855604b0dfeb34bc2f3eb
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ua-parser-js@npm:^1.0.32":
|
||||
version: 1.0.33
|
||||
resolution: "ua-parser-js@npm:1.0.33"
|
||||
|
||||
Reference in New Issue
Block a user