diff --git a/Dockerfile b/Dockerfile
index a73e75ae46..70957e3ae6 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -70,7 +70,7 @@ ENV HELM_VERSION=v3.10.3
ENV TERRAFORM_VERSION=v1.2.9
# renovate: datasource=github-releases depName=pluralsh/plural-cli
-ENV CLI_VERSION=v0.8.1
+ENV CLI_VERSION=v0.8.2
# renovate: datasource=github-tags depName=kubernetes/kubernetes
ENV KUBECTL_VERSION=v1.25.5
diff --git a/assets/src/components/cd/globalSettings/GlobalSettings.tsx b/assets/src/components/cd/globalSettings/GlobalSettings.tsx
index 60a38c70ae..d4054419b7 100644
--- a/assets/src/components/cd/globalSettings/GlobalSettings.tsx
+++ b/assets/src/components/cd/globalSettings/GlobalSettings.tsx
@@ -15,7 +15,9 @@ import {
useDeploymentSettingsQuery,
} from 'generated/graphql'
-import { useMemo } from 'react'
+import { useContext, useMemo } from 'react'
+
+import { LoginContext } from 'components/contexts'
import { CD_BASE_CRUMBS } from '../ContinuousDeployment'
@@ -47,6 +49,10 @@ const directory = [
path: 'repositories',
label: 'Repositories',
},
+ {
+ path: 'auto-update',
+ label: 'Auto Update',
+ },
]
type GlobalSettingsContextType = {
@@ -60,6 +66,7 @@ export const useGlobalSettingsContext = () =>
export function GlobalSettings() {
const theme = useTheme()
const { pathname } = useLocation()
+ const { configuration } = useContext(LoginContext)
const { data, refetch } = useDeploymentSettingsQuery({})
const outletContext = useMemo(
@@ -70,6 +77,16 @@ export function GlobalSettings() {
[data, refetch]
)
+ const prunedDirectory = useMemo(
+ () =>
+ directory.filter(
+ ({ path }) =>
+ path !== 'auto-update' ||
+ (configuration?.byok && !data?.deploymentSettings?.selfManaged)
+ ),
+ [configuration, data]
+ )
+
return (
@@ -80,7 +97,7 @@ export function GlobalSettings() {
}}
>
diff --git a/assets/src/components/cd/globalSettings/SelfManage.tsx b/assets/src/components/cd/globalSettings/SelfManage.tsx
new file mode 100644
index 0000000000..a0e152a71f
--- /dev/null
+++ b/assets/src/components/cd/globalSettings/SelfManage.tsx
@@ -0,0 +1,44 @@
+import { CodeEditor } from '@pluralsh/design-system'
+import { GqlError } from 'components/utils/Alert'
+import { ScrollablePage } from 'components/utils/layout/ScrollablePage'
+import { useSelfManageMutation } from 'generated/graphql'
+import { useState } from 'react'
+import { useNavigate } from 'react-router-dom'
+
+const INTRO_TEXT =
+ '# Paste your helm values file here\n' +
+ '# this will create a service that will auto-update your instance\n' +
+ '# with these values persisted throughout'
+
+export default function SelfManage() {
+ const navigate = useNavigate()
+ const [values, setValues] = useState(INTRO_TEXT)
+ const [mutation, { loading, error }] = useSelfManageMutation({
+ variables: { values },
+ onCompleted: () => navigate('/cd/services'),
+ })
+
+ return (
+
+ {error && (
+
+ )}
+ mutation()}
+ saveLabel="Configure"
+ />
+
+ )
+}
diff --git a/assets/src/components/cd/repos/HelmHealthChip.tsx b/assets/src/components/cd/repos/HelmHealthChip.tsx
new file mode 100644
index 0000000000..948b69ba0f
--- /dev/null
+++ b/assets/src/components/cd/repos/HelmHealthChip.tsx
@@ -0,0 +1,35 @@
+import { Chip, Tooltip } from '@pluralsh/design-system'
+
+export function HelmHealthChip({
+ ready,
+ message,
+}: {
+ ready: boolean
+ message?: string | null | undefined
+}) {
+ const chip = (
+
+ {ready ? 'Ready' : 'Failed'}
+
+ )
+
+ const errorLines = (message || '').split('\n').map((line, i, arr) => (
+ <>
+ {line}
+ {i !== arr.length - 1 &&
}
+ >
+ ))
+
+ if (message) {
+ return (
+ {errorLines}}
+ >
+ {chip}
+
+ )
+ }
+
+ return chip
+}
diff --git a/assets/src/components/cd/services/ServiceRevisionColumns.tsx b/assets/src/components/cd/services/ServiceRevisionColumns.tsx
index 9f3528ec08..fced41d5c4 100644
--- a/assets/src/components/cd/services/ServiceRevisionColumns.tsx
+++ b/assets/src/components/cd/services/ServiceRevisionColumns.tsx
@@ -22,21 +22,28 @@ import { useServiceContext } from './service/ServiceDetails'
const columnHelper =
createColumnHelper>()
-const ColGitRef = columnHelper.accessor((row) => row?.git.ref, {
+const ColGitRef = columnHelper.accessor((row) => row, {
id: 'gitRef',
- header: 'Commit ref',
+ header: 'Revision',
meta: { truncate: true },
- cell: ({ row: { original }, getValue }) => (
-
-
-
- ),
+ cell: ({ getValue }) => {
+ const rev = getValue()
+ const ref = rev?.helm?.chart
+ ? `${rev.helm.chart}@${rev.helm.version}`
+ : rev?.git?.ref
+
+ return (
+
+
+
+ )
+ },
})
const ColMessage = columnHelper.accessor((row) => row?.message, {
@@ -164,7 +171,7 @@ const ColActions = columnHelper.accessor((row) => row, {
following revision:
-
{revision?.git.ref}
+ {revision?.git?.ref}
sha: {revision?.sha}
diff --git a/assets/src/components/cd/services/ServiceSettings.tsx b/assets/src/components/cd/services/ServiceSettings.tsx
index a67fb5af81..e55f20e023 100644
--- a/assets/src/components/cd/services/ServiceSettings.tsx
+++ b/assets/src/components/cd/services/ServiceSettings.tsx
@@ -1,10 +1,12 @@
import { Button, Switch } from '@pluralsh/design-system'
import {
ServiceDeploymentsRowFragment,
+ ServiceUpdateAttributes,
+ useHelmRepositoryQuery,
useUpdateServiceDeploymentMutation,
} from 'generated/graphql'
import { useTheme } from 'styled-components'
-import { FormEvent, useCallback, useEffect, useRef } from 'react'
+import { FormEvent, useCallback, useEffect, useMemo, useRef } from 'react'
import { GqlError } from 'components/utils/Alert'
import { ModalMountTransition } from 'components/utils/ModalMountTransition'
@@ -17,6 +19,7 @@ import {
ServiceGitFolderField,
ServiceGitRefField,
} from './deployModal/DeployServiceSettingsGit'
+import { ChartForm } from './deployModal/DeployServiceSettingsHelm'
export function ServiceSettings({
serviceDeployment,
@@ -41,6 +44,26 @@ export function ServiceSettings({
)
}
+function ChartUpdate({ repo, state, updateState }) {
+ const { data } = useHelmRepositoryQuery({
+ variables: {
+ name: repo?.name || '',
+ namespace: repo?.namespace || '',
+ },
+ skip: !repo?.name || !repo?.namespace,
+ })
+
+ return (
+ updateState({ helmChart: chart })}
+ version={state.helmVersion}
+ setVersion={(vsn) => updateState({ helmVersion: vsn })}
+ />
+ )
+}
+
export function ModalForm({
serviceDeployment,
open,
@@ -59,22 +82,39 @@ export function ModalForm({
update: updateState,
hasUpdates,
} = useUpdateState({
- gitRef: serviceDeployment.git.ref ?? '',
- gitFolder: serviceDeployment.git.folder ?? '',
+ gitRef: serviceDeployment.git?.ref ?? '',
+ gitFolder: serviceDeployment.git?.folder ?? '',
+ helmChart: serviceDeployment.helm?.chart ?? '',
+ helmVersion: serviceDeployment.helm?.version ?? '',
protect: !!serviceDeployment.protect,
})
+ const attributes = useMemo(() => {
+ const git =
+ state.gitRef && state.gitFolder
+ ? { folder: state.gitFolder, ref: state.gitRef }
+ : null
+ const helm =
+ state.helmChart && state.helmVersion
+ ? { chart: state.helmChart, version: state.helmVersion }
+ : null
+ let attributes: ServiceUpdateAttributes = { protect: state.protect }
+
+ if (git) {
+ attributes = { git, ...attributes }
+ }
+ if (helm) {
+ attributes = { helm, ...attributes }
+ }
+
+ return attributes
+ }, [state])
+
const [updateService, { loading, error }] =
useUpdateServiceDeploymentMutation({
variables: {
id: serviceDeployment.id,
- attributes: {
- git: {
- folder: state.gitFolder,
- ref: state.gitRef,
- },
- protect: state.protect,
- },
+ attributes,
},
onCompleted: () => {
refetch?.()
@@ -138,18 +178,29 @@ export function ModalForm({
gap: theme.spacing.medium,
}}
>
- {
- updateState({ gitRef: e.currentTarget.value })
- }}
- />
- {
- updateState({ gitFolder: e.currentTarget.value })
- }}
- />
+ {!serviceDeployment.helm?.chart && (
+ <>
+ {
+ updateState({ gitRef: e.currentTarget.value })
+ }}
+ />
+ {
+ updateState({ gitFolder: e.currentTarget.value })
+ }}
+ />
+ >
+ )}
+ {serviceDeployment.helm?.chart && (
+
+ )}
updateState({ protect: checked })}
diff --git a/assets/src/components/cd/services/ServicesColumns.tsx b/assets/src/components/cd/services/ServicesColumns.tsx
index 5f31468a44..e72335018e 100644
--- a/assets/src/components/cd/services/ServicesColumns.tsx
+++ b/assets/src/components/cd/services/ServicesColumns.tsx
@@ -82,56 +82,73 @@ export const ColCluster = columnHelper.accessor(
}
)
-export const ColRepo = columnHelper.accessor(
- ({ node }) => node?.repository?.url,
- {
- id: 'repository',
- header: 'Repository',
- enableSorting: true,
- meta: { truncate: true, gridTemplate: 'minmax(180px,1fr)' },
- cell: ({ getValue }) => (
+export const ColRepo = columnHelper.accessor(({ node }) => node, {
+ id: 'repository',
+ header: 'Repository',
+ enableSorting: true,
+ meta: { truncate: true, gridTemplate: 'minmax(180px,1fr)' },
+ cell: ({ getValue }) => {
+ const theme = useTheme()
+ const svc = getValue()
+ const git = svc?.repository
+ const helm = svc?.helmRepository
+ const url = git?.url || helm?.spec?.url || ''
+
+ return (
}
+ icon={
+ git ? (
+
+ ) : (
+ getProviderIconURL('byok', theme.mode === 'dark')
+ )
+ }
>
- {getValue()}
+ {url}
- ),
- }
-)
+ )
+ },
+})
export const ColRef = columnHelper.accessor(({ node }) => node, {
id: 'gitLocation',
- header: 'Git Location',
+ header: 'Reference',
enableSorting: true,
// meta: { truncate: true },
cell: ({ getValue }) => {
const svc = getValue()
if (!svc) return null
- const {
- git: { ref, folder },
- message,
- } = svc
+ const { message } = svc
- const refStr = shortenSha1(ref)
+ const refStr = shortenSha1(svc.git?.ref || '')
return (
- {message || ''}}
- >
-
- {refStr}@{folder}
-
-
+ <>
+ {svc.helm && (
+
+ {svc.helm?.chart}@{svc.helm?.version}
+
+ )}
+ {svc.git && (
+ {message || ''}}
+ >
+
+ {refStr}@{svc.git?.folder}
+
+
+ )}
+ >
)
},
})
diff --git a/assets/src/components/cd/services/deployModal/DeployService.tsx b/assets/src/components/cd/services/deployModal/DeployService.tsx
index 68b4b5471b..ae205f0c1a 100644
--- a/assets/src/components/cd/services/deployModal/DeployService.tsx
+++ b/assets/src/components/cd/services/deployModal/DeployService.tsx
@@ -4,6 +4,7 @@ import {
GitHubIcon,
PadlockLockedIcon,
Stepper,
+ Switch,
} from '@pluralsh/design-system'
import {
useClustersTinyQuery,
@@ -26,10 +27,12 @@ import {
DeployServiceSettingsSecrets,
Secret,
} from './DeployServiceSettingsSecrets'
+import DeployServiceSettingsHelm from './DeployServiceSettingsHelm'
enum FormState {
Initial = 'initial',
Git = 'git',
+ Helm = 'helm',
Secrets = 'secrets',
}
@@ -78,6 +81,9 @@ export function DeployServiceModal({
const [clusterId, setClusterId] = useState('')
const [name, setName] = useState('')
const [repositoryId, setRepositoryId] = useState('')
+ const [repository, setRepository] = useState(null)
+ const [chart, setChart] = useState('')
+ const [version, setVersion] = useState('')
const [gitFolder, setGitFolder] = useState('')
const [gitRef, setGitRef] = useState('')
const [namespace, setNamespace] = useState('')
@@ -99,6 +105,10 @@ export function DeployServiceModal({
}))
}, [secrets])
+ const helm =
+ repository && chart && version ? { repository, chart, version } : null
+ const git = gitRef && gitFolder ? { ref: gitRef, folder: gitFolder } : null
+
const [mutation, { loading: mutationLoading, error: mutationError }] =
useCreateServiceDeploymentMutation({
variables: {
@@ -107,7 +117,8 @@ export function DeployServiceModal({
repositoryId,
name,
namespace,
- git: { ref: gitRef, folder: gitFolder },
+ git,
+ helm,
configuration,
},
},
@@ -127,9 +138,12 @@ export function DeployServiceModal({
const initialFormValid = name && namespace && clusterId
const allowGoToGit = formState === FormState.Initial && initialFormValid
- const gitSettingsValid = repositoryId && gitFolder && gitRef
+ const gitSettingsValid =
+ (repositoryId && gitFolder && gitRef) || (chart && version && repository)
const allowGoToSecrets =
- formState === FormState.Git && initialFormValid && gitSettingsValid
+ (formState === FormState.Git || formState === FormState.Helm) &&
+ initialFormValid &&
+ gitSettingsValid
const allowDeploy =
formState === FormState.Secrets &&
@@ -190,7 +204,7 @@ export function DeployServiceModal({
Go back
>
- ) : formState === FormState.Git ? (
+ ) : formState === FormState.Git || formState === FormState.Helm ? (
<>
+
+ setFormState(selected ? FormState.Helm : FormState.Git)
+ }
+ >
+ Use Helm Source
+
+ ) : formState === FormState.Helm ? (
+
) : (
<>
+
+
+
+
+
+
+ >
+ )
+}
+
+export function ChartForm({ charts, chart, version, setChart, setVersion }) {
+ if (charts?.length === 0) {
+ return (
+
+ )
+ }
+ const selectedChart = charts.find((c) => c.name === chart)
+
+ return (
+ <>
+
+
+
+
+
+
+ >
+ )
+}
+
+function EmptyState({ loading }) {
+ if (loading) return
+
+ return <>Looks like you need to register a helm repository first...>
+}
+
+const keyToRepo = (key) => {
+ const parts = (key || '').split(':')
+
+ if (parts.length === 2) return { namespace: parts[0], name: parts[1] }
+
+ return null
+}
+
+export default function DeployServiceSettingsHelm({
+ repository,
+ setRepository,
+ chart,
+ setChart,
+ version,
+ setVersion,
+}) {
+ const { data, loading } = useHelmRepositoriesQuery({
+ fetchPolicy: 'cache-and-network',
+ })
+
+ const { data: charts } = useHelmRepositoryQuery({
+ variables: {
+ name: repository?.name || '',
+ namespace: repository?.namespace || '',
+ },
+ skip: !repository?.name || !repository?.namespace,
+ })
+
+ if (!data?.helmRepositories) return
+
+ const repositories = data?.helmRepositories
+ const selectedRepository = repositories.find(
+ (r) =>
+ r?.metadata.name === repository?.name &&
+ r?.metadata.namespace === repository?.namespace
+ )
+
+ return (
+ <>
+
+
+
+
+ >
+ )
+}
diff --git a/assets/src/components/cd/services/service/ServiceDetails.tsx b/assets/src/components/cd/services/service/ServiceDetails.tsx
index 4fd2665e04..7210e8d075 100644
--- a/assets/src/components/cd/services/service/ServiceDetails.tsx
+++ b/assets/src/components/cd/services/service/ServiceDetails.tsx
@@ -81,7 +81,7 @@ export const getDirectory = ({
if (!serviceDeployment) {
return []
}
- const { name, componentStatus } = serviceDeployment
+ const { name, componentStatus, helm } = serviceDeployment
return [
{
@@ -90,6 +90,7 @@ export const getDirectory = ({
enabled: true,
},
{ path: 'secrets', label: 'Secrets', enabled: true },
+ { path: 'helm', label: 'Helm', enabled: !!helm },
{ path: 'revisions', label: 'Revisions', enabled: true },
{
path: 'docs',
diff --git a/assets/src/components/cd/services/service/ServiceDetailsSidecar.tsx b/assets/src/components/cd/services/service/ServiceDetailsSidecar.tsx
index 024c08b113..45d51798e9 100644
--- a/assets/src/components/cd/services/service/ServiceDetailsSidecar.tsx
+++ b/assets/src/components/cd/services/service/ServiceDetailsSidecar.tsx
@@ -25,7 +25,7 @@ export function ServiceDetailsSidecar({
if (!serviceDeployment) {
return null
}
- const { name, version, status, cluster, git } = serviceDeployment
+ const { name, version, status, cluster, git, helm } = serviceDeployment
return (
@@ -46,15 +46,28 @@ export function ServiceDetailsSidecar({
None
)}
- {git.folder}
-
- {git.ref}
-
+ {helm && {helm.chart}}
+ {helm && (
+
+ {helm.version}
+
+ )}
+ {git && {git.folder}}
+ {git && (
+
+ {git.ref}
+
+ )}
{cluster?.name && (
+ )
+ )
+}
+
+export default function ServiceHelm() {
+ const navigate = useNavigate()
+ const serviceId = useParams()[SERVICE_PARAM_ID]
+ const [values, setValues] = useState('')
+
+ const [mutation, { loading, error }] = useUpdateServiceDeploymentMutation({
+ variables: {
+ id: serviceId || '',
+ attributes: {
+ helm: { values },
+ },
+ },
+ onCompleted: () => navigate('/cd/services'),
+ })
+ const { data, error: fetchError } = useServiceDeploymentSecretsQuery({
+ variables: { id: serviceId || '' },
+ })
+
+ useEffect(() => {
+ if (data?.serviceDeployment?.helm?.values) {
+ setValues(data?.serviceDeployment?.helm?.values)
+ }
+ }, [data])
+
+ if (!data?.serviceDeployment?.helm) return
+
+ return (
+
+ {error && (
+
+ )}
+ mutation()}
+ saveLabel="Save"
+ />
+
+ )
+}
diff --git a/assets/src/components/layout/Console.tsx b/assets/src/components/layout/Console.tsx
index 5ae521ddd4..350642007a 100644
--- a/assets/src/components/layout/Console.tsx
+++ b/assets/src/components/layout/Console.tsx
@@ -4,7 +4,6 @@ import { MarkdocContextProvider } from '@pluralsh/design-system/dist/markdoc/Mar
import BillingSubscriptionProvider from 'components/billing/BillingSubscriptionProvider'
import BreadcrumbsProvider from 'components/contexts/BreadcrumbsProvider'
import ConsoleNavContextProvider from 'components/contexts/NavigationContext'
-import usePosthogIdentify from 'components/utils/Posthog'
import { A, Flex, Span } from 'honorable'
import { Outlet } from 'react-router-dom'
@@ -57,7 +56,7 @@ export default function Console() {
function ConsoleContent() {
const isProduction = import.meta.env.MODE === 'production'
- usePosthogIdentify()
+ // usePosthogIdentify()
return (
>>;
+ /** whether the byok cluster has been brought under self-management */
+ selfManaged?: Maybe;
updatedAt?: Maybe;
/** write policy across all clusters */
writeBindings?: Maybe>>;
@@ -1286,6 +1288,77 @@ export type GroupMemberEdge = {
node?: Maybe;
};
+/** a chart manifest entry, including all versions */
+export type HelmChartEntry = {
+ __typename?: 'HelmChartEntry';
+ /** the name of the chart */
+ name?: Maybe;
+ /** all found versions of the chart */
+ versions?: Maybe>>;
+};
+
+/** a chart version contained within a helm repository manifest */
+export type HelmChartVersion = {
+ __typename?: 'HelmChartVersion';
+ /** the version of the app contained w/in this chart */
+ appVersion?: Maybe;
+ /** sha digest of this chart's contents */
+ digest?: Maybe;
+ /** the name of the chart */
+ name?: Maybe;
+ type?: Maybe;
+ /** the version of the chart itself */
+ version?: Maybe;
+};
+
+export type HelmConfigAttributes = {
+ chart?: InputMaybe;
+ repository?: InputMaybe;
+ values?: InputMaybe;
+ valuesFiles?: InputMaybe>>;
+ version?: InputMaybe;
+};
+
+/** a crd representation of a helm repository */
+export type HelmRepository = {
+ __typename?: 'HelmRepository';
+ /** the charts found in this repository (heavy operation, don't do in list endpoints) */
+ charts?: Maybe>>;
+ metadata: Metadata;
+ spec: HelmRepositorySpec;
+ /** can fetch the status of a given helm repository */
+ status?: Maybe;
+};
+
+/** a specification of how a helm repository is fetched */
+export type HelmRepositorySpec = {
+ __typename?: 'HelmRepositorySpec';
+ provider?: Maybe;
+ type?: Maybe;
+ url: Scalars['String']['output'];
+};
+
+/** the state of this helm repository */
+export type HelmRepositoryStatus = {
+ __typename?: 'HelmRepositoryStatus';
+ message?: Maybe;
+ ready?: Maybe;
+};
+
+export type HelmSpec = {
+ __typename?: 'HelmSpec';
+ /** the name of the chart this service is using */
+ chart?: Maybe;
+ /** pointer to the flux helm repository resource used for this chart */
+ repository?: Maybe;
+ /** a helm values file to use with this service, requires auth and so is heavy to query */
+ values?: Maybe;
+ /** a list of relative paths to values files to use for helm applies */
+ valuesFiles?: Maybe>>;
+ /** the chart version in use currently */
+ version?: Maybe;
+};
+
export type HttpIngressRule = {
__typename?: 'HttpIngressRule';
paths?: Maybe>>;
@@ -1709,6 +1782,12 @@ export enum NotificationStatus {
Resolved = 'RESOLVED'
}
+export type ObjectReference = {
+ __typename?: 'ObjectReference';
+ name?: Maybe;
+ namespace?: Maybe;
+};
+
export type OverlayUpdate = {
__typename?: 'OverlayUpdate';
path?: Maybe>>;
@@ -2167,7 +2246,9 @@ export type Resources = {
export type Revision = {
__typename?: 'Revision';
/** git spec of the prior revision */
- git: GitRef;
+ git?: Maybe;
+ /** description of how helm charts should be applied */
+ helm?: Maybe;
/** id of this revision */
id: Scalars['ID']['output'];
insertedAt?: Maybe;
@@ -2306,6 +2387,7 @@ export type RootMutationType = {
rollbackService?: Maybe;
/** upserts a pipeline with a given name */
savePipeline?: Maybe;
+ selfManage?: Maybe;
signIn?: Maybe;
signup?: Maybe;
updateCluster?: Maybe;
@@ -2630,6 +2712,11 @@ export type RootMutationTypeSavePipelineArgs = {
};
+export type RootMutationTypeSelfManageArgs = {
+ values: Scalars['String']['input'];
+};
+
+
export type RootMutationTypeSignInArgs = {
email: Scalars['String']['input'];
password: Scalars['String']['input'];
@@ -2768,6 +2855,8 @@ export type RootQueryType = {
gitRepository?: Maybe;
groupMembers?: Maybe;
groups?: Maybe;
+ helmRepositories?: Maybe>>;
+ helmRepository?: Maybe;
ingress?: Maybe;
installations?: Maybe;
invite?: Maybe;
@@ -2986,6 +3075,12 @@ export type RootQueryTypeGroupsArgs = {
};
+export type RootQueryTypeHelmRepositoryArgs = {
+ name: Scalars['String']['input'];
+ namespace: Scalars['String']['input'];
+};
+
+
export type RootQueryTypeIngressArgs = {
name: Scalars['String']['input'];
namespace: Scalars['String']['input'];
@@ -3496,9 +3591,12 @@ export type ServiceDeployment = {
/** a list of errors generated by the deployment operator */
errors?: Maybe>>;
/** description on where in git the service's manifests should be fetched */
- git: GitRef;
+ git?: Maybe;
/** the global service this service is the source for */
globalService?: Maybe;
+ /** description of how helm charts should be applied */
+ helm?: Maybe;
+ helmRepository?: Maybe;
/** internal id of this service */
id: Scalars['ID']['output'];
insertedAt?: Maybe;
@@ -3549,7 +3647,8 @@ export type ServiceDeploymentRevisionsArgs = {
export type ServiceDeploymentAttributes = {
configuration?: InputMaybe>>;
docsPath?: InputMaybe;
- git: GitRefAttributes;
+ git?: InputMaybe;
+ helm?: InputMaybe;
kustomize?: InputMaybe;
name: Scalars['String']['input'];
namespace: Scalars['String']['input'];
@@ -3623,6 +3722,7 @@ export type ServiceStatusCount = {
export type ServiceUpdateAttributes = {
configuration?: InputMaybe>>;
git?: InputMaybe;
+ helm?: InputMaybe;
kustomize?: InputMaybe;
protect?: InputMaybe;
version?: InputMaybe;
@@ -4026,7 +4126,7 @@ export type InstallAddOnMutationVariables = Exact<{
}>;
-export type InstallAddOnMutation = { __typename?: 'RootMutationType', installAddOn?: { __typename?: 'ServiceDeployment', id: string, name: string, protect?: boolean | null, message?: string | null, insertedAt?: string | null, updatedAt?: string | null, deletedAt?: string | null, componentStatus?: string | null, status: ServiceDeploymentStatus, git: { __typename?: 'GitRef', ref: string, folder: string }, cluster?: { __typename?: 'Cluster', id: string, name: string, provider?: { __typename?: 'ClusterProvider', name: string, cloud: string } | null } | null, repository?: { __typename?: 'GitRepository', id: string, url: string } | null, errors?: Array<{ __typename?: 'ServiceError', message: string, source: string } | null> | null, components?: Array<{ __typename?: 'ServiceComponent', apiDeprecations?: Array<{ __typename?: 'ApiDeprecation', blocking?: boolean | null } | null> | null } | null> | null, globalService?: { __typename?: 'GlobalService', id: string, name: string } | null } | null };
+export type InstallAddOnMutation = { __typename?: 'RootMutationType', installAddOn?: { __typename?: 'ServiceDeployment', id: string, name: string, protect?: boolean | null, message?: string | null, insertedAt?: string | null, updatedAt?: string | null, deletedAt?: string | null, componentStatus?: string | null, status: ServiceDeploymentStatus, git?: { __typename?: 'GitRef', ref: string, folder: string } | null, helm?: { __typename?: 'HelmSpec', chart?: string | null, version?: string | null, repository?: { __typename?: 'ObjectReference', namespace?: string | null, name?: string | null } | null } | null, cluster?: { __typename?: 'Cluster', id: string, name: string, provider?: { __typename?: 'ClusterProvider', name: string, cloud: string } | null } | null, helmRepository?: { __typename?: 'HelmRepository', spec: { __typename?: 'HelmRepositorySpec', url: string }, status?: { __typename?: 'HelmRepositoryStatus', ready?: boolean | null, message?: string | null } | null } | null, repository?: { __typename?: 'GitRepository', id: string, url: string } | null, errors?: Array<{ __typename?: 'ServiceError', message: string, source: string } | null> | null, components?: Array<{ __typename?: 'ServiceComponent', apiDeprecations?: Array<{ __typename?: 'ApiDeprecation', blocking?: boolean | null } | null> | null } | null> | null, globalService?: { __typename?: 'GlobalService', id: string, name: string } | null } | null };
export type ClusterNodeFragment = { __typename?: 'Node', metadata: { __typename?: 'Metadata', name: string, namespace?: string | null, labels?: Array<{ __typename?: 'LabelPair', name?: string | null, value?: string | null } | null> | null, annotations?: Array<{ __typename?: 'LabelPair', name?: string | null, value?: string | null } | null> | null }, status: { __typename?: 'NodeStatus', phase?: string | null, allocatable?: Record | null, capacity?: Record | null, conditions?: Array<{ __typename?: 'NodeCondition', type?: string | null, status?: string | null, message?: string | null } | null> | null }, spec: { __typename?: 'NodeSpec', podCidr?: string | null, providerId?: string | null } };
@@ -4036,20 +4136,20 @@ export type TaintFragment = { __typename?: 'Taint', effect: string, key: string,
export type NodePoolFragment = { __typename?: 'NodePool', id: string, name: string, minSize: number, maxSize: number, instanceType: string, spot?: boolean | null, labels?: Record | null, taints?: Array<{ __typename?: 'Taint', effect: string, key: string, value: string } | null> | null };
-export type ApiDeprecationFragment = { __typename?: 'ApiDeprecation', availableIn?: string | null, blocking?: boolean | null, deprecatedIn?: string | null, removedIn?: string | null, replacement?: string | null, component?: { __typename?: 'ServiceComponent', group?: string | null, version?: string | null, kind: string, name: string, namespace?: string | null, service?: { __typename?: 'ServiceDeployment', git: { __typename?: 'GitRef', ref: string, folder: string }, repository?: { __typename?: 'GitRepository', httpsPath?: string | null, urlFormat?: string | null } | null } | null } | null };
+export type ApiDeprecationFragment = { __typename?: 'ApiDeprecation', availableIn?: string | null, blocking?: boolean | null, deprecatedIn?: string | null, removedIn?: string | null, replacement?: string | null, component?: { __typename?: 'ServiceComponent', group?: string | null, version?: string | null, kind: string, name: string, namespace?: string | null, service?: { __typename?: 'ServiceDeployment', git?: { __typename?: 'GitRef', ref: string, folder: string } | null, repository?: { __typename?: 'GitRepository', httpsPath?: string | null, urlFormat?: string | null } | null } | null } | null };
export type RuntimeServiceFragment = { __typename?: 'RuntimeService', id: string, name: string, version: string, addon?: { __typename?: 'RuntimeAddon', icon?: string | null, versions?: Array<{ __typename?: 'AddonVersion', version?: string | null, kube?: Array | null, incompatibilities?: Array<{ __typename?: 'VersionReference', version: string, name: string } | null> | null, requirements?: Array<{ __typename?: 'VersionReference', version: string, name: string } | null> | null } | null> | null } | null };
export type AddonVersionFragment = { __typename?: 'AddonVersion', version?: string | null, kube?: Array | null, incompatibilities?: Array<{ __typename?: 'VersionReference', version: string, name: string } | null> | null, requirements?: Array<{ __typename?: 'VersionReference', version: string, name: string } | null> | null };
-export type ClustersRowFragment = { __typename?: 'Cluster', currentVersion?: string | null, id: string, self?: boolean | null, protect?: boolean | null, name: string, handle?: string | null, installed?: boolean | null, pingedAt?: string | null, deletedAt?: string | null, version?: string | null, apiDeprecations?: Array<{ __typename?: 'ApiDeprecation', availableIn?: string | null, blocking?: boolean | null, deprecatedIn?: string | null, removedIn?: string | null, replacement?: string | null, component?: { __typename?: 'ServiceComponent', group?: string | null, version?: string | null, kind: string, name: string, namespace?: string | null, service?: { __typename?: 'ServiceDeployment', git: { __typename?: 'GitRef', ref: string, folder: string }, repository?: { __typename?: 'GitRepository', httpsPath?: string | null, urlFormat?: string | null } | null } | null } | null } | null> | null, nodes?: Array<{ __typename?: 'Node', status: { __typename?: 'NodeStatus', capacity?: Record | null } } | null> | null, nodeMetrics?: Array<{ __typename?: 'NodeMetric', usage?: { __typename?: 'NodeUsage', cpu?: string | null, memory?: string | null } | null } | null> | null, provider?: { __typename?: 'ClusterProvider', id: string, cloud: string, name: string, namespace: string, supportedVersions?: Array | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, repository?: { __typename?: 'GitRepository', url: string } | null } | null, status?: { __typename?: 'ClusterStatus', conditions?: Array<{ __typename?: 'ClusterCondition', lastTransitionTime?: string | null, message?: string | null, reason?: string | null, severity?: string | null, status?: string | null, type?: string | null } | null> | null } | null };
+export type ClustersRowFragment = { __typename?: 'Cluster', currentVersion?: string | null, id: string, self?: boolean | null, protect?: boolean | null, name: string, handle?: string | null, installed?: boolean | null, pingedAt?: string | null, deletedAt?: string | null, version?: string | null, apiDeprecations?: Array<{ __typename?: 'ApiDeprecation', availableIn?: string | null, blocking?: boolean | null, deprecatedIn?: string | null, removedIn?: string | null, replacement?: string | null, component?: { __typename?: 'ServiceComponent', group?: string | null, version?: string | null, kind: string, name: string, namespace?: string | null, service?: { __typename?: 'ServiceDeployment', git?: { __typename?: 'GitRef', ref: string, folder: string } | null, repository?: { __typename?: 'GitRepository', httpsPath?: string | null, urlFormat?: string | null } | null } | null } | null } | null> | null, nodes?: Array<{ __typename?: 'Node', status: { __typename?: 'NodeStatus', capacity?: Record | null } } | null> | null, nodeMetrics?: Array<{ __typename?: 'NodeMetric', usage?: { __typename?: 'NodeUsage', cpu?: string | null, memory?: string | null } | null } | null> | null, provider?: { __typename?: 'ClusterProvider', id: string, cloud: string, name: string, namespace: string, supportedVersions?: Array | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, repository?: { __typename?: 'GitRepository', url: string } | null } | null, status?: { __typename?: 'ClusterStatus', conditions?: Array<{ __typename?: 'ClusterCondition', lastTransitionTime?: string | null, message?: string | null, reason?: string | null, severity?: string | null, status?: string | null, type?: string | null } | null> | null } | null };
-export type ClusterFragment = { __typename?: 'Cluster', currentVersion?: string | null, id: string, name: string, handle?: string | null, pingedAt?: string | null, self?: boolean | null, version?: string | null, apiDeprecations?: Array<{ __typename?: 'ApiDeprecation', availableIn?: string | null, blocking?: boolean | null, deprecatedIn?: string | null, removedIn?: string | null, replacement?: string | null, component?: { __typename?: 'ServiceComponent', group?: string | null, version?: string | null, kind: string, name: string, namespace?: string | null, service?: { __typename?: 'ServiceDeployment', git: { __typename?: 'GitRef', ref: string, folder: string }, repository?: { __typename?: 'GitRepository', httpsPath?: string | null, urlFormat?: string | null } | null } | null } | null } | null> | null, nodePools?: Array<{ __typename?: 'NodePool', id: string, name: string, minSize: number, maxSize: number, instanceType: string, spot?: boolean | null, labels?: Record | null, taints?: Array<{ __typename?: 'Taint', effect: string, key: string, value: string } | null> | null } | null> | null, nodes?: Array<{ __typename?: 'Node', metadata: { __typename?: 'Metadata', name: string, namespace?: string | null, labels?: Array<{ __typename?: 'LabelPair', name?: string | null, value?: string | null } | null> | null, annotations?: Array<{ __typename?: 'LabelPair', name?: string | null, value?: string | null } | null> | null }, status: { __typename?: 'NodeStatus', phase?: string | null, allocatable?: Record | null, capacity?: Record | null, conditions?: Array<{ __typename?: 'NodeCondition', type?: string | null, status?: string | null, message?: string | null } | null> | null }, spec: { __typename?: 'NodeSpec', podCidr?: string | null, providerId?: string | null } } | null> | null, nodeMetrics?: Array<{ __typename?: 'NodeMetric', timestamp?: string | null, window?: string | null, metadata: { __typename?: 'Metadata', name: string, namespace?: string | null, labels?: Array<{ __typename?: 'LabelPair', name?: string | null, value?: string | null } | null> | null, annotations?: Array<{ __typename?: 'LabelPair', name?: string | null, value?: string | null } | null> | null }, usage?: { __typename?: 'NodeUsage', cpu?: string | null, memory?: string | null } | null } | null> | null, provider?: { __typename?: 'ClusterProvider', id: string, cloud: string, name: string, namespace: string, supportedVersions?: Array | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, repository?: { __typename?: 'GitRepository', url: string } | null } | null, status?: { __typename?: 'ClusterStatus', controlPlaneReady?: boolean | null, failureMessage?: string | null, failureReason?: string | null, phase?: string | null, conditions?: Array<{ __typename?: 'ClusterCondition', lastTransitionTime?: string | null, message?: string | null, reason?: string | null, severity?: string | null, status?: string | null, type?: string | null } | null> | null } | null, tags?: Array<{ __typename?: 'Tag', name: string, value: string } | null> | null };
+export type ClusterFragment = { __typename?: 'Cluster', currentVersion?: string | null, id: string, name: string, handle?: string | null, pingedAt?: string | null, self?: boolean | null, version?: string | null, apiDeprecations?: Array<{ __typename?: 'ApiDeprecation', availableIn?: string | null, blocking?: boolean | null, deprecatedIn?: string | null, removedIn?: string | null, replacement?: string | null, component?: { __typename?: 'ServiceComponent', group?: string | null, version?: string | null, kind: string, name: string, namespace?: string | null, service?: { __typename?: 'ServiceDeployment', git?: { __typename?: 'GitRef', ref: string, folder: string } | null, repository?: { __typename?: 'GitRepository', httpsPath?: string | null, urlFormat?: string | null } | null } | null } | null } | null> | null, nodePools?: Array<{ __typename?: 'NodePool', id: string, name: string, minSize: number, maxSize: number, instanceType: string, spot?: boolean | null, labels?: Record | null, taints?: Array<{ __typename?: 'Taint', effect: string, key: string, value: string } | null> | null } | null> | null, nodes?: Array<{ __typename?: 'Node', metadata: { __typename?: 'Metadata', name: string, namespace?: string | null, labels?: Array<{ __typename?: 'LabelPair', name?: string | null, value?: string | null } | null> | null, annotations?: Array<{ __typename?: 'LabelPair', name?: string | null, value?: string | null } | null> | null }, status: { __typename?: 'NodeStatus', phase?: string | null, allocatable?: Record | null, capacity?: Record | null, conditions?: Array<{ __typename?: 'NodeCondition', type?: string | null, status?: string | null, message?: string | null } | null> | null }, spec: { __typename?: 'NodeSpec', podCidr?: string | null, providerId?: string | null } } | null> | null, nodeMetrics?: Array<{ __typename?: 'NodeMetric', timestamp?: string | null, window?: string | null, metadata: { __typename?: 'Metadata', name: string, namespace?: string | null, labels?: Array<{ __typename?: 'LabelPair', name?: string | null, value?: string | null } | null> | null, annotations?: Array<{ __typename?: 'LabelPair', name?: string | null, value?: string | null } | null> | null }, usage?: { __typename?: 'NodeUsage', cpu?: string | null, memory?: string | null } | null } | null> | null, provider?: { __typename?: 'ClusterProvider', id: string, cloud: string, name: string, namespace: string, supportedVersions?: Array | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, repository?: { __typename?: 'GitRepository', url: string } | null } | null, status?: { __typename?: 'ClusterStatus', controlPlaneReady?: boolean | null, failureMessage?: string | null, failureReason?: string | null, phase?: string | null, conditions?: Array<{ __typename?: 'ClusterCondition', lastTransitionTime?: string | null, message?: string | null, reason?: string | null, severity?: string | null, status?: string | null, type?: string | null } | null> | null } | null, tags?: Array<{ __typename?: 'Tag', name: string, value: string } | null> | null };
export type ClustersQueryVariables = Exact<{ [key: string]: never; }>;
-export type ClustersQuery = { __typename?: 'RootQueryType', clusters?: { __typename?: 'ClusterConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, endCursor?: string | null }, edges?: Array<{ __typename?: 'ClusterEdge', node?: { __typename?: 'Cluster', currentVersion?: string | null, id: string, self?: boolean | null, protect?: boolean | null, name: string, handle?: string | null, installed?: boolean | null, pingedAt?: string | null, deletedAt?: string | null, version?: string | null, apiDeprecations?: Array<{ __typename?: 'ApiDeprecation', availableIn?: string | null, blocking?: boolean | null, deprecatedIn?: string | null, removedIn?: string | null, replacement?: string | null, component?: { __typename?: 'ServiceComponent', group?: string | null, version?: string | null, kind: string, name: string, namespace?: string | null, service?: { __typename?: 'ServiceDeployment', git: { __typename?: 'GitRef', ref: string, folder: string }, repository?: { __typename?: 'GitRepository', httpsPath?: string | null, urlFormat?: string | null } | null } | null } | null } | null> | null, nodes?: Array<{ __typename?: 'Node', status: { __typename?: 'NodeStatus', capacity?: Record | null } } | null> | null, nodeMetrics?: Array<{ __typename?: 'NodeMetric', usage?: { __typename?: 'NodeUsage', cpu?: string | null, memory?: string | null } | null } | null> | null, provider?: { __typename?: 'ClusterProvider', id: string, cloud: string, name: string, namespace: string, supportedVersions?: Array | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, repository?: { __typename?: 'GitRepository', url: string } | null } | null, status?: { __typename?: 'ClusterStatus', conditions?: Array<{ __typename?: 'ClusterCondition', lastTransitionTime?: string | null, message?: string | null, reason?: string | null, severity?: string | null, status?: string | null, type?: string | null } | null> | null } | null } | null } | null> | null } | null };
+export type ClustersQuery = { __typename?: 'RootQueryType', clusters?: { __typename?: 'ClusterConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, endCursor?: string | null }, edges?: Array<{ __typename?: 'ClusterEdge', node?: { __typename?: 'Cluster', currentVersion?: string | null, id: string, self?: boolean | null, protect?: boolean | null, name: string, handle?: string | null, installed?: boolean | null, pingedAt?: string | null, deletedAt?: string | null, version?: string | null, apiDeprecations?: Array<{ __typename?: 'ApiDeprecation', availableIn?: string | null, blocking?: boolean | null, deprecatedIn?: string | null, removedIn?: string | null, replacement?: string | null, component?: { __typename?: 'ServiceComponent', group?: string | null, version?: string | null, kind: string, name: string, namespace?: string | null, service?: { __typename?: 'ServiceDeployment', git?: { __typename?: 'GitRef', ref: string, folder: string } | null, repository?: { __typename?: 'GitRepository', httpsPath?: string | null, urlFormat?: string | null } | null } | null } | null } | null> | null, nodes?: Array<{ __typename?: 'Node', status: { __typename?: 'NodeStatus', capacity?: Record | null } } | null> | null, nodeMetrics?: Array<{ __typename?: 'NodeMetric', usage?: { __typename?: 'NodeUsage', cpu?: string | null, memory?: string | null } | null } | null> | null, provider?: { __typename?: 'ClusterProvider', id: string, cloud: string, name: string, namespace: string, supportedVersions?: Array | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, repository?: { __typename?: 'GitRepository', url: string } | null } | null, status?: { __typename?: 'ClusterStatus', conditions?: Array<{ __typename?: 'ClusterCondition', lastTransitionTime?: string | null, message?: string | null, reason?: string | null, severity?: string | null, status?: string | null, type?: string | null } | null> | null } | null } | null } | null> | null } | null };
export type ClusterTinyFragment = { __typename?: 'Cluster', id: string, name: string, provider?: { __typename?: 'ClusterProvider', cloud: string } | null };
@@ -4063,7 +4163,7 @@ export type ClusterQueryVariables = Exact<{
}>;
-export type ClusterQuery = { __typename?: 'RootQueryType', cluster?: { __typename?: 'Cluster', currentVersion?: string | null, id: string, name: string, handle?: string | null, pingedAt?: string | null, self?: boolean | null, version?: string | null, apiDeprecations?: Array<{ __typename?: 'ApiDeprecation', availableIn?: string | null, blocking?: boolean | null, deprecatedIn?: string | null, removedIn?: string | null, replacement?: string | null, component?: { __typename?: 'ServiceComponent', group?: string | null, version?: string | null, kind: string, name: string, namespace?: string | null, service?: { __typename?: 'ServiceDeployment', git: { __typename?: 'GitRef', ref: string, folder: string }, repository?: { __typename?: 'GitRepository', httpsPath?: string | null, urlFormat?: string | null } | null } | null } | null } | null> | null, nodePools?: Array<{ __typename?: 'NodePool', id: string, name: string, minSize: number, maxSize: number, instanceType: string, spot?: boolean | null, labels?: Record | null, taints?: Array<{ __typename?: 'Taint', effect: string, key: string, value: string } | null> | null } | null> | null, nodes?: Array<{ __typename?: 'Node', metadata: { __typename?: 'Metadata', name: string, namespace?: string | null, labels?: Array<{ __typename?: 'LabelPair', name?: string | null, value?: string | null } | null> | null, annotations?: Array<{ __typename?: 'LabelPair', name?: string | null, value?: string | null } | null> | null }, status: { __typename?: 'NodeStatus', phase?: string | null, allocatable?: Record | null, capacity?: Record | null, conditions?: Array<{ __typename?: 'NodeCondition', type?: string | null, status?: string | null, message?: string | null } | null> | null }, spec: { __typename?: 'NodeSpec', podCidr?: string | null, providerId?: string | null } } | null> | null, nodeMetrics?: Array<{ __typename?: 'NodeMetric', timestamp?: string | null, window?: string | null, metadata: { __typename?: 'Metadata', name: string, namespace?: string | null, labels?: Array<{ __typename?: 'LabelPair', name?: string | null, value?: string | null } | null> | null, annotations?: Array<{ __typename?: 'LabelPair', name?: string | null, value?: string | null } | null> | null }, usage?: { __typename?: 'NodeUsage', cpu?: string | null, memory?: string | null } | null } | null> | null, provider?: { __typename?: 'ClusterProvider', id: string, cloud: string, name: string, namespace: string, supportedVersions?: Array | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, repository?: { __typename?: 'GitRepository', url: string } | null } | null, status?: { __typename?: 'ClusterStatus', controlPlaneReady?: boolean | null, failureMessage?: string | null, failureReason?: string | null, phase?: string | null, conditions?: Array<{ __typename?: 'ClusterCondition', lastTransitionTime?: string | null, message?: string | null, reason?: string | null, severity?: string | null, status?: string | null, type?: string | null } | null> | null } | null, tags?: Array<{ __typename?: 'Tag', name: string, value: string } | null> | null } | null };
+export type ClusterQuery = { __typename?: 'RootQueryType', cluster?: { __typename?: 'Cluster', currentVersion?: string | null, id: string, name: string, handle?: string | null, pingedAt?: string | null, self?: boolean | null, version?: string | null, apiDeprecations?: Array<{ __typename?: 'ApiDeprecation', availableIn?: string | null, blocking?: boolean | null, deprecatedIn?: string | null, removedIn?: string | null, replacement?: string | null, component?: { __typename?: 'ServiceComponent', group?: string | null, version?: string | null, kind: string, name: string, namespace?: string | null, service?: { __typename?: 'ServiceDeployment', git?: { __typename?: 'GitRef', ref: string, folder: string } | null, repository?: { __typename?: 'GitRepository', httpsPath?: string | null, urlFormat?: string | null } | null } | null } | null } | null> | null, nodePools?: Array<{ __typename?: 'NodePool', id: string, name: string, minSize: number, maxSize: number, instanceType: string, spot?: boolean | null, labels?: Record | null, taints?: Array<{ __typename?: 'Taint', effect: string, key: string, value: string } | null> | null } | null> | null, nodes?: Array<{ __typename?: 'Node', metadata: { __typename?: 'Metadata', name: string, namespace?: string | null, labels?: Array<{ __typename?: 'LabelPair', name?: string | null, value?: string | null } | null> | null, annotations?: Array<{ __typename?: 'LabelPair', name?: string | null, value?: string | null } | null> | null }, status: { __typename?: 'NodeStatus', phase?: string | null, allocatable?: Record | null, capacity?: Record | null, conditions?: Array<{ __typename?: 'NodeCondition', type?: string | null, status?: string | null, message?: string | null } | null> | null }, spec: { __typename?: 'NodeSpec', podCidr?: string | null, providerId?: string | null } } | null> | null, nodeMetrics?: Array<{ __typename?: 'NodeMetric', timestamp?: string | null, window?: string | null, metadata: { __typename?: 'Metadata', name: string, namespace?: string | null, labels?: Array<{ __typename?: 'LabelPair', name?: string | null, value?: string | null } | null> | null, annotations?: Array<{ __typename?: 'LabelPair', name?: string | null, value?: string | null } | null> | null }, usage?: { __typename?: 'NodeUsage', cpu?: string | null, memory?: string | null } | null } | null> | null, provider?: { __typename?: 'ClusterProvider', id: string, cloud: string, name: string, namespace: string, supportedVersions?: Array | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, repository?: { __typename?: 'GitRepository', url: string } | null } | null, status?: { __typename?: 'ClusterStatus', controlPlaneReady?: boolean | null, failureMessage?: string | null, failureReason?: string | null, phase?: string | null, conditions?: Array<{ __typename?: 'ClusterCondition', lastTransitionTime?: string | null, message?: string | null, reason?: string | null, severity?: string | null, status?: string | null, type?: string | null } | null> | null } | null, tags?: Array<{ __typename?: 'Tag', name: string, value: string } | null> | null } | null };
export type ClusterPodsQueryVariables = Exact<{
clusterId?: InputMaybe;
@@ -4097,7 +4197,7 @@ export type RuntimeServicesQueryVariables = Exact<{
}>;
-export type RuntimeServicesQuery = { __typename?: 'RootQueryType', cluster?: { __typename?: 'Cluster', runtimeServices?: Array<{ __typename?: 'RuntimeService', id: string, name: string, version: string, service?: { __typename?: 'ServiceDeployment', git: { __typename?: 'GitRef', ref: string, folder: string }, repository?: { __typename?: 'GitRepository', httpsPath?: string | null, urlFormat?: string | null } | null } | null, addonVersion?: { __typename?: 'AddonVersion', blocking?: boolean | null, version?: string | null, kube?: Array | null, incompatibilities?: Array<{ __typename?: 'VersionReference', version: string, name: string } | null> | null, requirements?: Array<{ __typename?: 'VersionReference', version: string, name: string } | null> | null } | null, addon?: { __typename?: 'RuntimeAddon', icon?: string | null, versions?: Array<{ __typename?: 'AddonVersion', version?: string | null, kube?: Array | null, incompatibilities?: Array<{ __typename?: 'VersionReference', version: string, name: string } | null> | null, requirements?: Array<{ __typename?: 'VersionReference', version: string, name: string } | null> | null } | null> | null } | null } | null> | null } | null };
+export type RuntimeServicesQuery = { __typename?: 'RootQueryType', cluster?: { __typename?: 'Cluster', runtimeServices?: Array<{ __typename?: 'RuntimeService', id: string, name: string, version: string, service?: { __typename?: 'ServiceDeployment', git?: { __typename?: 'GitRef', ref: string, folder: string } | null, repository?: { __typename?: 'GitRepository', httpsPath?: string | null, urlFormat?: string | null } | null } | null, addonVersion?: { __typename?: 'AddonVersion', blocking?: boolean | null, version?: string | null, kube?: Array | null, incompatibilities?: Array<{ __typename?: 'VersionReference', version: string, name: string } | null> | null, requirements?: Array<{ __typename?: 'VersionReference', version: string, name: string } | null> | null } | null, addon?: { __typename?: 'RuntimeAddon', icon?: string | null, versions?: Array<{ __typename?: 'AddonVersion', version?: string | null, kube?: Array | null, incompatibilities?: Array<{ __typename?: 'VersionReference', version: string, name: string } | null> | null, requirements?: Array<{ __typename?: 'VersionReference', version: string, name: string } | null> | null } | null> | null } | null } | null> | null } | null };
export type UpdateClusterBindingsMutationVariables = Exact<{
id: Scalars['ID']['input'];
@@ -4113,21 +4213,21 @@ export type UpdateClusterMutationVariables = Exact<{
}>;
-export type UpdateClusterMutation = { __typename?: 'RootMutationType', updateCluster?: { __typename?: 'Cluster', currentVersion?: string | null, id: string, self?: boolean | null, protect?: boolean | null, name: string, handle?: string | null, installed?: boolean | null, pingedAt?: string | null, deletedAt?: string | null, version?: string | null, apiDeprecations?: Array<{ __typename?: 'ApiDeprecation', availableIn?: string | null, blocking?: boolean | null, deprecatedIn?: string | null, removedIn?: string | null, replacement?: string | null, component?: { __typename?: 'ServiceComponent', group?: string | null, version?: string | null, kind: string, name: string, namespace?: string | null, service?: { __typename?: 'ServiceDeployment', git: { __typename?: 'GitRef', ref: string, folder: string }, repository?: { __typename?: 'GitRepository', httpsPath?: string | null, urlFormat?: string | null } | null } | null } | null } | null> | null, nodes?: Array<{ __typename?: 'Node', status: { __typename?: 'NodeStatus', capacity?: Record | null } } | null> | null, nodeMetrics?: Array<{ __typename?: 'NodeMetric', usage?: { __typename?: 'NodeUsage', cpu?: string | null, memory?: string | null } | null } | null> | null, provider?: { __typename?: 'ClusterProvider', id: string, cloud: string, name: string, namespace: string, supportedVersions?: Array | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, repository?: { __typename?: 'GitRepository', url: string } | null } | null, status?: { __typename?: 'ClusterStatus', conditions?: Array<{ __typename?: 'ClusterCondition', lastTransitionTime?: string | null, message?: string | null, reason?: string | null, severity?: string | null, status?: string | null, type?: string | null } | null> | null } | null } | null };
+export type UpdateClusterMutation = { __typename?: 'RootMutationType', updateCluster?: { __typename?: 'Cluster', currentVersion?: string | null, id: string, self?: boolean | null, protect?: boolean | null, name: string, handle?: string | null, installed?: boolean | null, pingedAt?: string | null, deletedAt?: string | null, version?: string | null, apiDeprecations?: Array<{ __typename?: 'ApiDeprecation', availableIn?: string | null, blocking?: boolean | null, deprecatedIn?: string | null, removedIn?: string | null, replacement?: string | null, component?: { __typename?: 'ServiceComponent', group?: string | null, version?: string | null, kind: string, name: string, namespace?: string | null, service?: { __typename?: 'ServiceDeployment', git?: { __typename?: 'GitRef', ref: string, folder: string } | null, repository?: { __typename?: 'GitRepository', httpsPath?: string | null, urlFormat?: string | null } | null } | null } | null } | null> | null, nodes?: Array<{ __typename?: 'Node', status: { __typename?: 'NodeStatus', capacity?: Record | null } } | null> | null, nodeMetrics?: Array<{ __typename?: 'NodeMetric', usage?: { __typename?: 'NodeUsage', cpu?: string | null, memory?: string | null } | null } | null> | null, provider?: { __typename?: 'ClusterProvider', id: string, cloud: string, name: string, namespace: string, supportedVersions?: Array | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, repository?: { __typename?: 'GitRepository', url: string } | null } | null, status?: { __typename?: 'ClusterStatus', conditions?: Array<{ __typename?: 'ClusterCondition', lastTransitionTime?: string | null, message?: string | null, reason?: string | null, severity?: string | null, status?: string | null, type?: string | null } | null> | null } | null } | null };
export type CreateClusterMutationVariables = Exact<{
attributes: ClusterAttributes;
}>;
-export type CreateClusterMutation = { __typename?: 'RootMutationType', createCluster?: { __typename?: 'Cluster', deployToken?: string | null, currentVersion?: string | null, id: string, name: string, handle?: string | null, pingedAt?: string | null, self?: boolean | null, version?: string | null, apiDeprecations?: Array<{ __typename?: 'ApiDeprecation', availableIn?: string | null, blocking?: boolean | null, deprecatedIn?: string | null, removedIn?: string | null, replacement?: string | null, component?: { __typename?: 'ServiceComponent', group?: string | null, version?: string | null, kind: string, name: string, namespace?: string | null, service?: { __typename?: 'ServiceDeployment', git: { __typename?: 'GitRef', ref: string, folder: string }, repository?: { __typename?: 'GitRepository', httpsPath?: string | null, urlFormat?: string | null } | null } | null } | null } | null> | null, nodePools?: Array<{ __typename?: 'NodePool', id: string, name: string, minSize: number, maxSize: number, instanceType: string, spot?: boolean | null, labels?: Record | null, taints?: Array<{ __typename?: 'Taint', effect: string, key: string, value: string } | null> | null } | null> | null, nodes?: Array<{ __typename?: 'Node', metadata: { __typename?: 'Metadata', name: string, namespace?: string | null, labels?: Array<{ __typename?: 'LabelPair', name?: string | null, value?: string | null } | null> | null, annotations?: Array<{ __typename?: 'LabelPair', name?: string | null, value?: string | null } | null> | null }, status: { __typename?: 'NodeStatus', phase?: string | null, allocatable?: Record | null, capacity?: Record | null, conditions?: Array<{ __typename?: 'NodeCondition', type?: string | null, status?: string | null, message?: string | null } | null> | null }, spec: { __typename?: 'NodeSpec', podCidr?: string | null, providerId?: string | null } } | null> | null, nodeMetrics?: Array<{ __typename?: 'NodeMetric', timestamp?: string | null, window?: string | null, metadata: { __typename?: 'Metadata', name: string, namespace?: string | null, labels?: Array<{ __typename?: 'LabelPair', name?: string | null, value?: string | null } | null> | null, annotations?: Array<{ __typename?: 'LabelPair', name?: string | null, value?: string | null } | null> | null }, usage?: { __typename?: 'NodeUsage', cpu?: string | null, memory?: string | null } | null } | null> | null, provider?: { __typename?: 'ClusterProvider', id: string, cloud: string, name: string, namespace: string, supportedVersions?: Array | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, repository?: { __typename?: 'GitRepository', url: string } | null } | null, status?: { __typename?: 'ClusterStatus', controlPlaneReady?: boolean | null, failureMessage?: string | null, failureReason?: string | null, phase?: string | null, conditions?: Array<{ __typename?: 'ClusterCondition', lastTransitionTime?: string | null, message?: string | null, reason?: string | null, severity?: string | null, status?: string | null, type?: string | null } | null> | null } | null, tags?: Array<{ __typename?: 'Tag', name: string, value: string } | null> | null } | null };
+export type CreateClusterMutation = { __typename?: 'RootMutationType', createCluster?: { __typename?: 'Cluster', deployToken?: string | null, currentVersion?: string | null, id: string, name: string, handle?: string | null, pingedAt?: string | null, self?: boolean | null, version?: string | null, apiDeprecations?: Array<{ __typename?: 'ApiDeprecation', availableIn?: string | null, blocking?: boolean | null, deprecatedIn?: string | null, removedIn?: string | null, replacement?: string | null, component?: { __typename?: 'ServiceComponent', group?: string | null, version?: string | null, kind: string, name: string, namespace?: string | null, service?: { __typename?: 'ServiceDeployment', git?: { __typename?: 'GitRef', ref: string, folder: string } | null, repository?: { __typename?: 'GitRepository', httpsPath?: string | null, urlFormat?: string | null } | null } | null } | null } | null> | null, nodePools?: Array<{ __typename?: 'NodePool', id: string, name: string, minSize: number, maxSize: number, instanceType: string, spot?: boolean | null, labels?: Record | null, taints?: Array<{ __typename?: 'Taint', effect: string, key: string, value: string } | null> | null } | null> | null, nodes?: Array<{ __typename?: 'Node', metadata: { __typename?: 'Metadata', name: string, namespace?: string | null, labels?: Array<{ __typename?: 'LabelPair', name?: string | null, value?: string | null } | null> | null, annotations?: Array<{ __typename?: 'LabelPair', name?: string | null, value?: string | null } | null> | null }, status: { __typename?: 'NodeStatus', phase?: string | null, allocatable?: Record | null, capacity?: Record | null, conditions?: Array<{ __typename?: 'NodeCondition', type?: string | null, status?: string | null, message?: string | null } | null> | null }, spec: { __typename?: 'NodeSpec', podCidr?: string | null, providerId?: string | null } } | null> | null, nodeMetrics?: Array<{ __typename?: 'NodeMetric', timestamp?: string | null, window?: string | null, metadata: { __typename?: 'Metadata', name: string, namespace?: string | null, labels?: Array<{ __typename?: 'LabelPair', name?: string | null, value?: string | null } | null> | null, annotations?: Array<{ __typename?: 'LabelPair', name?: string | null, value?: string | null } | null> | null }, usage?: { __typename?: 'NodeUsage', cpu?: string | null, memory?: string | null } | null } | null> | null, provider?: { __typename?: 'ClusterProvider', id: string, cloud: string, name: string, namespace: string, supportedVersions?: Array | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, repository?: { __typename?: 'GitRepository', url: string } | null } | null, status?: { __typename?: 'ClusterStatus', controlPlaneReady?: boolean | null, failureMessage?: string | null, failureReason?: string | null, phase?: string | null, conditions?: Array<{ __typename?: 'ClusterCondition', lastTransitionTime?: string | null, message?: string | null, reason?: string | null, severity?: string | null, status?: string | null, type?: string | null } | null> | null } | null, tags?: Array<{ __typename?: 'Tag', name: string, value: string } | null> | null } | null };
export type DeleteClusterMutationVariables = Exact<{
id: Scalars['ID']['input'];
}>;
-export type DeleteClusterMutation = { __typename?: 'RootMutationType', deleteCluster?: { __typename?: 'Cluster', currentVersion?: string | null, id: string, name: string, handle?: string | null, pingedAt?: string | null, self?: boolean | null, version?: string | null, apiDeprecations?: Array<{ __typename?: 'ApiDeprecation', availableIn?: string | null, blocking?: boolean | null, deprecatedIn?: string | null, removedIn?: string | null, replacement?: string | null, component?: { __typename?: 'ServiceComponent', group?: string | null, version?: string | null, kind: string, name: string, namespace?: string | null, service?: { __typename?: 'ServiceDeployment', git: { __typename?: 'GitRef', ref: string, folder: string }, repository?: { __typename?: 'GitRepository', httpsPath?: string | null, urlFormat?: string | null } | null } | null } | null } | null> | null, nodePools?: Array<{ __typename?: 'NodePool', id: string, name: string, minSize: number, maxSize: number, instanceType: string, spot?: boolean | null, labels?: Record | null, taints?: Array<{ __typename?: 'Taint', effect: string, key: string, value: string } | null> | null } | null> | null, nodes?: Array<{ __typename?: 'Node', metadata: { __typename?: 'Metadata', name: string, namespace?: string | null, labels?: Array<{ __typename?: 'LabelPair', name?: string | null, value?: string | null } | null> | null, annotations?: Array<{ __typename?: 'LabelPair', name?: string | null, value?: string | null } | null> | null }, status: { __typename?: 'NodeStatus', phase?: string | null, allocatable?: Record | null, capacity?: Record | null, conditions?: Array<{ __typename?: 'NodeCondition', type?: string | null, status?: string | null, message?: string | null } | null> | null }, spec: { __typename?: 'NodeSpec', podCidr?: string | null, providerId?: string | null } } | null> | null, nodeMetrics?: Array<{ __typename?: 'NodeMetric', timestamp?: string | null, window?: string | null, metadata: { __typename?: 'Metadata', name: string, namespace?: string | null, labels?: Array<{ __typename?: 'LabelPair', name?: string | null, value?: string | null } | null> | null, annotations?: Array<{ __typename?: 'LabelPair', name?: string | null, value?: string | null } | null> | null }, usage?: { __typename?: 'NodeUsage', cpu?: string | null, memory?: string | null } | null } | null> | null, provider?: { __typename?: 'ClusterProvider', id: string, cloud: string, name: string, namespace: string, supportedVersions?: Array | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, repository?: { __typename?: 'GitRepository', url: string } | null } | null, status?: { __typename?: 'ClusterStatus', controlPlaneReady?: boolean | null, failureMessage?: string | null, failureReason?: string | null, phase?: string | null, conditions?: Array<{ __typename?: 'ClusterCondition', lastTransitionTime?: string | null, message?: string | null, reason?: string | null, severity?: string | null, status?: string | null, type?: string | null } | null> | null } | null, tags?: Array<{ __typename?: 'Tag', name: string, value: string } | null> | null } | null };
+export type DeleteClusterMutation = { __typename?: 'RootMutationType', deleteCluster?: { __typename?: 'Cluster', currentVersion?: string | null, id: string, name: string, handle?: string | null, pingedAt?: string | null, self?: boolean | null, version?: string | null, apiDeprecations?: Array<{ __typename?: 'ApiDeprecation', availableIn?: string | null, blocking?: boolean | null, deprecatedIn?: string | null, removedIn?: string | null, replacement?: string | null, component?: { __typename?: 'ServiceComponent', group?: string | null, version?: string | null, kind: string, name: string, namespace?: string | null, service?: { __typename?: 'ServiceDeployment', git?: { __typename?: 'GitRef', ref: string, folder: string } | null, repository?: { __typename?: 'GitRepository', httpsPath?: string | null, urlFormat?: string | null } | null } | null } | null } | null> | null, nodePools?: Array<{ __typename?: 'NodePool', id: string, name: string, minSize: number, maxSize: number, instanceType: string, spot?: boolean | null, labels?: Record | null, taints?: Array<{ __typename?: 'Taint', effect: string, key: string, value: string } | null> | null } | null> | null, nodes?: Array<{ __typename?: 'Node', metadata: { __typename?: 'Metadata', name: string, namespace?: string | null, labels?: Array<{ __typename?: 'LabelPair', name?: string | null, value?: string | null } | null> | null, annotations?: Array<{ __typename?: 'LabelPair', name?: string | null, value?: string | null } | null> | null }, status: { __typename?: 'NodeStatus', phase?: string | null, allocatable?: Record | null, capacity?: Record | null, conditions?: Array<{ __typename?: 'NodeCondition', type?: string | null, status?: string | null, message?: string | null } | null> | null }, spec: { __typename?: 'NodeSpec', podCidr?: string | null, providerId?: string | null } } | null> | null, nodeMetrics?: Array<{ __typename?: 'NodeMetric', timestamp?: string | null, window?: string | null, metadata: { __typename?: 'Metadata', name: string, namespace?: string | null, labels?: Array<{ __typename?: 'LabelPair', name?: string | null, value?: string | null } | null> | null, annotations?: Array<{ __typename?: 'LabelPair', name?: string | null, value?: string | null } | null> | null }, usage?: { __typename?: 'NodeUsage', cpu?: string | null, memory?: string | null } | null } | null> | null, provider?: { __typename?: 'ClusterProvider', id: string, cloud: string, name: string, namespace: string, supportedVersions?: Array | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, repository?: { __typename?: 'GitRepository', url: string } | null } | null, status?: { __typename?: 'ClusterStatus', controlPlaneReady?: boolean | null, failureMessage?: string | null, failureReason?: string | null, phase?: string | null, conditions?: Array<{ __typename?: 'ClusterCondition', lastTransitionTime?: string | null, message?: string | null, reason?: string | null, severity?: string | null, status?: string | null, type?: string | null } | null> | null } | null, tags?: Array<{ __typename?: 'Tag', name: string, value: string } | null> | null } | null };
export type MetricResponseFragment = { __typename?: 'MetricResponse', metric?: Record | null, values?: Array<{ __typename?: 'MetricResult', timestamp?: any | null, value?: string | null } | null> | null };
@@ -4145,11 +4245,28 @@ export type UsageQuery = { __typename?: 'RootQueryType', cpu?: Array<{ __typenam
export type GitRepositoryFragment = { __typename?: 'GitRepository', id: string, url: string, health?: GitHealth | null, authMethod?: AuthMethod | null, editable?: boolean | null, error?: string | null, insertedAt?: string | null, pulledAt?: string | null, updatedAt?: string | null, urlFormat?: string | null, httpsPath?: string | null };
+export type HelmRepositoryFragment = { __typename?: 'HelmRepository', metadata: { __typename?: 'Metadata', namespace?: string | null, name: string }, spec: { __typename?: 'HelmRepositorySpec', url: string, type?: string | null, provider?: string | null }, status?: { __typename?: 'HelmRepositoryStatus', ready?: boolean | null, message?: string | null } | null };
+
+export type HelmChartVersionFragment = { __typename?: 'HelmChartVersion', name?: string | null, appVersion?: string | null, version?: string | null, digest?: string | null };
+
export type GitRepositoriesQueryVariables = Exact<{ [key: string]: never; }>;
export type GitRepositoriesQuery = { __typename?: 'RootQueryType', gitRepositories?: { __typename?: 'GitRepositoryConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, endCursor?: string | null }, edges?: Array<{ __typename?: 'GitRepositoryEdge', node?: { __typename?: 'GitRepository', id: string, url: string, health?: GitHealth | null, authMethod?: AuthMethod | null, editable?: boolean | null, error?: string | null, insertedAt?: string | null, pulledAt?: string | null, updatedAt?: string | null, urlFormat?: string | null, httpsPath?: string | null } | null } | null> | null } | null };
+export type HelmRepositoriesQueryVariables = Exact<{ [key: string]: never; }>;
+
+
+export type HelmRepositoriesQuery = { __typename?: 'RootQueryType', helmRepositories?: Array<{ __typename?: 'HelmRepository', metadata: { __typename?: 'Metadata', namespace?: string | null, name: string }, spec: { __typename?: 'HelmRepositorySpec', url: string, type?: string | null, provider?: string | null }, status?: { __typename?: 'HelmRepositoryStatus', ready?: boolean | null, message?: string | null } | null } | null> | null };
+
+export type HelmRepositoryQueryVariables = Exact<{
+ namespace: Scalars['String']['input'];
+ name: Scalars['String']['input'];
+}>;
+
+
+export type HelmRepositoryQuery = { __typename?: 'RootQueryType', helmRepository?: { __typename?: 'HelmRepository', charts?: Array<{ __typename?: 'HelmChartEntry', name?: string | null, versions?: Array<{ __typename?: 'HelmChartVersion', name?: string | null, appVersion?: string | null, version?: string | null, digest?: string | null } | null> | null } | null> | null, metadata: { __typename?: 'Metadata', namespace?: string | null, name: string }, spec: { __typename?: 'HelmRepositorySpec', url: string, type?: string | null, provider?: string | null }, status?: { __typename?: 'HelmRepositoryStatus', ready?: boolean | null, message?: string | null } | null } | null };
+
export type CreateGitRepositoryMutationVariables = Exact<{
attributes: GitAttributes;
}>;
@@ -4191,39 +4308,39 @@ export type DeleteGlobalServiceMutationVariables = Exact<{
export type DeleteGlobalServiceMutation = { __typename?: 'RootMutationType', deleteGlobalService?: { __typename?: 'GlobalService', id: string } | null };
-export type DeploymentSettingsFragment = { __typename?: 'DeploymentSettings', id: string, name: string, enabled: boolean, insertedAt?: string | null, updatedAt?: string | null, artifactRepository?: { __typename?: 'GitRepository', id: string, url: string, health?: GitHealth | null, authMethod?: AuthMethod | null, editable?: boolean | null, error?: string | null, insertedAt?: string | null, pulledAt?: string | null, updatedAt?: string | null, urlFormat?: string | null, httpsPath?: string | null } | null, deployerRepository?: { __typename?: 'GitRepository', id: string, url: string, health?: GitHealth | null, authMethod?: AuthMethod | null, editable?: boolean | null, error?: string | null, insertedAt?: string | null, pulledAt?: string | null, updatedAt?: string | null, urlFormat?: string | null, httpsPath?: string | null } | null, createBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, readBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, writeBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, gitBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null };
+export type DeploymentSettingsFragment = { __typename?: 'DeploymentSettings', id: string, name: string, enabled: boolean, selfManaged?: boolean | null, insertedAt?: string | null, updatedAt?: string | null, artifactRepository?: { __typename?: 'GitRepository', id: string, url: string, health?: GitHealth | null, authMethod?: AuthMethod | null, editable?: boolean | null, error?: string | null, insertedAt?: string | null, pulledAt?: string | null, updatedAt?: string | null, urlFormat?: string | null, httpsPath?: string | null } | null, deployerRepository?: { __typename?: 'GitRepository', id: string, url: string, health?: GitHealth | null, authMethod?: AuthMethod | null, editable?: boolean | null, error?: string | null, insertedAt?: string | null, pulledAt?: string | null, updatedAt?: string | null, urlFormat?: string | null, httpsPath?: string | null } | null, createBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, readBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, writeBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, gitBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null };
export type UpdateDeploymentSettingsMutationVariables = Exact<{
attributes: DeploymentSettingsAttributes;
}>;
-export type UpdateDeploymentSettingsMutation = { __typename?: 'RootMutationType', updateDeploymentSettings?: { __typename?: 'DeploymentSettings', id: string, name: string, enabled: boolean, insertedAt?: string | null, updatedAt?: string | null, artifactRepository?: { __typename?: 'GitRepository', id: string, url: string, health?: GitHealth | null, authMethod?: AuthMethod | null, editable?: boolean | null, error?: string | null, insertedAt?: string | null, pulledAt?: string | null, updatedAt?: string | null, urlFormat?: string | null, httpsPath?: string | null } | null, deployerRepository?: { __typename?: 'GitRepository', id: string, url: string, health?: GitHealth | null, authMethod?: AuthMethod | null, editable?: boolean | null, error?: string | null, insertedAt?: string | null, pulledAt?: string | null, updatedAt?: string | null, urlFormat?: string | null, httpsPath?: string | null } | null, createBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, readBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, writeBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, gitBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null } | null };
+export type UpdateDeploymentSettingsMutation = { __typename?: 'RootMutationType', updateDeploymentSettings?: { __typename?: 'DeploymentSettings', id: string, name: string, enabled: boolean, selfManaged?: boolean | null, insertedAt?: string | null, updatedAt?: string | null, artifactRepository?: { __typename?: 'GitRepository', id: string, url: string, health?: GitHealth | null, authMethod?: AuthMethod | null, editable?: boolean | null, error?: string | null, insertedAt?: string | null, pulledAt?: string | null, updatedAt?: string | null, urlFormat?: string | null, httpsPath?: string | null } | null, deployerRepository?: { __typename?: 'GitRepository', id: string, url: string, health?: GitHealth | null, authMethod?: AuthMethod | null, editable?: boolean | null, error?: string | null, insertedAt?: string | null, pulledAt?: string | null, updatedAt?: string | null, urlFormat?: string | null, httpsPath?: string | null } | null, createBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, readBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, writeBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, gitBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null } | null };
export type DeploymentSettingsQueryVariables = Exact<{ [key: string]: never; }>;
-export type DeploymentSettingsQuery = { __typename?: 'RootQueryType', deploymentSettings?: { __typename?: 'DeploymentSettings', id: string, name: string, enabled: boolean, insertedAt?: string | null, updatedAt?: string | null, artifactRepository?: { __typename?: 'GitRepository', id: string, url: string, health?: GitHealth | null, authMethod?: AuthMethod | null, editable?: boolean | null, error?: string | null, insertedAt?: string | null, pulledAt?: string | null, updatedAt?: string | null, urlFormat?: string | null, httpsPath?: string | null } | null, deployerRepository?: { __typename?: 'GitRepository', id: string, url: string, health?: GitHealth | null, authMethod?: AuthMethod | null, editable?: boolean | null, error?: string | null, insertedAt?: string | null, pulledAt?: string | null, updatedAt?: string | null, urlFormat?: string | null, httpsPath?: string | null } | null, createBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, readBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, writeBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, gitBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null } | null };
+export type DeploymentSettingsQuery = { __typename?: 'RootQueryType', deploymentSettings?: { __typename?: 'DeploymentSettings', id: string, name: string, enabled: boolean, selfManaged?: boolean | null, insertedAt?: string | null, updatedAt?: string | null, artifactRepository?: { __typename?: 'GitRepository', id: string, url: string, health?: GitHealth | null, authMethod?: AuthMethod | null, editable?: boolean | null, error?: string | null, insertedAt?: string | null, pulledAt?: string | null, updatedAt?: string | null, urlFormat?: string | null, httpsPath?: string | null } | null, deployerRepository?: { __typename?: 'GitRepository', id: string, url: string, health?: GitHealth | null, authMethod?: AuthMethod | null, editable?: boolean | null, error?: string | null, insertedAt?: string | null, pulledAt?: string | null, updatedAt?: string | null, urlFormat?: string | null, httpsPath?: string | null } | null, createBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, readBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, writeBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, gitBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null } | null };
export type PipelineServiceDeploymentFragment = { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null };
export type PipelineGateFragment = { __typename?: 'PipelineGate', id: string, name: string, state: GateState, type: GateType, insertedAt?: string | null, updatedAt?: string | null, approver?: { __typename?: 'User', id: string, pluralId?: string | null, name: string, email: string, profile?: string | null, backgroundColor?: string | null, readTimestamp?: string | null, roles?: { __typename?: 'UserRoles', admin?: boolean | null } | null } | null };
-export type RevisionFragment = { __typename?: 'Revision', id: string, insertedAt?: string | null, updatedAt?: string | null, message?: string | null, sha?: string | null, version: string, git: { __typename?: 'GitRef', ref: string, folder: string } };
+export type RevisionFragment = { __typename?: 'Revision', id: string, insertedAt?: string | null, updatedAt?: string | null, message?: string | null, sha?: string | null, version: string, git?: { __typename?: 'GitRef', ref: string, folder: string } | null };
-export type PromotionServiceFragment = { __typename?: 'PromotionService', id: string, insertedAt?: string | null, updatedAt?: string | null, revision?: { __typename?: 'Revision', id: string, insertedAt?: string | null, updatedAt?: string | null, message?: string | null, sha?: string | null, version: string, git: { __typename?: 'GitRef', ref: string, folder: string } } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null };
+export type PromotionServiceFragment = { __typename?: 'PromotionService', id: string, insertedAt?: string | null, updatedAt?: string | null, revision?: { __typename?: 'Revision', id: string, insertedAt?: string | null, updatedAt?: string | null, message?: string | null, sha?: string | null, version: string, git?: { __typename?: 'GitRef', ref: string, folder: string } | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null };
-export type PipelinePromotionFragment = { __typename?: 'PipelinePromotion', id: string, insertedAt?: string | null, updatedAt?: string | null, promotedAt?: string | null, revisedAt?: string | null, services?: Array<{ __typename?: 'PromotionService', id: string, insertedAt?: string | null, updatedAt?: string | null, revision?: { __typename?: 'Revision', id: string, insertedAt?: string | null, updatedAt?: string | null, message?: string | null, sha?: string | null, version: string, git: { __typename?: 'GitRef', ref: string, folder: string } } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null };
+export type PipelinePromotionFragment = { __typename?: 'PipelinePromotion', id: string, insertedAt?: string | null, updatedAt?: string | null, promotedAt?: string | null, revisedAt?: string | null, services?: Array<{ __typename?: 'PromotionService', id: string, insertedAt?: string | null, updatedAt?: string | null, revision?: { __typename?: 'Revision', id: string, insertedAt?: string | null, updatedAt?: string | null, message?: string | null, sha?: string | null, version: string, git?: { __typename?: 'GitRef', ref: string, folder: string } | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null };
export type PromotionCriteriaFragment = { __typename?: 'PromotionCriteria', id: string, secrets?: Array | null, insertedAt?: string | null, updatedAt?: string | null, source?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null };
export type StageServiceFragment = { __typename?: 'StageService', id: string, insertedAt?: string | null, updatedAt?: string | null, criteria?: { __typename?: 'PromotionCriteria', id: string, secrets?: Array | null, insertedAt?: string | null, updatedAt?: string | null, source?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null };
-export type PipelineStageFragment = { __typename?: 'PipelineStage', id: string, name: string, insertedAt?: string | null, updatedAt?: string | null, promotion?: { __typename?: 'PipelinePromotion', id: string, insertedAt?: string | null, updatedAt?: string | null, promotedAt?: string | null, revisedAt?: string | null, services?: Array<{ __typename?: 'PromotionService', id: string, insertedAt?: string | null, updatedAt?: string | null, revision?: { __typename?: 'Revision', id: string, insertedAt?: string | null, updatedAt?: string | null, message?: string | null, sha?: string | null, version: string, git: { __typename?: 'GitRef', ref: string, folder: string } } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null } | null, services?: Array<{ __typename?: 'StageService', id: string, insertedAt?: string | null, updatedAt?: string | null, criteria?: { __typename?: 'PromotionCriteria', id: string, secrets?: Array | null, insertedAt?: string | null, updatedAt?: string | null, source?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null };
+export type PipelineStageFragment = { __typename?: 'PipelineStage', id: string, name: string, insertedAt?: string | null, updatedAt?: string | null, promotion?: { __typename?: 'PipelinePromotion', id: string, insertedAt?: string | null, updatedAt?: string | null, promotedAt?: string | null, revisedAt?: string | null, services?: Array<{ __typename?: 'PromotionService', id: string, insertedAt?: string | null, updatedAt?: string | null, revision?: { __typename?: 'Revision', id: string, insertedAt?: string | null, updatedAt?: string | null, message?: string | null, sha?: string | null, version: string, git?: { __typename?: 'GitRef', ref: string, folder: string } | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null } | null, services?: Array<{ __typename?: 'StageService', id: string, insertedAt?: string | null, updatedAt?: string | null, criteria?: { __typename?: 'PromotionCriteria', id: string, secrets?: Array | null, insertedAt?: string | null, updatedAt?: string | null, source?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null };
-export type PipelineStageEdgeFragment = { __typename?: 'PipelineStageEdge', id: string, insertedAt?: string | null, promotedAt?: string | null, updatedAt?: string | null, gates?: Array<{ __typename?: 'PipelineGate', id: string, name: string, state: GateState, type: GateType, insertedAt?: string | null, updatedAt?: string | null, approver?: { __typename?: 'User', id: string, pluralId?: string | null, name: string, email: string, profile?: string | null, backgroundColor?: string | null, readTimestamp?: string | null, roles?: { __typename?: 'UserRoles', admin?: boolean | null } | null } | null } | null> | null, from: { __typename?: 'PipelineStage', id: string, name: string, insertedAt?: string | null, updatedAt?: string | null, promotion?: { __typename?: 'PipelinePromotion', id: string, insertedAt?: string | null, updatedAt?: string | null, promotedAt?: string | null, revisedAt?: string | null, services?: Array<{ __typename?: 'PromotionService', id: string, insertedAt?: string | null, updatedAt?: string | null, revision?: { __typename?: 'Revision', id: string, insertedAt?: string | null, updatedAt?: string | null, message?: string | null, sha?: string | null, version: string, git: { __typename?: 'GitRef', ref: string, folder: string } } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null } | null, services?: Array<{ __typename?: 'StageService', id: string, insertedAt?: string | null, updatedAt?: string | null, criteria?: { __typename?: 'PromotionCriteria', id: string, secrets?: Array | null, insertedAt?: string | null, updatedAt?: string | null, source?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null }, to: { __typename?: 'PipelineStage', id: string, name: string, insertedAt?: string | null, updatedAt?: string | null, promotion?: { __typename?: 'PipelinePromotion', id: string, insertedAt?: string | null, updatedAt?: string | null, promotedAt?: string | null, revisedAt?: string | null, services?: Array<{ __typename?: 'PromotionService', id: string, insertedAt?: string | null, updatedAt?: string | null, revision?: { __typename?: 'Revision', id: string, insertedAt?: string | null, updatedAt?: string | null, message?: string | null, sha?: string | null, version: string, git: { __typename?: 'GitRef', ref: string, folder: string } } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null } | null, services?: Array<{ __typename?: 'StageService', id: string, insertedAt?: string | null, updatedAt?: string | null, criteria?: { __typename?: 'PromotionCriteria', id: string, secrets?: Array | null, insertedAt?: string | null, updatedAt?: string | null, source?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null } };
+export type PipelineStageEdgeFragment = { __typename?: 'PipelineStageEdge', id: string, insertedAt?: string | null, promotedAt?: string | null, updatedAt?: string | null, gates?: Array<{ __typename?: 'PipelineGate', id: string, name: string, state: GateState, type: GateType, insertedAt?: string | null, updatedAt?: string | null, approver?: { __typename?: 'User', id: string, pluralId?: string | null, name: string, email: string, profile?: string | null, backgroundColor?: string | null, readTimestamp?: string | null, roles?: { __typename?: 'UserRoles', admin?: boolean | null } | null } | null } | null> | null, from: { __typename?: 'PipelineStage', id: string, name: string, insertedAt?: string | null, updatedAt?: string | null, promotion?: { __typename?: 'PipelinePromotion', id: string, insertedAt?: string | null, updatedAt?: string | null, promotedAt?: string | null, revisedAt?: string | null, services?: Array<{ __typename?: 'PromotionService', id: string, insertedAt?: string | null, updatedAt?: string | null, revision?: { __typename?: 'Revision', id: string, insertedAt?: string | null, updatedAt?: string | null, message?: string | null, sha?: string | null, version: string, git?: { __typename?: 'GitRef', ref: string, folder: string } | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null } | null, services?: Array<{ __typename?: 'StageService', id: string, insertedAt?: string | null, updatedAt?: string | null, criteria?: { __typename?: 'PromotionCriteria', id: string, secrets?: Array | null, insertedAt?: string | null, updatedAt?: string | null, source?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null }, to: { __typename?: 'PipelineStage', id: string, name: string, insertedAt?: string | null, updatedAt?: string | null, promotion?: { __typename?: 'PipelinePromotion', id: string, insertedAt?: string | null, updatedAt?: string | null, promotedAt?: string | null, revisedAt?: string | null, services?: Array<{ __typename?: 'PromotionService', id: string, insertedAt?: string | null, updatedAt?: string | null, revision?: { __typename?: 'Revision', id: string, insertedAt?: string | null, updatedAt?: string | null, message?: string | null, sha?: string | null, version: string, git?: { __typename?: 'GitRef', ref: string, folder: string } | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null } | null, services?: Array<{ __typename?: 'StageService', id: string, insertedAt?: string | null, updatedAt?: string | null, criteria?: { __typename?: 'PromotionCriteria', id: string, secrets?: Array | null, insertedAt?: string | null, updatedAt?: string | null, source?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null } };
-export type PipelineFragment = { __typename?: 'Pipeline', id: string, name: string, insertedAt?: string | null, updatedAt?: string | null, edges?: Array<{ __typename?: 'PipelineStageEdge', id: string, insertedAt?: string | null, promotedAt?: string | null, updatedAt?: string | null, gates?: Array<{ __typename?: 'PipelineGate', id: string, name: string, state: GateState, type: GateType, insertedAt?: string | null, updatedAt?: string | null, approver?: { __typename?: 'User', id: string, pluralId?: string | null, name: string, email: string, profile?: string | null, backgroundColor?: string | null, readTimestamp?: string | null, roles?: { __typename?: 'UserRoles', admin?: boolean | null } | null } | null } | null> | null, from: { __typename?: 'PipelineStage', id: string, name: string, insertedAt?: string | null, updatedAt?: string | null, promotion?: { __typename?: 'PipelinePromotion', id: string, insertedAt?: string | null, updatedAt?: string | null, promotedAt?: string | null, revisedAt?: string | null, services?: Array<{ __typename?: 'PromotionService', id: string, insertedAt?: string | null, updatedAt?: string | null, revision?: { __typename?: 'Revision', id: string, insertedAt?: string | null, updatedAt?: string | null, message?: string | null, sha?: string | null, version: string, git: { __typename?: 'GitRef', ref: string, folder: string } } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null } | null, services?: Array<{ __typename?: 'StageService', id: string, insertedAt?: string | null, updatedAt?: string | null, criteria?: { __typename?: 'PromotionCriteria', id: string, secrets?: Array | null, insertedAt?: string | null, updatedAt?: string | null, source?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null }, to: { __typename?: 'PipelineStage', id: string, name: string, insertedAt?: string | null, updatedAt?: string | null, promotion?: { __typename?: 'PipelinePromotion', id: string, insertedAt?: string | null, updatedAt?: string | null, promotedAt?: string | null, revisedAt?: string | null, services?: Array<{ __typename?: 'PromotionService', id: string, insertedAt?: string | null, updatedAt?: string | null, revision?: { __typename?: 'Revision', id: string, insertedAt?: string | null, updatedAt?: string | null, message?: string | null, sha?: string | null, version: string, git: { __typename?: 'GitRef', ref: string, folder: string } } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null } | null, services?: Array<{ __typename?: 'StageService', id: string, insertedAt?: string | null, updatedAt?: string | null, criteria?: { __typename?: 'PromotionCriteria', id: string, secrets?: Array | null, insertedAt?: string | null, updatedAt?: string | null, source?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null } } | null> | null, stages?: Array<{ __typename?: 'PipelineStage', id: string, name: string, insertedAt?: string | null, updatedAt?: string | null, promotion?: { __typename?: 'PipelinePromotion', id: string, insertedAt?: string | null, updatedAt?: string | null, promotedAt?: string | null, revisedAt?: string | null, services?: Array<{ __typename?: 'PromotionService', id: string, insertedAt?: string | null, updatedAt?: string | null, revision?: { __typename?: 'Revision', id: string, insertedAt?: string | null, updatedAt?: string | null, message?: string | null, sha?: string | null, version: string, git: { __typename?: 'GitRef', ref: string, folder: string } } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null } | null, services?: Array<{ __typename?: 'StageService', id: string, insertedAt?: string | null, updatedAt?: string | null, criteria?: { __typename?: 'PromotionCriteria', id: string, secrets?: Array | null, insertedAt?: string | null, updatedAt?: string | null, source?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null } | null> | null };
+export type PipelineFragment = { __typename?: 'Pipeline', id: string, name: string, insertedAt?: string | null, updatedAt?: string | null, edges?: Array<{ __typename?: 'PipelineStageEdge', id: string, insertedAt?: string | null, promotedAt?: string | null, updatedAt?: string | null, gates?: Array<{ __typename?: 'PipelineGate', id: string, name: string, state: GateState, type: GateType, insertedAt?: string | null, updatedAt?: string | null, approver?: { __typename?: 'User', id: string, pluralId?: string | null, name: string, email: string, profile?: string | null, backgroundColor?: string | null, readTimestamp?: string | null, roles?: { __typename?: 'UserRoles', admin?: boolean | null } | null } | null } | null> | null, from: { __typename?: 'PipelineStage', id: string, name: string, insertedAt?: string | null, updatedAt?: string | null, promotion?: { __typename?: 'PipelinePromotion', id: string, insertedAt?: string | null, updatedAt?: string | null, promotedAt?: string | null, revisedAt?: string | null, services?: Array<{ __typename?: 'PromotionService', id: string, insertedAt?: string | null, updatedAt?: string | null, revision?: { __typename?: 'Revision', id: string, insertedAt?: string | null, updatedAt?: string | null, message?: string | null, sha?: string | null, version: string, git?: { __typename?: 'GitRef', ref: string, folder: string } | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null } | null, services?: Array<{ __typename?: 'StageService', id: string, insertedAt?: string | null, updatedAt?: string | null, criteria?: { __typename?: 'PromotionCriteria', id: string, secrets?: Array | null, insertedAt?: string | null, updatedAt?: string | null, source?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null }, to: { __typename?: 'PipelineStage', id: string, name: string, insertedAt?: string | null, updatedAt?: string | null, promotion?: { __typename?: 'PipelinePromotion', id: string, insertedAt?: string | null, updatedAt?: string | null, promotedAt?: string | null, revisedAt?: string | null, services?: Array<{ __typename?: 'PromotionService', id: string, insertedAt?: string | null, updatedAt?: string | null, revision?: { __typename?: 'Revision', id: string, insertedAt?: string | null, updatedAt?: string | null, message?: string | null, sha?: string | null, version: string, git?: { __typename?: 'GitRef', ref: string, folder: string } | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null } | null, services?: Array<{ __typename?: 'StageService', id: string, insertedAt?: string | null, updatedAt?: string | null, criteria?: { __typename?: 'PromotionCriteria', id: string, secrets?: Array | null, insertedAt?: string | null, updatedAt?: string | null, source?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null } } | null> | null, stages?: Array<{ __typename?: 'PipelineStage', id: string, name: string, insertedAt?: string | null, updatedAt?: string | null, promotion?: { __typename?: 'PipelinePromotion', id: string, insertedAt?: string | null, updatedAt?: string | null, promotedAt?: string | null, revisedAt?: string | null, services?: Array<{ __typename?: 'PromotionService', id: string, insertedAt?: string | null, updatedAt?: string | null, revision?: { __typename?: 'Revision', id: string, insertedAt?: string | null, updatedAt?: string | null, message?: string | null, sha?: string | null, version: string, git?: { __typename?: 'GitRef', ref: string, folder: string } | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null } | null, services?: Array<{ __typename?: 'StageService', id: string, insertedAt?: string | null, updatedAt?: string | null, criteria?: { __typename?: 'PromotionCriteria', id: string, secrets?: Array | null, insertedAt?: string | null, updatedAt?: string | null, source?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null } | null> | null };
export type PipelinesQueryVariables = Exact<{
first?: InputMaybe;
@@ -4231,14 +4348,14 @@ export type PipelinesQueryVariables = Exact<{
}>;
-export type PipelinesQuery = { __typename?: 'RootQueryType', pipelines?: { __typename?: 'PipelineConnection', edges?: Array<{ __typename?: 'PipelineEdge', cursor?: string | null, node?: { __typename?: 'Pipeline', id: string, name: string, insertedAt?: string | null, updatedAt?: string | null, edges?: Array<{ __typename?: 'PipelineStageEdge', id: string, insertedAt?: string | null, promotedAt?: string | null, updatedAt?: string | null, gates?: Array<{ __typename?: 'PipelineGate', id: string, name: string, state: GateState, type: GateType, insertedAt?: string | null, updatedAt?: string | null, approver?: { __typename?: 'User', id: string, pluralId?: string | null, name: string, email: string, profile?: string | null, backgroundColor?: string | null, readTimestamp?: string | null, roles?: { __typename?: 'UserRoles', admin?: boolean | null } | null } | null } | null> | null, from: { __typename?: 'PipelineStage', id: string, name: string, insertedAt?: string | null, updatedAt?: string | null, promotion?: { __typename?: 'PipelinePromotion', id: string, insertedAt?: string | null, updatedAt?: string | null, promotedAt?: string | null, revisedAt?: string | null, services?: Array<{ __typename?: 'PromotionService', id: string, insertedAt?: string | null, updatedAt?: string | null, revision?: { __typename?: 'Revision', id: string, insertedAt?: string | null, updatedAt?: string | null, message?: string | null, sha?: string | null, version: string, git: { __typename?: 'GitRef', ref: string, folder: string } } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null } | null, services?: Array<{ __typename?: 'StageService', id: string, insertedAt?: string | null, updatedAt?: string | null, criteria?: { __typename?: 'PromotionCriteria', id: string, secrets?: Array | null, insertedAt?: string | null, updatedAt?: string | null, source?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null }, to: { __typename?: 'PipelineStage', id: string, name: string, insertedAt?: string | null, updatedAt?: string | null, promotion?: { __typename?: 'PipelinePromotion', id: string, insertedAt?: string | null, updatedAt?: string | null, promotedAt?: string | null, revisedAt?: string | null, services?: Array<{ __typename?: 'PromotionService', id: string, insertedAt?: string | null, updatedAt?: string | null, revision?: { __typename?: 'Revision', id: string, insertedAt?: string | null, updatedAt?: string | null, message?: string | null, sha?: string | null, version: string, git: { __typename?: 'GitRef', ref: string, folder: string } } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null } | null, services?: Array<{ __typename?: 'StageService', id: string, insertedAt?: string | null, updatedAt?: string | null, criteria?: { __typename?: 'PromotionCriteria', id: string, secrets?: Array | null, insertedAt?: string | null, updatedAt?: string | null, source?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null } } | null> | null, stages?: Array<{ __typename?: 'PipelineStage', id: string, name: string, insertedAt?: string | null, updatedAt?: string | null, promotion?: { __typename?: 'PipelinePromotion', id: string, insertedAt?: string | null, updatedAt?: string | null, promotedAt?: string | null, revisedAt?: string | null, services?: Array<{ __typename?: 'PromotionService', id: string, insertedAt?: string | null, updatedAt?: string | null, revision?: { __typename?: 'Revision', id: string, insertedAt?: string | null, updatedAt?: string | null, message?: string | null, sha?: string | null, version: string, git: { __typename?: 'GitRef', ref: string, folder: string } } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null } | null, services?: Array<{ __typename?: 'StageService', id: string, insertedAt?: string | null, updatedAt?: string | null, criteria?: { __typename?: 'PromotionCriteria', id: string, secrets?: Array | null, insertedAt?: string | null, updatedAt?: string | null, source?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null } | null> | null } | null } | null> | null, pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, endCursor?: string | null } } | null };
+export type PipelinesQuery = { __typename?: 'RootQueryType', pipelines?: { __typename?: 'PipelineConnection', edges?: Array<{ __typename?: 'PipelineEdge', cursor?: string | null, node?: { __typename?: 'Pipeline', id: string, name: string, insertedAt?: string | null, updatedAt?: string | null, edges?: Array<{ __typename?: 'PipelineStageEdge', id: string, insertedAt?: string | null, promotedAt?: string | null, updatedAt?: string | null, gates?: Array<{ __typename?: 'PipelineGate', id: string, name: string, state: GateState, type: GateType, insertedAt?: string | null, updatedAt?: string | null, approver?: { __typename?: 'User', id: string, pluralId?: string | null, name: string, email: string, profile?: string | null, backgroundColor?: string | null, readTimestamp?: string | null, roles?: { __typename?: 'UserRoles', admin?: boolean | null } | null } | null } | null> | null, from: { __typename?: 'PipelineStage', id: string, name: string, insertedAt?: string | null, updatedAt?: string | null, promotion?: { __typename?: 'PipelinePromotion', id: string, insertedAt?: string | null, updatedAt?: string | null, promotedAt?: string | null, revisedAt?: string | null, services?: Array<{ __typename?: 'PromotionService', id: string, insertedAt?: string | null, updatedAt?: string | null, revision?: { __typename?: 'Revision', id: string, insertedAt?: string | null, updatedAt?: string | null, message?: string | null, sha?: string | null, version: string, git?: { __typename?: 'GitRef', ref: string, folder: string } | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null } | null, services?: Array<{ __typename?: 'StageService', id: string, insertedAt?: string | null, updatedAt?: string | null, criteria?: { __typename?: 'PromotionCriteria', id: string, secrets?: Array | null, insertedAt?: string | null, updatedAt?: string | null, source?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null }, to: { __typename?: 'PipelineStage', id: string, name: string, insertedAt?: string | null, updatedAt?: string | null, promotion?: { __typename?: 'PipelinePromotion', id: string, insertedAt?: string | null, updatedAt?: string | null, promotedAt?: string | null, revisedAt?: string | null, services?: Array<{ __typename?: 'PromotionService', id: string, insertedAt?: string | null, updatedAt?: string | null, revision?: { __typename?: 'Revision', id: string, insertedAt?: string | null, updatedAt?: string | null, message?: string | null, sha?: string | null, version: string, git?: { __typename?: 'GitRef', ref: string, folder: string } | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null } | null, services?: Array<{ __typename?: 'StageService', id: string, insertedAt?: string | null, updatedAt?: string | null, criteria?: { __typename?: 'PromotionCriteria', id: string, secrets?: Array | null, insertedAt?: string | null, updatedAt?: string | null, source?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null } } | null> | null, stages?: Array<{ __typename?: 'PipelineStage', id: string, name: string, insertedAt?: string | null, updatedAt?: string | null, promotion?: { __typename?: 'PipelinePromotion', id: string, insertedAt?: string | null, updatedAt?: string | null, promotedAt?: string | null, revisedAt?: string | null, services?: Array<{ __typename?: 'PromotionService', id: string, insertedAt?: string | null, updatedAt?: string | null, revision?: { __typename?: 'Revision', id: string, insertedAt?: string | null, updatedAt?: string | null, message?: string | null, sha?: string | null, version: string, git?: { __typename?: 'GitRef', ref: string, folder: string } | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null } | null, services?: Array<{ __typename?: 'StageService', id: string, insertedAt?: string | null, updatedAt?: string | null, criteria?: { __typename?: 'PromotionCriteria', id: string, secrets?: Array | null, insertedAt?: string | null, updatedAt?: string | null, source?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null } | null> | null } | null } | null> | null, pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, endCursor?: string | null } } | null };
export type PipelineQueryVariables = Exact<{
id: Scalars['ID']['input'];
}>;
-export type PipelineQuery = { __typename?: 'RootQueryType', pipeline?: { __typename?: 'Pipeline', id: string, name: string, insertedAt?: string | null, updatedAt?: string | null, edges?: Array<{ __typename?: 'PipelineStageEdge', id: string, insertedAt?: string | null, promotedAt?: string | null, updatedAt?: string | null, gates?: Array<{ __typename?: 'PipelineGate', id: string, name: string, state: GateState, type: GateType, insertedAt?: string | null, updatedAt?: string | null, approver?: { __typename?: 'User', id: string, pluralId?: string | null, name: string, email: string, profile?: string | null, backgroundColor?: string | null, readTimestamp?: string | null, roles?: { __typename?: 'UserRoles', admin?: boolean | null } | null } | null } | null> | null, from: { __typename?: 'PipelineStage', id: string, name: string, insertedAt?: string | null, updatedAt?: string | null, promotion?: { __typename?: 'PipelinePromotion', id: string, insertedAt?: string | null, updatedAt?: string | null, promotedAt?: string | null, revisedAt?: string | null, services?: Array<{ __typename?: 'PromotionService', id: string, insertedAt?: string | null, updatedAt?: string | null, revision?: { __typename?: 'Revision', id: string, insertedAt?: string | null, updatedAt?: string | null, message?: string | null, sha?: string | null, version: string, git: { __typename?: 'GitRef', ref: string, folder: string } } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null } | null, services?: Array<{ __typename?: 'StageService', id: string, insertedAt?: string | null, updatedAt?: string | null, criteria?: { __typename?: 'PromotionCriteria', id: string, secrets?: Array | null, insertedAt?: string | null, updatedAt?: string | null, source?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null }, to: { __typename?: 'PipelineStage', id: string, name: string, insertedAt?: string | null, updatedAt?: string | null, promotion?: { __typename?: 'PipelinePromotion', id: string, insertedAt?: string | null, updatedAt?: string | null, promotedAt?: string | null, revisedAt?: string | null, services?: Array<{ __typename?: 'PromotionService', id: string, insertedAt?: string | null, updatedAt?: string | null, revision?: { __typename?: 'Revision', id: string, insertedAt?: string | null, updatedAt?: string | null, message?: string | null, sha?: string | null, version: string, git: { __typename?: 'GitRef', ref: string, folder: string } } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null } | null, services?: Array<{ __typename?: 'StageService', id: string, insertedAt?: string | null, updatedAt?: string | null, criteria?: { __typename?: 'PromotionCriteria', id: string, secrets?: Array | null, insertedAt?: string | null, updatedAt?: string | null, source?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null } } | null> | null, stages?: Array<{ __typename?: 'PipelineStage', id: string, name: string, insertedAt?: string | null, updatedAt?: string | null, promotion?: { __typename?: 'PipelinePromotion', id: string, insertedAt?: string | null, updatedAt?: string | null, promotedAt?: string | null, revisedAt?: string | null, services?: Array<{ __typename?: 'PromotionService', id: string, insertedAt?: string | null, updatedAt?: string | null, revision?: { __typename?: 'Revision', id: string, insertedAt?: string | null, updatedAt?: string | null, message?: string | null, sha?: string | null, version: string, git: { __typename?: 'GitRef', ref: string, folder: string } } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null } | null, services?: Array<{ __typename?: 'StageService', id: string, insertedAt?: string | null, updatedAt?: string | null, criteria?: { __typename?: 'PromotionCriteria', id: string, secrets?: Array | null, insertedAt?: string | null, updatedAt?: string | null, source?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null } | null> | null } | null };
+export type PipelineQuery = { __typename?: 'RootQueryType', pipeline?: { __typename?: 'Pipeline', id: string, name: string, insertedAt?: string | null, updatedAt?: string | null, edges?: Array<{ __typename?: 'PipelineStageEdge', id: string, insertedAt?: string | null, promotedAt?: string | null, updatedAt?: string | null, gates?: Array<{ __typename?: 'PipelineGate', id: string, name: string, state: GateState, type: GateType, insertedAt?: string | null, updatedAt?: string | null, approver?: { __typename?: 'User', id: string, pluralId?: string | null, name: string, email: string, profile?: string | null, backgroundColor?: string | null, readTimestamp?: string | null, roles?: { __typename?: 'UserRoles', admin?: boolean | null } | null } | null } | null> | null, from: { __typename?: 'PipelineStage', id: string, name: string, insertedAt?: string | null, updatedAt?: string | null, promotion?: { __typename?: 'PipelinePromotion', id: string, insertedAt?: string | null, updatedAt?: string | null, promotedAt?: string | null, revisedAt?: string | null, services?: Array<{ __typename?: 'PromotionService', id: string, insertedAt?: string | null, updatedAt?: string | null, revision?: { __typename?: 'Revision', id: string, insertedAt?: string | null, updatedAt?: string | null, message?: string | null, sha?: string | null, version: string, git?: { __typename?: 'GitRef', ref: string, folder: string } | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null } | null, services?: Array<{ __typename?: 'StageService', id: string, insertedAt?: string | null, updatedAt?: string | null, criteria?: { __typename?: 'PromotionCriteria', id: string, secrets?: Array | null, insertedAt?: string | null, updatedAt?: string | null, source?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null }, to: { __typename?: 'PipelineStage', id: string, name: string, insertedAt?: string | null, updatedAt?: string | null, promotion?: { __typename?: 'PipelinePromotion', id: string, insertedAt?: string | null, updatedAt?: string | null, promotedAt?: string | null, revisedAt?: string | null, services?: Array<{ __typename?: 'PromotionService', id: string, insertedAt?: string | null, updatedAt?: string | null, revision?: { __typename?: 'Revision', id: string, insertedAt?: string | null, updatedAt?: string | null, message?: string | null, sha?: string | null, version: string, git?: { __typename?: 'GitRef', ref: string, folder: string } | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null } | null, services?: Array<{ __typename?: 'StageService', id: string, insertedAt?: string | null, updatedAt?: string | null, criteria?: { __typename?: 'PromotionCriteria', id: string, secrets?: Array | null, insertedAt?: string | null, updatedAt?: string | null, source?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null } } | null> | null, stages?: Array<{ __typename?: 'PipelineStage', id: string, name: string, insertedAt?: string | null, updatedAt?: string | null, promotion?: { __typename?: 'PipelinePromotion', id: string, insertedAt?: string | null, updatedAt?: string | null, promotedAt?: string | null, revisedAt?: string | null, services?: Array<{ __typename?: 'PromotionService', id: string, insertedAt?: string | null, updatedAt?: string | null, revision?: { __typename?: 'Revision', id: string, insertedAt?: string | null, updatedAt?: string | null, message?: string | null, sha?: string | null, version: string, git?: { __typename?: 'GitRef', ref: string, folder: string } | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null } | null, services?: Array<{ __typename?: 'StageService', id: string, insertedAt?: string | null, updatedAt?: string | null, criteria?: { __typename?: 'PromotionCriteria', id: string, secrets?: Array | null, insertedAt?: string | null, updatedAt?: string | null, source?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, status: ServiceDeploymentStatus, componentStatus?: string | null, cluster?: { __typename?: 'Cluster', id: string, name: string } | null } | null } | null> | null } | null> | null } | null };
export type ApproveGateMutationVariables = Exact<{
id: Scalars['ID']['input'];
@@ -4278,15 +4395,15 @@ export type DeleteClusterProviderMutationVariables = Exact<{
export type DeleteClusterProviderMutation = { __typename?: 'RootMutationType', deleteClusterProvider?: { __typename?: 'ClusterProvider', id: string, name: string, namespace: string, cloud: string, editable?: boolean | null, supportedVersions?: Array | null, deletedAt?: string | null, insertedAt?: string | null, updatedAt?: string | null, git: { __typename?: 'GitRef', folder: string, ref: string }, repository?: { __typename?: 'GitRepository', id: string, url: string } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string } | null, credentials?: Array<{ __typename?: 'ProviderCredential', id: string, insertedAt?: string | null, kind: string, name: string, namespace: string, updatedAt?: string | null } | null> | null } | null };
-export type ServiceDeploymentRevisionFragment = { __typename?: 'Revision', id: string, sha?: string | null, version: string, message?: string | null, updatedAt?: string | null, insertedAt?: string | null, git: { __typename?: 'GitRef', folder: string, ref: string } };
+export type ServiceDeploymentRevisionFragment = { __typename?: 'Revision', id: string, sha?: string | null, version: string, message?: string | null, updatedAt?: string | null, insertedAt?: string | null, helm?: { __typename?: 'HelmSpec', chart?: string | null, version?: string | null } | null, git?: { __typename?: 'GitRef', folder: string, ref: string } | null };
-export type ServiceDeploymentsRowFragment = { __typename?: 'ServiceDeployment', id: string, name: string, protect?: boolean | null, message?: string | null, insertedAt?: string | null, updatedAt?: string | null, deletedAt?: string | null, componentStatus?: string | null, status: ServiceDeploymentStatus, git: { __typename?: 'GitRef', ref: string, folder: string }, cluster?: { __typename?: 'Cluster', id: string, name: string, provider?: { __typename?: 'ClusterProvider', name: string, cloud: string } | null } | null, repository?: { __typename?: 'GitRepository', id: string, url: string } | null, errors?: Array<{ __typename?: 'ServiceError', message: string, source: string } | null> | null, components?: Array<{ __typename?: 'ServiceComponent', apiDeprecations?: Array<{ __typename?: 'ApiDeprecation', blocking?: boolean | null } | null> | null } | null> | null, globalService?: { __typename?: 'GlobalService', id: string, name: string } | null };
+export type ServiceDeploymentsRowFragment = { __typename?: 'ServiceDeployment', id: string, name: string, protect?: boolean | null, message?: string | null, insertedAt?: string | null, updatedAt?: string | null, deletedAt?: string | null, componentStatus?: string | null, status: ServiceDeploymentStatus, git?: { __typename?: 'GitRef', ref: string, folder: string } | null, helm?: { __typename?: 'HelmSpec', chart?: string | null, version?: string | null, repository?: { __typename?: 'ObjectReference', namespace?: string | null, name?: string | null } | null } | null, cluster?: { __typename?: 'Cluster', id: string, name: string, provider?: { __typename?: 'ClusterProvider', name: string, cloud: string } | null } | null, helmRepository?: { __typename?: 'HelmRepository', spec: { __typename?: 'HelmRepositorySpec', url: string }, status?: { __typename?: 'HelmRepositoryStatus', ready?: boolean | null, message?: string | null } | null } | null, repository?: { __typename?: 'GitRepository', id: string, url: string } | null, errors?: Array<{ __typename?: 'ServiceError', message: string, source: string } | null> | null, components?: Array<{ __typename?: 'ServiceComponent', apiDeprecations?: Array<{ __typename?: 'ApiDeprecation', blocking?: boolean | null } | null> | null } | null> | null, globalService?: { __typename?: 'GlobalService', id: string, name: string } | null };
-export type ServiceDeploymentDetailsFragment = { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, componentStatus?: string | null, status: ServiceDeploymentStatus, version: string, cluster?: { __typename?: 'Cluster', id: string, name: string } | null, docs?: Array<{ __typename?: 'GitFile', content: string, path: string } | null> | null, git: { __typename?: 'GitRef', folder: string, ref: string }, components?: Array<{ __typename?: 'ServiceComponent', apiDeprecations?: Array<{ __typename?: 'ApiDeprecation', blocking?: boolean | null } | null> | null } | null> | null };
+export type ServiceDeploymentDetailsFragment = { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, componentStatus?: string | null, status: ServiceDeploymentStatus, version: string, cluster?: { __typename?: 'Cluster', id: string, name: string } | null, helm?: { __typename?: 'HelmSpec', chart?: string | null, version?: string | null, repository?: { __typename?: 'ObjectReference', namespace?: string | null, name?: string | null } | null } | null, docs?: Array<{ __typename?: 'GitFile', content: string, path: string } | null> | null, git?: { __typename?: 'GitRef', folder: string, ref: string } | null, components?: Array<{ __typename?: 'ServiceComponent', apiDeprecations?: Array<{ __typename?: 'ApiDeprecation', blocking?: boolean | null } | null> | null } | null> | null };
-export type ServiceDeploymentComponentFragment = { __typename?: 'ServiceComponent', id: string, name: string, group?: string | null, kind: string, namespace?: string | null, state?: ComponentState | null, synced: boolean, version?: string | null, apiDeprecations?: Array<{ __typename?: 'ApiDeprecation', availableIn?: string | null, blocking?: boolean | null, deprecatedIn?: string | null, removedIn?: string | null, replacement?: string | null, component?: { __typename?: 'ServiceComponent', group?: string | null, version?: string | null, kind: string, name: string, namespace?: string | null, service?: { __typename?: 'ServiceDeployment', git: { __typename?: 'GitRef', ref: string, folder: string }, repository?: { __typename?: 'GitRepository', httpsPath?: string | null, urlFormat?: string | null } | null } | null } | null } | null> | null };
+export type ServiceDeploymentComponentFragment = { __typename?: 'ServiceComponent', id: string, name: string, group?: string | null, kind: string, namespace?: string | null, state?: ComponentState | null, synced: boolean, version?: string | null, apiDeprecations?: Array<{ __typename?: 'ApiDeprecation', availableIn?: string | null, blocking?: boolean | null, deprecatedIn?: string | null, removedIn?: string | null, replacement?: string | null, component?: { __typename?: 'ServiceComponent', group?: string | null, version?: string | null, kind: string, name: string, namespace?: string | null, service?: { __typename?: 'ServiceDeployment', git?: { __typename?: 'GitRef', ref: string, folder: string } | null, repository?: { __typename?: 'GitRepository', httpsPath?: string | null, urlFormat?: string | null } | null } | null } | null } | null> | null };
-export type ServiceDeploymentRevisionsFragment = { __typename?: 'ServiceDeployment', revision?: { __typename?: 'Revision', id: string, sha?: string | null, version: string, message?: string | null, updatedAt?: string | null, insertedAt?: string | null, git: { __typename?: 'GitRef', folder: string, ref: string } } | null, revisions?: { __typename?: 'RevisionConnection', edges?: Array<{ __typename?: 'RevisionEdge', node?: { __typename?: 'Revision', id: string, sha?: string | null, version: string, message?: string | null, updatedAt?: string | null, insertedAt?: string | null, git: { __typename?: 'GitRef', folder: string, ref: string } } | null } | null> | null } | null };
+export type ServiceDeploymentRevisionsFragment = { __typename?: 'ServiceDeployment', revision?: { __typename?: 'Revision', id: string, sha?: string | null, version: string, message?: string | null, updatedAt?: string | null, insertedAt?: string | null, helm?: { __typename?: 'HelmSpec', chart?: string | null, version?: string | null } | null, git?: { __typename?: 'GitRef', folder: string, ref: string } | null } | null, revisions?: { __typename?: 'RevisionConnection', edges?: Array<{ __typename?: 'RevisionEdge', node?: { __typename?: 'Revision', id: string, sha?: string | null, version: string, message?: string | null, updatedAt?: string | null, insertedAt?: string | null, helm?: { __typename?: 'HelmSpec', chart?: string | null, version?: string | null } | null, git?: { __typename?: 'GitRef', folder: string, ref: string } | null } | null } | null> | null } | null };
export type ServiceDeploymentsQueryVariables = Exact<{
first?: InputMaybe;
@@ -4297,7 +4414,7 @@ export type ServiceDeploymentsQueryVariables = Exact<{
}>;
-export type ServiceDeploymentsQuery = { __typename?: 'RootQueryType', serviceDeployments?: { __typename?: 'ServiceDeploymentConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, endCursor?: string | null }, edges?: Array<{ __typename?: 'ServiceDeploymentEdge', node?: { __typename?: 'ServiceDeployment', id: string, name: string, protect?: boolean | null, message?: string | null, insertedAt?: string | null, updatedAt?: string | null, deletedAt?: string | null, componentStatus?: string | null, status: ServiceDeploymentStatus, git: { __typename?: 'GitRef', ref: string, folder: string }, cluster?: { __typename?: 'Cluster', id: string, name: string, provider?: { __typename?: 'ClusterProvider', name: string, cloud: string } | null } | null, repository?: { __typename?: 'GitRepository', id: string, url: string } | null, errors?: Array<{ __typename?: 'ServiceError', message: string, source: string } | null> | null, components?: Array<{ __typename?: 'ServiceComponent', apiDeprecations?: Array<{ __typename?: 'ApiDeprecation', blocking?: boolean | null } | null> | null } | null> | null, globalService?: { __typename?: 'GlobalService', id: string, name: string } | null } | null } | null> | null } | null };
+export type ServiceDeploymentsQuery = { __typename?: 'RootQueryType', serviceDeployments?: { __typename?: 'ServiceDeploymentConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, endCursor?: string | null }, edges?: Array<{ __typename?: 'ServiceDeploymentEdge', node?: { __typename?: 'ServiceDeployment', id: string, name: string, protect?: boolean | null, message?: string | null, insertedAt?: string | null, updatedAt?: string | null, deletedAt?: string | null, componentStatus?: string | null, status: ServiceDeploymentStatus, git?: { __typename?: 'GitRef', ref: string, folder: string } | null, helm?: { __typename?: 'HelmSpec', chart?: string | null, version?: string | null, repository?: { __typename?: 'ObjectReference', namespace?: string | null, name?: string | null } | null } | null, cluster?: { __typename?: 'Cluster', id: string, name: string, provider?: { __typename?: 'ClusterProvider', name: string, cloud: string } | null } | null, helmRepository?: { __typename?: 'HelmRepository', spec: { __typename?: 'HelmRepositorySpec', url: string }, status?: { __typename?: 'HelmRepositoryStatus', ready?: boolean | null, message?: string | null } | null } | null, repository?: { __typename?: 'GitRepository', id: string, url: string } | null, errors?: Array<{ __typename?: 'ServiceError', message: string, source: string } | null> | null, components?: Array<{ __typename?: 'ServiceComponent', apiDeprecations?: Array<{ __typename?: 'ApiDeprecation', blocking?: boolean | null } | null> | null } | null> | null, globalService?: { __typename?: 'GlobalService', id: string, name: string } | null } | null } | null> | null } | null };
export type ServiceDeploymentsTinyQueryVariables = Exact<{ [key: string]: never; }>;
@@ -4309,28 +4426,28 @@ export type ServiceDeploymentQueryVariables = Exact<{
}>;
-export type ServiceDeploymentQuery = { __typename?: 'RootQueryType', serviceDeployment?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, componentStatus?: string | null, status: ServiceDeploymentStatus, version: string, cluster?: { __typename?: 'Cluster', id: string, name: string } | null, docs?: Array<{ __typename?: 'GitFile', content: string, path: string } | null> | null, git: { __typename?: 'GitRef', folder: string, ref: string }, components?: Array<{ __typename?: 'ServiceComponent', apiDeprecations?: Array<{ __typename?: 'ApiDeprecation', blocking?: boolean | null } | null> | null } | null> | null } | null };
+export type ServiceDeploymentQuery = { __typename?: 'RootQueryType', serviceDeployment?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string, componentStatus?: string | null, status: ServiceDeploymentStatus, version: string, cluster?: { __typename?: 'Cluster', id: string, name: string } | null, helm?: { __typename?: 'HelmSpec', chart?: string | null, version?: string | null, repository?: { __typename?: 'ObjectReference', namespace?: string | null, name?: string | null } | null } | null, docs?: Array<{ __typename?: 'GitFile', content: string, path: string } | null> | null, git?: { __typename?: 'GitRef', folder: string, ref: string } | null, components?: Array<{ __typename?: 'ServiceComponent', apiDeprecations?: Array<{ __typename?: 'ApiDeprecation', blocking?: boolean | null } | null> | null } | null> | null } | null };
export type ServiceDeploymentComponentsQueryVariables = Exact<{
id: Scalars['ID']['input'];
}>;
-export type ServiceDeploymentComponentsQuery = { __typename?: 'RootQueryType', serviceDeployment?: { __typename?: 'ServiceDeployment', id: string, name: string, cluster?: { __typename?: 'Cluster', id: string, name: string, handle?: string | null } | null, components?: Array<{ __typename?: 'ServiceComponent', id: string, name: string, group?: string | null, kind: string, namespace?: string | null, state?: ComponentState | null, synced: boolean, version?: string | null, apiDeprecations?: Array<{ __typename?: 'ApiDeprecation', availableIn?: string | null, blocking?: boolean | null, deprecatedIn?: string | null, removedIn?: string | null, replacement?: string | null, component?: { __typename?: 'ServiceComponent', group?: string | null, version?: string | null, kind: string, name: string, namespace?: string | null, service?: { __typename?: 'ServiceDeployment', git: { __typename?: 'GitRef', ref: string, folder: string }, repository?: { __typename?: 'GitRepository', httpsPath?: string | null, urlFormat?: string | null } | null } | null } | null } | null> | null } | null> | null } | null };
+export type ServiceDeploymentComponentsQuery = { __typename?: 'RootQueryType', serviceDeployment?: { __typename?: 'ServiceDeployment', id: string, name: string, cluster?: { __typename?: 'Cluster', id: string, name: string, handle?: string | null } | null, components?: Array<{ __typename?: 'ServiceComponent', id: string, name: string, group?: string | null, kind: string, namespace?: string | null, state?: ComponentState | null, synced: boolean, version?: string | null, apiDeprecations?: Array<{ __typename?: 'ApiDeprecation', availableIn?: string | null, blocking?: boolean | null, deprecatedIn?: string | null, removedIn?: string | null, replacement?: string | null, component?: { __typename?: 'ServiceComponent', group?: string | null, version?: string | null, kind: string, name: string, namespace?: string | null, service?: { __typename?: 'ServiceDeployment', git?: { __typename?: 'GitRef', ref: string, folder: string } | null, repository?: { __typename?: 'GitRepository', httpsPath?: string | null, urlFormat?: string | null } | null } | null } | null } | null> | null } | null> | null } | null };
export type ServiceDeploymentSecretsQueryVariables = Exact<{
id: Scalars['ID']['input'];
}>;
-export type ServiceDeploymentSecretsQuery = { __typename?: 'RootQueryType', serviceDeployment?: { __typename?: 'ServiceDeployment', configuration?: Array<{ __typename?: 'ServiceConfiguration', name: string, value: string } | null> | null } | null };
+export type ServiceDeploymentSecretsQuery = { __typename?: 'RootQueryType', serviceDeployment?: { __typename?: 'ServiceDeployment', configuration?: Array<{ __typename?: 'ServiceConfiguration', name: string, value: string } | null> | null, helm?: { __typename?: 'HelmSpec', values?: string | null } | null } | null };
export type ServiceDeploymentRevisionsQueryVariables = Exact<{
id: Scalars['ID']['input'];
}>;
-export type ServiceDeploymentRevisionsQuery = { __typename?: 'RootQueryType', serviceDeployment?: { __typename?: 'ServiceDeployment', revision?: { __typename?: 'Revision', id: string, sha?: string | null, version: string, message?: string | null, updatedAt?: string | null, insertedAt?: string | null, git: { __typename?: 'GitRef', folder: string, ref: string } } | null, revisions?: { __typename?: 'RevisionConnection', edges?: Array<{ __typename?: 'RevisionEdge', node?: { __typename?: 'Revision', id: string, sha?: string | null, version: string, message?: string | null, updatedAt?: string | null, insertedAt?: string | null, git: { __typename?: 'GitRef', folder: string, ref: string } } | null } | null> | null } | null } | null };
+export type ServiceDeploymentRevisionsQuery = { __typename?: 'RootQueryType', serviceDeployment?: { __typename?: 'ServiceDeployment', revision?: { __typename?: 'Revision', id: string, sha?: string | null, version: string, message?: string | null, updatedAt?: string | null, insertedAt?: string | null, helm?: { __typename?: 'HelmSpec', chart?: string | null, version?: string | null } | null, git?: { __typename?: 'GitRef', folder: string, ref: string } | null } | null, revisions?: { __typename?: 'RevisionConnection', edges?: Array<{ __typename?: 'RevisionEdge', node?: { __typename?: 'Revision', id: string, sha?: string | null, version: string, message?: string | null, updatedAt?: string | null, insertedAt?: string | null, helm?: { __typename?: 'HelmSpec', chart?: string | null, version?: string | null } | null, git?: { __typename?: 'GitRef', folder: string, ref: string } | null } | null } | null> | null } | null } | null };
export type CreateServiceDeploymentMutationVariables = Exact<{
attributes: ServiceDeploymentAttributes;
@@ -4339,7 +4456,7 @@ export type CreateServiceDeploymentMutationVariables = Exact<{
}>;
-export type CreateServiceDeploymentMutation = { __typename?: 'RootMutationType', createServiceDeployment?: { __typename?: 'ServiceDeployment', id: string, name: string, protect?: boolean | null, message?: string | null, insertedAt?: string | null, updatedAt?: string | null, deletedAt?: string | null, componentStatus?: string | null, status: ServiceDeploymentStatus, git: { __typename?: 'GitRef', ref: string, folder: string }, cluster?: { __typename?: 'Cluster', id: string, name: string, provider?: { __typename?: 'ClusterProvider', name: string, cloud: string } | null } | null, repository?: { __typename?: 'GitRepository', id: string, url: string } | null, errors?: Array<{ __typename?: 'ServiceError', message: string, source: string } | null> | null, components?: Array<{ __typename?: 'ServiceComponent', apiDeprecations?: Array<{ __typename?: 'ApiDeprecation', blocking?: boolean | null } | null> | null } | null> | null, globalService?: { __typename?: 'GlobalService', id: string, name: string } | null } | null };
+export type CreateServiceDeploymentMutation = { __typename?: 'RootMutationType', createServiceDeployment?: { __typename?: 'ServiceDeployment', id: string, name: string, protect?: boolean | null, message?: string | null, insertedAt?: string | null, updatedAt?: string | null, deletedAt?: string | null, componentStatus?: string | null, status: ServiceDeploymentStatus, git?: { __typename?: 'GitRef', ref: string, folder: string } | null, helm?: { __typename?: 'HelmSpec', chart?: string | null, version?: string | null, repository?: { __typename?: 'ObjectReference', namespace?: string | null, name?: string | null } | null } | null, cluster?: { __typename?: 'Cluster', id: string, name: string, provider?: { __typename?: 'ClusterProvider', name: string, cloud: string } | null } | null, helmRepository?: { __typename?: 'HelmRepository', spec: { __typename?: 'HelmRepositorySpec', url: string }, status?: { __typename?: 'HelmRepositoryStatus', ready?: boolean | null, message?: string | null } | null } | null, repository?: { __typename?: 'GitRepository', id: string, url: string } | null, errors?: Array<{ __typename?: 'ServiceError', message: string, source: string } | null> | null, components?: Array<{ __typename?: 'ServiceComponent', apiDeprecations?: Array<{ __typename?: 'ApiDeprecation', blocking?: boolean | null } | null> | null } | null> | null, globalService?: { __typename?: 'GlobalService', id: string, name: string } | null } | null };
export type UpdateServiceDeploymentMutationVariables = Exact<{
id: Scalars['ID']['input'];
@@ -4347,7 +4464,7 @@ export type UpdateServiceDeploymentMutationVariables = Exact<{
}>;
-export type UpdateServiceDeploymentMutation = { __typename?: 'RootMutationType', updateServiceDeployment?: { __typename?: 'ServiceDeployment', version: string, configuration?: Array<{ __typename?: 'ServiceConfiguration', name: string, value: string } | null> | null, git: { __typename?: 'GitRef', folder: string, ref: string } } | null };
+export type UpdateServiceDeploymentMutation = { __typename?: 'RootMutationType', updateServiceDeployment?: { __typename?: 'ServiceDeployment', version: string, configuration?: Array<{ __typename?: 'ServiceConfiguration', name: string, value: string } | null> | null, git?: { __typename?: 'GitRef', folder: string, ref: string } | null } | null };
export type MergeServiceMutationVariables = Exact<{
id: Scalars['ID']['input'];
@@ -4370,7 +4487,7 @@ export type RollbackServiceMutationVariables = Exact<{
}>;
-export type RollbackServiceMutation = { __typename?: 'RootMutationType', rollbackService?: { __typename?: 'ServiceDeployment', id: string, name: string, protect?: boolean | null, message?: string | null, insertedAt?: string | null, updatedAt?: string | null, deletedAt?: string | null, componentStatus?: string | null, status: ServiceDeploymentStatus, git: { __typename?: 'GitRef', ref: string, folder: string }, cluster?: { __typename?: 'Cluster', id: string, name: string, provider?: { __typename?: 'ClusterProvider', name: string, cloud: string } | null } | null, repository?: { __typename?: 'GitRepository', id: string, url: string } | null, errors?: Array<{ __typename?: 'ServiceError', message: string, source: string } | null> | null, components?: Array<{ __typename?: 'ServiceComponent', apiDeprecations?: Array<{ __typename?: 'ApiDeprecation', blocking?: boolean | null } | null> | null } | null> | null, globalService?: { __typename?: 'GlobalService', id: string, name: string } | null } | null };
+export type RollbackServiceMutation = { __typename?: 'RootMutationType', rollbackService?: { __typename?: 'ServiceDeployment', id: string, name: string, protect?: boolean | null, message?: string | null, insertedAt?: string | null, updatedAt?: string | null, deletedAt?: string | null, componentStatus?: string | null, status: ServiceDeploymentStatus, git?: { __typename?: 'GitRef', ref: string, folder: string } | null, helm?: { __typename?: 'HelmSpec', chart?: string | null, version?: string | null, repository?: { __typename?: 'ObjectReference', namespace?: string | null, name?: string | null } | null } | null, cluster?: { __typename?: 'Cluster', id: string, name: string, provider?: { __typename?: 'ClusterProvider', name: string, cloud: string } | null } | null, helmRepository?: { __typename?: 'HelmRepository', spec: { __typename?: 'HelmRepositorySpec', url: string }, status?: { __typename?: 'HelmRepositoryStatus', ready?: boolean | null, message?: string | null } | null } | null, repository?: { __typename?: 'GitRepository', id: string, url: string } | null, errors?: Array<{ __typename?: 'ServiceError', message: string, source: string } | null> | null, components?: Array<{ __typename?: 'ServiceComponent', apiDeprecations?: Array<{ __typename?: 'ApiDeprecation', blocking?: boolean | null } | null> | null } | null> | null, globalService?: { __typename?: 'GlobalService', id: string, name: string } | null } | null };
export type UpdateRbacMutationVariables = Exact<{
serviceId?: InputMaybe;
@@ -4381,6 +4498,13 @@ export type UpdateRbacMutationVariables = Exact<{
export type UpdateRbacMutation = { __typename?: 'RootMutationType', updateRbac?: boolean | null };
+export type SelfManageMutationVariables = Exact<{
+ values: Scalars['String']['input'];
+}>;
+
+
+export type SelfManageMutation = { __typename?: 'RootMutationType', selfManage?: { __typename?: 'ServiceDeployment', id: string, name: string, protect?: boolean | null, message?: string | null, insertedAt?: string | null, updatedAt?: string | null, deletedAt?: string | null, componentStatus?: string | null, status: ServiceDeploymentStatus, git?: { __typename?: 'GitRef', ref: string, folder: string } | null, helm?: { __typename?: 'HelmSpec', chart?: string | null, version?: string | null, repository?: { __typename?: 'ObjectReference', namespace?: string | null, name?: string | null } | null } | null, cluster?: { __typename?: 'Cluster', id: string, name: string, provider?: { __typename?: 'ClusterProvider', name: string, cloud: string } | null } | null, helmRepository?: { __typename?: 'HelmRepository', spec: { __typename?: 'HelmRepositorySpec', url: string }, status?: { __typename?: 'HelmRepositoryStatus', ready?: boolean | null, message?: string | null } | null } | null, repository?: { __typename?: 'GitRepository', id: string, url: string } | null, errors?: Array<{ __typename?: 'ServiceError', message: string, source: string } | null> | null, components?: Array<{ __typename?: 'ServiceComponent', apiDeprecations?: Array<{ __typename?: 'ApiDeprecation', blocking?: boolean | null } | null> | null } | null> | null, globalService?: { __typename?: 'GlobalService', id: string, name: string } | null } | null };
+
export type ServiceDeploymentBindingsFragment = { __typename?: 'ServiceDeployment', readBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, writeBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null };
export type ServiceDeploymentBindingsQueryVariables = Exact<{
@@ -5109,6 +5233,31 @@ export const MetricResponseFragmentDoc = gql`
}
}
`;
+export const HelmRepositoryFragmentDoc = gql`
+ fragment HelmRepository on HelmRepository {
+ metadata {
+ namespace
+ name
+ }
+ spec {
+ url
+ type
+ provider
+ }
+ status {
+ ready
+ message
+ }
+}
+ `;
+export const HelmChartVersionFragmentDoc = gql`
+ fragment HelmChartVersion on HelmChartVersion {
+ name
+ appVersion
+ version
+ digest
+}
+ `;
export const GlobalServiceFragmentDoc = gql`
fragment GlobalService on GlobalService {
id
@@ -5151,6 +5300,7 @@ export const DeploymentSettingsFragmentDoc = gql`
id
name
enabled
+ selfManaged
insertedAt
updatedAt
artifactRepository {
@@ -5376,6 +5526,14 @@ export const ServiceDeploymentsRowFragmentDoc = gql`
ref
folder
}
+ helm {
+ chart
+ version
+ repository {
+ namespace
+ name
+ }
+ }
cluster {
id
name
@@ -5384,6 +5542,15 @@ export const ServiceDeploymentsRowFragmentDoc = gql`
cloud
}
}
+ helmRepository {
+ spec {
+ url
+ }
+ status {
+ ready
+ message
+ }
+ }
repository {
id
url
@@ -5420,6 +5587,14 @@ export const ServiceDeploymentDetailsFragmentDoc = gql`
name
}
version
+ helm {
+ chart
+ version
+ repository {
+ namespace
+ name
+ }
+ }
docs {
content
path
@@ -5458,6 +5633,10 @@ export const ServiceDeploymentRevisionFragmentDoc = gql`
message
updatedAt
insertedAt
+ helm {
+ chart
+ version
+ }
git {
folder
ref
@@ -6756,6 +6935,93 @@ export type GitRepositoriesQueryHookResult = ReturnType;
export type GitRepositoriesSuspenseQueryHookResult = ReturnType;
export type GitRepositoriesQueryResult = Apollo.QueryResult;
+export const HelmRepositoriesDocument = gql`
+ query HelmRepositories {
+ helmRepositories {
+ ...HelmRepository
+ }
+}
+ ${HelmRepositoryFragmentDoc}`;
+
+/**
+ * __useHelmRepositoriesQuery__
+ *
+ * To run a query within a React component, call `useHelmRepositoriesQuery` and pass it any options that fit your needs.
+ * When your component renders, `useHelmRepositoriesQuery` returns an object from Apollo Client that contains loading, error, and data properties
+ * you can use to render your UI.
+ *
+ * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
+ *
+ * @example
+ * const { data, loading, error } = useHelmRepositoriesQuery({
+ * variables: {
+ * },
+ * });
+ */
+export function useHelmRepositoriesQuery(baseOptions?: Apollo.QueryHookOptions) {
+ const options = {...defaultOptions, ...baseOptions}
+ return Apollo.useQuery(HelmRepositoriesDocument, options);
+ }
+export function useHelmRepositoriesLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) {
+ const options = {...defaultOptions, ...baseOptions}
+ return Apollo.useLazyQuery(HelmRepositoriesDocument, options);
+ }
+export function useHelmRepositoriesSuspenseQuery(baseOptions?: Apollo.SuspenseQueryHookOptions) {
+ const options = {...defaultOptions, ...baseOptions}
+ return Apollo.useSuspenseQuery(HelmRepositoriesDocument, options);
+ }
+export type HelmRepositoriesQueryHookResult = ReturnType;
+export type HelmRepositoriesLazyQueryHookResult = ReturnType;
+export type HelmRepositoriesSuspenseQueryHookResult = ReturnType;
+export type HelmRepositoriesQueryResult = Apollo.QueryResult;
+export const HelmRepositoryDocument = gql`
+ query HelmRepository($namespace: String!, $name: String!) {
+ helmRepository(namespace: $namespace, name: $name) {
+ ...HelmRepository
+ charts {
+ name
+ versions {
+ ...HelmChartVersion
+ }
+ }
+ }
+}
+ ${HelmRepositoryFragmentDoc}
+${HelmChartVersionFragmentDoc}`;
+
+/**
+ * __useHelmRepositoryQuery__
+ *
+ * To run a query within a React component, call `useHelmRepositoryQuery` and pass it any options that fit your needs.
+ * When your component renders, `useHelmRepositoryQuery` returns an object from Apollo Client that contains loading, error, and data properties
+ * you can use to render your UI.
+ *
+ * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
+ *
+ * @example
+ * const { data, loading, error } = useHelmRepositoryQuery({
+ * variables: {
+ * namespace: // value for 'namespace'
+ * name: // value for 'name'
+ * },
+ * });
+ */
+export function useHelmRepositoryQuery(baseOptions: Apollo.QueryHookOptions) {
+ const options = {...defaultOptions, ...baseOptions}
+ return Apollo.useQuery(HelmRepositoryDocument, options);
+ }
+export function useHelmRepositoryLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) {
+ const options = {...defaultOptions, ...baseOptions}
+ return Apollo.useLazyQuery(HelmRepositoryDocument, options);
+ }
+export function useHelmRepositorySuspenseQuery(baseOptions?: Apollo.SuspenseQueryHookOptions) {
+ const options = {...defaultOptions, ...baseOptions}
+ return Apollo.useSuspenseQuery(HelmRepositoryDocument, options);
+ }
+export type HelmRepositoryQueryHookResult = ReturnType;
+export type HelmRepositoryLazyQueryHookResult = ReturnType;
+export type HelmRepositorySuspenseQueryHookResult = ReturnType;
+export type HelmRepositoryQueryResult = Apollo.QueryResult;
export const CreateGitRepositoryDocument = gql`
mutation CreateGitRepository($attributes: GitAttributes!) {
createGitRepository(attributes: $attributes) {
@@ -7473,6 +7739,9 @@ export const ServiceDeploymentSecretsDocument = gql`
name
value
}
+ helm {
+ values
+ }
}
}
`;
@@ -7767,6 +8036,39 @@ export function useUpdateRbacMutation(baseOptions?: Apollo.MutationHookOptions;
export type UpdateRbacMutationResult = Apollo.MutationResult;
export type UpdateRbacMutationOptions = Apollo.BaseMutationOptions;
+export const SelfManageDocument = gql`
+ mutation SelfManage($values: String!) {
+ selfManage(values: $values) {
+ ...ServiceDeploymentsRow
+ }
+}
+ ${ServiceDeploymentsRowFragmentDoc}`;
+export type SelfManageMutationFn = Apollo.MutationFunction;
+
+/**
+ * __useSelfManageMutation__
+ *
+ * To run a mutation, you first call `useSelfManageMutation` within a React component and pass it any options that fit your needs.
+ * When your component renders, `useSelfManageMutation` returns a tuple that includes:
+ * - A mutate function that you can call at any time to execute the mutation
+ * - An object with fields that represent the current status of the mutation's execution
+ *
+ * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
+ *
+ * @example
+ * const [selfManageMutation, { data, loading, error }] = useSelfManageMutation({
+ * variables: {
+ * values: // value for 'values'
+ * },
+ * });
+ */
+export function useSelfManageMutation(baseOptions?: Apollo.MutationHookOptions) {
+ const options = {...defaultOptions, ...baseOptions}
+ return Apollo.useMutation(SelfManageDocument, options);
+ }
+export type SelfManageMutationHookResult = ReturnType;
+export type SelfManageMutationResult = Apollo.MutationResult;
+export type SelfManageMutationOptions = Apollo.BaseMutationOptions;
export const ServiceDeploymentBindingsDocument = gql`
query ServiceDeploymentBindings($id: ID!) {
serviceDeployment(id: $id) {
@@ -9166,6 +9468,8 @@ export const namedOperations = {
RuntimeServices: 'RuntimeServices',
Usage: 'Usage',
GitRepositories: 'GitRepositories',
+ HelmRepositories: 'HelmRepositories',
+ HelmRepository: 'HelmRepository',
DeploymentSettings: 'DeploymentSettings',
Pipelines: 'Pipelines',
Pipeline: 'Pipeline',
@@ -9223,6 +9527,7 @@ export const namedOperations = {
DeleteServiceDeployment: 'DeleteServiceDeployment',
RollbackService: 'RollbackService',
UpdateRbac: 'UpdateRbac',
+ SelfManage: 'SelfManage',
RestorePostgres: 'RestorePostgres',
CreateGroupMember: 'CreateGroupMember',
DeleteGroupMember: 'DeleteGroupMember',
@@ -9259,6 +9564,8 @@ export const namedOperations = {
ClusterBindings: 'ClusterBindings',
MetricResponse: 'MetricResponse',
GitRepository: 'GitRepository',
+ HelmRepository: 'HelmRepository',
+ HelmChartVersion: 'HelmChartVersion',
GlobalService: 'GlobalService',
DeploymentSettings: 'DeploymentSettings',
PipelineServiceDeployment: 'PipelineServiceDeployment',
diff --git a/assets/src/graph/cdGitRepos.graphql b/assets/src/graph/cdGitRepos.graphql
index f33f7062d1..1f7b113d5a 100644
--- a/assets/src/graph/cdGitRepos.graphql
+++ b/assets/src/graph/cdGitRepos.graphql
@@ -12,6 +12,29 @@ fragment GitRepository on GitRepository {
httpsPath
}
+fragment HelmRepository on HelmRepository {
+ metadata {
+ namespace
+ name
+ }
+ spec {
+ url
+ type
+ provider
+ }
+ status {
+ ready
+ message
+ }
+}
+
+fragment HelmChartVersion on HelmChartVersion {
+ name
+ appVersion
+ version
+ digest
+}
+
query GitRepositories {
gitRepositories(first: 100) {
pageInfo {
@@ -25,6 +48,24 @@ query GitRepositories {
}
}
+query HelmRepositories {
+ helmRepositories {
+ ...HelmRepository
+ }
+}
+
+query HelmRepository($namespace: String!, $name: String!) {
+ helmRepository(namespace: $namespace, name: $name) {
+ ...HelmRepository
+ charts {
+ name
+ versions {
+ ...HelmChartVersion
+ }
+ }
+ }
+}
+
mutation CreateGitRepository($attributes: GitAttributes!) {
createGitRepository(attributes: $attributes) {
...GitRepository
diff --git a/assets/src/graph/cdGlobalSettings.graphql b/assets/src/graph/cdGlobalSettings.graphql
index f2efe40bdf..1706b41e02 100644
--- a/assets/src/graph/cdGlobalSettings.graphql
+++ b/assets/src/graph/cdGlobalSettings.graphql
@@ -2,6 +2,7 @@ fragment DeploymentSettings on DeploymentSettings {
id
name
enabled
+ selfManaged
insertedAt
updatedAt
artifactRepository {
diff --git a/assets/src/graph/cdServices.graphql b/assets/src/graph/cdServices.graphql
index fabf9d20e5..12d87b89f0 100644
--- a/assets/src/graph/cdServices.graphql
+++ b/assets/src/graph/cdServices.graphql
@@ -5,6 +5,10 @@ fragment ServiceDeploymentRevision on Revision {
message
updatedAt
insertedAt
+ helm {
+ chart
+ version
+ }
git {
folder
ref
@@ -20,6 +24,14 @@ fragment ServiceDeploymentsRow on ServiceDeployment {
ref
folder
}
+ helm {
+ chart
+ version
+ repository {
+ namespace
+ name
+ }
+ }
cluster {
id
name
@@ -28,6 +40,15 @@ fragment ServiceDeploymentsRow on ServiceDeployment {
cloud
}
}
+ helmRepository {
+ spec {
+ url
+ }
+ status {
+ ready
+ message
+ }
+ }
repository {
id
url
@@ -63,6 +84,14 @@ fragment ServiceDeploymentDetails on ServiceDeployment {
name
}
version
+ helm {
+ chart
+ version
+ repository {
+ namespace
+ name
+ }
+ }
docs {
content
path
@@ -175,6 +204,9 @@ query ServiceDeploymentSecrets($id: ID!) {
name
value
}
+ helm {
+ values
+ }
}
}
@@ -240,6 +272,12 @@ mutation UpdateRbac($serviceId: ID, $clusterId: ID, $rbac: RbacAttributes!) {
updateRbac(serviceId: $serviceId, clusterId: $clusterId, rbac: $rbac)
}
+mutation SelfManage($values: String!) {
+ selfManage(values: $values) {
+ ...ServiceDeploymentsRow
+ }
+}
+
fragment ServiceDeploymentBindings on ServiceDeployment {
readBindings {
...PolicyBinding
diff --git a/assets/src/index.tsx b/assets/src/index.tsx
index 9320ff3cd1..7b5eb3db6f 100644
--- a/assets/src/index.tsx
+++ b/assets/src/index.tsx
@@ -2,22 +2,21 @@ import { createRoot } from 'react-dom/client'
import './index.css'
import 'regenerator-runtime/runtime'
-import posthog from 'posthog-js'
import App from './App'
// import * as serviceWorker from './serviceWorker'
-posthog.init('phc_r0v4jbKz8Rr27mfqgO15AN5BMuuvnU8hCFedd6zpSDy', {
- api_host: 'https://posthog.plural.sh',
- disable_session_recording: true,
- opt_out_capturing_by_default: true,
-})
+// posthog.init('phc_r0v4jbKz8Rr27mfqgO15AN5BMuuvnU8hCFedd6zpSDy', {
+// api_host: 'https://posthog.plural.sh',
+// disable_session_recording: true,
+// opt_out_capturing_by_default: true,
+// })
-// add `source: console` to all events
-posthog.register({
- source: 'console',
-})
+// // add `source: console` to all events
+// posthog.register({
+// source: 'console',
+// })
const container = document.getElementById('root') as Element
const root = createRoot(container)
diff --git a/assets/src/routes/cdRoutes.tsx b/assets/src/routes/cdRoutes.tsx
index a8b059c6f2..4ce2864e7e 100644
--- a/assets/src/routes/cdRoutes.tsx
+++ b/assets/src/routes/cdRoutes.tsx
@@ -34,6 +34,10 @@ import { useCDEnabled } from 'components/cd/utils/useCDEnabled'
import Pipelines from 'components/cd/pipelines/Pipelines'
+import ServiceHelm from 'components/cd/services/service/ServiceHelm'
+
+import SelfManage from 'components/cd/globalSettings/SelfManage'
+
import Cluster from '../components/cd/cluster/Cluster'
import ClusterServices from '../components/cd/cluster/ClusterServices'
import ClusterNodes from '../components/cd/cluster/ClusterNodes'
@@ -190,6 +194,10 @@ const globalSettingsRoutes = (
path="repositories"
element={}
/>
+ }
+ />
)
@@ -304,6 +312,10 @@ const serviceDetailsRoutes = (
element={}
path="revisions"
/>
+ }
+ path="helm"
+ />
}
path="docs"
diff --git a/assets/src/routes/rootRoutes.tsx b/assets/src/routes/rootRoutes.tsx
index ebddf9b01b..b4ea8503ba 100644
--- a/assets/src/routes/rootRoutes.tsx
+++ b/assets/src/routes/rootRoutes.tsx
@@ -1,7 +1,5 @@
import { Outlet, Route } from 'react-router-dom'
-import { usePosthog } from 'components/utils/Posthog'
-
import { Suspense } from 'react'
import LoadingIndicator from 'components/utils/LoadingIndicator'
@@ -16,7 +14,7 @@ import { OAuthCallback } from '../components/login/OauthCallback'
import { consoleRoutes } from './consoleRoutes'
function Root() {
- usePosthog()
+ // usePosthog()
return (
}>
diff --git a/charts/console/templates/_helpers.tpl b/charts/console/templates/_helpers.tpl
index c746e1a1fa..d4e428a7ab 100644
--- a/charts/console/templates/_helpers.tpl
+++ b/charts/console/templates/_helpers.tpl
@@ -65,8 +65,6 @@ spec: {{ .Values.secrets.config | toYaml | nindent 2 }}
{{- end }}
- name: KAS_DNS
value: {{ .Values.ingress.kas_dns }}
-- name: DEPLOYED_AT
- value: {{ now | unixEpoch | quote }}
- name: NAMESPACE
valueFrom:
fieldRef:
diff --git a/charts/console/templates/migration.yaml b/charts/console/templates/migration.yaml
index cf188ba21d..af1d47c537 100644
--- a/charts/console/templates/migration.yaml
+++ b/charts/console/templates/migration.yaml
@@ -1,7 +1,7 @@
apiVersion: batch/v1
kind: Job
metadata:
- name: {{ include "console.migration-name" . }}
+ name: console-migration-{{ .Values.image.tag | default .Chart.AppVersion | sha256sum | trunc 8 }}
labels:
platform.plural.sh/ignore: 'true'
{{ include "console.labels" . | nindent 4 }}
diff --git a/config/config.exs b/config/config.exs
index 494e581f43..cd49ffebc3 100644
--- a/config/config.exs
+++ b/config/config.exs
@@ -81,6 +81,7 @@ config :console,
config :porcelain, driver: Porcelain.Driver.Basic
+config :http_stream, adapter: HTTPStream.Adapter.HTTPoison
config :console, Console.PartitionedCache,
primary: [
diff --git a/crds/helmchart.yaml b/crds/helmchart.yaml
new file mode 100644
index 0000000000..6951b85378
--- /dev/null
+++ b/crds/helmchart.yaml
@@ -0,0 +1,697 @@
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ config.k8s.io/owning-inventory: 5eed945f-8ec8-44a8-84ea-6775417586eb
+ controller-gen.kubebuilder.io/version: v0.12.0
+ creationTimestamp: 2023-11-22T19:11:41Z
+ generation: 1
+ labels:
+ app.kubernetes.io/component: source-controller
+ app.kubernetes.io/instance: flux-source-controller
+ app.kubernetes.io/managed-by: Helm
+ app.kubernetes.io/part-of: flux
+ app.kubernetes.io/version: 2.1.2
+ helm.sh/chart: flux2-2.11.1
+ managedFields:
+ - apiVersion: apiextensions.k8s.io/v1
+ fieldsType: FieldsV1
+ fieldsV1:
+ f:metadata:
+ f:annotations:
+ f:config.k8s.io/owning-inventory: {}
+ f:controller-gen.kubebuilder.io/version: {}
+ f:labels:
+ f:app.kubernetes.io/component: {}
+ f:app.kubernetes.io/instance: {}
+ f:app.kubernetes.io/managed-by: {}
+ f:app.kubernetes.io/part-of: {}
+ f:app.kubernetes.io/version: {}
+ f:helm.sh/chart: {}
+ f:spec:
+ f:group: {}
+ f:names:
+ f:kind: {}
+ f:listKind: {}
+ f:plural: {}
+ f:shortNames: {}
+ f:singular: {}
+ f:scope: {}
+ f:versions: {}
+ manager: application/apply-patch
+ operation: Apply
+ time: 2023-11-22T19:11:41Z
+ - apiVersion: apiextensions.k8s.io/v1
+ fieldsType: FieldsV1
+ fieldsV1:
+ f:status:
+ f:acceptedNames:
+ f:kind: {}
+ f:listKind: {}
+ f:plural: {}
+ f:shortNames: {}
+ f:singular: {}
+ f:conditions:
+ k:{"type":"Established"}:
+ .: {}
+ f:lastTransitionTime: {}
+ f:message: {}
+ f:reason: {}
+ f:status: {}
+ f:type: {}
+ k:{"type":"NamesAccepted"}:
+ .: {}
+ f:lastTransitionTime: {}
+ f:message: {}
+ f:reason: {}
+ f:status: {}
+ f:type: {}
+ manager: kube-apiserver
+ operation: Update
+ subresource: status
+ time: 2023-11-22T19:11:41Z
+ name: helmcharts.source.toolkit.fluxcd.io
+ resourceVersion: "78768215"
+ uid: 6c8ba5d3-33de-44dc-9057-429e60d71a56
+spec:
+ conversion:
+ strategy: None
+ group: source.toolkit.fluxcd.io
+ names:
+ kind: HelmChart
+ listKind: HelmChartList
+ plural: helmcharts
+ shortNames:
+ - hc
+ singular: helmchart
+ scope: Namespaced
+ versions:
+ - additionalPrinterColumns:
+ - jsonPath: .spec.chart
+ name: Chart
+ type: string
+ - jsonPath: .spec.version
+ name: Version
+ type: string
+ - jsonPath: .spec.sourceRef.kind
+ name: Source Kind
+ type: string
+ - jsonPath: .spec.sourceRef.name
+ name: Source Name
+ type: string
+ - jsonPath: .status.conditions[?(@.type=="Ready")].status
+ name: Ready
+ type: string
+ - jsonPath: .status.conditions[?(@.type=="Ready")].message
+ name: Status
+ type: string
+ - jsonPath: .metadata.creationTimestamp
+ name: Age
+ type: date
+ name: v1beta1
+ schema:
+ openAPIV3Schema:
+ description: HelmChart is the Schema for the helmcharts API
+ properties:
+ apiVersion:
+ description: "APIVersion defines the versioned schema of this representation of
+ an object. Servers should convert recognized schemas to the
+ latest internal value, and may reject unrecognized values. More
+ info:
+ https://git.k8s.io/community/contributors/devel/sig-architectur\
+ e/api-conventions.md#resources"
+ type: string
+ kind:
+ description: "Kind is a string value representing the REST resource this object
+ represents. Servers may infer this from the endpoint the client
+ submits requests to. Cannot be updated. In CamelCase. More info:
+ https://git.k8s.io/community/contributors/devel/sig-architectur\
+ e/api-conventions.md#types-kinds"
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: HelmChartSpec defines the desired state of a Helm chart.
+ properties:
+ accessFrom:
+ description: AccessFrom defines an Access Control List for allowing
+ cross-namespace references to this object.
+ properties:
+ namespaceSelectors:
+ description: NamespaceSelectors is the list of namespace selectors to which this
+ ACL applies. Items in this list are evaluated using a
+ logical OR operation.
+ items:
+ description: NamespaceSelector selects the namespaces to which this ACL applies.
+ An empty map of MatchLabels matches all namespaces in
+ a cluster.
+ properties:
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: MatchLabels is a map of {key,value} pairs. A single {key,value} in
+ the matchLabels map is equivalent to an element of
+ matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains
+ only "value". The requirements are ANDed.
+ type: object
+ type: object
+ type: array
+ required:
+ - namespaceSelectors
+ type: object
+ chart:
+ description: The name or path the Helm chart is available at in the SourceRef.
+ type: string
+ interval:
+ description: The interval at which to check the Source for updates.
+ type: string
+ reconcileStrategy:
+ default: ChartVersion
+ description: Determines what enables the creation of a new artifact. Valid
+ values are ('ChartVersion', 'Revision'). See the
+ documentation of the values for an explanation on their
+ behavior. Defaults to ChartVersion when omitted.
+ enum:
+ - ChartVersion
+ - Revision
+ type: string
+ sourceRef:
+ description: The reference to the Source the chart is available at.
+ properties:
+ apiVersion:
+ description: APIVersion of the referent.
+ type: string
+ kind:
+ description: Kind of the referent, valid values are ('HelmRepository',
+ 'GitRepository', 'Bucket').
+ enum:
+ - HelmRepository
+ - GitRepository
+ - Bucket
+ type: string
+ name:
+ description: Name of the referent.
+ type: string
+ required:
+ - kind
+ - name
+ type: object
+ suspend:
+ description: This flag tells the controller to suspend the reconciliation of
+ this source.
+ type: boolean
+ valuesFile:
+ description: Alternative values file to use as the default chart values,
+ expected to be a relative path in the SourceRef. Deprecated
+ in favor of ValuesFiles, for backwards compatibility the
+ file defined here is merged before the ValuesFiles items.
+ Ignored when omitted.
+ type: string
+ valuesFiles:
+ description: Alternative list of values files to use as the chart values
+ (values.yaml is not included by default), expected to be a
+ relative path in the SourceRef. Values files are merged in
+ the order of this list with the last file overriding the
+ first. Ignored when omitted.
+ items:
+ type: string
+ type: array
+ version:
+ default: "*"
+ description: The chart version semver expression, ignored for charts from
+ GitRepository and Bucket sources. Defaults to latest when
+ omitted.
+ type: string
+ required:
+ - chart
+ - interval
+ - sourceRef
+ type: object
+ status:
+ default:
+ observedGeneration: -1
+ description: HelmChartStatus defines the observed state of the HelmChart.
+ properties:
+ artifact:
+ description: Artifact represents the output of the last successful chart sync.
+ properties:
+ checksum:
+ description: Checksum is the SHA256 checksum of the artifact.
+ type: string
+ lastUpdateTime:
+ description: LastUpdateTime is the timestamp corresponding to the last update of
+ this artifact.
+ format: date-time
+ type: string
+ path:
+ description: Path is the relative file path of this artifact.
+ type: string
+ revision:
+ description: Revision is a human readable identifier traceable in the origin
+ source system. It can be a Git commit SHA, Git tag, a
+ Helm index timestamp, a Helm chart version, etc.
+ type: string
+ url:
+ description: URL is the HTTP address of this artifact.
+ type: string
+ required:
+ - path
+ - url
+ type: object
+ conditions:
+ description: Conditions holds the conditions for the HelmChart.
+ items:
+ description: >-
+ Condition contains details for one aspect of the current
+ state of this API Resource. --- This struct is intended
+ for direct use as an array at the field path
+ .status.conditions. For example,
+ type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: "Available", "Progressing", and "Degraded" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,1,rep,name=conditions"`
+ // other fields }
+ properties:
+ lastTransitionTime:
+ description: lastTransitionTime is the last time the condition transitioned from
+ one status to another. This should be when the
+ underlying condition changed. If that is not known,
+ then using the time when the API field changed is
+ acceptable.
+ format: date-time
+ type: string
+ message:
+ description: message is a human readable message indicating details about the
+ transition. This may be an empty string.
+ maxLength: 32768
+ type: string
+ observedGeneration:
+ description: observedGeneration represents the .metadata.generation that the
+ condition was set based upon. For instance, if
+ .metadata.generation is currently 12, but the
+ .status.conditions[x].observedGeneration is 9, the
+ condition is out of date with respect to the current
+ state of the instance.
+ format: int64
+ minimum: 0
+ type: integer
+ reason:
+ description: reason contains a programmatic identifier indicating the reason for
+ the condition's last transition. Producers of specific
+ condition types may define expected values and
+ meanings for this field, and whether the values are
+ considered a guaranteed API. The value should be a
+ CamelCase string. This field may not be empty.
+ maxLength: 1024
+ minLength: 1
+ pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
+ type: string
+ status:
+ description: status of the condition, one of True, False, Unknown.
+ enum:
+ - "True"
+ - "False"
+ - Unknown
+ type: string
+ type:
+ description: type of condition in CamelCase or in foo.example.com/CamelCase. ---
+ Many .condition.type values are consistent across
+ resources like Available, but because arbitrary
+ conditions can be useful (see
+ .node.status.conditions), the ability to deconflict is
+ important. The regex it matches is
+ (dns1123SubdomainFmt/)?(qualifiedNameFmt)
+ maxLength: 316
+ pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
+ type: string
+ required:
+ - lastTransitionTime
+ - message
+ - reason
+ - status
+ - type
+ type: object
+ type: array
+ lastHandledReconcileAt:
+ description: LastHandledReconcileAt holds the value of the most recent reconcile
+ request value, so a change of the annotation value can be
+ detected.
+ type: string
+ observedGeneration:
+ description: ObservedGeneration is the last observed generation.
+ format: int64
+ type: integer
+ url:
+ description: URL is the download link for the last chart pulled.
+ type: string
+ type: object
+ type: object
+ served: true
+ storage: false
+ subresources:
+ status: {}
+ - additionalPrinterColumns:
+ - jsonPath: .spec.chart
+ name: Chart
+ type: string
+ - jsonPath: .spec.version
+ name: Version
+ type: string
+ - jsonPath: .spec.sourceRef.kind
+ name: Source Kind
+ type: string
+ - jsonPath: .spec.sourceRef.name
+ name: Source Name
+ type: string
+ - jsonPath: .metadata.creationTimestamp
+ name: Age
+ type: date
+ - jsonPath: .status.conditions[?(@.type=="Ready")].status
+ name: Ready
+ type: string
+ - jsonPath: .status.conditions[?(@.type=="Ready")].message
+ name: Status
+ type: string
+ name: v1beta2
+ schema:
+ openAPIV3Schema:
+ description: HelmChart is the Schema for the helmcharts API.
+ properties:
+ apiVersion:
+ description: "APIVersion defines the versioned schema of this representation of
+ an object. Servers should convert recognized schemas to the
+ latest internal value, and may reject unrecognized values. More
+ info:
+ https://git.k8s.io/community/contributors/devel/sig-architectur\
+ e/api-conventions.md#resources"
+ type: string
+ kind:
+ description: "Kind is a string value representing the REST resource this object
+ represents. Servers may infer this from the endpoint the client
+ submits requests to. Cannot be updated. In CamelCase. More info:
+ https://git.k8s.io/community/contributors/devel/sig-architectur\
+ e/api-conventions.md#types-kinds"
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: HelmChartSpec specifies the desired state of a Helm chart.
+ properties:
+ accessFrom:
+ description: "AccessFrom specifies an Access Control List for allowing
+ cross-namespace references to this object. NOTE: Not
+ implemented, provisional as of
+ https://github.com/fluxcd/flux2/pull/2092"
+ properties:
+ namespaceSelectors:
+ description: NamespaceSelectors is the list of namespace selectors to which this
+ ACL applies. Items in this list are evaluated using a
+ logical OR operation.
+ items:
+ description: NamespaceSelector selects the namespaces to which this ACL applies.
+ An empty map of MatchLabels matches all namespaces in
+ a cluster.
+ properties:
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: MatchLabels is a map of {key,value} pairs. A single {key,value} in
+ the matchLabels map is equivalent to an element of
+ matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains
+ only "value". The requirements are ANDed.
+ type: object
+ type: object
+ type: array
+ required:
+ - namespaceSelectors
+ type: object
+ chart:
+ description: Chart is the name or path the Helm chart is available at in the
+ SourceRef.
+ type: string
+ interval:
+ description: Interval at which the HelmChart SourceRef is checked for updates.
+ This interval is approximate and may be subject to jitter to
+ ensure efficient use of resources.
+ pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$
+ type: string
+ reconcileStrategy:
+ default: ChartVersion
+ description: ReconcileStrategy determines what enables the creation of a new
+ artifact. Valid values are ('ChartVersion', 'Revision'). See
+ the documentation of the values for an explanation on their
+ behavior. Defaults to ChartVersion when omitted.
+ enum:
+ - ChartVersion
+ - Revision
+ type: string
+ sourceRef:
+ description: SourceRef is the reference to the Source the chart is available at.
+ properties:
+ apiVersion:
+ description: APIVersion of the referent.
+ type: string
+ kind:
+ description: Kind of the referent, valid values are ('HelmRepository',
+ 'GitRepository', 'Bucket').
+ enum:
+ - HelmRepository
+ - GitRepository
+ - Bucket
+ type: string
+ name:
+ description: Name of the referent.
+ type: string
+ required:
+ - kind
+ - name
+ type: object
+ suspend:
+ description: Suspend tells the controller to suspend the reconciliation of this
+ source.
+ type: boolean
+ valuesFile:
+ description: ValuesFile is an alternative values file to use as the default
+ chart values, expected to be a relative path in the
+ SourceRef. Deprecated in favor of ValuesFiles, for backwards
+ compatibility the file specified here is merged before the
+ ValuesFiles items. Ignored when omitted.
+ type: string
+ valuesFiles:
+ description: ValuesFiles is an alternative list of values files to use as the
+ chart values (values.yaml is not included by default),
+ expected to be a relative path in the SourceRef. Values
+ files are merged in the order of this list with the last
+ file overriding the first. Ignored when omitted.
+ items:
+ type: string
+ type: array
+ verify:
+ description: Verify contains the secret name containing the trusted public keys
+ used to verify the signature and specifies which provider to
+ use to check whether OCI image is authentic. This field is
+ only supported when using HelmRepository source with
+ spec.type 'oci'. Chart dependencies, which are not bundled
+ in the umbrella chart artifact, are not verified.
+ properties:
+ provider:
+ default: cosign
+ description: Provider specifies the technology used to sign the OCI Artifact.
+ enum:
+ - cosign
+ type: string
+ secretRef:
+ description: SecretRef specifies the Kubernetes Secret containing the trusted
+ public keys.
+ properties:
+ name:
+ description: Name of the referent.
+ type: string
+ required:
+ - name
+ type: object
+ required:
+ - provider
+ type: object
+ version:
+ default: "*"
+ description: Version is the chart version semver expression, ignored for charts
+ from GitRepository and Bucket sources. Defaults to latest
+ when omitted.
+ type: string
+ required:
+ - chart
+ - interval
+ - sourceRef
+ type: object
+ status:
+ default:
+ observedGeneration: -1
+ description: HelmChartStatus records the observed state of the HelmChart.
+ properties:
+ artifact:
+ description: Artifact represents the output of the last successful
+ reconciliation.
+ properties:
+ digest:
+ description: Digest is the digest of the file in the form of
+ ':'.
+ pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$
+ type: string
+ lastUpdateTime:
+ description: LastUpdateTime is the timestamp corresponding to the last update of
+ the Artifact.
+ format: date-time
+ type: string
+ metadata:
+ additionalProperties:
+ type: string
+ description: Metadata holds upstream information such as OCI annotations.
+ type: object
+ path:
+ description: Path is the relative file path of the Artifact. It can be used to
+ locate the file in the root of the Artifact storage on
+ the local file system of the controller managing the
+ Source.
+ type: string
+ revision:
+ description: Revision is a human-readable identifier traceable in the origin
+ source system. It can be a Git commit SHA, Git tag, a
+ Helm chart version, etc.
+ type: string
+ size:
+ description: Size is the number of bytes in the file.
+ format: int64
+ type: integer
+ url:
+ description: URL is the HTTP address of the Artifact as exposed by the
+ controller managing the Source. It can be used to
+ retrieve the Artifact for consumption, e.g. by another
+ controller applying the Artifact contents.
+ type: string
+ required:
+ - lastUpdateTime
+ - path
+ - revision
+ - url
+ type: object
+ conditions:
+ description: Conditions holds the conditions for the HelmChart.
+ items:
+ description: >-
+ Condition contains details for one aspect of the current
+ state of this API Resource. --- This struct is intended
+ for direct use as an array at the field path
+ .status.conditions. For example,
+ type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: "Available", "Progressing", and "Degraded" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,1,rep,name=conditions"`
+ // other fields }
+ properties:
+ lastTransitionTime:
+ description: lastTransitionTime is the last time the condition transitioned from
+ one status to another. This should be when the
+ underlying condition changed. If that is not known,
+ then using the time when the API field changed is
+ acceptable.
+ format: date-time
+ type: string
+ message:
+ description: message is a human readable message indicating details about the
+ transition. This may be an empty string.
+ maxLength: 32768
+ type: string
+ observedGeneration:
+ description: observedGeneration represents the .metadata.generation that the
+ condition was set based upon. For instance, if
+ .metadata.generation is currently 12, but the
+ .status.conditions[x].observedGeneration is 9, the
+ condition is out of date with respect to the current
+ state of the instance.
+ format: int64
+ minimum: 0
+ type: integer
+ reason:
+ description: reason contains a programmatic identifier indicating the reason for
+ the condition's last transition. Producers of specific
+ condition types may define expected values and
+ meanings for this field, and whether the values are
+ considered a guaranteed API. The value should be a
+ CamelCase string. This field may not be empty.
+ maxLength: 1024
+ minLength: 1
+ pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
+ type: string
+ status:
+ description: status of the condition, one of True, False, Unknown.
+ enum:
+ - "True"
+ - "False"
+ - Unknown
+ type: string
+ type:
+ description: type of condition in CamelCase or in foo.example.com/CamelCase. ---
+ Many .condition.type values are consistent across
+ resources like Available, but because arbitrary
+ conditions can be useful (see
+ .node.status.conditions), the ability to deconflict is
+ important. The regex it matches is
+ (dns1123SubdomainFmt/)?(qualifiedNameFmt)
+ maxLength: 316
+ pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
+ type: string
+ required:
+ - lastTransitionTime
+ - message
+ - reason
+ - status
+ - type
+ type: object
+ type: array
+ lastHandledReconcileAt:
+ description: LastHandledReconcileAt holds the value of the most recent reconcile
+ request value, so a change of the annotation value can be
+ detected.
+ type: string
+ observedChartName:
+ description: ObservedChartName is the last observed chart name as specified by
+ the resolved chart reference.
+ type: string
+ observedGeneration:
+ description: ObservedGeneration is the last observed generation of the HelmChart
+ object.
+ format: int64
+ type: integer
+ observedSourceArtifactRevision:
+ description: ObservedSourceArtifactRevision is the last observed
+ Artifact.Revision of the HelmChartSpec.SourceRef.
+ type: string
+ url:
+ description: URL is the dynamic fetch link for the latest Artifact. It is
+ provided on a "best effort" basis, and using the precise
+ BucketStatus.Artifact data is recommended.
+ type: string
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
+status:
+ acceptedNames:
+ kind: HelmChart
+ listKind: HelmChartList
+ plural: helmcharts
+ shortNames:
+ - hc
+ singular: helmchart
+ conditions:
+ - lastTransitionTime: 2023-11-22T19:11:41Z
+ message: no conflicts found
+ reason: NoConflicts
+ status: "True"
+ type: NamesAccepted
+ - lastTransitionTime: 2023-11-22T19:11:41Z
+ message: the initial names have been accepted
+ reason: InitialNamesAccepted
+ status: "True"
+ type: Established
+ storedVersions:
+ - v1beta2
\ No newline at end of file
diff --git a/crds/helmrepository.yaml b/crds/helmrepository.yaml
new file mode 100644
index 0000000000..8b1d196b22
--- /dev/null
+++ b/crds/helmrepository.yaml
@@ -0,0 +1,630 @@
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ config.k8s.io/owning-inventory: 5eed945f-8ec8-44a8-84ea-6775417586eb
+ controller-gen.kubebuilder.io/version: v0.12.0
+ creationTimestamp: 2023-11-22T19:11:41Z
+ generation: 1
+ labels:
+ app.kubernetes.io/component: source-controller
+ app.kubernetes.io/instance: flux-source-controller
+ app.kubernetes.io/managed-by: Helm
+ app.kubernetes.io/part-of: flux
+ app.kubernetes.io/version: 2.1.2
+ helm.sh/chart: flux2-2.11.1
+ managedFields:
+ - apiVersion: apiextensions.k8s.io/v1
+ fieldsType: FieldsV1
+ fieldsV1:
+ f:metadata:
+ f:annotations:
+ f:config.k8s.io/owning-inventory: {}
+ f:controller-gen.kubebuilder.io/version: {}
+ f:labels:
+ f:app.kubernetes.io/component: {}
+ f:app.kubernetes.io/instance: {}
+ f:app.kubernetes.io/managed-by: {}
+ f:app.kubernetes.io/part-of: {}
+ f:app.kubernetes.io/version: {}
+ f:helm.sh/chart: {}
+ f:spec:
+ f:group: {}
+ f:names:
+ f:kind: {}
+ f:listKind: {}
+ f:plural: {}
+ f:shortNames: {}
+ f:singular: {}
+ f:scope: {}
+ f:versions: {}
+ manager: application/apply-patch
+ operation: Apply
+ time: 2023-11-22T19:11:41Z
+ - apiVersion: apiextensions.k8s.io/v1
+ fieldsType: FieldsV1
+ fieldsV1:
+ f:status:
+ f:acceptedNames:
+ f:kind: {}
+ f:listKind: {}
+ f:plural: {}
+ f:shortNames: {}
+ f:singular: {}
+ f:conditions:
+ k:{"type":"Established"}:
+ .: {}
+ f:lastTransitionTime: {}
+ f:message: {}
+ f:reason: {}
+ f:status: {}
+ f:type: {}
+ k:{"type":"NamesAccepted"}:
+ .: {}
+ f:lastTransitionTime: {}
+ f:message: {}
+ f:reason: {}
+ f:status: {}
+ f:type: {}
+ manager: kube-apiserver
+ operation: Update
+ subresource: status
+ time: 2023-11-22T19:11:42Z
+ name: helmrepositories.source.toolkit.fluxcd.io
+ resourceVersion: "78768226"
+ uid: a0308237-9185-46dd-937b-841f90eb1b1c
+spec:
+ conversion:
+ strategy: None
+ group: source.toolkit.fluxcd.io
+ names:
+ kind: HelmRepository
+ listKind: HelmRepositoryList
+ plural: helmrepositories
+ shortNames:
+ - helmrepo
+ singular: helmrepository
+ scope: Namespaced
+ versions:
+ - additionalPrinterColumns:
+ - jsonPath: .spec.url
+ name: URL
+ type: string
+ - jsonPath: .status.conditions[?(@.type=="Ready")].status
+ name: Ready
+ type: string
+ - jsonPath: .status.conditions[?(@.type=="Ready")].message
+ name: Status
+ type: string
+ - jsonPath: .metadata.creationTimestamp
+ name: Age
+ type: date
+ name: v1beta1
+ schema:
+ openAPIV3Schema:
+ description: HelmRepository is the Schema for the helmrepositories API
+ properties:
+ apiVersion:
+ description: "APIVersion defines the versioned schema of this representation of
+ an object. Servers should convert recognized schemas to the
+ latest internal value, and may reject unrecognized values. More
+ info:
+ https://git.k8s.io/community/contributors/devel/sig-architectur\
+ e/api-conventions.md#resources"
+ type: string
+ kind:
+ description: "Kind is a string value representing the REST resource this object
+ represents. Servers may infer this from the endpoint the client
+ submits requests to. Cannot be updated. In CamelCase. More info:
+ https://git.k8s.io/community/contributors/devel/sig-architectur\
+ e/api-conventions.md#types-kinds"
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: HelmRepositorySpec defines the reference to a Helm repository.
+ properties:
+ accessFrom:
+ description: AccessFrom defines an Access Control List for allowing
+ cross-namespace references to this object.
+ properties:
+ namespaceSelectors:
+ description: NamespaceSelectors is the list of namespace selectors to which this
+ ACL applies. Items in this list are evaluated using a
+ logical OR operation.
+ items:
+ description: NamespaceSelector selects the namespaces to which this ACL applies.
+ An empty map of MatchLabels matches all namespaces in
+ a cluster.
+ properties:
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: MatchLabels is a map of {key,value} pairs. A single {key,value} in
+ the matchLabels map is equivalent to an element of
+ matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains
+ only "value". The requirements are ANDed.
+ type: object
+ type: object
+ type: array
+ required:
+ - namespaceSelectors
+ type: object
+ interval:
+ description: The interval at which to check the upstream for updates.
+ type: string
+ passCredentials:
+ description: PassCredentials allows the credentials from the SecretRef to be
+ passed on to a host that does not match the host as defined
+ in URL. This may be required if the host of the advertised
+ chart URLs in the index differ from the defined URL.
+ Enabling this should be done with caution, as it can
+ potentially result in credentials getting stolen in a
+ MITM-attack.
+ type: boolean
+ secretRef:
+ description: The name of the secret containing authentication credentials for
+ the Helm repository. For HTTP/S basic auth the secret must
+ contain username and password fields. For TLS the secret
+ must contain a certFile and keyFile, and/or caFile fields.
+ properties:
+ name:
+ description: Name of the referent.
+ type: string
+ required:
+ - name
+ type: object
+ suspend:
+ description: This flag tells the controller to suspend the reconciliation of
+ this source.
+ type: boolean
+ timeout:
+ default: 60s
+ description: The timeout of index downloading, defaults to 60s.
+ type: string
+ url:
+ description: The Helm repository URL, a valid URL contains at least a protocol
+ and host.
+ type: string
+ required:
+ - interval
+ - url
+ type: object
+ status:
+ default:
+ observedGeneration: -1
+ description: HelmRepositoryStatus defines the observed state of the
+ HelmRepository.
+ properties:
+ artifact:
+ description: Artifact represents the output of the last successful repository
+ sync.
+ properties:
+ checksum:
+ description: Checksum is the SHA256 checksum of the artifact.
+ type: string
+ lastUpdateTime:
+ description: LastUpdateTime is the timestamp corresponding to the last update of
+ this artifact.
+ format: date-time
+ type: string
+ path:
+ description: Path is the relative file path of this artifact.
+ type: string
+ revision:
+ description: Revision is a human readable identifier traceable in the origin
+ source system. It can be a Git commit SHA, Git tag, a
+ Helm index timestamp, a Helm chart version, etc.
+ type: string
+ url:
+ description: URL is the HTTP address of this artifact.
+ type: string
+ required:
+ - path
+ - url
+ type: object
+ conditions:
+ description: Conditions holds the conditions for the HelmRepository.
+ items:
+ description: >-
+ Condition contains details for one aspect of the current
+ state of this API Resource. --- This struct is intended
+ for direct use as an array at the field path
+ .status.conditions. For example,
+ type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: "Available", "Progressing", and "Degraded" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,1,rep,name=conditions"`
+ // other fields }
+ properties:
+ lastTransitionTime:
+ description: lastTransitionTime is the last time the condition transitioned from
+ one status to another. This should be when the
+ underlying condition changed. If that is not known,
+ then using the time when the API field changed is
+ acceptable.
+ format: date-time
+ type: string
+ message:
+ description: message is a human readable message indicating details about the
+ transition. This may be an empty string.
+ maxLength: 32768
+ type: string
+ observedGeneration:
+ description: observedGeneration represents the .metadata.generation that the
+ condition was set based upon. For instance, if
+ .metadata.generation is currently 12, but the
+ .status.conditions[x].observedGeneration is 9, the
+ condition is out of date with respect to the current
+ state of the instance.
+ format: int64
+ minimum: 0
+ type: integer
+ reason:
+ description: reason contains a programmatic identifier indicating the reason for
+ the condition's last transition. Producers of specific
+ condition types may define expected values and
+ meanings for this field, and whether the values are
+ considered a guaranteed API. The value should be a
+ CamelCase string. This field may not be empty.
+ maxLength: 1024
+ minLength: 1
+ pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
+ type: string
+ status:
+ description: status of the condition, one of True, False, Unknown.
+ enum:
+ - "True"
+ - "False"
+ - Unknown
+ type: string
+ type:
+ description: type of condition in CamelCase or in foo.example.com/CamelCase. ---
+ Many .condition.type values are consistent across
+ resources like Available, but because arbitrary
+ conditions can be useful (see
+ .node.status.conditions), the ability to deconflict is
+ important. The regex it matches is
+ (dns1123SubdomainFmt/)?(qualifiedNameFmt)
+ maxLength: 316
+ pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
+ type: string
+ required:
+ - lastTransitionTime
+ - message
+ - reason
+ - status
+ - type
+ type: object
+ type: array
+ lastHandledReconcileAt:
+ description: LastHandledReconcileAt holds the value of the most recent reconcile
+ request value, so a change of the annotation value can be
+ detected.
+ type: string
+ observedGeneration:
+ description: ObservedGeneration is the last observed generation.
+ format: int64
+ type: integer
+ url:
+ description: URL is the download link for the last index fetched.
+ type: string
+ type: object
+ type: object
+ served: true
+ storage: false
+ subresources:
+ status: {}
+ - additionalPrinterColumns:
+ - jsonPath: .spec.url
+ name: URL
+ type: string
+ - jsonPath: .metadata.creationTimestamp
+ name: Age
+ type: date
+ - jsonPath: .status.conditions[?(@.type=="Ready")].status
+ name: Ready
+ type: string
+ - jsonPath: .status.conditions[?(@.type=="Ready")].message
+ name: Status
+ type: string
+ name: v1beta2
+ schema:
+ openAPIV3Schema:
+ description: HelmRepository is the Schema for the helmrepositories API.
+ properties:
+ apiVersion:
+ description: "APIVersion defines the versioned schema of this representation of
+ an object. Servers should convert recognized schemas to the
+ latest internal value, and may reject unrecognized values. More
+ info:
+ https://git.k8s.io/community/contributors/devel/sig-architectur\
+ e/api-conventions.md#resources"
+ type: string
+ kind:
+ description: "Kind is a string value representing the REST resource this object
+ represents. Servers may infer this from the endpoint the client
+ submits requests to. Cannot be updated. In CamelCase. More info:
+ https://git.k8s.io/community/contributors/devel/sig-architectur\
+ e/api-conventions.md#types-kinds"
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: HelmRepositorySpec specifies the required configuration to produce
+ an Artifact for a Helm repository index YAML.
+ properties:
+ accessFrom:
+ description: "AccessFrom specifies an Access Control List for allowing
+ cross-namespace references to this object. NOTE: Not
+ implemented, provisional as of
+ https://github.com/fluxcd/flux2/pull/2092"
+ properties:
+ namespaceSelectors:
+ description: NamespaceSelectors is the list of namespace selectors to which this
+ ACL applies. Items in this list are evaluated using a
+ logical OR operation.
+ items:
+ description: NamespaceSelector selects the namespaces to which this ACL applies.
+ An empty map of MatchLabels matches all namespaces in
+ a cluster.
+ properties:
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: MatchLabels is a map of {key,value} pairs. A single {key,value} in
+ the matchLabels map is equivalent to an element of
+ matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains
+ only "value". The requirements are ANDed.
+ type: object
+ type: object
+ type: array
+ required:
+ - namespaceSelectors
+ type: object
+ certSecretRef:
+ description: >-
+ CertSecretRef can be given the name of a Secret containing
+ either or both of
+ - a PEM-encoded client certificate (`tls.crt`) and private key (`tls.key`); - a PEM-encoded CA certificate (`ca.crt`)
+ and whichever are supplied, will be used for connecting to the registry. The client cert and key are useful if you are authenticating with a certificate; the CA cert is useful if you are using a self-signed server certificate. The Secret must be of type `Opaque` or `kubernetes.io/tls`.
+ It takes precedence over the values specified in the Secret referred to by `.spec.secretRef`.
+ properties:
+ name:
+ description: Name of the referent.
+ type: string
+ required:
+ - name
+ type: object
+ interval:
+ description: Interval at which the HelmRepository URL is checked for updates.
+ This interval is approximate and may be subject to jitter to
+ ensure efficient use of resources.
+ pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$
+ type: string
+ passCredentials:
+ description: PassCredentials allows the credentials from the SecretRef to be
+ passed on to a host that does not match the host as defined
+ in URL. This may be required if the host of the advertised
+ chart URLs in the index differ from the defined URL.
+ Enabling this should be done with caution, as it can
+ potentially result in credentials getting stolen in a
+ MITM-attack.
+ type: boolean
+ provider:
+ default: generic
+ description: Provider used for authentication, can be 'aws', 'azure', 'gcp' or
+ 'generic'. This field is optional, and only taken into
+ account if the .spec.type field is set to 'oci'. When not
+ specified, defaults to 'generic'.
+ enum:
+ - generic
+ - aws
+ - azure
+ - gcp
+ type: string
+ secretRef:
+ description: SecretRef specifies the Secret containing authentication
+ credentials for the HelmRepository. For HTTP/S basic auth
+ the secret must contain 'username' and 'password' fields.
+ Support for TLS auth using the 'certFile' and 'keyFile',
+ and/or 'caFile' keys is deprecated. Please use
+ `.spec.certSecretRef` instead.
+ properties:
+ name:
+ description: Name of the referent.
+ type: string
+ required:
+ - name
+ type: object
+ suspend:
+ description: Suspend tells the controller to suspend the reconciliation of this
+ HelmRepository.
+ type: boolean
+ timeout:
+ default: 60s
+ description: Timeout is used for the index fetch operation for an HTTPS helm
+ repository, and for remote OCI Repository operations like
+ pulling for an OCI helm repository. Its default value is
+ 60s.
+ pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$
+ type: string
+ type:
+ description: Type of the HelmRepository. When this field is set to "oci", the
+ URL field value must be prefixed with "oci://".
+ enum:
+ - default
+ - oci
+ type: string
+ url:
+ description: URL of the Helm repository, a valid URL contains at least a
+ protocol and host.
+ type: string
+ required:
+ - interval
+ - url
+ type: object
+ status:
+ default:
+ observedGeneration: -1
+ description: HelmRepositoryStatus records the observed state of the
+ HelmRepository.
+ properties:
+ artifact:
+ description: Artifact represents the last successful HelmRepository
+ reconciliation.
+ properties:
+ digest:
+ description: Digest is the digest of the file in the form of
+ ':'.
+ pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$
+ type: string
+ lastUpdateTime:
+ description: LastUpdateTime is the timestamp corresponding to the last update of
+ the Artifact.
+ format: date-time
+ type: string
+ metadata:
+ additionalProperties:
+ type: string
+ description: Metadata holds upstream information such as OCI annotations.
+ type: object
+ path:
+ description: Path is the relative file path of the Artifact. It can be used to
+ locate the file in the root of the Artifact storage on
+ the local file system of the controller managing the
+ Source.
+ type: string
+ revision:
+ description: Revision is a human-readable identifier traceable in the origin
+ source system. It can be a Git commit SHA, Git tag, a
+ Helm chart version, etc.
+ type: string
+ size:
+ description: Size is the number of bytes in the file.
+ format: int64
+ type: integer
+ url:
+ description: URL is the HTTP address of the Artifact as exposed by the
+ controller managing the Source. It can be used to
+ retrieve the Artifact for consumption, e.g. by another
+ controller applying the Artifact contents.
+ type: string
+ required:
+ - lastUpdateTime
+ - path
+ - revision
+ - url
+ type: object
+ conditions:
+ description: Conditions holds the conditions for the HelmRepository.
+ items:
+ description: >-
+ Condition contains details for one aspect of the current
+ state of this API Resource. --- This struct is intended
+ for direct use as an array at the field path
+ .status.conditions. For example,
+ type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: "Available", "Progressing", and "Degraded" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,1,rep,name=conditions"`
+ // other fields }
+ properties:
+ lastTransitionTime:
+ description: lastTransitionTime is the last time the condition transitioned from
+ one status to another. This should be when the
+ underlying condition changed. If that is not known,
+ then using the time when the API field changed is
+ acceptable.
+ format: date-time
+ type: string
+ message:
+ description: message is a human readable message indicating details about the
+ transition. This may be an empty string.
+ maxLength: 32768
+ type: string
+ observedGeneration:
+ description: observedGeneration represents the .metadata.generation that the
+ condition was set based upon. For instance, if
+ .metadata.generation is currently 12, but the
+ .status.conditions[x].observedGeneration is 9, the
+ condition is out of date with respect to the current
+ state of the instance.
+ format: int64
+ minimum: 0
+ type: integer
+ reason:
+ description: reason contains a programmatic identifier indicating the reason for
+ the condition's last transition. Producers of specific
+ condition types may define expected values and
+ meanings for this field, and whether the values are
+ considered a guaranteed API. The value should be a
+ CamelCase string. This field may not be empty.
+ maxLength: 1024
+ minLength: 1
+ pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
+ type: string
+ status:
+ description: status of the condition, one of True, False, Unknown.
+ enum:
+ - "True"
+ - "False"
+ - Unknown
+ type: string
+ type:
+ description: type of condition in CamelCase or in foo.example.com/CamelCase. ---
+ Many .condition.type values are consistent across
+ resources like Available, but because arbitrary
+ conditions can be useful (see
+ .node.status.conditions), the ability to deconflict is
+ important. The regex it matches is
+ (dns1123SubdomainFmt/)?(qualifiedNameFmt)
+ maxLength: 316
+ pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
+ type: string
+ required:
+ - lastTransitionTime
+ - message
+ - reason
+ - status
+ - type
+ type: object
+ type: array
+ lastHandledReconcileAt:
+ description: LastHandledReconcileAt holds the value of the most recent reconcile
+ request value, so a change of the annotation value can be
+ detected.
+ type: string
+ observedGeneration:
+ description: ObservedGeneration is the last observed generation of the
+ HelmRepository object.
+ format: int64
+ type: integer
+ url:
+ description: URL is the dynamic fetch link for the latest Artifact. It is
+ provided on a "best effort" basis, and using the precise
+ HelmRepositoryStatus.Artifact data is recommended.
+ type: string
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
+status:
+ acceptedNames:
+ kind: HelmRepository
+ listKind: HelmRepositoryList
+ plural: helmrepositories
+ shortNames:
+ - helmrepo
+ singular: helmrepository
+ conditions:
+ - lastTransitionTime: 2023-11-22T19:11:41Z
+ message: no conflicts found
+ reason: NoConflicts
+ status: "True"
+ type: NamesAccepted
+ - lastTransitionTime: 2023-11-22T19:11:42Z
+ message: the initial names have been accepted
+ reason: InitialNamesAccepted
+ status: "True"
+ type: Established
+ storedVersions:
+ - v1beta2
\ No newline at end of file
diff --git a/lib/console.ex b/lib/console.ex
index 247aaec7e7..0e16296348 100644
--- a/lib/console.ex
+++ b/lib/console.ex
@@ -138,6 +138,11 @@ defmodule Console do
|> Base.url_encode64()
end
+ def shab16(body) do
+ :crypto.hash(:sha, body)
+ |> Base.encode16(case: :lower)
+ end
+
def put_path(map, [k], value), do: Map.put(map, k, value)
def put_path(map, [k | rest], value) do
case map do
diff --git a/lib/console/application.ex b/lib/console/application.ex
index fc0bc1a2e7..7f8451fa3c 100644
--- a/lib/console/application.ex
+++ b/lib/console/application.ex
@@ -21,6 +21,7 @@ defmodule Console.Application do
{Registry, [keys: :unique, name: Console.Deployments.Pipelines.Supervisor.registry()]},
{Cluster.Supervisor, [topologies, [name: Console.ClusterSupervisor]]},
Console.Deployments.Git.Supervisor,
+ Console.Deployments.Helm.Server,
Console.Deployments.Pipelines.Supervisor,
Console.Deployments.Git.Kick,
Console.Deployments.Deprecations.Table,
diff --git a/lib/console/commands/plural.ex b/lib/console/commands/plural.ex
index 18cdd28b79..8f8da2136d 100644
--- a/lib/console/commands/plural.ex
+++ b/lib/console/commands/plural.ex
@@ -21,9 +21,9 @@ defmodule Console.Commands.Plural do
with conf when is_binary(conf) <- kubeconfig,
{:ok, f} <- Briefly.create(),
:ok <- File.write(f, conf) do
- plural("deployments", ["install", "--url", url, "--token", token], [{"KUBECONFIG", f}, {"PLURAL_INSTALL_AGENT_CONFIRM", "true"}])
+ plural_home("deployments", ["install", "--url", url, "--token", token, "--force"], [{"KUBECONFIG", f}, {"PLURAL_INSTALL_AGENT_CONFIRM", "true"}])
else
- nil -> plural("deployments", ["install", "--url", url, "--token", token], [{"PLURAL_INSTALL_AGENT_CONFIRM", "true"}])
+ nil -> plural_home("deployments", ["install", "--url", url, "--token", token, "--force"], [{"PLURAL_INSTALL_AGENT_CONFIRM", "true"}])
err -> err
end
end
@@ -47,5 +47,8 @@ defmodule Console.Commands.Plural do
def repair(), do: plural("repair", [])
+ def plural_home(command, args, env \\ []),
+ do: cmd("plural", [command | args], System.user_home(), env)
+
def plural(command, args, env \\ []), do: cmd("plural", [command | args], workspace(), env)
end
diff --git a/lib/console/deployments/git.ex b/lib/console/deployments/git.ex
index 6d42da0bab..86da8a16d3 100644
--- a/lib/console/deployments/git.ex
+++ b/lib/console/deployments/git.ex
@@ -73,6 +73,17 @@ defmodule Console.Deployments.Git do
end
end
+ @doc """
+ Fetches all helm repos registered in this cluster so far
+ """
+ @spec list_helm_repositories() :: {:ok, [Kube.HelmRepository.t]} | Console.error
+ def list_helm_repositories() do
+ case Kube.Client.list_helm_repositories() do
+ {:ok, %{items: items}} -> {:ok, items}
+ _ -> {:ok, []}
+ end
+ end
+
def status(%GitRepository{} = repo, status) do
GitRepository.status_changeset(repo, status)
|> Console.Repo.update()
diff --git a/lib/console/deployments/helm/cache.ex b/lib/console/deployments/helm/cache.ex
new file mode 100644
index 0000000000..c728e74ab3
--- /dev/null
+++ b/lib/console/deployments/helm/cache.ex
@@ -0,0 +1,41 @@
+defmodule Console.Deployments.Helm.Cache do
+ require Logger
+ alias Kube.HelmChart
+ alias Console.Deployments.Tar
+
+ defstruct [:dir]
+
+ def new() do
+ {:ok, dir} = Briefly.create(directory: true)
+ %__MODULE__{dir: dir}
+ end
+
+ def fetch(%__MODULE__{dir: dir}, %HelmChart{
+ spec: %HelmChart.Spec{chart: chart},
+ status: %HelmChart.Status{artifact: %HelmChart.Status.Artifact{digest: sha, url: url}}
+ }) when is_binary(url) do
+ cache_path = Path.join(dir, sha)
+ case File.exists?(cache_path) do
+ true -> File.open(cache_path)
+ false -> build_tarball(url, cache_path, chart)
+ end
+ end
+ def fetch(_, _), do: {:error, "chart not yet loaded"}
+
+ defp build_tarball(url, path, chart) do
+ with {:ok, f} <- Tar.from_url(url),
+ {:ok, contents} <- Tar.tar_stream(f),
+ :ok <- Tar.tarball(path, remove_prefix(contents, chart)),
+ do: File.open(path)
+ end
+
+ def refresh(%__MODULE__{dir: dir}) do
+ Logger.info "expiring helm chart cache..."
+ File.rm_rf!(dir)
+ new()
+ end
+
+ defp remove_prefix(contents, chart) do
+ Enum.map(contents, fn {path, content} -> {String.trim_leading(path, "#{chart}/"), content} end)
+ end
+end
diff --git a/lib/console/deployments/helm/charts.ex b/lib/console/deployments/helm/charts.ex
new file mode 100644
index 0000000000..7e029b4ef1
--- /dev/null
+++ b/lib/console/deployments/helm/charts.ex
@@ -0,0 +1,64 @@
+defmodule Console.Deployments.Helm.Charts do
+ alias Kube.Client
+ alias Kube.HelmChart
+ alias Console.Schema.Service
+ alias Console.Deployments.Helm.Server
+ alias Kazan.Models.Apimachinery.Meta.V1, as: MetaV1
+
+ @doc """
+ Downloads a chart artifact from the found chart crd of the given service
+ """
+ @spec artifact(Service.t) :: {:ok, File.t, binary} | Console.error
+ def artifact(%Service{} = svc) do
+ with {:ok, chart} <- get(svc),
+ {:ok, f} <- Server.fetch(chart) do
+ {:ok, f, chart.status.artifact.digest}
+ else
+ {:ok, _} -> {:error, "chart not yet loaded"}
+ err -> err
+ end
+ end
+
+ @spec get(Service.t) :: {:ok, HelmChart.t} | Console.error
+ def get(%Service{helm: %Service.Helm{chart: chart, version: vsn, repository: %{namespace: ns, name: n}}})
+ when is_binary(chart) and is_binary(vsn) do
+ name = chart_name(n, chart, vsn)
+ case Client.get_helm_chart(ns, name) do
+ {:ok, chart} -> {:ok, chart}
+ _ -> jit_create(ns, name, n, chart, vsn)
+ end
+ end
+ def get(_), do: {:error, "service does not reference a helm chart"}
+
+ defp jit_create(namespace, name, repo, chart, version) do
+ Client.create_helm_chart(%HelmChart{
+ metadata: %MetaV1.ObjectMeta{
+ name: name,
+ namespace: namespace,
+ annotations: %{
+ "platform.plural.sh/helm-chart" => "true"
+ }
+ },
+ spec: %HelmChart.Spec{
+ interval: "5m0s",
+ chart: chart,
+ version: version,
+ reconcile_strategy: "ChartVersion",
+ source_ref: %HelmChart.Spec.SourceRef{
+ kind: "HelmRepository",
+ name: repo,
+ },
+ }
+ }, namespace)
+ end
+
+ @doc """
+ fetches the crd name we use for a given chart
+ """
+ @spec chart_name(binary, binary, binary) :: binary
+ def chart_name(repo, chart, vsn) do
+ vsn = Console.shab16(vsn)
+ |> String.slice(0..6)
+ "plrl-#{repo}-#{chart}-#{vsn}"
+ end
+end
diff --git a/lib/console/deployments/helm/repository.ex b/lib/console/deployments/helm/repository.ex
new file mode 100644
index 0000000000..6156de574d
--- /dev/null
+++ b/lib/console/deployments/helm/repository.ex
@@ -0,0 +1,38 @@
+defmodule Console.Deployments.Helm.Repository do
+ alias Kube.HelmRepository
+ alias Console.Deployments.Helm.{Schema, Chart}
+
+ @doc """
+ Fetches a helm repository by namespace/name
+ """
+ @spec get(binary, binary) :: {:ok, HelmRepository.t} | Console.error
+ def get(ns, n), do: Kube.Client.get_helm_repository(ns, n)
+
+ @doc """
+ Gets the current status of this repository object
+ """
+ @spec status(HelmRepository.t) :: {:ok, %{ready: boolean, message: binary}} | Console.error
+ def status(%HelmRepository{status: %HelmRepository.Status{conditions: [_ | _] = conditions}}) do
+ case Enum.find(conditions, & &1.type == "Ready") do
+ %{status: status, message: message} -> {:ok, %{ready: status == "True", message: message}}
+ _ -> {:ok, %{ready: false}}
+ end
+ end
+ def status(_), do: {:ok, %{ready: false}}
+
+ @doc """
+ it will fetch the charts for a helm repository if they can be found
+ """
+ @spec charts(HelmRepository.t) :: {:ok, [%{name: binary, chart: Chart.t}]} | Console.error
+ def charts(%HelmRepository{status: %HelmRepository.Status{
+ artifact: %HelmRepository.Status.Artifact{url: url}
+ }}) when is_binary(url) do
+ with {:ok, %HTTPoison.Response{status_code: 200, body: body}} <- HTTPoison.get(url),
+ {:ok, yaml} <- YamlElixir.read_from_string(body) do
+ helm = %Schema{entries: yaml["entries"]}
+ helm = Schema.transform(helm)
+ {:ok, helm.entries}
+ end
+ end
+ def charts(_), do: {:ok, []}
+end
diff --git a/lib/console/deployments/helm/schema.ex b/lib/console/deployments/helm/schema.ex
new file mode 100644
index 0000000000..e545f66e4c
--- /dev/null
+++ b/lib/console/deployments/helm/schema.ex
@@ -0,0 +1,29 @@
+defmodule Console.Deployments.Helm.Chart do
+ @type t :: %__MODULE__{}
+ defstruct [:app_version, :version, :name, :type, :application, :digest]
+
+ def build(map) do
+ %__MODULE__{
+ app_version: map["appVersion"],
+ version: map["version"],
+ name: map["name"],
+ type: map["type"],
+ application: map["application"],
+ digest: map["digest"]
+ }
+ end
+end
+
+defmodule Console.Deployments.Helm.Schema do
+ alias Console.Deployments.Helm.Chart
+
+ defstruct [:entries, :apiVersion]
+
+ def transform(%__MODULE__{entries: %{} = entries} = repo) do
+ entries = Enum.map(entries, fn {name, charts} ->
+ %{name: name, versions: Enum.map(charts, &Chart.build/1)}
+ end)
+ %{repo | entries: entries}
+ end
+ def transform(pass), do: pass
+end
diff --git a/lib/console/deployments/helm/server.ex b/lib/console/deployments/helm/server.ex
new file mode 100644
index 0000000000..de01806881
--- /dev/null
+++ b/lib/console/deployments/helm/server.ex
@@ -0,0 +1,23 @@
+defmodule Console.Deployments.Helm.Server do
+ use GenServer
+ alias Kube.HelmChart
+ alias Console.Deployments.Helm.Cache
+
+ @expiry :timer.minutes(60)
+
+ def start_link(opts \\ :ok) do
+ GenServer.start_link(__MODULE__, opts, name: __MODULE__)
+ end
+
+ def init(_) do
+ :timer.send_interval(@expiry, :expire)
+ {:ok, Cache.new()}
+ end
+
+ def fetch(%HelmChart{} = chart), do: GenServer.call(__MODULE__, {:fetch, chart})
+
+ def handle_call({:fetch, chart}, _, cache), do: {:reply, Cache.fetch(cache, chart), cache}
+
+ def handle_info(:expire, cache), do: {:noreply, Cache.refresh(cache)}
+ def handle_info(_, cache), do: {:noreply, cache}
+end
diff --git a/lib/console/deployments/pipelines.ex b/lib/console/deployments/pipelines.ex
index 96d0d9ca1a..f5111f907c 100644
--- a/lib/console/deployments/pipelines.ex
+++ b/lib/console/deployments/pipelines.ex
@@ -245,9 +245,12 @@ defmodule Console.Deployments.Pipelines do
end
defp promote_edge(xact, _, _), do: xact
- defp promote_service(%Revision{sha: sha, git: %{folder: f}} = rev, %StageService{service_id: id} = ss) do
+ defp promote_service(%Revision{sha: sha} = rev, %StageService{service_id: id} = ss) do
with {:ok, configs} <- configs(rev, ss) do
- Map.merge(%{git: %{ref: sha, folder: f}}, configs)
+ Map.merge(%{
+ git: rev.git && %{ref: sha, folder: rev.git.folder},
+ helm: rev.helm && %{version: rev.helm.version, chart: rev.helm.chart}
+ }, configs)
|> Services.update_service(id)
end
end
diff --git a/lib/console/deployments/pubsub/recurse.ex b/lib/console/deployments/pubsub/recurse.ex
index 1891fb6714..2756da299c 100644
--- a/lib/console/deployments/pubsub/recurse.ex
+++ b/lib/console/deployments/pubsub/recurse.ex
@@ -18,11 +18,20 @@ defimpl Console.PubSub.Recurse, for: Console.PubSub.ServiceComponentsUpdated do
def process(_), do: :ok
end
+defimpl Console.PubSub.Recurse, for: Console.PubSub.ServiceCreated do
+ alias Console.Schema.Service
+ alias Console.Deployments.Helm.Charts
+
+ def process(%{item: %Service{} = svc}), do: Charts.get(svc)
+end
+
defimpl Console.PubSub.Recurse, for: Console.PubSub.ServiceUpdated do
alias Console.Deployments.Global
+ alias Console.Deployments.Helm.Charts
alias Console.Schema.{User, Service, GlobalService}
def process(%{item: %Service{} = item, actor: %User{}}) do
+ Charts.get(item)
case Console.Repo.preload(item, [:global_service]) do
%Service{global_service: %GlobalService{} = global} ->
{:global, Global.sync_clusters(global)}
diff --git a/lib/console/deployments/services.ex b/lib/console/deployments/services.ex
index 7159d8cf12..8a33d39df9 100644
--- a/lib/console/deployments/services.ex
+++ b/lib/console/deployments/services.ex
@@ -2,8 +2,9 @@ defmodule Console.Deployments.Services do
use Console.Services.Base
import Console.Deployments.Policies
alias Console.PubSub
- alias Console.Schema.{Service, ServiceComponent, Revision, User, Cluster, ClusterProvider, ApiDeprecation}
- alias Console.Deployments.{Secrets.Store, Git, Clusters, Deprecations.Checker, AddOns}
+ alias Console.Schema.{Service, ServiceComponent, Revision, User, Cluster, ClusterProvider, ApiDeprecation, GitRepository}
+ alias Console.Deployments.{Secrets.Store, Settings, Git, Clusters, Deprecations.Checker, AddOns, Tar}
+ alias Console.Deployments.Helm
require Logger
@type service_resp :: {:ok, Service.t} | Console.error
@@ -25,8 +26,27 @@ defmodule Console.Deployments.Services do
def tarball(%Service{id: id}), do: api_url("v1/git/tarballs?id=#{id}")
+ @doc """
+ Constructs a filestream for the tar artifact of a service, and perhaps performs some JIT modifications
+ before sending it upstream to the given client.
+ """
+ @spec tarstream(Service.t) :: {:ok, File.t} | Console.error
+ def tarstream(%Service{helm: %Service.Helm{values: values}} = svc) when is_binary(values) do
+ with {:ok, tar} <- tarfile(svc),
+ do: Tar.splice(tar, %{"values.yaml.liquid" => values})
+ end
+ def tarstream(%Service{} = svc), do: tarfile(svc)
+
+ defp tarfile(%Service{helm: %Service.Helm{chart: c, version: v}} = svc) when is_binary(c) and is_binary(v) do
+ with {:ok, f, sha} <- Helm.Charts.artifact(svc),
+ {:ok, _} <- update_sha_without_revision(svc, sha),
+ do: {:ok, f}
+ end
+ defp tarfile(%Service{} = svc), do: Git.Discovery.fetch(svc)
+
def referenced?(id) do
- Enum.map([Cluster.for_service(id), ClusterProvider.for_service(id)], &Console.Repo.exists?/1)
+ [Cluster.for_service(id), ClusterProvider.for_service(id)]
+ |> Enum.map(&Console.Repo.exists?/1)
|> Enum.any?(& &1)
end
@@ -55,6 +75,11 @@ defmodule Console.Deployments.Services do
|> Service.changeset(add_version(attrs, "0.0.1"))
|> Console.Repo.insert()
end)
+ |> add_operation(:check_repo, fn
+ %{base: %{helm: %{repository: %{namespace: ns, name: n}}}} ->
+ Helm.Repository.get(ns, n)
+ _ -> {:ok, true}
+ end)
|> add_operation(:revision, fn %{base: base} -> create_revision(add_version(attrs, "0.0.1"), base) end)
|> add_revision()
|> execute(extract: :service)
@@ -188,7 +213,8 @@ defmodule Console.Deployments.Services do
end)
|> add_operation(:create, fn %{source: source, config: config} ->
Map.take(source, [:repository_id, :sha, :name, :namespace])
- |> Map.put(:git, Map.from_struct(source.git))
+ |> Console.dedupe(:git, source.git && %{ref: source.git.ref, folder: source.git.folder})
+ |> Console.dedupe(:helm, source.helm && Console.mapify(source.helm))
|> Map.merge(attrs)
|> Map.put(:configuration, config)
|> create_service(cluster_id, user)
@@ -197,6 +223,37 @@ defmodule Console.Deployments.Services do
|> notify(:create, user)
end
+ @doc """
+ Allows the console to manage its own upgrades, given the original installation values file
+ """
+ @spec self_manage(binary, User.t) :: service_resp
+ def self_manage(values, %User{} = user) do
+ start_transaction()
+ |> add_operation(:values, fn _ -> YamlElixir.read_from_string(values) end)
+ |> add_operation(:git, fn _ ->
+ url = "https://github.com/pluralsh/console.git"
+ case Git.get_by_url(url) do
+ %GitRepository{} = git -> {:ok, git}
+ _ -> Git.create_repository(%{url: url}, user)
+ end
+ end)
+ |> add_operation(:settings, fn _ ->
+ Settings.update(%{self_managed: true}, user)
+ end)
+ |> add_operation(:service, fn %{git: git} ->
+ cluster = Clusters.local_cluster()
+ create_service(%{
+ name: "console",
+ namespace: "plrl-console",
+ repository_id: git.id,
+ protect: true,
+ git: %{ref: "master", folder: "charts/console"},
+ helm: %{values: values},
+ }, cluster.id, user)
+ end)
+ |> execute(extract: :service)
+ end
+
@doc """
Updates the sha of a service if relevant
"""
@@ -219,7 +276,8 @@ defmodule Console.Deployments.Services do
end)
|> add_operation(:revision, fn %{base: base} ->
add_version(%{sha: sha, message: msg}, base.version)
- |> Console.dedupe(:git, %{ref: sha, folder: base.git.folder})
+ |> Console.dedupe(:git, base.git && %{ref: sha, folder: base.git.folder})
+ |> Console.dedupe(:helm, base.helm && Console.mapify(base.helm))
|> Console.dedupe(:configuration, fn ->
{:ok, secrets} = configuration(base)
Enum.map(secrets, fn {k, v} -> %{name: k, value: v} end)
@@ -230,6 +288,25 @@ defmodule Console.Deployments.Services do
|> notify(:update, :ignore)
end
+ defp update_sha_without_revision(%Service{sha: sha} = svc, sha), do: {:ok, svc}
+ defp update_sha_without_revision(%Service{id: id}, sha) do
+ start_transaction()
+ |> add_operation(:base, fn _ ->
+ get_service!(id)
+ |> Service.changeset(%{sha: sha})
+ |> Repo.update()
+ end)
+ |> add_operation(:current, fn %{base: base} ->
+ case Repo.preload(base, [:revision]) do
+ %{revision: %Revision{} = revision} ->
+ Revision.update_changeset(revision, %{sha: sha})
+ |> Repo.update()
+ _ -> {:ok, base}
+ end
+ end)
+ |> execute(extract: :base)
+ end
+
def update_service(attrs, svc_id) when is_binary(svc_id),
do: update_service(attrs, get_service!(svc_id))
def update_service(attrs, %Service{} = svc) do
@@ -240,7 +317,8 @@ defmodule Console.Deployments.Services do
end)
|> add_operation(:revision, fn %{base: base} ->
add_version(attrs, base.version)
- |> Console.dedupe(:git, Map.take(base.git, ~w(ref folder)a))
+ |> Console.dedupe(:git, base.git && Console.mapify(base.git))
+ |> Console.dedupe(:helm, base.helm && Console.mapify(base.helm))
|> Console.dedupe(:configuration, fn ->
{:ok, secrets} = configuration(base)
Enum.map(secrets, fn {k, v} -> %{name: k, value: v} end)
@@ -257,7 +335,7 @@ defmodule Console.Deployments.Services do
fetches the docs for a given service out of git, and renders them as a list of file path/content pairs
"""
@spec docs(Service.t) :: [%{path: binary, content: binary}]
- def docs(%Service{} = svc) do
+ def docs(%Service{repository_id: id} = svc) when is_binary(id) do
with {:ok, f} <- Git.Discovery.docs(svc),
{:ok, res} <- AddOns.tar_stream(f) do
{:ok, Enum.map(res, fn {name, content} -> %{path: name, content: content} end)}
@@ -267,6 +345,7 @@ defmodule Console.Deployments.Services do
{:error, "could not fetch docs"}
end
end
+ def docs(_), do: {:ok, []}
@doc """
Rollbacks a service to a given revision id, all configuration will then be fetched via that revision
@@ -286,12 +365,12 @@ defmodule Console.Deployments.Services do
end
end)
|> add_operation(:update, fn %{service: svc, revision: rev} ->
- svc
- |> Service.rollback_changeset(%{
+ Service.rollback_changeset(svc, %{
status: :stale,
revision_id: rev.id,
sha: rev.sha,
- git: Map.take(rev.git, [:ref, :folder])
+ git: rev.git && Map.take(rev.git, [:ref, :folder]),
+ helm: rev.helm && Console.mapify(rev.helm)
})
|> Repo.update()
end)
diff --git a/lib/console/deployments/tar.ex b/lib/console/deployments/tar.ex
new file mode 100644
index 0000000000..d5d1614053
--- /dev/null
+++ b/lib/console/deployments/tar.ex
@@ -0,0 +1,59 @@
+defmodule Console.Deployments.Tar do
+ @type err :: Console.error
+
+ @doc """
+ Streams a tar from a url to a local file and returns a handle
+ """
+ @spec from_url(binary) :: {:ok, File.t} | err
+ def from_url(url) do
+ stream = HTTPStream.get(url)
+ with {:ok, tmp} <- Briefly.create(),
+ :ok <- Stream.into(stream, File.stream!(tmp)) |> Stream.run(),
+ do: File.open(tmp)
+ end
+
+ @doc """
+ Converts a list of tar contents to a new tarball file and returns a working handle
+ """
+ @spec tarball([{binary, binary}]) :: {:ok, File.t} | err
+ def tarball(contents) do
+ with {:ok, tmp} <- Briefly.create(),
+ :ok <- tarball(tmp, contents),
+ do: File.open(tmp)
+ end
+
+ @spec tarball(binary, [{binary, binary}]) :: :ok | err
+ def tarball(file, contents) do
+ tar_contents = Enum.map(contents, fn {p, c} -> {to_charlist(p), c} end)
+ to_charlist(file)
+ |> :erl_tar.create(tar_contents, [:compressed])
+ end
+
+ @doc """
+ Takes a tar file and adds a set of additional files to it, then returns a new file handle to it
+ """
+ @spec splice(File.t, map) :: {:ok, File.t} | err
+ def splice(tar_file, additional) do
+ with {:ok, contents} <- tar_stream(tar_file) do
+ Map.new(contents)
+ |> Map.merge(additional)
+ |> Map.to_list()
+ |> tarball()
+ end
+ end
+
+ @doc """
+ Streams a tar from an open file and returns a list of file names/contents
+ """
+ @spec tar_stream(File.t) :: {:ok, [{binary, binary}]} | err
+ def tar_stream(tar_file) do
+ try do
+ with {:ok, tmp} <- Briefly.create(),
+ _ <- IO.binstream(tar_file, 1024) |> Enum.into(File.stream!(tmp)),
+ {:ok, res} <- :erl_tar.extract(tmp, [:compressed, :memory]),
+ do: {:ok, Enum.map(res, fn {name, content} -> {to_string(name), to_string(content)} end)}
+ after
+ File.close(tar_file)
+ end
+ end
+end
diff --git a/lib/console/graphql.ex b/lib/console/graphql.ex
index 2be52ced8d..5132e27c12 100644
--- a/lib/console/graphql.ex
+++ b/lib/console/graphql.ex
@@ -3,7 +3,7 @@ defmodule Console.GraphQl do
use Absinthe.Relay.Schema, :modern
import Console.GraphQl.Helpers
alias Console.Middleware.{SafeResolution, ErrorHandler}
- alias Console.GraphQl.Resolvers.{Build, User, Kubecost, License, UserLoader, Deployments}
+ alias Console.GraphQl.Resolvers.{Build, User, Kubecost, License, UserLoader, HelmRepositoryLoader, Deployments}
import_types Absinthe.Type.Custom
import_types Absinthe.Plug.Types
@@ -28,7 +28,8 @@ defmodule Console.GraphQl do
Kubecost,
License,
Deployments,
- UserLoader
+ UserLoader,
+ HelmRepositoryLoader
]
def context(ctx) do
diff --git a/lib/console/graphql/deployments.ex b/lib/console/graphql/deployments.ex
index cc1e1523d5..9a10d9af50 100644
--- a/lib/console/graphql/deployments.ex
+++ b/lib/console/graphql/deployments.ex
@@ -24,6 +24,7 @@ defmodule Console.GraphQl.Deployments do
field :id, non_null(:id)
field :enabled, non_null(:boolean), description: "whether you've yet to enable CD for this instance"
field :name, non_null(:string)
+ field :self_managed, :boolean, description: "whether the byok cluster has been brought under self-management"
field :artifact_repository, :git_repository, resolve: dataloader(Deployments), description: "the repo to fetch CAPI manifests from, for both providers and clusters"
field :deployer_repository, :git_repository, resolve: dataloader(Deployments), description: "the repo to fetch the deploy operators manifests from"
diff --git a/lib/console/graphql/deployments/git.ex b/lib/console/graphql/deployments/git.ex
index 4808477794..1a484e3197 100644
--- a/lib/console/graphql/deployments/git.ex
+++ b/lib/console/graphql/deployments/git.ex
@@ -27,11 +27,53 @@ defmodule Console.GraphQl.Deployments.Git do
field :https_path, :string, description: "the https url for this git repo"
field :url_format, :string, description: "a format string to get the http url for a subfolder in a git repo"
- field :editable, :boolean, resolve: &Deployments.editable/3, description: "whether the current user can edit this repo"
+ field :editable, :boolean,
+ resolve: &Deployments.editable/3,
+ description: "whether the current user can edit this repo"
timestamps()
end
+ @desc "a crd representation of a helm repository"
+ object :helm_repository do
+ field :metadata, non_null(:metadata)
+ field :spec, non_null(:helm_repository_spec)
+ field :charts, list_of(:helm_chart_entry),
+ resolve: &Deployments.helm_charts/3,
+ description: "the charts found in this repository (heavy operation, don't do in list endpoints)"
+ field :status, :helm_repository_status,
+ resolve: &Deployments.helm_status/3,
+ description: "can fetch the status of a given helm repository"
+ end
+
+ @desc "a specification of how a helm repository is fetched"
+ object :helm_repository_spec do
+ field :provider, :string
+ field :url, non_null(:string)
+ field :type, :string
+ end
+
+ @desc "the state of this helm repository"
+ object :helm_repository_status do
+ field :ready, :boolean
+ field :message, :string
+ end
+
+ @desc "a chart manifest entry, including all versions"
+ object :helm_chart_entry do
+ field :name, :string, description: "the name of the chart"
+ field :versions, list_of(:helm_chart_version), description: "all found versions of the chart"
+ end
+
+ @desc "a chart version contained within a helm repository manifest"
+ object :helm_chart_version do
+ field :app_version, :string, description: "the version of the app contained w/in this chart"
+ field :version, :string, description: "the version of the chart itself"
+ field :name, :string, description: "the name of the chart"
+ field :type, :string
+ field :digest, :string, description: "sha digest of this chart's contents"
+ end
+
connection node_type: :git_repository
delta :git_repository
@@ -50,6 +92,20 @@ defmodule Console.GraphQl.Deployments.Git do
resolve &Deployments.list_git_repositories/2
end
+
+ field :helm_repositories, list_of(:helm_repository) do
+ middleware Authenticated
+
+ resolve &Deployments.list_helm_repositories/2
+ end
+
+ field :helm_repository, :helm_repository do
+ middleware Authenticated
+ arg :name, non_null(:string)
+ arg :namespace, non_null(:string)
+
+ resolve &Deployments.get_helm_repository/2
+ end
end
object :git_mutations do
diff --git a/lib/console/graphql/deployments/service.ex b/lib/console/graphql/deployments/service.ex
index b589f9a0a8..09fd8db62a 100644
--- a/lib/console/graphql/deployments/service.ex
+++ b/lib/console/graphql/deployments/service.ex
@@ -14,7 +14,8 @@ defmodule Console.GraphQl.Deployments.Service do
field :sync_config, :sync_config_attributes
field :protect, :boolean
field :repository_id, non_null(:id)
- field :git, non_null(:git_ref_attributes)
+ field :git, :git_ref_attributes
+ field :helm, :helm_config_attributes
field :kustomize, :kustomize_attributes
field :configuration, list_of(:config_attributes)
field :read_bindings, list_of(:policy_binding_attributes)
@@ -26,6 +27,14 @@ defmodule Console.GraphQl.Deployments.Service do
field :diff_normalizer, :diff_normalizer_attributes
end
+ input_object :helm_config_attributes do
+ field :values, :string
+ field :values_files, list_of(:string)
+ field :chart, :string
+ field :version, :string
+ field :repository, :namespaced_name
+ end
+
input_object :metadata_attributes do
field :labels, :map
field :annotations, :map
@@ -43,6 +52,7 @@ defmodule Console.GraphQl.Deployments.Service do
field :version, :string
field :protect, :boolean
field :git, :git_ref_attributes
+ field :helm, :helm_config_attributes
field :configuration, list_of(:config_attributes)
field :kustomize, :kustomize_attributes
end
@@ -95,7 +105,12 @@ defmodule Console.GraphQl.Deployments.Service do
field :namespace, non_null(:string), description: "kubernetes namespace this service will be deployed to"
field :status, non_null(:service_deployment_status), description: "A summary status enum for the health of this service"
field :version, non_null(:string), description: "semver of this service"
- field :git, non_null(:git_ref), description: "description on where in git the service's manifests should be fetched"
+ field :git, :git_ref, description: "description on where in git the service's manifests should be fetched"
+ field :helm, :helm_spec, description: "description of how helm charts should be applied", resolve: fn
+ %{helm: %{} = helm} = svc, _, _ ->
+ {:ok, Map.put(helm, :parent, svc)}
+ svc, _, _ -> {:ok, svc.helm}
+ end
field :protect, :boolean, description: "if true, deletion of this service is not allowed"
field :sha, :string, description: "latest git sha we pulled from"
field :tarball, :string, resolve: &Deployments.tarball/3, description: "https url to fetch the latest tarball of kubernetes manifests"
@@ -110,6 +125,11 @@ defmodule Console.GraphQl.Deployments.Service do
field :repository, :git_repository, resolve: dataloader(Deployments), description: "the git repo of this service"
+ field :helm_repository, :helm_repository, resolve: fn
+ svc, _, %{context: %{loader: loader}} ->
+ manual_dataloader(loader, Console.GraphQl.Resolvers.HelmRepositoryLoader, :helm, svc)
+ end
+
field :read_bindings, list_of(:policy_binding), resolve: dataloader(Deployments), description: "read policy for this service"
field :write_bindings, list_of(:policy_binding), resolve: dataloader(Deployments), description: "write policy of this service"
@@ -135,7 +155,8 @@ defmodule Console.GraphQl.Deployments.Service do
object :revision do
field :id, non_null(:id), description: "id of this revision"
field :version, non_null(:string), description: "the service's semver"
- field :git, non_null(:git_ref), description: "git spec of the prior revision"
+ field :git, :git_ref, description: "git spec of the prior revision"
+ field :helm, :helm_spec, description: "description of how helm charts should be applied"
field :sha, :string, description: "the sha this service was pulled from"
field :message, :string, description: "the commit message for this revision"
@@ -148,6 +169,20 @@ defmodule Console.GraphQl.Deployments.Service do
field :folder, non_null(:string), description: "the folder manifests live under"
end
+ object :object_reference do
+ field :name, :string
+ field :namespace, :string
+ end
+
+ object :helm_spec do
+ field :chart, :string, description: "the name of the chart this service is using"
+ field :values, :string, description: "a helm values file to use with this service, requires auth and so is heavy to query",
+ resolve: &Deployments.helm_values/3
+ field :repository, :object_reference, description: "pointer to the flux helm repository resource used for this chart"
+ field :version, :string, description: "the chart version in use currently"
+ field :values_files, list_of(:string), description: "a list of relative paths to values files to use for helm applies"
+ end
+
@desc "a configuration item k/v pair"
object :service_configuration do
field :name, non_null(:string)
@@ -341,6 +376,13 @@ defmodule Console.GraphQl.Deployments.Service do
safe_resolve &Deployments.clone_service/2
end
+ field :self_manage, :service_deployment do
+ middleware Authenticated
+ arg :values, non_null(:string)
+
+ resolve &Deployments.self_manage/2
+ end
+
field :create_global_service, :global_service do
middleware Authenticated
arg :service_id, :id
diff --git a/lib/console/graphql/resolvers/dataloader.ex b/lib/console/graphql/resolvers/dataloader.ex
new file mode 100644
index 0000000000..66bea91025
--- /dev/null
+++ b/lib/console/graphql/resolvers/dataloader.ex
@@ -0,0 +1,44 @@
+
+defmodule Console.GraphQl.Resolvers.HelmRepositoryLoader do
+ alias Console.Deployments.Git
+
+ def data(_) do
+ Dataloader.KV.new(&query/2, max_concurrency: 1)
+ end
+
+ def query(_, services) do
+ repos = fetch_repos()
+ Map.new(services, & {&1, repos[key(&1)]})
+ end
+
+ def fetch_repos() do
+ case Git.list_helm_repositories() do
+ {:ok, repos} ->
+ Map.new(repos, & {{&1.metadata.namespace, &1.metadata.name}, &1})
+ _ -> %{}
+ end
+ end
+
+ defp key(%{helm: %{repository: %{namespace: ns, name: n}}}), do: {ns, n}
+ defp key(_), do: nil
+end
+
+defmodule Console.GraphQl.Resolvers.UserLoader do
+ alias Console.Schema.User
+
+ def data(_) do
+ Dataloader.KV.new(&query/2, max_concurrency: 1)
+ end
+
+ def query(_, emails) do
+ users = fetch_users(emails)
+ Map.new(emails, & {&1, users[&1]})
+ end
+
+ def fetch_users(emails) do
+ MapSet.to_list(emails)
+ |> User.with_emails()
+ |> Console.Repo.all()
+ |> Map.new(& {&1.email, &1})
+ end
+end
diff --git a/lib/console/graphql/resolvers/deployments.ex b/lib/console/graphql/resolvers/deployments.ex
index cfdc89f85d..872c1dc954 100644
--- a/lib/console/graphql/resolvers/deployments.ex
+++ b/lib/console/graphql/resolvers/deployments.ex
@@ -2,6 +2,7 @@ defmodule Console.GraphQl.Resolvers.Deployments do
use Console.GraphQl.Resolvers.Base, model: Console.Schema.Cluster
import Console.Deployments.Policies, only: [allow: 3]
alias Console.Deployments.{Clusters, Services, Git, Settings, Global, Pipelines, AddOns}
+ alias Console.Deployments.Helm.Repository
alias Console.Schema.{
Cluster,
ClusterNodePool,
@@ -144,6 +145,14 @@ defmodule Console.GraphQl.Resolvers.Deployments do
|> paginate(args)
end
+ def get_helm_repository(%{name: name, namespace: ns}, _), do: Kube.Client.get_helm_repository(ns, name)
+
+ def list_helm_repositories(_, _), do: Git.list_helm_repositories()
+
+ def helm_charts(helm, _, _), do: Repository.charts(helm)
+
+ def helm_status(helm, _, _), do: Repository.status(helm)
+
def resolve_cluster(_, %{context: %{cluster: cluster}}), do: {:ok, cluster}
def resolve_cluster(%{handle: handle}, %{context: %{current_user: user}}) do
Clusters.find!(handle)
@@ -214,6 +223,13 @@ defmodule Console.GraphQl.Resolvers.Deployments do
end
end
+ def helm_values(%{parent: service} = helm, _, ctx) do
+ case allow(service, actor(ctx), :secrets) do
+ {:ok, _} -> {:ok, helm.values}
+ err -> err
+ end
+ end
+
def runtime_services(cluster, _, _), do: {:ok, Clusters.runtime_services(cluster)}
def enable(_, %{context: %{current_user: user}}), do: Settings.enable(user)
@@ -283,6 +299,9 @@ defmodule Console.GraphQl.Resolvers.Deployments do
def update_service_components(%{id: id} = args, %{context: %{cluster: cluster}}),
do: Services.update_components(Map.take(args, [:errors, :components]), id, cluster)
+ def self_manage(%{values: values}, %{context: %{current_user: user}}),
+ do: Services.self_manage(values, user)
+
def create_git_repository(%{attributes: attrs}, %{context: %{current_user: user}}),
do: Git.create_repository(attrs, user)
diff --git a/lib/console/graphql/resolvers/user_loader.ex b/lib/console/graphql/resolvers/user_loader.ex
deleted file mode 100644
index 4092f06e17..0000000000
--- a/lib/console/graphql/resolvers/user_loader.ex
+++ /dev/null
@@ -1,19 +0,0 @@
-defmodule Console.GraphQl.Resolvers.UserLoader do
- alias Console.Schema.User
-
- def data(_) do
- Dataloader.KV.new(&query/2, max_concurrency: 1)
- end
-
- def query(_, emails) do
- users = fetch_users(emails)
- Map.new(emails, & {&1, users[&1]})
- end
-
- def fetch_users(emails) do
- MapSet.to_list(emails)
- |> User.with_emails()
- |> Console.Repo.all()
- |> Map.new(& {&1.email, &1})
- end
-end
diff --git a/lib/console/graphql/schema/base.ex b/lib/console/graphql/schema/base.ex
index 8e849cc8fb..8bcfbf59d0 100644
--- a/lib/console/graphql/schema/base.ex
+++ b/lib/console/graphql/schema/base.ex
@@ -18,6 +18,7 @@ defmodule Console.GraphQl.Schema.Base do
use Absinthe.Schema.Notation
use Absinthe.Relay.Schema.Notation, :modern
import Absinthe.Resolution.Helpers
+ import Console.GraphQl.Schema.Helpers
import Console.GraphQl.Schema.Base
alias Console.Middleware.{Authenticated, AdminRequired, Rbac, Feature, ClusterAuthenticated}
end
diff --git a/lib/console/graphql/schema/helpers.ex b/lib/console/graphql/schema/helpers.ex
new file mode 100644
index 0000000000..a5fe23bea0
--- /dev/null
+++ b/lib/console/graphql/schema/helpers.ex
@@ -0,0 +1,11 @@
+defmodule Console.GraphQl.Schema.Helpers do
+ import Absinthe.Resolution.Helpers
+
+ def manual_dataloader(loader, resolver, queryable, args) do
+ loader
+ |> Dataloader.load(resolver, queryable, args)
+ |> on_load(fn loader ->
+ {:ok, Dataloader.get(loader, resolver, queryable, args)}
+ end)
+ end
+end
diff --git a/lib/console/schema/deployment_settings.ex b/lib/console/schema/deployment_settings.ex
index f943190bec..87499424a2 100644
--- a/lib/console/schema/deployment_settings.ex
+++ b/lib/console/schema/deployment_settings.ex
@@ -5,6 +5,7 @@ defmodule Console.Schema.DeploymentSettings do
schema "deployment_settings" do
field :name, :string
field :enabled, :boolean
+ field :self_managed, :boolean
field :write_policy_id, :binary_id
field :read_policy_id, :binary_id
field :create_policy_id, :binary_id
@@ -33,7 +34,7 @@ defmodule Console.Schema.DeploymentSettings do
timestamps()
end
- @valid ~w(name enabled artifact_repository_id deployer_repository_id)a
+ @valid ~w(name enabled self_managed artifact_repository_id deployer_repository_id)a
def changeset(model, attrs \\ %{}) do
model
diff --git a/lib/console/schema/revision.ex b/lib/console/schema/revision.ex
index 1512e5fa62..df566a6f17 100644
--- a/lib/console/schema/revision.ex
+++ b/lib/console/schema/revision.ex
@@ -7,7 +7,9 @@ defmodule Console.Schema.Revision do
field :sha, :string
field :message, :string
- embeds_one :git, Service.Git, on_replace: :update
+ embeds_one :git, Service.Git, on_replace: :update
+ embeds_one :helm, Service.Helm, on_replace: :update
+
belongs_to :service, Service
has_many :configuration, ServiceConfiguration
@@ -41,6 +43,7 @@ defmodule Console.Schema.Revision do
|> cast(attrs, @valid)
|> put_change(:id, Piazza.Ecto.UUID.generate_monotonic())
|> cast_embed(:git)
+ |> cast_embed(:helm)
|> cast_assoc(:configuration)
|> validate_required(~w(version)a)
end
diff --git a/lib/console/schema/service.ex b/lib/console/schema/service.ex
index 7e328ffbf3..bac538c348 100644
--- a/lib/console/schema/service.ex
+++ b/lib/console/schema/service.ex
@@ -33,6 +33,25 @@ defmodule Console.Schema.Service do
end
end
+ defmodule Helm do
+ use Piazza.Ecto.Schema
+
+ embedded_schema do
+ field :values, Piazza.Ecto.EncryptedString
+ field :chart, :string
+ field :version, :string
+ field :values_files, {:array, :string}
+
+ embeds_one :repository, Console.Schema.NamespacedName
+ end
+
+ def changeset(model, attrs \\ %{}) do
+ model
+ |> cast(attrs, ~w(values chart version values_files)a)
+ |> cast_embed(:repository)
+ end
+ end
+
schema "services" do
field :name, :string
field :component_status, :string
@@ -47,7 +66,9 @@ defmodule Console.Schema.Service do
field :deleted_at, :utc_datetime_usec
field :protect, :boolean
- embeds_one :git, Git, on_replace: :update
+ embeds_one :git, Git, on_replace: :update
+ embeds_one :helm, Helm, on_replace: :update
+
embeds_one :sync_config, SyncConfig, on_replace: :update do
embeds_many :diff_normalizers, DiffNormalizer
embeds_one :namespace_metadata, Metadata
@@ -157,6 +178,7 @@ defmodule Console.Schema.Service do
|> kubernetes_names([:name, :namespace])
|> semver(:version)
|> cast_embed(:git)
+ |> cast_embed(:helm)
|> cast_embed(:sync_config, with: &sync_config_changeset/2)
|> cast_embed(:kustomize, with: &kustomize_changeset/2)
|> cast_assoc(:components)
@@ -170,7 +192,7 @@ defmodule Console.Schema.Service do
|> unique_constraint([:cluster_id, :owner_id])
|> put_new_change(:write_policy_id, &Ecto.UUID.generate/0)
|> put_new_change(:read_policy_id, &Ecto.UUID.generate/0)
- |> validate_required([:name, :namespace, :version, :cluster_id, :repository_id])
+ |> validate_required([:name, :namespace, :version, :cluster_id])
end
def rollback_changeset(model, attrs \\ %{}) do
diff --git a/lib/console_web/controllers/git_controller.ex b/lib/console_web/controllers/git_controller.ex
index 25d67e70de..125d7e2ff6 100644
--- a/lib/console_web/controllers/git_controller.ex
+++ b/lib/console_web/controllers/git_controller.ex
@@ -1,13 +1,13 @@
defmodule ConsoleWeb.GitController do
use ConsoleWeb, :controller
- alias Console.Deployments.{Services, Git.Discovery}
+ alias Console.Deployments.Services
alias Console.Schema.Cluster
require Logger
def tarball(conn, %{"id" => service_id}) do
with %Cluster{} = cluster <- ConsoleWeb.Plugs.Token.get_cluster(conn),
{:ok, svc} <- Services.authorized(service_id, cluster),
- {{:ok, f}, _} <- {Discovery.fetch(svc), svc} do
+ {{:ok, f}, _} <- {Services.tarstream(svc), svc} do
try do
conn =
conn
diff --git a/lib/kube/client.ex b/lib/kube/client.ex
index 0ae5ad5770..5897357df7 100644
--- a/lib/kube/client.ex
+++ b/lib/kube/client.ex
@@ -24,6 +24,8 @@ defmodule Kube.Client do
get_request :get_wireguard_peer, Kube.WireguardPeer
get_request :get_wireguard_server, Kube.WireguardServer
get_request :get_cluster, Kube.Cluster
+ get_request :get_helm_repository, Kube.HelmRepository
+ get_request :get_helm_chart, Kube.HelmChart
delete_request :delete_wireguard_peer, Kube.WireguardPeer
delete_request :delete_certificate, Kube.Certificate
@@ -32,12 +34,14 @@ defmodule Kube.Client do
create_request :create_postgresql, Kube.Postgresql
create_request :create_vertical_pod_autoscaler, Kube.VerticalPodAutoscaler
create_request :create_statefulset_resize, Kube.StatefulSetResize
+ create_request :create_helm_chart, Kube.HelmChart
list_all_request :list_postgresqls, Kube.Postgresql.List
list_all_request :list_slashcommands, Kube.SlashCommand.List
list_all_request :list_licenses, Kube.License.List
list_all_request :list_applications, Kube.Application.List
list_all_request :list_metrics, Kube.NodeMetric.List
+ list_all_request :list_helm_repositories, Kube.HelmRepository.List
def raw(path) do
%Kazan.Request{
diff --git a/lib/kube/models.ex b/lib/kube/models.ex
index 976157777b..f741da2f99 100644
--- a/lib/kube/models.ex
+++ b/lib/kube/models.ex
@@ -5,6 +5,8 @@ Kube.Parser.parse(path: "crds/postgresql.yaml", module: Kube.Postgresql)
Kube.Parser.parse(path: "crds/cert-manager.yaml", module: Kube.Certificate)
Kube.Parser.parse(path: "crds/application.yaml", module: Kube.Application)
Kube.Parser.parse(path: "crds/clusters.cluster.x-k8s.io.yaml", module: Kube.Cluster)
+Kube.Parser.parse(path: "crds/helmrepository.yaml", module: Kube.HelmRepository)
+Kube.Parser.parse(path: "crds/helmchart.yaml", module: Kube.HelmChart)
# plural crds
Kube.Parser.parse(path: "crds/license.yaml", module: Kube.License)
diff --git a/lib/kube/parser.ex b/lib/kube/parser.ex
index d5e14f5564..33526560fe 100644
--- a/lib/kube/parser.ex
+++ b/lib/kube/parser.ex
@@ -160,9 +160,10 @@ defmodule Kube.Parser do
"spec" => %{
"group" => group,
"names" => %{"plural" => path, "kind" => kind},
- "versions" => [%{"name" => v, "schema" => %{"openAPIV3Schema" => schema}} | _]
+ "versions" => [_ | _] = vsns
}
}) do
+ %{"name" => v, "schema" => %{"openAPIV3Schema" => schema}} = List.last(vsns)
{group, v, path, kind, schema}
end
end
diff --git a/mix.exs b/mix.exs
index a4a2a4f0f1..a509c35486 100644
--- a/mix.exs
+++ b/mix.exs
@@ -101,7 +101,6 @@ defmodule Console.MixProject do
{:quantum, "~> 2.3"},
{:yaml_elixir, "~> 2.9"},
{:poison, "~> 5.0", override: true},
- {:mojito, "~> 0.3.0"},
{:ets, "~> 0.9"},
{:reverse_proxy_plug, "~> 1.2.1"},
{:kazan, "~> 0.11", github: "michaeljguarino/kazan", ref: "e26d21b324fd8b09bbc20ffde783d10a314684d9"},
@@ -110,7 +109,7 @@ defmodule Console.MixProject do
{:prometheus_ex, "~> 3.0"},
{:prometheus_plugs, "~> 1.1.1"},
{:guardian, "~> 1.2.1"},
- {:httpoison, "~> 1.7"},
+ {:httpoison, "~> 1.7", override: true},
{:nebulex, "== 2.0.0"},
{:shards, "~> 1.0"}, #=> For using :shards as backend
{:decorator, "~> 1.3"}, #=> For using Caching Annotations
@@ -125,6 +124,11 @@ defmodule Console.MixProject do
{:websockex, "~> 0.4.3"},
{:briefly, "~> 0.4.0"},
{:libring, "~> 1.0"},
+ {:http_stream, "~> 1.0.0"},
+
+ # if using the Mint adapter:
+ {:castore, "~> 0.1.7"},
+ {:mint, "~> 1.1.0"},
{:phoenix_client, "~> 0.11", git: "https://github.com/michaeljguarino/phoenix_client.git", branch: "mguarino/channel-listen"},
{:botanist, "~> 0.1.0", git: "https://github.com/michaeljguarino/botanist.git", branch: "ecto3"},
{:elixpath, "~> 0.1.1", git: "https://github.com/mtannaan/elixpath.git"},
diff --git a/mix.lock b/mix.lock
index 2cd64e50b2..4326a267dc 100644
--- a/mix.lock
+++ b/mix.lock
@@ -12,7 +12,7 @@
"botanist": {:git, "https://github.com/michaeljguarino/botanist.git", "10244d96a88c3a5aa4f77f343bbb59643c623986", [branch: "ecto3"]},
"bourne": {:hex, :bourne, "1.1.0", "60a8bb3d5ad533a3a18257de9304e70e6bb2f4d7f354a529ef3f47c327c2dd97", [:mix], [{:ecto, "~> 2.1", [hex: :ecto, repo: "hexpm", optional: false]}], "hexpm", "81a389611ad067dc305d5ba4674280ea2b99ef012bca5e7de48357545edc05bc"},
"briefly": {:hex, :briefly, "0.4.1", "c90c0511e64bde1fe8da7e244e14acf5bc78c3f6d033db778205e1fa2feafa5c", [:mix], [], "hexpm", "fc0cafcd19c4ed0d0906ae5cf627cc6ce76b8652a160c6bde0ab9d77304ebb0a"},
- "castore": {:hex, :castore, "0.1.7", "1ca19eee705cde48c9e809e37fdd0730510752cc397745e550f6065a56a701e9", [:mix], [], "hexpm", "a2ae2c13d40e9c308387f1aceb14786dca019ebc2a11484fb2a9f797ea0aa0d8"},
+ "castore": {:hex, :castore, "0.1.22", "4127549e411bedd012ca3a308dede574f43819fe9394254ca55ab4895abfa1a2", [:mix], [], "hexpm", "c17576df47eb5aa1ee40cc4134316a99f5cad3e215d5c77b8dd3cfef12a22cac"},
"certifi": {:hex, :certifi, "2.9.0", "6f2a475689dd47f19fb74334859d460a2dc4e3252a3324bd2111b8f0429e7e21", [:rebar3], [], "hexpm", "266da46bdb06d6c6d35fde799bcb28d36d985d424ad7c08b5bb48f5b5cdd4641"},
"combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], [], "hexpm", "1b1dbc1790073076580d0d1d64e42eae2366583e7aecd455d1215b0d16f2451b"},
"comeonin": {:hex, :comeonin, "5.1.3", "4c9880ed348cc0330c74086b4383ffb0b5a599aa603416497b7374c168cae340", [:mix], [], "hexpm", "94c2853c79ab65e600b8646c62231f1bfcb2245f707684ed82b2c19cf61bfe1f"},
@@ -52,6 +52,7 @@
"hackney": {:hex, :hackney, "1.18.1", "f48bf88f521f2a229fc7bae88cf4f85adc9cd9bcf23b5dc8eb6a1788c662c4f6", [:rebar3], [{:certifi, "~>2.9.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~>6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~>1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~>1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "a4ecdaff44297e9b5894ae499e9a070ea1888c84afdd1fd9b7b2bc384950128e"},
"hash_ring": {:hex, :hash_ring, "0.4.2", "65d7e84ee911c2f07e53193711013ec9b9761c5eb180720e31224b776c98f502", [:rebar3], [], "hexpm", "c327d99b1e2af41b50e5c4803a9bee7932db2c0f39ad7854a9fdad7e42444066"},
"horde": {:hex, :horde, "0.8.1", "c35a018d7dc2438e94d1204ef86978d01a4fb16fbd9877aafc4a82e735eeeee3", [:mix], [{:delta_crdt, "~> 0.5.10", [hex: :delta_crdt, repo: "hexpm", optional: false]}, {:libring, "~> 1.4", [hex: :libring, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_poller, "~> 0.4.0", [hex: :telemetry_poller, repo: "hexpm", optional: false]}], "hexpm", "2b3679fbb7ae6152fa8a25184da8ab7357b2ff044f9163a33684a5b0d7606758"},
+ "http_stream": {:hex, :http_stream, "1.0.0", "d40cc69eefb380508c01e004571159c26779902564558bffe1517a57764e019e", [:mix], [{:castore, "~> 0.1.7", [hex: :castore, repo: "hexpm", optional: true]}, {:httpoison, "~> 1.7.0", [hex: :httpoison, repo: "hexpm", optional: true]}, {:mint, "~> 1.1.0", [hex: :mint, repo: "hexpm", optional: true]}], "hexpm", "efa64a8800b7365a6e77b0647b289b9fa41fbbbb44a117c8ddc9b8c6fc69e126"},
"httpoison": {:hex, :httpoison, "1.8.1", "df030d96de89dad2e9983f92b0c506a642d4b1f4a819c96ff77d12796189c63e", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "35156a6d678d6d516b9229e208942c405cf21232edd632327ecfaf4fd03e79e0"},
"idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
"inet_cidr": {:hex, :inet_cidr, "1.0.4", "a05744ab7c221ca8e395c926c3919a821eb512e8f36547c062f62c4ca0cf3d6e", [:mix], [], "hexpm", "64a2d30189704ae41ca7dbdd587f5291db5d1dda1414e0774c29ffc81088c1bc"},
@@ -66,7 +67,7 @@
"mime": {:hex, :mime, "2.0.5", "dc34c8efd439abe6ae0343edbb8556f4d63f178594894720607772a041b04b02", [:mix], [], "hexpm", "da0d64a365c45bc9935cc5c8a7fc5e49a0e0f9932a761c55d6c52b142780a05c"},
"mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"},
"mimic": {:hex, :mimic, "1.3.0", "2fdca63b897fe4367542651ca83759a49536cefb7c7f9eea8146695112cb3ee1", [:mix], [], "hexpm", "3c9aa460b7992e381987d106433a29ac3c36e50be7c47f6e0ea46b3a3d7f559b"},
- "mint": {:hex, :mint, "0.2.1", "a2ec8729fcad5c8b6460e07dfa64b008b3d9697a9f4604cd5684a87b44677c99", [:mix], [{:castore, "~> 0.1.0", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm", "ba7e7e4e112bd40542bef94ab3ec2f270deb260d670859b66e2fc2f2f99a0664"},
+ "mint": {:hex, :mint, "1.1.0", "1fd0189edd9e3ffdbd7fcd8bc3835902b987a63ec6c4fd1aa8c2a56e2165f252", [:mix], [{:castore, "~> 0.1.0", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm", "5bfd316c3789340b682d5679a8116bcf2112e332447bdc20c1d62909ee45f48d"},
"mix_audit": {:hex, :mix_audit, "2.1.1", "653aa6d8f291fc4b017aa82bdb79a4017903902ebba57960ef199cbbc8c008a1", [:make, :mix], [{:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:yaml_elixir, "~> 2.9", [hex: :yaml_elixir, repo: "hexpm", optional: false]}], "hexpm", "541990c3ab3a7bb8c4aaa2ce2732a4ae160ad6237e5dcd5ad1564f4f85354db1"},
"mojito": {:hex, :mojito, "0.3.0", "806cd3c1832333a9ee784e7ea2799863fbe4de55ecb4623a8f4ef870c2844cc6", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: false]}, {:mint, "~> 0.2.1", [hex: :mint, repo: "hexpm", optional: false]}, {:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: false]}], "hexpm", "bf40fa4e7d6072f8ca93d55e0a0948aef6fa887376dcde4cb3857f98e68d1e87"},
"nebulex": {:hex, :nebulex, "2.0.0", "d33dc5a2b96ba09e5eb1c90e53dd1d036b0c006f1bb379bcc5c10acd0b140d6d", [:mix], [{:decorator, "~> 1.3", [hex: :decorator, repo: "hexpm", optional: true]}, {:shards, "~> 1.0", [hex: :shards, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "411c707e455408ae79ae7bfe7ada125967d016b83ff2a4e9763fd7cc2dd9372d"},
diff --git a/priv/repo/migrations/20231122232346_add_helm_revisions.exs b/priv/repo/migrations/20231122232346_add_helm_revisions.exs
new file mode 100644
index 0000000000..e50a7c9bac
--- /dev/null
+++ b/priv/repo/migrations/20231122232346_add_helm_revisions.exs
@@ -0,0 +1,9 @@
+defmodule Console.Repo.Migrations.AddHelmRevisions do
+ use Ecto.Migration
+
+ def change do
+ alter table(:revisions) do
+ add :helm, :map
+ end
+ end
+end
diff --git a/priv/repo/migrations/20231123164532_add_self_managed.exs b/priv/repo/migrations/20231123164532_add_self_managed.exs
new file mode 100644
index 0000000000..996313564a
--- /dev/null
+++ b/priv/repo/migrations/20231123164532_add_self_managed.exs
@@ -0,0 +1,9 @@
+defmodule Console.Repo.Migrations.AddSelfManaged do
+ use Ecto.Migration
+
+ def change do
+ alter table(:deployment_settings) do
+ add :self_managed, :boolean, default: false
+ end
+ end
+end
diff --git a/schema/schema.graphql b/schema/schema.graphql
index 4fabbfc7a2..071f6c79a0 100644
--- a/schema/schema.graphql
+++ b/schema/schema.graphql
@@ -147,6 +147,10 @@ type RootQueryType {
gitRepositories(after: String, first: Int, before: String, last: Int): GitRepositoryConnection
+ helmRepositories: [HelmRepository]
+
+ helmRepository(name: String!, namespace: String!): HelmRepository
+
"exchanges a kubeconfig token for user info"
tokenExchange(token: String!): User
@@ -368,6 +372,8 @@ type RootMutationType {
attributes: ServiceCloneAttributes!
): ServiceDeployment
+ selfManage(values: String!): ServiceDeployment
+
createGlobalService(
serviceId: ID
@@ -438,6 +444,9 @@ type DeploymentSettings {
name: String!
+ "whether the byok cluster has been brought under self-management"
+ selfManaged: Boolean
+
"the repo to fetch CAPI manifests from, for both providers and clusters"
artifactRepository: GitRepository
@@ -831,7 +840,8 @@ input ServiceDeploymentAttributes {
syncConfig: SyncConfigAttributes
protect: Boolean
repositoryId: ID!
- git: GitRefAttributes!
+ git: GitRefAttributes
+ helm: HelmConfigAttributes
kustomize: KustomizeAttributes
configuration: [ConfigAttributes]
readBindings: [PolicyBindingAttributes]
@@ -843,6 +853,14 @@ input SyncConfigAttributes {
diffNormalizer: DiffNormalizerAttributes
}
+input HelmConfigAttributes {
+ values: String
+ valuesFiles: [String]
+ chart: String
+ version: String
+ repository: NamespacedName
+}
+
input MetadataAttributes {
labels: Map
annotations: Map
@@ -860,6 +878,7 @@ input ServiceUpdateAttributes {
version: String
protect: Boolean
git: GitRefAttributes
+ helm: HelmConfigAttributes
configuration: [ConfigAttributes]
kustomize: KustomizeAttributes
}
@@ -924,7 +943,10 @@ type ServiceDeployment {
version: String!
"description on where in git the service's manifests should be fetched"
- git: GitRef!
+ git: GitRef
+
+ "description of how helm charts should be applied"
+ helm: HelmSpec
"if true, deletion of this service is not allowed"
protect: Boolean
@@ -956,6 +978,8 @@ type ServiceDeployment {
"the git repo of this service"
repository: GitRepository
+ helmRepository: HelmRepository
+
"read policy for this service"
readBindings: [PolicyBinding]
@@ -1003,7 +1027,10 @@ type Revision {
version: String!
"git spec of the prior revision"
- git: GitRef!
+ git: GitRef
+
+ "description of how helm charts should be applied"
+ helm: HelmSpec
"the sha this service was pulled from"
sha: String
@@ -1025,6 +1052,28 @@ type GitRef {
folder: String!
}
+type ObjectReference {
+ name: String
+ namespace: String
+}
+
+type HelmSpec {
+ "the name of the chart this service is using"
+ chart: String
+
+ "a helm values file to use with this service, requires auth and so is heavy to query"
+ values: String
+
+ "pointer to the flux helm repository resource used for this chart"
+ repository: ObjectReference
+
+ "the chart version in use currently"
+ version: String
+
+ "a list of relative paths to values files to use for helm applies"
+ valuesFiles: [String]
+}
+
"a configuration item k\/v pair"
type ServiceConfiguration {
name: String!
@@ -1699,6 +1748,58 @@ type GitRepository {
updatedAt: DateTime
}
+"a crd representation of a helm repository"
+type HelmRepository {
+ metadata: Metadata!
+
+ spec: HelmRepositorySpec!
+
+ "the charts found in this repository (heavy operation, don't do in list endpoints)"
+ charts: [HelmChartEntry]
+
+ "can fetch the status of a given helm repository"
+ status: HelmRepositoryStatus
+}
+
+"a specification of how a helm repository is fetched"
+type HelmRepositorySpec {
+ provider: String
+ url: String!
+ type: String
+}
+
+"the state of this helm repository"
+type HelmRepositoryStatus {
+ ready: Boolean
+ message: String
+}
+
+"a chart manifest entry, including all versions"
+type HelmChartEntry {
+ "the name of the chart"
+ name: String
+
+ "all found versions of the chart"
+ versions: [HelmChartVersion]
+}
+
+"a chart version contained within a helm repository manifest"
+type HelmChartVersion {
+ "the version of the app contained w\/in this chart"
+ appVersion: String
+
+ "the version of the chart itself"
+ version: String
+
+ "the name of the chart"
+ name: String
+
+ type: String
+
+ "sha digest of this chart's contents"
+ digest: String
+}
+
type GitRepositoryConnection {
pageInfo: PageInfo!
edges: [GitRepositoryEdge]
diff --git a/static/compatibilities/argo-rollouts.yaml b/static/compatibilities/argo-rollouts.yaml
new file mode 100644
index 0000000000..777d1e36a5
--- /dev/null
+++ b/static/compatibilities/argo-rollouts.yaml
@@ -0,0 +1,18 @@
+icon: https://avatars.githubusercontent.com/u/30269780?s=200&v=4
+versions:
+- version: 1.6.0
+ kube: ['1.28', '1.27', '1.26', '1.25', '1.24', '1.23', '1.22']
+ requirements: []
+ incompatibilities: []
+- version: 1.2.0
+ kube: ['1.28', '1.27', '1.26', '1.25', '1.24', '1.23', '1.22']
+ requirements: []
+ incompatibilities: []
+- version: 1.1.0
+ kube: ['1.21', '1.20', '1.19', '1.18', '1.17', '1.16']
+ requirements: []
+ incompatibilities: []
+- version: 0.0.0
+ kube: ['1.21', '1.20', '1.19', '1.18', '1.17', '1.16']
+ requirements: []
+ incompatibilities: []
\ No newline at end of file
diff --git a/static/compatibilities/kube-prometheus-stack.yaml b/static/compatibilities/kube-prometheus-stack.yaml
new file mode 100644
index 0000000000..fc157828a8
--- /dev/null
+++ b/static/compatibilities/kube-prometheus-stack.yaml
@@ -0,0 +1,22 @@
+icon: https://github.com/pluralsh/plural-artifacts/blob/main/monitoring/plural/icons/monitoring.png?raw=true
+versions:
+- version: 54.0.0
+ kube: ['1.28', '1.27', '1.26', '1.25', '1.24', '1.23', '1.22', '1.21', '1.20', '1.19']
+ requirements: []
+ incompatibilities: []
+- version: 50.0.0
+ kube: ['1.28', '1.27', '1.26', '1.25', '1.24', '1.23', '1.22', '1.21', '1.20', '1.19']
+ requirements: []
+ incompatibilities: []
+- version: 27.0.0
+ kube: ['1.24', '1.23', '1.22', '1.21', '1.20', '1.19']
+ requirements: []
+ incompatibilities: []
+- versin: 15.2.2
+ version: ['1.24', '1.23', '1.22', '1.21', '1.20', '1.19']
+ requirements: []
+ incompatibilities: []
+- version: 0.0.0
+ kube: ['1.21', '1.20', '1.19', '1.18', '1.17', '1.16']
+ requirements: []
+ incompatibilities: []
\ No newline at end of file
diff --git a/static/compatibilities/manifest.yaml b/static/compatibilities/manifest.yaml
index 1a2341659b..11e3550109 100644
--- a/static/compatibilities/manifest.yaml
+++ b/static/compatibilities/manifest.yaml
@@ -1,4 +1,6 @@
names:
- ingress-nginx
- cert-manager
-- external-dns
\ No newline at end of file
+- external-dns
+- argo-rollouts
+- kube-prometheus-stack
\ No newline at end of file
diff --git a/test-apps/helm-repositories/podinfo.yaml b/test-apps/helm-repositories/podinfo.yaml
new file mode 100644
index 0000000000..6280d745a4
--- /dev/null
+++ b/test-apps/helm-repositories/podinfo.yaml
@@ -0,0 +1,7 @@
+apiVersion: source.toolkit.fluxcd.io/v1beta2
+kind: HelmRepository
+metadata:
+ name: podinfo
+spec:
+ interval: 5m0s
+ url: https://stefanprodan.github.io/podinfo
\ No newline at end of file
diff --git a/test/console/deployments/clusters_test.exs b/test/console/deployments/clusters_test.exs
index 06be2cb4f0..2a379276c2 100644
--- a/test/console/deployments/clusters_test.exs
+++ b/test/console/deployments/clusters_test.exs
@@ -868,7 +868,7 @@ defmodule Console.Deployments.ClustersTest do
expect(Kube.Utils, :get_secret, fn ^ns, ^kubeconf_secret ->
{:ok, %CoreV1.Secret{data: %{"value" => Base.encode64("kubeconfig")}}}
end)
- expect(Console.Commands.Command, :cmd, fn "plural", ["deployments", "install", "--url", _, "--token", ^t], _, [{"KUBECONFIG", f}, {"PLURAL_INSTALL_AGENT_CONFIRM", "true"}] ->
+ expect(Console.Commands.Command, :cmd, fn "plural", ["deployments", "install", "--url", _, "--token", ^t, "--force"], _, [{"KUBECONFIG", f}, {"PLURAL_INSTALL_AGENT_CONFIRM", "true"}] ->
case File.read(f) do
{:ok, "kubeconfig"} -> {:ok, "yay"}
err -> {:error, err}
diff --git a/test/console/deployments/helm/repository_test.exs b/test/console/deployments/helm/repository_test.exs
new file mode 100644
index 0000000000..082b2cdcb9
--- /dev/null
+++ b/test/console/deployments/helm/repository_test.exs
@@ -0,0 +1,21 @@
+defmodule Console.Deployments.Helm.RepositoryTest do
+ use Console.DataCase
+ alias Console.Deployments.Helm.Repository
+ alias Kube.HelmRepository
+
+ describe "#charts/1" do
+ test "it will fetch charts for a helm repository" do
+ repo = %HelmRepository{
+ status: %HelmRepository.Status{
+ artifact: %HelmRepository.Status.Artifact{url: "https://pluralsh.github.io/console/index.yaml"}
+ }
+ }
+
+ {:ok, [%{name: "console", versions: [chart | _]}]} = Repository.charts(repo)
+
+ assert chart.name
+ assert chart.version
+ assert chart.app_version
+ end
+ end
+end
diff --git a/test/console/deployments/services_test.exs b/test/console/deployments/services_test.exs
index 7e5ae4628d..c315b67901 100644
--- a/test/console/deployments/services_test.exs
+++ b/test/console/deployments/services_test.exs
@@ -1,5 +1,6 @@
defmodule Console.Deployments.ServicesTest do
use Console.DataCase, async: true
+ use Mimic
alias Console.PubSub
alias Console.Deployments.Services
@@ -42,6 +43,43 @@ defmodule Console.Deployments.ServicesTest do
assert_receive {:event, %PubSub.ServiceCreated{item: ^service}}
end
+ test "it can create a helm-based service and initial revision" do
+ cluster = insert(:cluster)
+ user = admin_user()
+
+ expect(Kube.Client, :get_helm_repository, fn "helm-charts", "podinfo" -> {:ok, %Kube.HelmRepository{}} end)
+
+ {:ok, service} = Services.create_service(%{
+ name: "my-service",
+ namespace: "my-service",
+ version: "0.0.1",
+ helm: %{
+ chart: "podinfo",
+ version: "5.0",
+ repository: %{namespace: "helm-charts", name: "podinfo"},
+ },
+ configuration: [%{name: "name", value: "value"}]
+ }, cluster.id, user)
+
+ assert service.name == "my-service"
+ assert service.namespace == "my-service"
+ assert service.version == "0.0.1"
+ assert service.cluster_id == cluster.id
+ assert service.helm.chart == "podinfo"
+ assert service.helm.version == "5.0"
+ assert service.helm.repository.name == "podinfo"
+ assert service.status == :stale
+
+ %{revision: revision} = Console.Repo.preload(service, [:revision])
+ assert revision.helm.chart == service.helm.chart
+ assert revision.helm.version == service.helm.version
+
+ {:ok, secrets} = Services.configuration(service)
+ assert secrets["name"] == "value"
+
+ assert_receive {:event, %PubSub.ServiceCreated{item: ^service}}
+ end
+
test "you cannot create a service in a deleting cluster" do
cluster = insert(:cluster, deleted_at: Timex.now())
user = admin_user()
@@ -145,6 +183,46 @@ defmodule Console.Deployments.ServicesTest do
assert second.git.folder == "k8s"
end
+ test "helm services can be updated" do
+ cluster = insert(:cluster)
+ user = admin_user()
+ expect(Kube.Client, :get_helm_repository, fn _, _ -> {:ok, %Kube.HelmRepository{}} end)
+
+ {:ok, service} = Services.create_service(%{
+ name: "my-service",
+ namespace: "my-service",
+ version: "0.0.1",
+ helm: %{
+ chart: "chart",
+ version: "0.1.0",
+ repository: %{namespace: "ns", name: "name"}
+ },
+ configuration: [%{name: "name", value: "value"}]
+ }, cluster.id, user)
+
+ {:ok, updated} = Services.update_service(%{
+ helm: %{
+ chart: "chart",
+ version: "0.1.1"
+ },
+ }, service.id, user)
+
+ assert_receive {:event, %PubSub.ServiceUpdated{item: ^updated}}
+
+ assert updated.name == "my-service"
+ assert updated.namespace == "my-service"
+ assert updated.version == "0.0.1"
+ assert updated.helm.chart == "chart"
+ assert updated.helm.version == "0.1.1"
+ refute updated.git
+ assert updated.revision_id
+ assert updated.status == :stale
+
+ %{revision: revision} = Console.Repo.preload(updated, [:revision])
+ assert revision.helm.chart == updated.helm.chart
+ assert revision.helm.version == updated.helm.version
+ end
+
test "it will respect rbac" do
user = insert(:user)
cluster = insert(:cluster, write_bindings: [%{user_id: user.id}])
@@ -490,6 +568,26 @@ defmodule Console.Deployments.ServicesTest do
end
end
+ describe "#self_manage/2" do
+ test "admins can convert their byok consoles to self-managed" do
+ admin = admin_user()
+ settings = deployment_settings(create_bindings: [%{user_id: admin.id}])
+ insert(:cluster, self: true)
+
+ {:ok, console} = Services.self_manage("value: bogus", admin)
+
+ assert console.name == "console"
+ assert console.namespace == "plrl-console"
+ assert console.helm.values == "value: bogus"
+ assert console.git.ref == "master"
+ assert console.git.folder == "charts/console"
+ %{repository: repo} = Console.Repo.preload(console, [:repository])
+ assert repo.url == "https://github.com/pluralsh/console.git"
+
+ assert refetch(settings).self_managed
+ end
+ end
+
describe "#update_components/2" do
test "it will update the k8s components w/in the service" do
service = insert(:service)
@@ -717,7 +815,8 @@ end
defmodule Console.Deployments.ServicesAsyncTest do
use Console.DataCase, async: false
- alias Console.Deployments.Services
+ use Mimic
+ alias Console.Deployments.{Services, Tar}
describe "#docs/1" do
test "it can fetch the docs for a given service" do
@@ -728,4 +827,36 @@ defmodule Console.Deployments.ServicesAsyncTest do
assert content == "hello world"
end
end
+
+ describe "#tarstream/1" do
+ test "it can fetch a chart for a helm service" do
+ svc = insert(:service, helm: %{chart: "podinfo", version: "5.0", repository: %{name: "podinfo", namespace: "helm-charts"}})
+ name = Console.Deployments.Helm.Charts.chart_name("podinfo", "podinfo", "5.0")
+ expect(Kube.Client, :get_helm_chart, fn "helm-charts", ^name -> {:ok, %Kube.HelmChart{
+ spec: %Kube.HelmChart.Spec{chart: "podinfo"},
+ status: %Kube.HelmChart.Status{
+ artifact: %Kube.HelmChart.Status.Artifact{digest: "sha", url: "https://stefanprodan.github.io/podinfo/podinfo-6.5.3.tgz"}
+ }
+ }} end)
+
+ {:ok, f} = Services.tarstream(svc)
+ {:ok, content} = Tar.tar_stream(f)
+ content = Map.new(content)
+ assert content["Chart.yaml"]
+
+ assert refetch(svc).sha == "sha"
+ end
+
+ test "it can splice in a new values.yaml.tpl" do
+ git = insert(:git_repository, url: "https://github.com/pluralsh/console.git")
+ svc = insert(:service, helm: %{values: "value: test"}, repository: git, git: %{ref: "master", folder: "charts/console"})
+
+ {:ok, f} = Services.tarstream(svc)
+ {:ok, content} = Tar.tar_stream(f)
+
+ content = Map.new(content)
+ assert content["Chart.yaml"] =~ "console"
+ assert content["values.yaml.liquid"] == "value: test"
+ end
+ end
end
diff --git a/test/console/graphql/mutations/deployment_mutations_test.exs b/test/console/graphql/mutations/deployment_mutations_test.exs
index a53e3f002b..f4360013de 100644
--- a/test/console/graphql/mutations/deployment_mutations_test.exs
+++ b/test/console/graphql/mutations/deployment_mutations_test.exs
@@ -1026,6 +1026,25 @@ defmodule Console.GraphQl.DeploymentMutationsTest do
assert updated["state"] == "OPEN"
end
end
+
+ describe "selfManage" do
+ test "it can self-manage a byok console" do
+ admin = admin_user()
+ deployment_settings(create_bindings: [%{user_id: admin.id}])
+ insert(:cluster, self: true)
+
+ {:ok, %{data: %{"selfManage" => svc}}} = run_query("""
+ mutation SelfManage($values: String!) {
+ selfManage(values: $values) {
+ id
+ name
+ }
+ }
+ """, %{"values" => "value: bogus"}, %{current_user: admin})
+
+ assert svc["name"] == "console"
+ end
+ end
end
defmodule Console.GraphQl.Mutations.SyncDeploymentMutationsTest do
diff --git a/test/console/graphql/queries/deployment_queries_test.exs b/test/console/graphql/queries/deployment_queries_test.exs
index 69f6516a28..7a53631551 100644
--- a/test/console/graphql/queries/deployment_queries_test.exs
+++ b/test/console/graphql/queries/deployment_queries_test.exs
@@ -1,5 +1,7 @@
defmodule Console.GraphQl.DeploymentQueriesTest do
use Console.DataCase, async: true
+ alias Kube.HelmRepository
+ use Mimic
describe "gitRepositories" do
test "it can list git repositories" do
@@ -284,6 +286,36 @@ defmodule Console.GraphQl.DeploymentQueriesTest do
assert Enum.all?(found, & &1["name"])
end
+ test "it can sideload helm repositories" do
+ cluster = insert(:cluster)
+ services = insert_list(3, :service, cluster: cluster)
+ svc = insert(:service, cluster: cluster, helm: %{chart: "chart", version: "0.1.0", repository: %{namespace: "ns", name: "name"}})
+ expect(Kube.Client, :list_helm_repositories, fn ->
+ {:ok, %{items: [%Kube.HelmRepository{
+ metadata: %{namespace: "ns", name: "name"},
+ spec: %Kube.HelmRepository.Spec{url: "https://helm.sh"},
+ }]}}
+ end)
+
+ {:ok, %{data: %{"serviceDeployments" => found}}} = run_query("""
+ query Services($clusterId: ID!) {
+ serviceDeployments(clusterId: $clusterId, first: 5) {
+ edges {
+ node {
+ id
+ helmRepository { spec { url } }
+ }
+ }
+ }
+ }
+ """, %{"clusterId" => cluster.id}, %{current_user: admin_user()})
+
+ found = from_connection(found)
+
+ assert ids_equal(found, [svc | services])
+ assert Enum.any?(found, & &1["helmRepository"])
+ end
+
test "it can list services in the system by cluster handle" do
cluster = insert(:cluster, handle: "test")
services = insert_list(3, :service, cluster: cluster)
@@ -463,6 +495,50 @@ defmodule Console.GraphQl.DeploymentQueriesTest do
assert Enum.all?(found["components"], & &1["state"] == "RUNNING")
end
+ test "it can fetch helm values with rbac protection" do
+ user = admin_user()
+ reader = insert(:user)
+ cluster = insert(:cluster)
+ repository = insert(:git_repository)
+ {:ok, service} = create_service(cluster, user, [
+ name: "test",
+ namespace: "test",
+ git: %{ref: "master", folder: "k8s"},
+ helm: %{values: "secret: value"},
+ repository_id: repository.id,
+ configuration: [%{name: "name", value: "value"}],
+ read_bindings: [%{user_id: reader.id}]
+ ])
+
+ {:ok, %{data: %{"serviceDeployment" => found}}} = run_query("""
+ query Service($id: ID!) {
+ serviceDeployment(id: $id) {
+ name
+ namespace
+ git { ref folder }
+ helm { values }
+ repository { id }
+ }
+ }
+ """, %{"id" => service.id}, %{current_user: user})
+
+ assert found["helm"]["values"] == "secret: value"
+
+ {:ok, %{data: %{"serviceDeployment" => found}, errors: [_ | _]}} = run_query("""
+ query Service($id: ID!) {
+ serviceDeployment(id: $id) {
+ name
+ namespace
+ git { ref folder }
+ helm { values }
+ repository { id }
+ }
+ }
+ """, %{"id" => service.id}, %{current_user: reader})
+
+ refute found["helm"]["values"]
+ end
+
test "it respects rbac" do
user = insert(:user)
service = insert(:service, read_bindings: [%{user_id: user.id}])
@@ -721,4 +797,32 @@ defmodule Console.GraphQl.DeploymentQueriesTest do
assert found["id"] == job.id
end
end
+
+ describe "helmRepository" do
+ test "it can fetch the charts from a helm repository" do
+ expect(Kube.Client, :get_helm_repository, fn "helm-charts", "console" ->
+ {:ok, %HelmRepository{
+ status: %HelmRepository.Status{
+ artifact: %HelmRepository.Status.Artifact{url: "https://pluralsh.github.io/console/index.yaml"}
+ }
+ }}
+ end)
+
+ {:ok, %{data: %{"helmRepository" => repo}}} = run_query("""
+ query {
+ helmRepository(namespace: "helm-charts", name: "console") {
+ charts {
+ name
+ versions { name version appVersion }
+ }
+ }
+ }
+ """, %{}, %{current_user: admin_user()})
+
+ [%{"name" => "console", "versions" => [chart | _]} | _] = repo["charts"]
+ assert chart["name"] == "console"
+ assert chart["version"]
+ assert chart["appVersion"]
+ end
+ end
end
diff --git a/test/test_helper.exs b/test/test_helper.exs
index 675f4e689c..52e6896c87 100644
--- a/test/test_helper.exs
+++ b/test/test_helper.exs
@@ -11,7 +11,6 @@ Mimic.copy(Console.Plural.Context)
Mimic.copy(Console.Buffers.TokenAudit)
Mimic.copy(Console.Deployments.Git.Discovery)
Mimic.copy(Console.Deployments.Pipelines)
-Mimic.copy(Mojito)
Mimic.copy(Console)
Mimic.copy(Kazan)
Mimic.copy(HTTPoison)