diff --git a/webapp/src/dogma/common/components/DeleteConfirmationModal.tsx b/webapp/src/dogma/common/components/DeleteConfirmationModal.tsx
index 885028515..052f78ec2 100644
--- a/webapp/src/dogma/common/components/DeleteConfirmationModal.tsx
+++ b/webapp/src/dogma/common/components/DeleteConfirmationModal.tsx
@@ -26,6 +26,7 @@ import {
ModalHeader,
ModalOverlay,
} from '@chakra-ui/react';
+import { ReactNode } from 'react';
interface DeleteConfirmationModalProps {
isOpen: boolean;
@@ -38,6 +39,8 @@ interface DeleteConfirmationModalProps {
repoName?: string;
handleDelete: () => void;
isLoading: boolean;
+ // Optional extra content rendered below the confirmation text (e.g. a commit summary input).
+ children?: ReactNode;
}
export const DeleteConfirmationModal = ({
@@ -50,6 +53,7 @@ export const DeleteConfirmationModal = ({
repoName,
handleDelete,
isLoading,
+ children,
}: DeleteConfirmationModalProps): JSX.Element => {
const fromName = from ?? repoName ?? projectName;
return (
@@ -63,7 +67,7 @@ export const DeleteConfirmationModal = ({
{id}
- {fromName ? ` from ${fromName}` : ''}?
+ {fromName ? ` from ${fromName}` : ''}?{children}
diff --git a/webapp/src/dogma/features/xds/K8sAggregatorEditor.tsx b/webapp/src/dogma/features/xds/K8sAggregatorEditor.tsx
index 3327a9c4d..022304ad2 100644
--- a/webapp/src/dogma/features/xds/K8sAggregatorEditor.tsx
+++ b/webapp/src/dogma/features/xds/K8sAggregatorEditor.tsx
@@ -492,6 +492,7 @@ const NewK8sAggregatorEditor = ({ group }: { group: string }) => {
const [previewAggregator, { isLoading: isPreviewing }] = usePreviewK8sAggregatorMutation();
const { isOpen: previewOpen, onOpen: openPreview, onClose: closePreview } = useDisclosure();
const [previewResult, setPreviewResult] = useState(null);
+ const [commitSummary, setCommitSummary] = useState('');
const {
register,
control,
@@ -515,7 +516,12 @@ const NewK8sAggregatorEditor = ({ group }: { group: string }) => {
return;
}
try {
- await createAggregator({ group, aggregatorId: data.aggregatorId, body: buildBody(data) }).unwrap();
+ await createAggregator({
+ group,
+ aggregatorId: data.aggregatorId,
+ body: buildBody(data),
+ summary: commitSummary || undefined,
+ }).unwrap();
dispatch(
newNotification('Aggregator created', `Aggregator '${data.aggregatorId}' is created`, 'success'),
);
@@ -548,6 +554,14 @@ const NewK8sAggregatorEditor = ({ group }: { group: string }) => {
readOnly={false}
/>
+
+ Commit summary
+ setCommitSummary(e.target.value)}
+ placeholder="Create kubernetes endpoint: ..."
+ />
+
@@ -596,6 +610,8 @@ const ExistingK8sAggregatorEditor = ({ group, id }: { group: string; id: string
const [previewResult, setPreviewResult] = useState(null);
// An aggregator opens in read-only view; the user must click Edit to modify it (like the resource editors).
const [editing, setEditing] = useState(false);
+ const [commitSummary, setCommitSummary] = useState('');
+ const [deleteCommitSummary, setDeleteCommitSummary] = useState('');
const {
register,
control,
@@ -615,9 +631,15 @@ const ExistingK8sAggregatorEditor = ({ group, id }: { group: string; id: string
const onSubmit = async (formData: FormData) => {
const name = `groups/${group}/k8s/endpointAggregators/${id}`;
try {
- await updateAggregator({ group, id, body: buildBody(formData, name) }).unwrap();
+ await updateAggregator({
+ group,
+ id,
+ body: buildBody(formData, name),
+ summary: commitSummary || undefined,
+ }).unwrap();
dispatch(newNotification('Aggregator updated', `Aggregator '${id}' is updated`, 'success'));
setEditing(false);
+ setCommitSummary('');
} catch (err) {
dispatch(newNotification('Failed to update the aggregator', ErrorMessageParser.parse(err), 'error'));
}
@@ -628,6 +650,7 @@ const ExistingK8sAggregatorEditor = ({ group, id }: { group: string; id: string
reset(parseToFormData(id, (data as FileContentDto).content));
}
setEditing(false);
+ setCommitSummary('');
};
const onPreview = async (formData: FormData) => {
@@ -643,7 +666,7 @@ const ExistingK8sAggregatorEditor = ({ group, id }: { group: string; id: string
const handleDelete = async () => {
try {
- await deleteAggregator({ group, id }).unwrap();
+ await deleteAggregator({ group, id, summary: deleteCommitSummary || undefined }).unwrap();
dispatch(newNotification('Aggregator deleted', `Aggregator '${id}' is deleted`, 'success'));
Router.push(`/app/xds/group?name=${encodeURIComponent(group)}&type=k8sAggregators`);
} catch (err) {
@@ -651,6 +674,11 @@ const ExistingK8sAggregatorEditor = ({ group, id }: { group: string; id: string
}
};
+ const handleDeleteModalClose = () => {
+ setDeleteCommitSummary('');
+ onClose();
+ };
+
return (
{() => (
@@ -706,6 +734,14 @@ const ExistingK8sAggregatorEditor = ({ group, id }: { group: string; id: string
{editing && hasWrite && (
<>
+
+ Commit summary
+ setCommitSummary(e.target.value)}
+ placeholder="Update kubernetes endpoint aggregator: ..."
+ />
+
@@ -738,13 +774,22 @@ const ExistingK8sAggregatorEditor = ({ group, id }: { group: string; id: string
/>
+ >
+
+ Commit summary
+ setDeleteCommitSummary(e.target.value)}
+ placeholder="Delete kubernetes endpoint aggregator: ..."
+ />
+
+
)}
diff --git a/webapp/src/dogma/features/xds/ResourceEditor.tsx b/webapp/src/dogma/features/xds/ResourceEditor.tsx
index 4ee0e0611..efd23e1a0 100644
--- a/webapp/src/dogma/features/xds/ResourceEditor.tsx
+++ b/webapp/src/dogma/features/xds/ResourceEditor.tsx
@@ -79,6 +79,7 @@ const NewResourceEditor = ({ group, type }: { group: string; type: XdsResourceTy
const { hasWrite, isLoading: accessLoading } = useGroupWriteAccess(group);
const [id, setId] = useState('');
const [content, setContent] = useState(XDS_RESOURCE_TEMPLATES[type]);
+ const [commitSummary, setCommitSummary] = useState('');
const [createResource, { isLoading }] = useCreateResourceMutation();
const handleCreate = async () => {
@@ -93,7 +94,7 @@ const NewResourceEditor = ({ group, type }: { group: string; type: XdsResourceTy
return;
}
try {
- await createResource({ group, type, id, body: content }).unwrap();
+ await createResource({ group, type, id, body: content, summary: commitSummary || undefined }).unwrap();
dispatch(newNotification(`${meta.label} created`, `${meta.label} '${id}' is created`, 'success'));
Router.push(`/app/xds/group?name=${encodeURIComponent(group)}&type=${type}`);
} catch (err) {
@@ -120,6 +121,14 @@ const NewResourceEditor = ({ group, type }: { group: string; type: XdsResourceTy
setId(e.target.value)} placeholder={`Enter ${meta.label} ID ...`} />
+
+ Commit summary
+ setCommitSummary(e.target.value)}
+ placeholder={`Create ${meta.label.toLowerCase()}: ...`}
+ />
+
} onClick={handleCreate} isLoading={isLoading}>
@@ -192,6 +201,8 @@ const ExistingResourceEditor = ({
const [content, setContent] = useState('');
// A resource opens in read-only view; the user must click Edit to modify it (like the main web app).
const [editing, setEditing] = useState(false);
+ const [commitSummary, setCommitSummary] = useState('');
+ const [deleteCommitSummary, setDeleteCommitSummary] = useState('');
const [updateResource, { isLoading: isSaving }] = useUpdateResourceMutation();
const [deleteResource, { isLoading: isDeleting }] = useDeleteResourceMutation();
const { isOpen, onOpen, onClose } = useDisclosure();
@@ -217,9 +228,10 @@ const ExistingResourceEditor = ({
return;
}
try {
- await updateResource({ group, type, id, body: content }).unwrap();
+ await updateResource({ group, type, id, body: content, summary: commitSummary || undefined }).unwrap();
dispatch(newNotification(`${meta.label} updated`, `${meta.label} '${id}' is updated`, 'success'));
setEditing(false);
+ setCommitSummary('');
} catch (err) {
dispatch(newNotification(`Failed to update the ${meta.label}`, ErrorMessageParser.parse(err), 'error'));
}
@@ -228,11 +240,12 @@ const ExistingResourceEditor = ({
const handleCancel = () => {
setContent(originalContent);
setEditing(false);
+ setCommitSummary('');
};
const handleDelete = async () => {
try {
- await deleteResource({ group, type, id }).unwrap();
+ await deleteResource({ group, type, id, summary: deleteCommitSummary || undefined }).unwrap();
dispatch(newNotification(`${meta.label} deleted`, `${meta.label} '${id}' is deleted`, 'success'));
Router.push(`/app/xds/group?name=${encodeURIComponent(group)}&type=${type}`);
} catch (err) {
@@ -240,6 +253,11 @@ const ExistingResourceEditor = ({
}
};
+ const handleDeleteModalClose = () => {
+ setDeleteCommitSummary('');
+ onClose();
+ };
+
// Resources generated by a k8s aggregator are managed by the aggregator, so they are always read-only
// (no edit/save/delete). Otherwise the editor is read-only until the user clicks Edit.
const readOnly = k8s || !editing;
@@ -317,17 +335,27 @@ const ExistingResourceEditor = ({
readOnly={readOnly}
/>
{editing && hasWrite && (
-
-
- }
- onClick={handleSave}
- isLoading={isSaving}
- >
- Save
-
-
+ <>
+
+ Commit summary
+ setCommitSummary(e.target.value)}
+ placeholder={`Update ${meta.label.toLowerCase()}: ...`}
+ />
+
+
+
+ }
+ onClick={handleSave}
+ isLoading={isSaving}
+ >
+ Save
+
+
+ >
)}
@@ -338,13 +366,22 @@ const ExistingResourceEditor = ({
+ >
+
+ Commit summary
+ setDeleteCommitSummary(e.target.value)}
+ placeholder={`Delete ${meta.label.toLowerCase()}: ...`}
+ />
+
+
)
}
diff --git a/webapp/src/dogma/features/xds/xdsApiSlice.ts b/webapp/src/dogma/features/xds/xdsApiSlice.ts
index b55a123e9..261d5ac0a 100644
--- a/webapp/src/dogma/features/xds/xdsApiSlice.ts
+++ b/webapp/src/dogma/features/xds/xdsApiSlice.ts
@@ -67,12 +67,12 @@ export interface FileContentDto {
}
export type ResourceArg = { group: string; type: XdsResourceType };
-// `k8s` marks an endpoint generated by a k8s aggregator (stored under '/k8s/endpoints/'); it is read-only.
// `path` is the full repository path (e.g. '/clusters/foo.yaml') — when provided, it is used directly to
// avoid a .yaml→.json fallback request on servers that still have legacy .json files.
export type ResourceIdArg = ResourceArg & { id: string; k8s?: boolean; path?: string };
-export type CreateResourceArg = ResourceArg & { id: string; body: string };
-export type UpdateResourceArg = ResourceIdArg & { body: string };
+export type CreateResourceArg = ResourceArg & { id: string; body: string; summary?: string };
+export type UpdateResourceArg = ResourceIdArg & { body: string; summary?: string };
+export type DeleteResourceArg = ResourceIdArg & { summary?: string };
// Derives a Kubernetes endpoint aggregator id from its repository file path, e.g.
// '/k8s/endpointAggregators/foo.yaml' becomes 'foo'.
@@ -236,26 +236,27 @@ export const xdsApiSlice = createApi({
providesTags: ['Resource'],
}),
createResource: builder.mutation({
- query: ({ group, type, id, body }) => ({
- url: `/api/v1/xds/groups/${group}/${type}?${XDS_RESOURCE_META[type].idParam}=${encodeURIComponent(id)}`,
- method: 'POST',
- body: JSON.parse(body),
- }),
+ query: ({ group, type, id, body, summary }) => {
+ let url = `/api/v1/xds/groups/${group}/${type}?${XDS_RESOURCE_META[type].idParam}=${encodeURIComponent(id)}`;
+ if (summary) url += `&summary=${encodeURIComponent(summary)}`;
+ return { url, method: 'POST', body: JSON.parse(body) };
+ },
invalidatesTags: ['Resource'],
}),
updateResource: builder.mutation({
- query: ({ group, type, id, body }) => ({
- url: `/api/v1/xds/groups/${group}/${type}/${encodeResourcePath(id)}`,
- method: 'PATCH',
- body: JSON.parse(body),
- }),
+ query: ({ group, type, id, body, summary }) => {
+ let url = `/api/v1/xds/groups/${group}/${type}/${encodeResourcePath(id)}`;
+ if (summary) url += `?summary=${encodeURIComponent(summary)}`;
+ return { url, method: 'PATCH', body: JSON.parse(body) };
+ },
invalidatesTags: ['Resource'],
}),
- deleteResource: builder.mutation({
- query: ({ group, type, id }) => ({
- url: `/api/v1/xds/groups/${group}/${type}/${encodeResourcePath(id)}`,
- method: 'DELETE',
- }),
+ deleteResource: builder.mutation({
+ query: ({ group, type, id, summary }) => {
+ let url = `/api/v1/xds/groups/${group}/${type}/${encodeResourcePath(id)}`;
+ if (summary) url += `?summary=${encodeURIComponent(summary)}`;
+ return { url, method: 'DELETE' };
+ },
invalidatesTags: ['Resource'],
}),
@@ -305,30 +306,35 @@ export const xdsApiSlice = createApi({
body: JSON.parse(body),
}),
}),
- createK8sAggregator: builder.mutation({
- query: ({ group, aggregatorId, body }) => ({
- url: `/api/v1/xds/groups/${group}/k8s/endpointAggregators?aggregator_id=${encodeURIComponent(
- aggregatorId,
- )}`,
- method: 'POST',
- body: JSON.parse(body),
- }),
+ createK8sAggregator: builder.mutation<
+ unknown,
+ { group: string; aggregatorId: string; body: string; summary?: string }
+ >({
+ query: ({ group, aggregatorId, body, summary }) => {
+ let url = `/api/v1/xds/groups/${group}/k8s/endpointAggregators?aggregator_id=${encodeURIComponent(aggregatorId)}`;
+ if (summary) url += `&summary=${encodeURIComponent(summary)}`;
+ return { url, method: 'POST', body: JSON.parse(body) };
+ },
invalidatesTags: ['K8sAggregator'],
}),
- updateK8sAggregator: builder.mutation({
+ updateK8sAggregator: builder.mutation<
+ unknown,
+ { group: string; id: string; body: string; summary?: string }
+ >({
// The update RPC identifies the target by the `name` field carried in the body (not the path).
- query: ({ group, id, body }) => ({
- url: `/api/v1/xds/groups/${group}/k8s/endpointAggregators/${id}`,
- method: 'PATCH',
- body: JSON.parse(body),
- }),
+ query: ({ group, id, body, summary }) => {
+ let url = `/api/v1/xds/groups/${group}/k8s/endpointAggregators/${id}`;
+ if (summary) url += `?summary=${encodeURIComponent(summary)}`;
+ return { url, method: 'PATCH', body: JSON.parse(body) };
+ },
invalidatesTags: ['K8sAggregator'],
}),
- deleteK8sAggregator: builder.mutation({
- query: ({ group, id }) => ({
- url: `/api/v1/xds/groups/${group}/k8s/endpointAggregators/${id}`,
- method: 'DELETE',
- }),
+ deleteK8sAggregator: builder.mutation({
+ query: ({ group, id, summary }) => {
+ let url = `/api/v1/xds/groups/${group}/k8s/endpointAggregators/${id}`;
+ if (summary) url += `?summary=${encodeURIComponent(summary)}`;
+ return { url, method: 'DELETE' };
+ },
invalidatesTags: ['K8sAggregator'],
}),
diff --git a/xds/src/main/java/com/linecorp/centraldogma/xds/cluster/v1/XdsClusterService.java b/xds/src/main/java/com/linecorp/centraldogma/xds/cluster/v1/XdsClusterService.java
index 636747325..2ac981e8a 100644
--- a/xds/src/main/java/com/linecorp/centraldogma/xds/cluster/v1/XdsClusterService.java
+++ b/xds/src/main/java/com/linecorp/centraldogma/xds/cluster/v1/XdsClusterService.java
@@ -15,6 +15,7 @@
*/
package com.linecorp.centraldogma.xds.cluster.v1;
+import static com.google.common.base.Strings.isNullOrEmpty;
import static com.linecorp.centraldogma.server.internal.admin.auth.AuthUtil.currentAuthor;
import static com.linecorp.centraldogma.xds.internal.ControlPlaneService.CLUSTERS_DIRECTORY;
import static com.linecorp.centraldogma.xds.internal.XdsResourceManager.RESOURCE_ID_PATTERN;
@@ -78,8 +79,10 @@ public void createCluster(CreateClusterRequest request, StreamObserver
// can be set to false via the update API.
.setRespectDnsTtl(true)
.build();
+ final String createSummary = isNullOrEmpty(request.getSummary()) ?
+ "Create cluster: " + clusterName : request.getSummary();
xdsResourceManager.push(responseObserver, group, clusterName, CLUSTERS_DIRECTORY + clusterId + ".yaml",
- "Create cluster: " + clusterName, cluster, currentAuthor(), true);
+ createSummary, cluster, currentAuthor(), true);
}
@Override
@@ -88,8 +91,10 @@ public void updateCluster(UpdateClusterRequest request, StreamObserver
final String clusterName = cluster.getName();
final String group = checkClusterName(clusterName).group(1);
xdsResourceManager.checkWritePermission(group);
+ final String updateSummary = isNullOrEmpty(request.getSummary()) ?
+ "Update cluster: " + clusterName : request.getSummary();
xdsResourceManager.update(responseObserver, group, clusterName,
- "Update cluster: " + clusterName, cluster, currentAuthor());
+ updateSummary, cluster, currentAuthor());
}
@Override
@@ -97,8 +102,9 @@ public void deleteCluster(DeleteClusterRequest request, StreamObserver re
final String clusterName = request.getName();
final String group = checkClusterName(clusterName).group(1);
xdsResourceManager.checkWritePermission(group);
- xdsResourceManager.delete(responseObserver, group, clusterName, "Delete cluster: " + clusterName,
- currentAuthor());
+ final String deleteSummary = isNullOrEmpty(request.getSummary()) ?
+ "Delete cluster: " + clusterName : request.getSummary();
+ xdsResourceManager.delete(responseObserver, group, clusterName, deleteSummary, currentAuthor());
}
private static Matcher checkClusterName(String clusterName) {
diff --git a/xds/src/main/java/com/linecorp/centraldogma/xds/endpoint/v1/XdsEndpointService.java b/xds/src/main/java/com/linecorp/centraldogma/xds/endpoint/v1/XdsEndpointService.java
index c1ce7defe..6c2342197 100644
--- a/xds/src/main/java/com/linecorp/centraldogma/xds/endpoint/v1/XdsEndpointService.java
+++ b/xds/src/main/java/com/linecorp/centraldogma/xds/endpoint/v1/XdsEndpointService.java
@@ -15,6 +15,7 @@
*/
package com.linecorp.centraldogma.xds.endpoint.v1;
+import static com.google.common.base.Strings.isNullOrEmpty;
import static com.linecorp.centraldogma.server.internal.admin.auth.AuthUtil.currentAuthor;
import static com.linecorp.centraldogma.xds.internal.ControlPlaneService.CLUSTERS_DIRECTORY;
import static com.linecorp.centraldogma.xds.internal.ControlPlaneService.ENDPOINTS_DIRECTORY;
@@ -77,8 +78,10 @@ public void createEndpoint(CreateEndpointRequest request,
.toBuilder()
.setClusterName(clusterName)
.build();
+ final String createSummary =
+ isNullOrEmpty(request.getSummary()) ? "Create endpoint: " + clusterName : request.getSummary();
xdsResourceManager.push(responseObserver, group, clusterName, fileName(endpointId),
- "Create endpoint: " + clusterName, endpoint, currentAuthor(), true);
+ createSummary, endpoint, currentAuthor(), true);
}
private static String clusterName(String parent, String endpointId) {
@@ -97,8 +100,10 @@ public void updateEndpoint(UpdateEndpointRequest request,
final ClusterLoadAssignment endpoint = request.getEndpoint();
final String endpointId = matcher.group(2);
+ final String updateSummary =
+ isNullOrEmpty(request.getSummary()) ? "Update endpoint: " + endpointName : request.getSummary();
xdsResourceManager.update(responseObserver, group, endpointName,
- fileName(endpointId), "Update endpoint: " + endpointName,
+ fileName(endpointId), updateSummary,
endpoint.toBuilder()
.setClusterName(clusterName("groups/" + group, endpointId))
.build(), currentAuthor());
@@ -110,8 +115,10 @@ public void deleteEndpoint(DeleteEndpointRequest request, StreamObserver
final Matcher matcher = checkEndpointName(endpointName);
final String group = matcher.group(1);
xdsResourceManager.checkWritePermission(group);
+ final String deleteSummary =
+ isNullOrEmpty(request.getSummary()) ? "Delete endpoint: " + endpointName : request.getSummary();
xdsResourceManager.delete(responseObserver, group, endpointName, fileName(matcher.group(2)),
- "Delete endpoint: " + endpointName, currentAuthor());
+ deleteSummary, currentAuthor());
}
private static Matcher checkEndpointName(String endpointName) {
diff --git a/xds/src/main/java/com/linecorp/centraldogma/xds/k8s/v1/XdsKubernetesService.java b/xds/src/main/java/com/linecorp/centraldogma/xds/k8s/v1/XdsKubernetesService.java
index 204c84669..995a747eb 100644
--- a/xds/src/main/java/com/linecorp/centraldogma/xds/k8s/v1/XdsKubernetesService.java
+++ b/xds/src/main/java/com/linecorp/centraldogma/xds/k8s/v1/XdsKubernetesService.java
@@ -139,12 +139,14 @@ public void createKubernetesEndpointAggregator(
}
final Author author = currentAuthor();
final String fileName = K8S_ENDPOINT_AGGREGATORS_DIRECTORY + aggregatorId + ".yaml";
+ final String createSummary =
+ isNullOrEmpty(request.getSummary()) ? "Create kubernetes endpoint: " + kubernetesEndpointName
+ : request.getSummary();
validateKubernetesEndpointAndPush(
responseObserver, kubernetesLocalityLbEndpointsList, group, fileName,
() -> xdsResourceManager.push(
responseObserver, group, kubernetesEndpointName,
- fileName,
- "Create kubernetes endpoint: " + kubernetesEndpointName, aggregator, author, true));
+ fileName, createSummary, aggregator, author, true));
}
private void validateKubernetesEndpointAndPush(
@@ -373,11 +375,13 @@ public void updateKubernetesEndpointAggregator(
final KubernetesEndpointAggregator aggregator0 = aggregator.toBuilder().setClusterName(
AGGREGATORS_REPLCACE_PATTERN.matcher(aggregatorName).replaceFirst("/clusters/")).build();
final Author author = currentAuthor();
+ final String updateSummary =
+ isNullOrEmpty(request.getSummary()) ? "Update kubernetes endpoint aggregator: " + aggregatorName
+ : request.getSummary();
validateKubernetesEndpointAndPush(
responseObserver, kubernetesLocalityLbEndpointsList, group, fileName(group, aggregatorName),
() -> xdsResourceManager.update(
- responseObserver, group, aggregatorName,
- "Update kubernetes endpoint aggregator: " + aggregatorName, aggregator0, author));
+ responseObserver, group, aggregatorName, updateSummary, aggregator0, author));
}
private static Matcher checkAggregatorName(String aggregatorName) {
@@ -397,9 +401,10 @@ public void deleteKubernetesEndpointAggregator(DeleteKubernetesEndpointAggregato
final String aggregatorName = request.getName();
final String group = checkAggregatorName(aggregatorName).group(1);
xdsResourceManager.checkWritePermission(group);
- xdsResourceManager.delete(responseObserver, group, aggregatorName,
- "Delete kubernetes endpoint aggregator: " + aggregatorName,
- currentAuthor());
+ final String deleteSummary =
+ isNullOrEmpty(request.getSummary()) ? "Delete kubernetes endpoint aggregator: " + aggregatorName
+ : request.getSummary();
+ xdsResourceManager.delete(responseObserver, group, aggregatorName, deleteSummary, currentAuthor());
}
@Blocking
diff --git a/xds/src/main/java/com/linecorp/centraldogma/xds/listener/v1/XdsListenerService.java b/xds/src/main/java/com/linecorp/centraldogma/xds/listener/v1/XdsListenerService.java
index 9401028d0..5170e8cf0 100644
--- a/xds/src/main/java/com/linecorp/centraldogma/xds/listener/v1/XdsListenerService.java
+++ b/xds/src/main/java/com/linecorp/centraldogma/xds/listener/v1/XdsListenerService.java
@@ -15,6 +15,7 @@
*/
package com.linecorp.centraldogma.xds.listener.v1;
+import static com.google.common.base.Strings.isNullOrEmpty;
import static com.linecorp.centraldogma.server.internal.admin.auth.AuthUtil.currentAuthor;
import static com.linecorp.centraldogma.xds.internal.ControlPlaneService.LISTENERS_DIRECTORY;
import static com.linecorp.centraldogma.xds.internal.XdsResourceManager.RESOURCE_ID_PATTERN;
@@ -68,9 +69,11 @@ public void createListener(CreateListenerRequest request, StreamObserver
final String listenerName = request.getName();
final String group = checkListenerName(listenerName).group(1);
xdsResourceManager.checkWritePermission(group);
- xdsResourceManager.delete(responseObserver, group, listenerName, "Delete listener: " + listenerName,
- currentAuthor());
+ final String deleteSummary =
+ isNullOrEmpty(request.getSummary()) ? "Delete listener: " + listenerName : request.getSummary();
+ xdsResourceManager.delete(responseObserver, group, listenerName, deleteSummary, currentAuthor());
}
}
diff --git a/xds/src/main/java/com/linecorp/centraldogma/xds/route/v1/XdsRouteService.java b/xds/src/main/java/com/linecorp/centraldogma/xds/route/v1/XdsRouteService.java
index 00e0cd053..3d834c072 100644
--- a/xds/src/main/java/com/linecorp/centraldogma/xds/route/v1/XdsRouteService.java
+++ b/xds/src/main/java/com/linecorp/centraldogma/xds/route/v1/XdsRouteService.java
@@ -15,6 +15,7 @@
*/
package com.linecorp.centraldogma.xds.route.v1;
+import static com.google.common.base.Strings.isNullOrEmpty;
import static com.linecorp.centraldogma.server.internal.admin.auth.AuthUtil.currentAuthor;
import static com.linecorp.centraldogma.xds.internal.ControlPlaneService.ROUTES_DIRECTORY;
import static com.linecorp.centraldogma.xds.internal.XdsResourceManager.RESOURCE_ID_PATTERN;
@@ -68,8 +69,10 @@ public void createRoute(CreateRouteRequest request, StreamObserver respon
final String routeName = request.getName();
final String group = checkRouteName(routeName).group(1);
xdsResourceManager.checkWritePermission(group);
- xdsResourceManager.delete(responseObserver, group, routeName, "Delete route: " + routeName,
- currentAuthor());
+ final String deleteSummary = isNullOrEmpty(request.getSummary()) ?
+ "Delete route: " + routeName : request.getSummary();
+ xdsResourceManager.delete(responseObserver, group, routeName, deleteSummary, currentAuthor());
}
}
diff --git a/xds/src/main/proto/centraldogma/xds/cluster/v1/xds_cluster.proto b/xds/src/main/proto/centraldogma/xds/cluster/v1/xds_cluster.proto
index f0f06c88a..4a5995459 100644
--- a/xds/src/main/proto/centraldogma/xds/cluster/v1/xds_cluster.proto
+++ b/xds/src/main/proto/centraldogma/xds/cluster/v1/xds_cluster.proto
@@ -64,6 +64,9 @@ message CreateClusterRequest {
// Valid pattern is "^[a-z]([a-z0-9-/]*[a-z0-9])?$"
string cluster_id = 2 [(google.api.field_behavior) = REQUIRED];
envoy.config.cluster.v3.Cluster cluster = 3 [(google.api.field_behavior) = REQUIRED];
+
+ // The commit summary for this change. If not specified, a default message is used.
+ string summary = 4 [(google.api.field_behavior) = OPTIONAL];
}
message UpdateClusterRequest {
@@ -78,6 +81,9 @@ message UpdateClusterRequest {
// If set to true, and the cluster is not found, a new cluster will be created.
// In this situation, `update_mask` is ignored.
// bool allow_missing = 3;
+
+ // The commit summary for this change. If not specified, a default message is used.
+ string summary = 4 [(google.api.field_behavior) = OPTIONAL];
}
message DeleteClusterRequest {
@@ -87,4 +93,7 @@ message DeleteClusterRequest {
// If set to true, and the cluster is not found, the request will succeed
// but no action will be taken on the server
// bool allow_missing = 2;
+
+ // The commit summary for this change. If not specified, a default message is used.
+ string summary = 3 [(google.api.field_behavior) = OPTIONAL];
}
diff --git a/xds/src/main/proto/centraldogma/xds/endpoint/v1/xds_endpoint.proto b/xds/src/main/proto/centraldogma/xds/endpoint/v1/xds_endpoint.proto
index cb7c11e7e..fb3929af7 100644
--- a/xds/src/main/proto/centraldogma/xds/endpoint/v1/xds_endpoint.proto
+++ b/xds/src/main/proto/centraldogma/xds/endpoint/v1/xds_endpoint.proto
@@ -83,6 +83,9 @@ message CreateEndpointRequest {
// Valid pattern is "^[a-z]([a-z0-9-/]*[a-z0-9])?$"
string endpoint_id = 2 [(google.api.field_behavior) = REQUIRED];
envoy.config.endpoint.v3.ClusterLoadAssignment endpoint = 3 [(google.api.field_behavior) = REQUIRED];
+
+ // The commit summary for this change. If not specified, a default message is used.
+ string summary = 4 [(google.api.field_behavior) = OPTIONAL];
}
message UpdateEndpointRequest {
@@ -91,22 +94,28 @@ message UpdateEndpointRequest {
envoy.config.endpoint.v3.ClusterLoadAssignment endpoint = 2 [(google.api.field_behavior) = REQUIRED];
+ // The commit summary for this change. If not specified, a default message is used.
+ string summary = 3 [(google.api.field_behavior) = OPTIONAL];
+
// TODO(minwoox): Add the following fields.
// The list of fields to be updated.
- // google.protobuf.FieldMask update_mask = 2;
+ // google.protobuf.FieldMask update_mask = 4;
// If set to true, and the endpoint is not found, a new endpoint will be created.
// In this situation, `update_mask` is ignored.
- // bool allow_missing = 3;
+ // bool allow_missing = 5;
}
message DeleteEndpointRequest {
// Format: groups/{group}/endpoints/{endpoint}
string name = 1 [(google.api.field_behavior) = IDENTIFIER];
+ // The commit summary for this change. If not specified, a default message is used.
+ string summary = 2 [(google.api.field_behavior) = OPTIONAL];
+
// If set to true, and the endpoint is not found, the request will succeed
// but no action will be taken on the server
- // bool allow_missing = 2;
+ // bool allow_missing = 3;
}
message RegisterLocalityLbEndpointRequest {
diff --git a/xds/src/main/proto/centraldogma/xds/k8s/v1/xds_kubernetes.proto b/xds/src/main/proto/centraldogma/xds/k8s/v1/xds_kubernetes.proto
index 1d1b47bb4..82732661d 100644
--- a/xds/src/main/proto/centraldogma/xds/k8s/v1/xds_kubernetes.proto
+++ b/xds/src/main/proto/centraldogma/xds/k8s/v1/xds_kubernetes.proto
@@ -70,6 +70,9 @@ message CreateKubernetesEndpointAggregatorRequest {
// Valid pattern is "^[a-z]([a-z0-9-/]*[a-z0-9])?$"
string aggregator_id = 2 [(google.api.field_behavior) = REQUIRED];
KubernetesEndpointAggregator kubernetes_endpoint_aggregator = 3 [(google.api.field_behavior) = REQUIRED];
+
+ // The commit summary for this change. If not specified, a default message is used.
+ string summary = 4 [(google.api.field_behavior) = OPTIONAL];
}
message KubernetesEndpointAggregator {
@@ -150,14 +153,20 @@ message UpdateKubernetesEndpointAggregatorRequest {
// The kubernetes_endpoint_aggregator's `name` field is used to identify the endpoint to update.
KubernetesEndpointAggregator kubernetes_endpoint_aggregator = 1 [(google.api.field_behavior) = REQUIRED];
+ // The commit summary for this change. If not specified, a default message is used.
+ string summary = 2 [(google.api.field_behavior) = OPTIONAL];
+
// TODO(minwoox): Implement these fields
- // google.protobuf.FieldMask update_mask = 2;
+ // google.protobuf.FieldMask update_mask = 3;
//
- // bool allow_missing = 3;
+ // bool allow_missing = 4;
}
message DeleteKubernetesEndpointAggregatorRequest {
string name = 1 [(google.api.field_behavior) = IDENTIFIER];
+
+ // The commit summary for this change. If not specified, a default message is used.
+ string summary = 2 [(google.api.field_behavior) = OPTIONAL];
}
message PreviewKubernetesEndpointAggregatorRequest {
diff --git a/xds/src/main/proto/centraldogma/xds/listener/v1/xds_listener.proto b/xds/src/main/proto/centraldogma/xds/listener/v1/xds_listener.proto
index a385f7c62..8b518f917 100644
--- a/xds/src/main/proto/centraldogma/xds/listener/v1/xds_listener.proto
+++ b/xds/src/main/proto/centraldogma/xds/listener/v1/xds_listener.proto
@@ -64,6 +64,9 @@ message CreateListenerRequest {
// Valid pattern is "^[a-z]([a-z0-9-/]*[a-z0-9])?$"
string listener_id = 2 [(google.api.field_behavior) = REQUIRED];
envoy.config.listener.v3.Listener listener = 3 [(google.api.field_behavior) = REQUIRED];
+
+ // The commit summary for this change. If not specified, a default message is used.
+ string summary = 4 [(google.api.field_behavior) = OPTIONAL];
}
message UpdateListenerRequest {
@@ -71,20 +74,26 @@ message UpdateListenerRequest {
// Format: groups/{group}/listeners/{listener}
envoy.config.listener.v3.Listener listener = 1 [(google.api.field_behavior) = REQUIRED];
+ // The commit summary for this change. If not specified, a default message is used.
+ string summary = 2 [(google.api.field_behavior) = OPTIONAL];
+
// TODO(minwoox): Add the following fields.
// The list of fields to be updated.
- // google.protobuf.FieldMask update_mask = 2;
+ // google.protobuf.FieldMask update_mask = 3;
// If set to true, and the listener is not found, a new listener will be created.
// In this situation, `update_mask` is ignored.
- // bool allow_missing = 3;
+ // bool allow_missing = 4;
}
message DeleteListenerRequest {
// Format: groups/{group}/listeners/{listener}
string name = 1 [(google.api.field_behavior) = IDENTIFIER];
+ // The commit summary for this change. If not specified, a default message is used.
+ string summary = 2 [(google.api.field_behavior) = OPTIONAL];
+
// If set to true, and the listener is not found, the request will succeed
// but no action will be taken on the server
- // bool allow_missing = 2;
+ // bool allow_missing = 3;
}
diff --git a/xds/src/main/proto/centraldogma/xds/route/v1/xds_route.proto b/xds/src/main/proto/centraldogma/xds/route/v1/xds_route.proto
index 8cf9874a2..242dcc645 100644
--- a/xds/src/main/proto/centraldogma/xds/route/v1/xds_route.proto
+++ b/xds/src/main/proto/centraldogma/xds/route/v1/xds_route.proto
@@ -64,6 +64,9 @@ message CreateRouteRequest {
// Valid pattern is "^[a-z]([a-z0-9-/]*[a-z0-9])?$"
string route_id = 2 [(google.api.field_behavior) = REQUIRED];
envoy.config.route.v3.RouteConfiguration route = 3 [(google.api.field_behavior) = REQUIRED];
+
+ // The commit summary for this change. If not specified, a default message is used.
+ string summary = 4 [(google.api.field_behavior) = OPTIONAL];
}
message UpdateRouteRequest {
@@ -71,20 +74,26 @@ message UpdateRouteRequest {
// Format: groups/{group}/routes/{route}
envoy.config.route.v3.RouteConfiguration route = 1 [(google.api.field_behavior) = REQUIRED];
+ // The commit summary for this change. If not specified, a default message is used.
+ string summary = 2 [(google.api.field_behavior) = OPTIONAL];
+
// TODO(minwoox): Add the following fields.
// The list of fields to be updated.
- // google.protobuf.FieldMask update_mask = 2;
+ // google.protobuf.FieldMask update_mask = 3;
// If set to true, and the route is not found, a new route will be created.
// In this situation, `update_mask` is ignored.
- // bool allow_missing = 3;
+ // bool allow_missing = 4;
}
message DeleteRouteRequest {
// Format: groups/{group}/routes/{route}
string name = 1 [(google.api.field_behavior) = IDENTIFIER];
+ // The commit summary for this change. If not specified, a default message is used.
+ string summary = 2 [(google.api.field_behavior) = OPTIONAL];
+
// If set to true, and the Route is not found, the request will succeed
// but no action will be taken on the server
- // bool allow_missing = 2;
+ // bool allow_missing = 3;
}