350 lines
9.3 KiB
Jsonnet
350 lines
9.3 KiB
Jsonnet
|
|
local baseKube = import "k8s/configs/k.libsonnet";
|
||
|
|
|
||
|
|
local tanka = import "tanka-util/main.libsonnet";
|
||
|
|
local helm = tanka.helm.new(std.thisFile);
|
||
|
|
|
||
|
|
local baseKubeCompat = {
|
||
|
|
_Object(apiVersion, kind, name):: {
|
||
|
|
local this = self,
|
||
|
|
apiVersion: apiVersion,
|
||
|
|
kind: kind,
|
||
|
|
metadata: {
|
||
|
|
name: name,
|
||
|
|
labels: { name: std.join("-", std.split(this.metadata.name, ":")) },
|
||
|
|
annotations: {},
|
||
|
|
},
|
||
|
|
},
|
||
|
|
};
|
||
|
|
|
||
|
|
local splitThisFilePath = std.split(std.thisFile, "/");
|
||
|
|
local workspaceRoot = std.join('/', splitThisFilePath[:std.length(splitThisFilePath)-3]);
|
||
|
|
local workspaceRootLength = std.length(workspaceRoot);
|
||
|
|
{
|
||
|
|
helm: helm,
|
||
|
|
|
||
|
|
// Returns array of values from given object. Does not include hidden fields.
|
||
|
|
objectValues(o):: [o[field] for field in std.objectFields(o)],
|
||
|
|
|
||
|
|
asWorkspacePath(fullPath):
|
||
|
|
local isPrefixed = std.startsWith(fullPath,workspaceRoot);
|
||
|
|
if !isPrefixed then error fullPath + "is not prefixed by workspace root \"" + workspaceRoot + "\"" else
|
||
|
|
fullPath[workspaceRootLength+1 :],
|
||
|
|
|
||
|
|
errNeedField(name): error name + " must be defined",
|
||
|
|
|
||
|
|
SimpleFieldStruct(requiredFields): {
|
||
|
|
[requiredField]: $.errNeedField(requiredField)
|
||
|
|
for requiredField in requiredFields
|
||
|
|
},
|
||
|
|
simpleFieldStruct: $.SimpleFieldStruct,
|
||
|
|
|
||
|
|
Context: $.SimpleFieldStruct([
|
||
|
|
"helm"
|
||
|
|
]),
|
||
|
|
|
||
|
|
NewContext(helm): $.Context {
|
||
|
|
helm: helm
|
||
|
|
},
|
||
|
|
|
||
|
|
List(): {
|
||
|
|
apiVersion: "v1",
|
||
|
|
kind: "List",
|
||
|
|
items_:: {},
|
||
|
|
items: $.objectValues(self.items_),
|
||
|
|
},
|
||
|
|
|
||
|
|
#################
|
||
|
|
# Support utils #
|
||
|
|
#################
|
||
|
|
# For use in SERVICE.metadata.annotations position
|
||
|
|
# TODO(acmcarther): move this into
|
||
|
|
PrometheusScrapeable(port): {
|
||
|
|
"prometheus.io/scrape": "true",
|
||
|
|
"prometheus.io/port": std.toString(port),
|
||
|
|
},
|
||
|
|
|
||
|
|
NameVal(name, value): {
|
||
|
|
name: name,
|
||
|
|
value: value,
|
||
|
|
},
|
||
|
|
|
||
|
|
SvcUtil: {
|
||
|
|
# For use in SERVICE.spec.ports position
|
||
|
|
TCPServicePort(name, port): {
|
||
|
|
name: name,
|
||
|
|
port: port,
|
||
|
|
protocol: "TCP",
|
||
|
|
},
|
||
|
|
|
||
|
|
# For use in SERVICE.spec.ports position
|
||
|
|
UDPServicePort(name, port): {
|
||
|
|
name: name,
|
||
|
|
port: port,
|
||
|
|
protocol: "UDP",
|
||
|
|
},
|
||
|
|
|
||
|
|
# For use in SERVICE.spec
|
||
|
|
BasicHttpClusterIpSpec(internalPort): {
|
||
|
|
type: "ClusterIP",
|
||
|
|
ports: [
|
||
|
|
$.SvcUtil.TCPServicePort("http", 80) {
|
||
|
|
targetPort: internalPort
|
||
|
|
},
|
||
|
|
],
|
||
|
|
},
|
||
|
|
|
||
|
|
# For use in SERVICE.spec
|
||
|
|
BasicNodePortSpec(internalPort, nodePort): {
|
||
|
|
type: "NodePort",
|
||
|
|
ports: [
|
||
|
|
$.SvcUtil.TCPServicePort("tcp", internalPort) {
|
||
|
|
targetPort: internalPort,
|
||
|
|
nodePort: nodePort,
|
||
|
|
},
|
||
|
|
$.SvcUtil.UDPServicePort("udp", internalPort) {
|
||
|
|
targetPort: internalPort,
|
||
|
|
nodePort: nodePort,
|
||
|
|
},
|
||
|
|
],
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
DeployUtil: {
|
||
|
|
# For use in DEPLOYMENT.spec.template.spec.containers
|
||
|
|
VolumeMount(name, mountPath): {
|
||
|
|
name: name,
|
||
|
|
mountPath: mountPath,
|
||
|
|
},
|
||
|
|
|
||
|
|
# For use in DEPLOYMENT.spec.template.spec.volumes
|
||
|
|
VolumeClaimRef(name, claimName): {
|
||
|
|
name: name,
|
||
|
|
persistentVolumeClaim: {
|
||
|
|
claimName: claimName,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
|
||
|
|
# For use in DEPLOYMENT.spec.template.spec.containers.ports
|
||
|
|
ContainerPort(name, port): {
|
||
|
|
name: name,
|
||
|
|
containerPort: port,
|
||
|
|
},
|
||
|
|
ContainerTCPPort(name, port): {
|
||
|
|
name: name,
|
||
|
|
containerPort: port,
|
||
|
|
protocol: "TCP",
|
||
|
|
},
|
||
|
|
|
||
|
|
# For use in DEPLOYMENT.spec.strategy
|
||
|
|
SimpleRollingUpdate(): {
|
||
|
|
type: "RollingUpdate",
|
||
|
|
rollingUpdate: {
|
||
|
|
maxUnavailable: 1,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
|
||
|
|
# For use in DEPLOYMENT.spec.template.spec.*Probe
|
||
|
|
SimpleProbe(webPort, delaySeconds): {
|
||
|
|
httpGet: {
|
||
|
|
path: "/",
|
||
|
|
port: webPort,
|
||
|
|
},
|
||
|
|
initialDelaySeconds: delaySeconds,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
|
||
|
|
##########################
|
||
|
|
# Kube object definition #
|
||
|
|
##########################
|
||
|
|
Namespace(name): baseKube.Namespace(name),
|
||
|
|
|
||
|
|
StorageClass(name): baseKubeCompat._Object("storage.k8s.io/v1", "StorageClass", name) {
|
||
|
|
},
|
||
|
|
|
||
|
|
RecoverableSimplePvc(namespace, name, storageClass, quantity, recoverySpec): {
|
||
|
|
pv: if recoverySpec == null then {} else $.SimplePv(namespace, storageClass, quantity, recoverySpec.volumeName) {
|
||
|
|
spec+: {
|
||
|
|
nfs: {
|
||
|
|
path: recoverySpec.nfsPath,
|
||
|
|
server: recoverySpec.nfsServer,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
pvc: $.SimplePvc(namespace, name, storageClass, quantity) {
|
||
|
|
spec+: {
|
||
|
|
volumeName: if recoverySpec == null then null else recoverySpec.volumeName,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
RecoverableSimpleManyPvc(namespace, name, storageClass, quantity, recoverySpec): {
|
||
|
|
pv: if recoverySpec == null then {} else $.SimpleManyPv(namespace, storageClass, quantity, recoverySpec.volumeName) {
|
||
|
|
spec+: {
|
||
|
|
nfs: {
|
||
|
|
path: recoverySpec.nfsPath,
|
||
|
|
server: recoverySpec.nfsServer,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
pvc: $.SimpleManyPvc(namespace, name, storageClass, quantity) {
|
||
|
|
spec+: {
|
||
|
|
volumeName: if recoverySpec == null then null else recoverySpec.volumeName,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
# N.B. Actual storage must still be defined.
|
||
|
|
SimplePv(namespace, storageClass, quantity, name): baseKubeCompat._Object("v1", "PersistentVolume", name) {
|
||
|
|
metadata+: {
|
||
|
|
namespace: namespace,
|
||
|
|
},
|
||
|
|
spec+: {
|
||
|
|
storageClassName: storageClass,
|
||
|
|
volumeMode: "Filesystem",
|
||
|
|
persistentVolumeReclaimPolicy: "Delete",
|
||
|
|
capacity: {
|
||
|
|
storage: quantity,
|
||
|
|
},
|
||
|
|
accessModes: ["ReadWriteOnce"],
|
||
|
|
},
|
||
|
|
},
|
||
|
|
|
||
|
|
SimpleManyPv(namespace, storageClass, quantity, name): $.SimplePv(namespace, storageClass, quantity, name) {
|
||
|
|
spec+: {
|
||
|
|
accessModes: ["ReadWriteMany"],
|
||
|
|
},
|
||
|
|
},
|
||
|
|
|
||
|
|
SimplePvc(namespace, name, storageClass, quantity): baseKubeCompat._Object("v1", "PersistentVolumeClaim", name) {
|
||
|
|
metadata+: {
|
||
|
|
namespace: namespace,
|
||
|
|
},
|
||
|
|
spec: {
|
||
|
|
storageClassName: storageClass,
|
||
|
|
resources: {
|
||
|
|
requests: {
|
||
|
|
storage: quantity,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
accessModes: ["ReadWriteOnce"],
|
||
|
|
},
|
||
|
|
},
|
||
|
|
|
||
|
|
SimpleManyPvc(namespace, name, storageClass, quantity): $.SimplePvc(namespace, name, storageClass, quantity) {
|
||
|
|
spec+: {
|
||
|
|
accessModes: ["ReadWriteMany"],
|
||
|
|
},
|
||
|
|
},
|
||
|
|
|
||
|
|
Role(namespace, name): baseKubeCompat._Object("rbac.authorization.k8s.io/v1", "Role", name) {
|
||
|
|
metadata+: {
|
||
|
|
namespace: namespace,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
|
||
|
|
RoleBinding(namespace, name): baseKubeCompat._Object("rbac.authorization.k8s.io/v1", "RoleBinding", name) {
|
||
|
|
metadata+: {
|
||
|
|
namespace: namespace,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
|
||
|
|
ConfigMap(namespace, name): baseKubeCompat._Object("v1", "ConfigMap", name) {
|
||
|
|
metadata+: {
|
||
|
|
namespace: namespace,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
|
||
|
|
ClusterRole(name): baseKubeCompat._Object("rbac.authorization.k8s.io/v1", "ClusterRole", name) {
|
||
|
|
},
|
||
|
|
|
||
|
|
ClusterRoleBinding(name): baseKubeCompat._Object("rbac.authorization.k8s.io/v1", "ClusterRoleBinding", name) {
|
||
|
|
},
|
||
|
|
|
||
|
|
DaemonSet(namespace, name): baseKubeCompat._Object("apps/v1", "DaemonSet", name) {
|
||
|
|
metadata+: {
|
||
|
|
namespace: namespace,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
|
||
|
|
ServiceAccount(namespace, name): baseKubeCompat._Object("v1", "ServiceAccount", name) {
|
||
|
|
metadata+: {
|
||
|
|
namespace: namespace,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
|
||
|
|
Service(namespace, name): baseKubeCompat._Object("v1", "Service", name) {
|
||
|
|
metadata+: {
|
||
|
|
namespace: namespace,
|
||
|
|
},
|
||
|
|
# TODO(acmcarther): Figure out how to make this more useful
|
||
|
|
},
|
||
|
|
|
||
|
|
Deployment(namespace, name): baseKubeCompat._Object("apps/v1", "Deployment", name) {
|
||
|
|
metadata+: {
|
||
|
|
namespace: namespace,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
|
||
|
|
StatefulSet(namespace, name): baseKubeCompat._Object("apps/v1", "StatefulSet", name) {
|
||
|
|
metadata+: {
|
||
|
|
namespace: namespace,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
|
||
|
|
|
||
|
|
Ingress(namespace, name): baseKubeCompat._Object("networking.k8s.io/v1", "Ingress", name) {
|
||
|
|
metadata+: {
|
||
|
|
namespace: namespace,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
|
||
|
|
Secret(namespace, name): baseKubeCompat._Object("v1", "Secret", name) {
|
||
|
|
metadata+: {
|
||
|
|
namespace: namespace,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
|
||
|
|
CronJob(namespace, name): baseKubeCompat._Object("batch/v1", "CronJob", name) {
|
||
|
|
metadata+: {
|
||
|
|
namespace: namespace,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
Endpoints(namespace, name): baseKubeCompat._Object("v1", "Endpoints", name) {
|
||
|
|
metadata+: {
|
||
|
|
namespace: namespace,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
EndpointSlice(namespace, name): baseKubeCompat._Object("discovery.k8s.io/v1", "EndpointSlice", name) {
|
||
|
|
metadata+: {
|
||
|
|
namespace: namespace,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
|
||
|
|
ApiService(name): baseKubeCompat._Object("apiregistration.k8s.io/v1", "APIService", name) {},
|
||
|
|
|
||
|
|
IngressClass(name): baseKubeCompat._Object("networking.k8s.io/v1", "IngressClass", name) {},
|
||
|
|
|
||
|
|
ClusterIssuer(namespace, name): baseKubeCompat._Object("cert-manager.io/v1", "ClusterIssuer", name) {
|
||
|
|
metadata+: {
|
||
|
|
namespace: namespace,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
|
||
|
|
|
||
|
|
# Provides "curried" functions with namespace pre-bound
|
||
|
|
UsingNamespace(namespace): {
|
||
|
|
Endpoints(name): $.Endpoints(namespace, name),
|
||
|
|
EndpointSlice(name): $.EndpointSlice(namespace, name),
|
||
|
|
SimplePvc(name, storageClass, quantity): $.SimplePvc(namespace, name, storageClass, quantity),
|
||
|
|
SimpleManyPvc(name, storageClass, quantity): $.SimpleManyPvc(namespace, name, storageClass, quantity),
|
||
|
|
ServiceAccount(name): $.ServiceAccount(namespace, name),
|
||
|
|
Service(name): $.Service(namespace, name),
|
||
|
|
Deployment(name): $.Deployment(namespace, name),
|
||
|
|
CronJob(name): $.CronJob(namespace, name),
|
||
|
|
StatefulSet(name): $.StatefulSet(namespace, name),
|
||
|
|
Ingress(name): $.Ingress(namespace, name),
|
||
|
|
ConfigMap(name): $.ConfigMap(namespace, name),
|
||
|
|
},
|
||
|
|
}
|
||
|
|
|