Skip to content

Commit

Permalink
Basic Job Gate specification (#509)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaeljguarino authored Nov 20, 2023
1 parent 5d0e340 commit c90a758
Show file tree
Hide file tree
Showing 18 changed files with 605 additions and 6 deletions.
107 changes: 107 additions & 0 deletions assets/src/generated/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -788,6 +788,28 @@ export type Container = {
resources?: Maybe<Resources>;
};

/** the attributes for a container */
export type ContainerAttributes = {
args?: InputMaybe<Array<InputMaybe<Scalars['String']['input']>>>;
env?: InputMaybe<Array<InputMaybe<EnvAttributes>>>;
envFrom?: InputMaybe<Array<InputMaybe<EnvFromAttributes>>>;
image: Scalars['String']['input'];
};

/** container env variable */
export type ContainerEnv = {
__typename?: 'ContainerEnv';
name: Scalars['String']['output'];
value: Scalars['String']['output'];
};

/** env from declarations for containers */
export type ContainerEnvFrom = {
__typename?: 'ContainerEnvFrom';
configMap: Scalars['String']['output'];
secret: Scalars['String']['output'];
};

export type ContainerRecommendation = {
__typename?: 'ContainerRecommendation';
containerName?: Maybe<Scalars['String']['output']>;
Expand All @@ -804,6 +826,15 @@ export type ContainerResources = {
memory?: Maybe<Scalars['String']['output']>;
};

/** a shortform spec for job containers, designed for ease-of-use */
export type ContainerSpec = {
__typename?: 'ContainerSpec';
args?: Maybe<Array<Maybe<Scalars['String']['output']>>>;
env?: Maybe<Array<Maybe<ContainerEnv>>>;
envFrom?: Maybe<Array<Maybe<ContainerEnvFrom>>>;
image: Scalars['String']['output'];
};

export type ContainerState = {
__typename?: 'ContainerState';
running?: Maybe<RunningState>;
Expand Down Expand Up @@ -988,6 +1019,16 @@ export type DiffNormalizerAttributes = {
namespace: Scalars['String']['input'];
};

export type EnvAttributes = {
name: Scalars['String']['input'];
value: Scalars['String']['input'];
};

export type EnvFromAttributes = {
configMap: Scalars['String']['input'];
secret: Scalars['String']['input'];
};

export type Event = {
__typename?: 'Event';
action?: Maybe<Scalars['String']['output']>;
Expand All @@ -1005,18 +1046,50 @@ export type FileContent = {
path?: Maybe<Scalars['String']['output']>;
};

/** spec for a job gate */
export type GateJobAttributes = {
annotations?: InputMaybe<Scalars['Map']['input']>;
containers?: InputMaybe<Array<InputMaybe<ContainerAttributes>>>;
labels?: InputMaybe<Scalars['Map']['input']>;
namespace: Scalars['String']['input'];
/** if you'd rather define the job spec via straight k8s yaml */
raw?: InputMaybe<Scalars['String']['input']>;
serviceAccount?: InputMaybe<Scalars['String']['input']>;
};

/** detailed gate specifications */
export type GateSpec = {
__typename?: 'GateSpec';
job?: Maybe<JobGateSpec>;
};

/** a more refined spec for parameters needed for complex gates */
export type GateSpecAttributes = {
job?: InputMaybe<GateJobAttributes>;
};

export enum GateState {
Closed = 'CLOSED',
Open = 'OPEN',
Pending = 'PENDING'
}

export type GateStatusAttributes = {
jobRef?: InputMaybe<NamespacedName>;
};

export enum GateType {
Approval = 'APPROVAL',
Job = 'JOB',
Window = 'WINDOW'
}

/** the allowed inputs for a deployment agent gate update */
export type GateUpdateAttributes = {
state?: InputMaybe<GateState>;
status?: InputMaybe<GateStatusAttributes>;
};

export type GcpCloudAttributes = {
network?: InputMaybe<Scalars['String']['input']>;
project?: InputMaybe<Scalars['String']['input']>;
Expand Down Expand Up @@ -1272,6 +1345,23 @@ export type Job = {
status: JobStatus;
};

/** the full specification of a job gate */
export type JobGateSpec = {
__typename?: 'JobGateSpec';
/** any pod annotations to apply */
annotations?: Maybe<Scalars['Map']['output']>;
/** list of containers to run in this job */
containers?: Maybe<Array<Maybe<ContainerSpec>>>;
/** any pod labels to apply */
labels?: Maybe<Scalars['Map']['output']>;
/** the namespace the job will run in */
namespace: Scalars['String']['output'];
/** a raw kubernetes job resource, overrides any other configuration */
raw?: Maybe<Scalars['String']['output']>;
/** the service account the pod will use */
serviceAccount?: Maybe<Scalars['String']['output']>;
};

export type JobReference = {
__typename?: 'JobReference';
name: Scalars['String']['output'];
Expand Down Expand Up @@ -1463,6 +1553,11 @@ export type NamespaceStatus = {
phase?: Maybe<Scalars['String']['output']>;
};

export type NamespacedName = {
name: Scalars['String']['input'];
namespace: Scalars['String']['input'];
};

export type Node = {
__typename?: 'Node';
events?: Maybe<Array<Maybe<Event>>>;
Expand Down Expand Up @@ -1669,6 +1764,8 @@ export type PipelineGate = {
insertedAt?: Maybe<Scalars['DateTime']['output']>;
/** the name of this gate as seen in the UI */
name: Scalars['String']['output'];
/** more detailed specification for complex gates */
spec?: Maybe<GateSpec>;
/** the current state of this gate */
state: GateState;
/** the type of gate this is */
Expand All @@ -1684,6 +1781,8 @@ export type PipelineGateAttributes = {
clusterId?: InputMaybe<Scalars['String']['input']>;
/** the name of this gate */
name: Scalars['String']['input'];
/** a specification for more complex gate types */
spec?: InputMaybe<GateSpecAttributes>;
/** the type of gate this is */
type: GateType;
};
Expand Down Expand Up @@ -2181,6 +2280,7 @@ export type RootMutationType = {
updateClusterProvider?: Maybe<ClusterProvider>;
updateConfiguration?: Maybe<Configuration>;
updateDeploymentSettings?: Maybe<DeploymentSettings>;
updateGate?: Maybe<PipelineGate>;
updateGitRepository?: Maybe<GitRepository>;
updateGroup?: Maybe<Group>;
/** a reusable mutation for updating rbac settings on core services */
Expand Down Expand Up @@ -2529,6 +2629,12 @@ export type RootMutationTypeUpdateDeploymentSettingsArgs = {
};


export type RootMutationTypeUpdateGateArgs = {
attributes: GateUpdateAttributes;
id: Scalars['ID']['input'];
};


export type RootMutationTypeUpdateGitRepositoryArgs = {
attributes: GitAttributes;
id: Scalars['ID']['input'];
Expand Down Expand Up @@ -2599,6 +2705,7 @@ export type RootQueryType = {
cluster?: Maybe<Cluster>;
/** list all addons currently resident in the artifacts repo */
clusterAddOns?: Maybe<Array<Maybe<ClusterAddOn>>>;
clusterGates?: Maybe<Array<Maybe<PipelineGate>>>;
clusterInfo?: Maybe<ClusterInfo>;
/** fetches an individual cluster provider */
clusterProvider?: Maybe<ClusterProvider>;
Expand Down
4 changes: 2 additions & 2 deletions charts/console/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ apiVersion: v2
name: console
description: A Helm chart for Kubernetes
type: application
version: 0.1.5
appVersion: 0.6.5
version: 0.1.6
appVersion: 0.6.6
dependencies:
- name: kas
version: 0.0.3
Expand Down
4 changes: 4 additions & 0 deletions charts/console/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ spec: {{ .Values.secrets.config | toYaml | nindent 2 }}
{{- define "console.env" -}}
- name: HOST
value: {{ .Values.ingress.console_dns }}
{{- if .Values.externalIngress.hostname }}
- name: EXT_HOST
value: {{ .Values.externalIngress.hostname | quote }}
{{- end }}
- name: KAS_DNS
value: {{ .Values.ingress.kas_dns }}
- name: DEPLOYED_AT
Expand Down
30 changes: 30 additions & 0 deletions charts/console/templates/ingress.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,33 @@ spec:
name: console
port:
name: http
{{ if .Values.externalIngress.hostname }}
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: console-external
labels:
{{ include "console.labels" . | indent 4 }}
{{- with .Values.externalIngress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
ingressClassName: {{ .Values.externalIngress.ingressClass }}
tls:
- hosts:
- {{ .Values.externalIngress.hostname | quote }}
secretName: console-external-tls
rules:
- host: {{ .Values.externalIngress.hostname | quote }}
http:
paths:
- path: /ext
pathType: Prefix
backend:
service:
name: console
port:
name: http
{{ end }}
11 changes: 11 additions & 0 deletions charts/console/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,17 @@ ingress:
nginx.ingress.kubernetes.io/proxy-send-timeout: '3600'
nginx.ingress.kubernetes.io/session-cookie-path: /socket

externalIngress:
ingressClass: nginx
annotations:
kubernetes.io/tls-acme: "true"
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/affinity: cookie
nginx.ingress.kubernetes.io/force-ssl-redirect: 'true'
nginx.ingress.kubernetes.io/proxy-read-timeout: '3600'
nginx.ingress.kubernetes.io/proxy-send-timeout: '3600'
nginx.ingress.kubernetes.io/session-cookie-path: /ext/socket

postgres:
dsnSecret: postgres-dsn
dsnKey: dsn
Expand Down
25 changes: 24 additions & 1 deletion lib/console/deployments/pipelines.ex
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ defmodule Console.Deployments.Pipelines do
PromotionService,
User,
Revision,
Service
Service,
Cluster
}

@preload [:read_bindings, :write_bindings, edges: [:gates], stages: [services: :criteria]]
Expand Down Expand Up @@ -84,6 +85,17 @@ defmodule Console.Deployments.Pipelines do
do: Timex.after?(at, dt)
def promoted?(_, _), do: false

@doc """
Fetches all eligible gates for a cluster
"""
@spec for_cluster(Cluster.t) :: [PipelineGate.t]
def for_cluster(%Cluster{id: id}) do
PipelineGate.for_cluster(id)
|> PipelineGate.for_agent()
|> PipelineGate.pending()
|> Repo.all()
end

@doc """
If a user has pipeline write access, will approvate and open the given gate
"""
Expand All @@ -97,6 +109,17 @@ defmodule Console.Deployments.Pipelines do
|> notify(:approve, user)
end

@doc """
An update to a gate's status, to be called from w/in a deployment agent
"""
@spec update_gate(map, binary, Cluster.t) :: gate_resp
def update_gate(attrs, id, %Cluster{} = cluster) do
get_gate!(id)
|> PipelineGate.update_changeset(attrs)
|> allow(cluster, :update)
|> when_ok(:update)
end

@doc """
If a user has pipeline write access, will force open a gate
"""
Expand Down
4 changes: 4 additions & 0 deletions lib/console/deployments/policies/policies.ex
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ defmodule Console.Deployments.Policies do
when (is_list(r) and length(r) > 0) or (is_list(w) and length(w) > 0),
do: can?(user, Map.merge(resource, %{read_bindings: [], write_bindings: []}), :create)

def can?(%Cluster{id: id}, %PipelineGate{cluster_id: id}, :update),
do: :pass
def can?(_, %PipelineGate{}, :update), do: {:error, "forbidden"}

def can?(%User{} = user, %PipelineGate{type: :approval} = g, :approve),
do: can?(user, g, :write)
def can?(_, %PipelineGate{}, :approve), do: {:error, "only approval gates can be approved"}
Expand Down
2 changes: 2 additions & 0 deletions lib/console/external_graphql.ex
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,13 @@ defmodule Console.ExternalGraphQl do
query do
import_fields :public_service_queries
import_fields :public_cluster_queries
import_fields :public_pipeline_queries
end

mutation do
import_fields :public_cluster_mutations
import_fields :public_service_mutations
import_fields :public_pipeline_mutations
end


Expand Down
2 changes: 2 additions & 0 deletions lib/console/graphql/deployments.ex
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ defmodule Console.GraphQl.Deployments do
import_fields :pipeline_queries
import_fields :public_service_queries
import_fields :public_cluster_queries
import_fields :public_pipeline_queries

field :deployment_settings, :deployment_settings do
middleware Authenticated
Expand All @@ -72,6 +73,7 @@ defmodule Console.GraphQl.Deployments do
import_fields :pipeline_mutations
import_fields :public_cluster_mutations
import_fields :public_service_mutations
import_fields :public_pipeline_mutations

@desc "a reusable mutation for updating rbac settings on core services"
field :update_rbac, :boolean do
Expand Down
Loading

0 comments on commit c90a758

Please sign in to comment.