mirror of
https://github.com/rocky-linux/peridot.git
synced 2024-12-25 03:48:30 +00:00
332 lines
14 KiB
Plaintext
332 lines
14 KiB
Plaintext
|
local stage = std.extVar('stage');
|
||
|
local origUser = std.extVar('user');
|
||
|
local domainUser = std.extVar('domain_user');
|
||
|
local ociRegistry = std.extVar('oci_registry');
|
||
|
local ociRegistryRepo = std.extVar('oci_registry_repo');
|
||
|
local registry_secret = std.extVar('registry_secret');
|
||
|
|
||
|
local user = if domainUser != 'user-orig' then domainUser else origUser;
|
||
|
|
||
|
local stageNoDash = std.strReplace(stage, '-', '');
|
||
|
|
||
|
local kubernetes = import 'ci/kubernetes.jsonnet';
|
||
|
local db = import 'ci/db.jsonnet';
|
||
|
local mappings = import 'ci/mappings.jsonnet';
|
||
|
local utils = import 'ci/utils.jsonnet';
|
||
|
|
||
|
local labels = {
|
||
|
labels: db.label() + kubernetes.istio_labels(),
|
||
|
};
|
||
|
|
||
|
{
|
||
|
new(info)::
|
||
|
local metadata = {
|
||
|
name: info.name,
|
||
|
namespace: if stageNoDash == 'dev' then '%s-dev' % user else if std.objectHas(info, 'namespace') then info.namespace else info.name,
|
||
|
};
|
||
|
local fixed = kubernetes.fix_metadata(metadata);
|
||
|
local vshost(srv) = '%s-service.%s.svc.cluster.local' % [srv.name, fixed.namespace];
|
||
|
local infolabels = if info.backend then labels else { labels: kubernetes.istio_labels() };
|
||
|
local dbname = (if std.objectHas(info, 'dbname') then info.dbname else info.name);
|
||
|
local env = if std.objectHas(info, 'env') then info.env else [];
|
||
|
local sa_name = '%s-%s-serviceaccount' % [stageNoDash, fixed.name];
|
||
|
|
||
|
local extra_info = {
|
||
|
service_account_name: sa_name,
|
||
|
};
|
||
|
|
||
|
local envs = [stageNoDash];
|
||
|
|
||
|
local services = if std.objectHas(info, 'services') then info.services else
|
||
|
[{ name: '%s-%s-%s' % [metadata.name, port.name, env], port: port.containerPort, portName: port.name, expose: if std.objectHas(port, 'expose') then port.expose else false } for env in envs for port in info.ports];
|
||
|
|
||
|
local nssa = '001-ns-sa.yaml';
|
||
|
local migrate = '002-migrate.yaml';
|
||
|
local deployment = '003-deployment.yaml';
|
||
|
local svcVsDr = '004-svc-vs-dr.yaml';
|
||
|
local custom = '005-custom.yaml';
|
||
|
|
||
|
local legacyDb = if std.objectHas(info, 'legacyDb') then info.legacyDb else false;
|
||
|
|
||
|
local dbPassEnv = {
|
||
|
name: 'DATABASE_PASSWORD',
|
||
|
valueFrom: !utils.local_image,
|
||
|
value: if utils.local_image then 'postgres',
|
||
|
secret: if !utils.local_image then {
|
||
|
name: '%s-database-password' % db.staged_name(dbname),
|
||
|
key: 'password',
|
||
|
},
|
||
|
};
|
||
|
|
||
|
local shouldSecureEndpoint(srv) = if mappings.get_env_from_svc(srv.name) == 'prod' && mappings.is_external(srv.name) then false
|
||
|
else if mappings.should_expose_all(srv.name) then false
|
||
|
else if utils.local_image then false
|
||
|
else if !std.objectHas(srv, 'expose') || !srv.expose then false
|
||
|
else true;
|
||
|
local imagePullSecrets = if registry_secret != 'none' then [registry_secret] else [];
|
||
|
|
||
|
{
|
||
|
[nssa]: std.manifestYamlStream([
|
||
|
kubernetes.define_namespace(metadata.namespace, infolabels),
|
||
|
kubernetes.define_service_account(metadata {
|
||
|
name: '%s-%s' % [stageNoDash, fixed.name],
|
||
|
} + if std.objectHas(info, 'service_account_options') then info.service_account_options else {},
|
||
|
),
|
||
|
]),
|
||
|
[if std.objectHas(info, 'migrate') && info.migrate == true then migrate else null]:
|
||
|
std.manifestYamlStream([
|
||
|
kubernetes.define_service_account(metadata {
|
||
|
name: 'init-db-%s-%s' % [fixed.name, stageNoDash],
|
||
|
}),
|
||
|
kubernetes.define_role_binding(metadata, metadata.name + '-role', [{
|
||
|
kind: 'ServiceAccount',
|
||
|
name: 'init-db-%s-%s-serviceaccount' % [fixed.name, stageNoDash],
|
||
|
namespace: metadata.namespace,
|
||
|
}]),
|
||
|
kubernetes.define_cluster_role_binding(metadata, metadata.name + '-clusterrole', [{
|
||
|
kind: 'ServiceAccount',
|
||
|
name: 'init-db-%s-%s-serviceaccount' % [fixed.name, stageNoDash],
|
||
|
namespace: metadata.namespace,
|
||
|
}]),
|
||
|
kubernetes.define_role(
|
||
|
metadata {
|
||
|
name: 'init-db-%s-%s' % [fixed.name, stageNoDash],
|
||
|
},
|
||
|
[{
|
||
|
apiGroups: [''],
|
||
|
resources: ['secrets'],
|
||
|
verbs: ['create', 'get'],
|
||
|
}]
|
||
|
),
|
||
|
kubernetes.define_cluster_role(
|
||
|
metadata {
|
||
|
name: 'init-db-%s-%s' % [fixed.name, stageNoDash],
|
||
|
},
|
||
|
[{
|
||
|
apiGroups: [''],
|
||
|
resources: ['secrets'],
|
||
|
verbs: ['create', 'get'],
|
||
|
}]
|
||
|
),
|
||
|
kubernetes.define_role_binding(
|
||
|
metadata {
|
||
|
name: 'init-db-%s-%s' % [fixed.name, stageNoDash],
|
||
|
},
|
||
|
'init-db-%s-%s-role' % [fixed.name, stageNoDash],
|
||
|
[{
|
||
|
kind: 'ServiceAccount',
|
||
|
name: 'init-db-%s-%s-serviceaccount' % [fixed.name, stageNoDash],
|
||
|
namespace: fixed.namespace,
|
||
|
}],
|
||
|
),
|
||
|
kubernetes.define_cluster_role_binding(
|
||
|
metadata {
|
||
|
name: 'init-db-%s-%s' % [fixed.name, stageNoDash],
|
||
|
},
|
||
|
'init-db-%s-%s-clusterrole' % [fixed.name, stageNoDash],
|
||
|
[{
|
||
|
kind: 'ServiceAccount',
|
||
|
name: 'init-db-%s-%s-serviceaccount' % [fixed.name, stageNoDash],
|
||
|
namespace: fixed.namespace,
|
||
|
}],
|
||
|
),
|
||
|
if !legacyDb then kubernetes.define_job(metadata { name: 'request-cert' }, kubernetes.request_cdb_certs('initdb%s' % stageNoDash) + {
|
||
|
serviceAccount: '%s-%s-serviceaccount' % [stageNoDash, fixed.name],
|
||
|
}),
|
||
|
if info.migrate == true && dbname != '' then kubernetes.define_job(metadata { name: info.name + '-migrate' }, {
|
||
|
image: if std.objectHas(info, 'migrate_image') && info.migrate_image != null then info.migrate_image else info.image,
|
||
|
tag: if std.objectHas(info, 'migrate_tag') && info.migrate_tag != null then info.migrate_tag else info.tag,
|
||
|
command: if std.objectHas(info, 'migrate_command') && info.migrate_command != null then info.migrate_command else ['/bin/sh'],
|
||
|
serviceAccount: 'init-db-%s-%s-serviceaccount' % [fixed.name, stageNoDash],
|
||
|
imagePullSecrets: imagePullSecrets,
|
||
|
args: if std.objectHas(info, 'migrate_args') && info.migrate_args != null then info.migrate_args else [
|
||
|
'-c',
|
||
|
'export REAL_DSN=`echo $%s | sed -e "s/REPLACEME/${DATABASE_PASSWORD}/g"%s`; /usr/bin/migrate -source file:///migrations -database $REAL_DSN up' % [info.dsn.name, if legacyDb then '' else ' | sed -e "s/postgresql/cockroachdb/g"'],
|
||
|
],
|
||
|
volumes: (if std.objectHas(info, 'volumes') then info.volumes(metadata) else []) + (if !legacyDb then kubernetes.request_cdb_certs_volumes() else []),
|
||
|
initContainers: [
|
||
|
if !legacyDb then kubernetes.request_cdb_certs('%s%s' % [metadata.name, stageNoDash]) + {
|
||
|
serviceAccount: '%s-%s-serviceaccount' % [stageNoDash, fixed.name],
|
||
|
},
|
||
|
{
|
||
|
name: 'initdb',
|
||
|
image: 'quay.io/peridot/initdb:v0.1.4',
|
||
|
command: ['/bin/sh'],
|
||
|
args: ['-c', '/bundle/initdb*'],
|
||
|
volumes: if !legacyDb then kubernetes.request_cdb_certs_volumes(),
|
||
|
env: [
|
||
|
{
|
||
|
name: 'INITDB_TARGET_DB',
|
||
|
value: db.staged_name(dbname),
|
||
|
},
|
||
|
{
|
||
|
name: 'INITDB_PRODUCTION',
|
||
|
value: 'true',
|
||
|
},
|
||
|
{
|
||
|
name: 'INITDB_DATABASE_URL',
|
||
|
value: if legacyDb then db.dsn_legacy('postgres', true) else db.dsn('initdb'),
|
||
|
},
|
||
|
],
|
||
|
},
|
||
|
],
|
||
|
env: [
|
||
|
dbPassEnv,
|
||
|
info.dsn,
|
||
|
],
|
||
|
annotations: {
|
||
|
'sidecar.istio.io/inject': 'false',
|
||
|
},
|
||
|
}) else {},
|
||
|
]),
|
||
|
[deployment]: std.manifestYamlStream([
|
||
|
kubernetes.define_deployment(
|
||
|
metadata,
|
||
|
{
|
||
|
replicas: if std.objectHas(info, 'replicas') then info.replicas else 1,
|
||
|
image: info.image,
|
||
|
tag: info.tag,
|
||
|
command: if std.objectHas(info, 'command') then [info.command] else null,
|
||
|
fsGroup: if std.objectHas(info, 'fsGroup') then info.fsGroup else null,
|
||
|
fsUser: if std.objectHas(info, 'fsUser') then info.fsUser else null,
|
||
|
imagePullSecrets: imagePullSecrets,
|
||
|
labels: db.label(),
|
||
|
annotations: if std.objectHas(info, 'annotations') then info.annotations,
|
||
|
initContainers: if !legacyDb && info.backend then [kubernetes.request_cdb_certs('%s%s' % [metadata.name, stageNoDash]) + {
|
||
|
serviceAccount: '%s-%s-serviceaccount' % [stageNoDash, fixed.name],
|
||
|
}],
|
||
|
volumes: (if std.objectHas(info, 'volumes') then info.volumes(metadata) else []) + (if !legacyDb then kubernetes.request_cdb_certs_volumes() else []),
|
||
|
ports: std.map(function(x) x { expose: null, external: null }, info.ports),
|
||
|
health: if std.objectHas(info, 'health') then info.health,
|
||
|
env: env + (if dbname != '' && info.backend then ([dbPassEnv]) else []) + [
|
||
|
{
|
||
|
name: 'SELF_IDENTITY',
|
||
|
value: 'spiffe://cluster.local/ns/%s/sa/%s-%s-serviceaccount' % [fixed.namespace, stageNoDash, fixed.name],
|
||
|
},
|
||
|
] + [
|
||
|
if std.objectHas(srv, 'expose') && srv.expose then {
|
||
|
name: '%s_PUBLIC_URL' % [std.asciiUpper(std.strReplace(std.strReplace(srv.name, stage, ''), '-', '_'))],
|
||
|
value: 'https://%s' % mappings.get(srv.name, user),
|
||
|
} else null,
|
||
|
for srv in services],
|
||
|
limits: if std.objectHas(info, 'limits') then info.limits,
|
||
|
requests: if std.objectHas(info, 'requests') then info.requests,
|
||
|
args: if std.objectHas(info, 'args') then info.args else [],
|
||
|
serviceAccount: '%s-%s-serviceaccount' % [stageNoDash, fixed.name],
|
||
|
},
|
||
|
),
|
||
|
]),
|
||
|
[svcVsDr]:
|
||
|
std.manifestYamlStream(
|
||
|
[kubernetes.define_service(metadata { name: srv.name }, srv.port, srv.port, portName=srv.portName, selector=metadata.name, env=mappings.get_env_from_svc(srv.name)) for srv in services] +
|
||
|
[kubernetes.define_virtual_service(metadata { name: srv.name + '-internal' }, {
|
||
|
hosts: [vshost(srv)],
|
||
|
gateways: [],
|
||
|
http: [
|
||
|
{
|
||
|
route: [{
|
||
|
destination: {
|
||
|
host: vshost(srv),
|
||
|
subset: mappings.get_env_from_svc(srv.name),
|
||
|
port: {
|
||
|
number: srv.port,
|
||
|
},
|
||
|
},
|
||
|
} + (if std.objectHas(info, 'internal_route_options') then info.internal_route_options else {})],
|
||
|
},
|
||
|
],
|
||
|
},) for srv in services] +
|
||
|
[if std.objectHas(srv, 'expose') && srv.expose then kubernetes.define_virtual_service(
|
||
|
metadata {
|
||
|
name: srv.name,
|
||
|
annotations: {
|
||
|
'external-dns.alpha.kubernetes.io/target': if mappings.is_external(srv.name) then 'ingress.build.resf.org' else 'ingress-internal.build.resf.org',
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
hosts: [mappings.get(srv.name, user)],
|
||
|
gateways: if mappings.is_external(srv.name) then ['istio-system/base-gateway-public'] else ['istio-system/base-gateway-confidential'],
|
||
|
http: [
|
||
|
{
|
||
|
route: [{
|
||
|
destination: {
|
||
|
host: vshost(srv),
|
||
|
subset: mappings.get_env_from_svc(srv.name),
|
||
|
port: {
|
||
|
number: srv.port,
|
||
|
},
|
||
|
},
|
||
|
} + (if std.objectHas(info, 'external_route_options') then info.external_route_options else {})],
|
||
|
},
|
||
|
],
|
||
|
}
|
||
|
) else null for srv in services] +
|
||
|
[{
|
||
|
apiVersion: 'security.istio.io/v1beta1',
|
||
|
kind: 'RequestAuthentication',
|
||
|
metadata: metadata {
|
||
|
name: srv.name,
|
||
|
},
|
||
|
spec: {
|
||
|
selector: {
|
||
|
matchLabels: {
|
||
|
app: metadata.name,
|
||
|
env: mappings.get_env_from_svc(srv.name),
|
||
|
},
|
||
|
},
|
||
|
// todo(mustafa): Introduce ObsidianProxy to support BeyondCorp
|
||
|
jwtRules: if shouldSecureEndpoint(srv) then [{
|
||
|
issuer: 'https://cloud.google.com/iap',
|
||
|
jwksUri: 'https://www.gstatic.com/iap/verify/public_key-jwk',
|
||
|
fromHeaders: [{ name: 'x-goog-iap-jwt-assertion' }],
|
||
|
}] else [],
|
||
|
},
|
||
|
} for srv in services] +
|
||
|
[{
|
||
|
apiVersion: 'security.istio.io/v1beta1',
|
||
|
kind: 'AuthorizationPolicy',
|
||
|
metadata: metadata {
|
||
|
name: srv.name,
|
||
|
},
|
||
|
spec: {
|
||
|
selector: {
|
||
|
matchLabels: {
|
||
|
app: metadata.name,
|
||
|
env: mappings.get_env_from_svc(srv.name),
|
||
|
},
|
||
|
},
|
||
|
action: 'ALLOW',
|
||
|
rules: [(if shouldSecureEndpoint(srv) then {
|
||
|
from: [],
|
||
|
} else {}) + {
|
||
|
to: [{
|
||
|
operation: {
|
||
|
ports: [std.toString(srv.port)]
|
||
|
}
|
||
|
}]
|
||
|
}],
|
||
|
},
|
||
|
} for srv in services] +
|
||
|
[kubernetes.define_destination_rule(metadata { name: srv.name }, {
|
||
|
host: vshost(srv),
|
||
|
trafficPolicy: {
|
||
|
tls: {
|
||
|
mode: 'ISTIO_MUTUAL',
|
||
|
},
|
||
|
},
|
||
|
subsets: [
|
||
|
{
|
||
|
name: mappings.get_env_from_svc(srv.name),
|
||
|
labels: {
|
||
|
app: metadata.name,
|
||
|
env: mappings.get_env_from_svc(srv.name),
|
||
|
},
|
||
|
},
|
||
|
],
|
||
|
},) for srv in services]
|
||
|
),
|
||
|
[if std.objectHas(info, 'custom_job_items') then custom else null]:
|
||
|
std.manifestYamlStream(if std.objectHas(info, 'custom_job_items') then info.custom_job_items(metadata, extra_info) else [{}]),
|
||
|
},
|
||
|
}
|