From d8692794a9a4233d21ae88a9114294a84ac5fe1c Mon Sep 17 00:00:00 2001
From: Frederic Branczyk <fbranczyk@gmail.com>
Date: Sun, 8 Apr 2018 14:53:30 +0200
Subject: [PATCH] kube-prometheus: Convert to jsonnet

---
 .gitignore                                    |  1 +
 build.sh                                      | 19 ++++
 .../alertmanager-main-secret.libsonnet        | 25 ++++++
 ...lertmanager-main-service-account.libsonnet |  8 ++
 .../alertmanager-main-service.libsonnet       | 12 +++
 .../alertmanager/alertmanager-main.libsonnet  | 19 ++++
 jsonnet/alertmanager/alertmanager.libsonnet   |  6 ++
 jsonnet/kube-prometheus.jsonnet               | 62 +++++++++++++
 ...ate-metrics-cluster-role-binding.libsonnet | 12 +++
 .../kube-state-metrics-cluster-role.libsonnet | 75 ++++++++++++++++
 .../kube-state-metrics-deployment.libsonnet   | 86 +++++++++++++++++++
 .../kube-state-metrics-role-binding.libsonnet | 13 +++
 .../kube-state-metrics-role.libsonnet         | 28 ++++++
 ...be-state-metrics-service-account.libsonnet |  8 ++
 .../kube-state-metrics-service.libsonnet      | 15 ++++
 .../kube-state-metrics.libsonnet              |  9 ++
 ...de-exporter-cluster-role-binding.libsonnet | 12 +++
 .../node-exporter-cluster-role.libsonnet      | 26 ++++++
 .../node-exporter-daemonset.libsonnet         | 58 +++++++++++++
 .../node-exporter-service-account.libsonnet   |  8 ++
 .../node-exporter-service.libsonnet           | 14 +++
 jsonnet/node-exporter/node-exporter.libsonnet |  7 ++
 ...us-operator-cluster-role-binding.libsonnet | 12 +++
 ...prometheus-operator-cluster-role.libsonnet | 80 +++++++++++++++++
 .../prometheus-operator-deployment.libsonnet  | 30 +++++++
 ...metheus-operator-service-account.libsonnet |  8 ++
 .../prometheus-operator-service.libsonnet     | 14 +++
 .../prometheus-operator.libsonnet             |  7 ++
 ...metheus-k8s-cluster-role-binding.libsonnet | 12 +++
 .../prometheus-k8s-cluster-role.libsonnet     | 21 +++++
 ...ometheus-k8s-role-binding-config.libsonnet |  5 ++
 ...metheus-k8s-role-binding-default.libsonnet |  5 ++
 ...eus-k8s-role-binding-kube-system.libsonnet |  5 ++
 ...theus-k8s-role-binding-namespace.libsonnet |  5 ++
 .../prometheus-k8s-role-config.libsonnet      | 18 ++++
 .../prometheus-k8s-role-default.libsonnet     |  5 ++
 .../prometheus-k8s-role-kube-system.libsonnet |  5 ++
 .../prometheus-k8s-role-namespace.libsonnet   |  5 ++
 .../prometheus-k8s-service-account.libsonnet  |  8 ++
 ...k8s-service-monitor-alertmanager.libsonnet | 32 +++++++
 ...us-k8s-service-monitor-apiserver.libsonnet | 40 +++++++++
 ...heus-k8s-service-monitor-coredns.libsonnet | 35 ++++++++
 ...-monitor-kube-controller-manager.libsonnet | 33 +++++++
 ...s-service-monitor-kube-scheduler.libsonnet | 33 +++++++
 ...rvice-monitor-kube-state-metrics.libsonnet | 48 +++++++++++
 ...heus-k8s-service-monitor-kubelet.libsonnet | 49 +++++++++++
 ...8s-service-monitor-node-exporter.libsonnet | 38 ++++++++
 ...vice-monitor-prometheus-operator.libsonnet | 26 ++++++
 ...s-k8s-service-monitor-prometheus.libsonnet | 32 +++++++
 .../prometheus-k8s-service.libsonnet          | 13 +++
 jsonnet/prometheus/prometheus-k8s.libsonnet   | 43 ++++++++++
 ...rometheus-namespace-role-binding.libsonnet | 13 +++
 .../prometheus-namespace-role.libsonnet       | 21 +++++
 jsonnet/prometheus/prometheus.libsonnet       | 25 ++++++
 54 files changed, 1249 insertions(+)
 create mode 100644 .gitignore
 create mode 100755 build.sh
 create mode 100644 jsonnet/alertmanager/alertmanager-main-secret.libsonnet
 create mode 100644 jsonnet/alertmanager/alertmanager-main-service-account.libsonnet
 create mode 100644 jsonnet/alertmanager/alertmanager-main-service.libsonnet
 create mode 100644 jsonnet/alertmanager/alertmanager-main.libsonnet
 create mode 100644 jsonnet/alertmanager/alertmanager.libsonnet
 create mode 100644 jsonnet/kube-prometheus.jsonnet
 create mode 100644 jsonnet/kube-state-metrics/kube-state-metrics-cluster-role-binding.libsonnet
 create mode 100644 jsonnet/kube-state-metrics/kube-state-metrics-cluster-role.libsonnet
 create mode 100644 jsonnet/kube-state-metrics/kube-state-metrics-deployment.libsonnet
 create mode 100644 jsonnet/kube-state-metrics/kube-state-metrics-role-binding.libsonnet
 create mode 100644 jsonnet/kube-state-metrics/kube-state-metrics-role.libsonnet
 create mode 100644 jsonnet/kube-state-metrics/kube-state-metrics-service-account.libsonnet
 create mode 100644 jsonnet/kube-state-metrics/kube-state-metrics-service.libsonnet
 create mode 100644 jsonnet/kube-state-metrics/kube-state-metrics.libsonnet
 create mode 100644 jsonnet/node-exporter/node-exporter-cluster-role-binding.libsonnet
 create mode 100644 jsonnet/node-exporter/node-exporter-cluster-role.libsonnet
 create mode 100644 jsonnet/node-exporter/node-exporter-daemonset.libsonnet
 create mode 100644 jsonnet/node-exporter/node-exporter-service-account.libsonnet
 create mode 100644 jsonnet/node-exporter/node-exporter-service.libsonnet
 create mode 100644 jsonnet/node-exporter/node-exporter.libsonnet
 create mode 100644 jsonnet/prometheus-operator/prometheus-operator-cluster-role-binding.libsonnet
 create mode 100644 jsonnet/prometheus-operator/prometheus-operator-cluster-role.libsonnet
 create mode 100644 jsonnet/prometheus-operator/prometheus-operator-deployment.libsonnet
 create mode 100644 jsonnet/prometheus-operator/prometheus-operator-service-account.libsonnet
 create mode 100644 jsonnet/prometheus-operator/prometheus-operator-service.libsonnet
 create mode 100644 jsonnet/prometheus-operator/prometheus-operator.libsonnet
 create mode 100644 jsonnet/prometheus/prometheus-k8s-cluster-role-binding.libsonnet
 create mode 100644 jsonnet/prometheus/prometheus-k8s-cluster-role.libsonnet
 create mode 100644 jsonnet/prometheus/prometheus-k8s-role-binding-config.libsonnet
 create mode 100644 jsonnet/prometheus/prometheus-k8s-role-binding-default.libsonnet
 create mode 100644 jsonnet/prometheus/prometheus-k8s-role-binding-kube-system.libsonnet
 create mode 100644 jsonnet/prometheus/prometheus-k8s-role-binding-namespace.libsonnet
 create mode 100644 jsonnet/prometheus/prometheus-k8s-role-config.libsonnet
 create mode 100644 jsonnet/prometheus/prometheus-k8s-role-default.libsonnet
 create mode 100644 jsonnet/prometheus/prometheus-k8s-role-kube-system.libsonnet
 create mode 100644 jsonnet/prometheus/prometheus-k8s-role-namespace.libsonnet
 create mode 100644 jsonnet/prometheus/prometheus-k8s-service-account.libsonnet
 create mode 100644 jsonnet/prometheus/prometheus-k8s-service-monitor-alertmanager.libsonnet
 create mode 100644 jsonnet/prometheus/prometheus-k8s-service-monitor-apiserver.libsonnet
 create mode 100644 jsonnet/prometheus/prometheus-k8s-service-monitor-coredns.libsonnet
 create mode 100644 jsonnet/prometheus/prometheus-k8s-service-monitor-kube-controller-manager.libsonnet
 create mode 100644 jsonnet/prometheus/prometheus-k8s-service-monitor-kube-scheduler.libsonnet
 create mode 100644 jsonnet/prometheus/prometheus-k8s-service-monitor-kube-state-metrics.libsonnet
 create mode 100644 jsonnet/prometheus/prometheus-k8s-service-monitor-kubelet.libsonnet
 create mode 100644 jsonnet/prometheus/prometheus-k8s-service-monitor-node-exporter.libsonnet
 create mode 100644 jsonnet/prometheus/prometheus-k8s-service-monitor-prometheus-operator.libsonnet
 create mode 100644 jsonnet/prometheus/prometheus-k8s-service-monitor-prometheus.libsonnet
 create mode 100644 jsonnet/prometheus/prometheus-k8s-service.libsonnet
 create mode 100644 jsonnet/prometheus/prometheus-k8s.libsonnet
 create mode 100644 jsonnet/prometheus/prometheus-namespace-role-binding.libsonnet
 create mode 100644 jsonnet/prometheus/prometheus-namespace-role.libsonnet
 create mode 100644 jsonnet/prometheus/prometheus.libsonnet

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..3fec32c8
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+tmp/
diff --git a/build.sh b/build.sh
new file mode 100755
index 00000000..a42a6bb7
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+set -e
+set -x
+
+prefix="tmp/manifests"
+json="tmp/manifests.json"
+
+rm -rf ${prefix}
+mkdir -p $(dirname "${json}")
+jsonnet -J /home/brancz/.jsonnet-bundler/src/git/git@github.com-ksonnet-ksonnet-lib/master jsonnet/kube-prometheus.jsonnet > ${json}
+
+files=$(jq -r 'keys[]' ${json})
+
+for file in ${files}; do
+    dir=$(dirname "${file}")
+    path="${prefix}/${dir}"
+    mkdir -p ${path}
+    jq -r ".[\"${file}\"]" ${json} | yaml2json | json2yaml > "${prefix}/${file}"
+done
diff --git a/jsonnet/alertmanager/alertmanager-main-secret.libsonnet b/jsonnet/alertmanager/alertmanager-main-secret.libsonnet
new file mode 100644
index 00000000..fca16566
--- /dev/null
+++ b/jsonnet/alertmanager/alertmanager-main-secret.libsonnet
@@ -0,0 +1,25 @@
+local k = import "ksonnet.beta.3/k.libsonnet";
+local secret = k.core.v1.secret;
+
+local plainConfig = "global:
+  resolve_timeout: 5m
+route:
+  group_by: ['job']
+  group_wait: 30s
+  group_interval: 5m
+  repeat_interval: 12h
+  receiver: 'null'
+  routes:
+  - match:
+      alertname: DeadMansSwitch
+    receiver: 'null'
+receivers:
+- name: 'null'";
+
+local config = std.base64(plainConfig);
+
+{
+    new(namespace)::
+        secret.new("alertmanager-main", {"alertmanager.yaml": config}) +
+          secret.mixin.metadata.withNamespace(namespace)
+}
diff --git a/jsonnet/alertmanager/alertmanager-main-service-account.libsonnet b/jsonnet/alertmanager/alertmanager-main-service-account.libsonnet
new file mode 100644
index 00000000..89ca2f80
--- /dev/null
+++ b/jsonnet/alertmanager/alertmanager-main-service-account.libsonnet
@@ -0,0 +1,8 @@
+local k = import "ksonnet.beta.3/k.libsonnet";
+local serviceAccount = k.core.v1.serviceAccount;
+
+{
+    new(namespace)::
+        serviceAccount.new("alertmanager-main") +
+          serviceAccount.mixin.metadata.withNamespace(namespace)
+}
diff --git a/jsonnet/alertmanager/alertmanager-main-service.libsonnet b/jsonnet/alertmanager/alertmanager-main-service.libsonnet
new file mode 100644
index 00000000..e89f009f
--- /dev/null
+++ b/jsonnet/alertmanager/alertmanager-main-service.libsonnet
@@ -0,0 +1,12 @@
+local k = import "ksonnet.beta.3/k.libsonnet";
+local service = k.core.v1.service;
+local servicePort = k.core.v1.service.mixin.spec.portsType;
+
+local alertmanagerPort = servicePort.newNamed("web", 9093, "web");
+
+{
+    new(namespace)::
+        service.new("alertmanager-main", {app: "alertmanager", alertmanager: "main"}, alertmanagerPort) +
+          service.mixin.metadata.withNamespace(namespace) +
+          service.mixin.metadata.withLabels({alertmanager: "main"})
+}
diff --git a/jsonnet/alertmanager/alertmanager-main.libsonnet b/jsonnet/alertmanager/alertmanager-main.libsonnet
new file mode 100644
index 00000000..63e06a16
--- /dev/null
+++ b/jsonnet/alertmanager/alertmanager-main.libsonnet
@@ -0,0 +1,19 @@
+{
+    new(namespace)::
+        {
+          apiVersion: "monitoring.coreos.com/v1",
+          kind: "Alertmanager",
+          metadata: {
+            name: "main",
+            namespace: namespace,
+            labels: {
+              alertmanager: "main",
+            },
+          },
+          spec: {
+            replicas: 3,
+            version: "v0.14.0",
+            serviceAccountName: "alertmanager-main",
+          },
+        }
+}
diff --git a/jsonnet/alertmanager/alertmanager.libsonnet b/jsonnet/alertmanager/alertmanager.libsonnet
new file mode 100644
index 00000000..ef837aba
--- /dev/null
+++ b/jsonnet/alertmanager/alertmanager.libsonnet
@@ -0,0 +1,6 @@
+{
+    config:: import "alertmanager-main-secret.libsonnet",
+    serviceAccount:: import "alertmanager-main-service-account.libsonnet",
+    service:: import "alertmanager-main-service.libsonnet",
+    alertmanager:: import "alertmanager-main.libsonnet",
+}
diff --git a/jsonnet/kube-prometheus.jsonnet b/jsonnet/kube-prometheus.jsonnet
new file mode 100644
index 00000000..3a0ef2cf
--- /dev/null
+++ b/jsonnet/kube-prometheus.jsonnet
@@ -0,0 +1,62 @@
+local k = import "ksonnet.beta.3/k.libsonnet";
+
+local alertmanager = import "alertmanager/alertmanager.libsonnet";
+local ksm = import "kube-state-metrics/kube-state-metrics.libsonnet";
+local nodeExporter = import "node-exporter/node-exporter.libsonnet";
+local po = import "prometheus-operator/prometheus-operator.libsonnet";
+local prometheus = import "prometheus/prometheus.libsonnet";
+
+local namespace = "monitoring";
+
+local objects = {
+    "alertmanager-main/alertmanager-main-secret.yaml":          alertmanager.config.new(namespace),
+    "alertmanager-main/alertmanager-main-service-account.yaml": alertmanager.serviceAccount.new(namespace),
+    "alertmanager-main/alertmanager-main-service.yaml":         alertmanager.service.new(namespace),
+    "alertmanager-main/alertmanager-main.yaml":                 alertmanager.alertmanager.new(namespace),
+
+    "kube-state-metrics/kube-state-metrics-cluster-role-binding": ksm.clusterRoleBinding.new(namespace),
+    "kube-state-metrics/kube-state-metrics-cluster-role.yaml":    ksm.clusterRole.new(),
+    "kube-state-metrics/kube-state-metrics-deployment.yaml":      ksm.deployment.new(namespace),
+    "kube-state-metrics/kube-state-metrics-role-binding.yaml":    ksm.roleBinding.new(namespace),
+    "kube-state-metrics/kube-state-metrics-role.yaml":            ksm.role.new(namespace),
+    "kube-state-metrics/kube-state-metrics-service-account.yaml": ksm.serviceAccount.new(namespace),
+    "kube-state-metrics/kube-state-metrics-service.yaml":         ksm.service.new(namespace),
+
+    "node-exporter/node-exporter-cluster-role-binding.yaml": nodeExporter.clusterRoleBinding.new(namespace),
+    "node-exporter/node-exporter-cluster-role.yaml": nodeExporter.clusterRole.new(),
+    "node-exporter/node-exporter-daemonset.yaml": nodeExporter.daemonset.new(namespace),
+    "node-exporter/node-exporter-service-account.yaml": nodeExporter.serviceAccount.new(namespace),
+    "node-exporter/node-exporter-service.yaml": nodeExporter.service.new(namespace),
+
+    "prometheus-operator/prometheus-operator-cluster-role-binding.yaml": po.clusterRoleBinding.new(namespace),
+    "prometheus-operator/prometheus-operator-cluster-role.yaml":         po.clusterRole.new(),
+    "prometheus-operator/prometheus-operator-deployment.yaml":           po.deployment.new(namespace),
+    "prometheus-operator/prometheus-operator-service.yaml":              po.service.new(namespace),
+    "prometheus-operator/prometheus-operator-service-account.yaml":      po.serviceAccount.new(namespace),
+
+    "prometheus-k8s/prometheus-k8s-cluster-role-binding.yaml":                    prometheus.clusterRoleBinding.new(namespace),
+    "prometheus-k8s/prometheus-k8s-cluster-role.yaml":                            prometheus.clusterRole.new(),
+    "prometheus-k8s/prometheus-k8s-service-account.yaml":                         prometheus.serviceAccount.new(namespace),
+    "prometheus-k8s/prometheus-k8s-service.yaml":                                 prometheus.service.new(namespace),
+    "prometheus-k8s/prometheus-k8s.yaml":                                         prometheus.prometheus.new(namespace),
+    "prometheus-k8s/prometheus-k8s-role-binding-config.yaml":                     prometheus.roleBindingConfig.new(namespace),
+    "prometheus-k8s/prometheus-k8s-role-binding-namespace.yaml":                  prometheus.roleBindingNamespace.new(namespace),
+    "prometheus-k8s/prometheus-k8s-role-binding-kube-system.yaml":                prometheus.roleBindingKubeSystem.new(namespace),
+    "prometheus-k8s/prometheus-k8s-role-binding-default.yaml":                    prometheus.roleBindingDefault.new(namespace),
+    "prometheus-k8s/prometheus-k8s-role-config.yaml":                             prometheus.roleConfig.new(namespace),
+    "prometheus-k8s/prometheus-k8s-role-namespace.yaml":                          prometheus.roleNamespace.new(namespace),
+    "prometheus-k8s/prometheus-k8s-role-kube-system.yaml":                        prometheus.roleKubeSystem.new(),
+    "prometheus-k8s/prometheus-k8s-role-default.yaml":                            prometheus.roleDefault.new(),
+    "prometheus-k8s/prometheus-k8s-service-monitor-alertmanager.yaml":            prometheus.serviceMonitorAlertmanager.new(namespace),
+    "prometheus-k8s/prometheus-k8s-service-monitor-apiserver.yaml":               prometheus.serviceMonitorApiserver.new(namespace),
+    "prometheus-k8s/prometheus-k8s-service-monitor-coredns.yaml":                 prometheus.serviceMonitorCoreDNS.new(namespace),
+    "prometheus-k8s/prometheus-k8s-service-monitor-kube-controller-manager.yaml": prometheus.serviceMonitorControllerManager.new(namespace),
+    "prometheus-k8s/prometheus-k8s-service-monitor-kube-scheduler.yaml":          prometheus.serviceMonitorScheduler.new(namespace),
+    "prometheus-k8s/prometheus-k8s-service-monitor-kube-state-metrics.yaml":      prometheus.serviceMonitorKubeStateMetrics.new(namespace),
+    "prometheus-k8s/prometheus-k8s-service-monitor-kubelet.yaml":                 prometheus.serviceMonitorKubelet.new(namespace),
+    "prometheus-k8s/prometheus-k8s-service-monitor-node-exporter.yaml":           prometheus.serviceMonitorNodeExporter.new(namespace),
+    "prometheus-k8s/prometheus-k8s-service-monitor-prometheus-operator.yaml":     prometheus.serviceMonitorPrometheusOperator.new(namespace),
+    "prometheus-k8s/prometheus-k8s-service-monitor-prometheus.yaml":              prometheus.serviceMonitorPrometheus.new(namespace),
+};
+
+{[path]: std.manifestYamlDoc(objects[path]) for path in std.objectFields(objects)}
diff --git a/jsonnet/kube-state-metrics/kube-state-metrics-cluster-role-binding.libsonnet b/jsonnet/kube-state-metrics/kube-state-metrics-cluster-role-binding.libsonnet
new file mode 100644
index 00000000..ae150c35
--- /dev/null
+++ b/jsonnet/kube-state-metrics/kube-state-metrics-cluster-role-binding.libsonnet
@@ -0,0 +1,12 @@
+local k = import "ksonnet.beta.3/k.libsonnet";
+local clusterRoleBinding = k.rbac.v1.clusterRoleBinding;
+
+{
+    new(namespace)::
+        clusterRoleBinding.new() +
+          clusterRoleBinding.mixin.metadata.withName("kube-state-metrics") +
+          clusterRoleBinding.mixin.roleRef.withApiGroup("rbac.authorization.k8s.io") +
+          clusterRoleBinding.mixin.roleRef.withName("kube-state-metrics") +
+          clusterRoleBinding.mixin.roleRef.mixinInstance({kind: "ClusterRole"}) +
+          clusterRoleBinding.withSubjects([{kind: "ServiceAccount", name: "kube-state-metrics", namespace: namespace}])
+}
diff --git a/jsonnet/kube-state-metrics/kube-state-metrics-cluster-role.libsonnet b/jsonnet/kube-state-metrics/kube-state-metrics-cluster-role.libsonnet
new file mode 100644
index 00000000..976d850a
--- /dev/null
+++ b/jsonnet/kube-state-metrics/kube-state-metrics-cluster-role.libsonnet
@@ -0,0 +1,75 @@
+local k = import "ksonnet.beta.3/k.libsonnet";
+local clusterRole = k.rbac.v1.clusterRole;
+local policyRule = clusterRole.rulesType;
+
+local coreRule = policyRule.new() +
+  policyRule.withApiGroups([""]) +
+  policyRule.withResources([
+    "configmaps",
+    "secrets",
+    "nodes",
+    "pods",
+    "services",
+    "resourcequotas",
+    "replicationcontrollers",
+    "limitranges",
+    "persistentvolumeclaims",
+    "persistentvolumes",
+    "namespaces",
+    "endpoints",
+  ]) +
+  policyRule.withVerbs(["list", "watch"]);
+
+local extensionsRule = policyRule.new() +
+  policyRule.withApiGroups(["extensions"]) +
+  policyRule.withResources([
+    "daemonsets",
+    "deployments",
+    "replicasets",
+  ]) +
+  policyRule.withVerbs(["list", "watch"]);
+
+local appsRule = policyRule.new() +
+  policyRule.withApiGroups(["apps"]) +
+  policyRule.withResources([
+    "statefulsets",
+  ]) +
+  policyRule.withVerbs(["list", "watch"]);
+
+local batchRule = policyRule.new() +
+  policyRule.withApiGroups(["batch"]) +
+  policyRule.withResources([
+    "cronjobs",
+    "jobs",
+  ]) +
+  policyRule.withVerbs(["list", "watch"]);
+
+local autoscalingRule = policyRule.new() +
+  policyRule.withApiGroups(["autoscaling"]) +
+  policyRule.withResources([
+    "horizontalpodautoscalers",
+  ]) +
+  policyRule.withVerbs(["list", "watch"]);
+
+local authenticationRole = policyRule.new() +
+  policyRule.withApiGroups(["authentication.k8s.io"]) +
+  policyRule.withResources([
+    "tokenreviews",
+  ]) +
+  policyRule.withVerbs(["create"]);
+
+local authorizationRole = policyRule.new() +
+  policyRule.withApiGroups(["authorization.k8s.io"]) +
+  policyRule.withResources([
+    "subjectaccessreviews",
+  ]) +
+  policyRule.withVerbs(["create"]);
+
+local rules = [coreRule, extensionsRule, appsRule, batchRule, autoscalingRule, authenticationRole, authorizationRole];
+
+{
+    new()::
+        clusterRole.new() +
+          clusterRole.mixin.metadata.withName("kube-state-metrics") +
+          clusterRole.withRules(rules)
+}
diff --git a/jsonnet/kube-state-metrics/kube-state-metrics-deployment.libsonnet b/jsonnet/kube-state-metrics/kube-state-metrics-deployment.libsonnet
new file mode 100644
index 00000000..e873fa30
--- /dev/null
+++ b/jsonnet/kube-state-metrics/kube-state-metrics-deployment.libsonnet
@@ -0,0 +1,86 @@
+local k = import "ksonnet.beta.3/k.libsonnet";
+local deployment = k.apps.v1beta2.deployment;
+
+local deployment = k.apps.v1beta2.deployment;
+local container = k.apps.v1beta2.deployment.mixin.spec.template.spec.containersType;
+local volume = k.apps.v1beta2.deployment.mixin.spec.template.spec.volumesType;
+local containerPort = container.portsType;
+local containerVolumeMount = container.volumeMountsType;
+local podSelector = deployment.mixin.spec.template.spec.selectorType;
+
+local kubeStateMetricsVersion = "v1.3.0";
+local kubeRbacProxyVersion = "v0.3.0";
+local addonResizerVersion = "1.0";
+local podLabels = {"app": "kube-state-metrics"};
+
+local proxyClusterMetrics =
+  container.new("kube-rbac-proxy-main", "quay.io/coreos/kube-rbac-proxy:" + kubeRbacProxyVersion) +
+  container.withArgs([
+	"--secure-listen-address=:8443",
+	"--upstream=http://127.0.0.1:8081/",
+  ]) +
+  container.withPorts(containerPort.newNamed("https-main", 8443)) +
+  container.mixin.resources.withRequests({cpu: "10m", memory: "20Mi"}) +
+  container.mixin.resources.withLimits({cpu: "20m", memory: "40Mi"});
+
+local proxySelfMetrics =
+  container.new("kube-rbac-proxy-self", "quay.io/coreos/kube-rbac-proxy:" + kubeRbacProxyVersion) +
+  container.withArgs([
+	"--secure-listen-address=:9443",
+	"--upstream=http://127.0.0.1:8082/",
+  ]) +
+  container.withPorts(containerPort.newNamed("https-self", 9443)) +
+  container.mixin.resources.withRequests({cpu: "10m", memory: "20Mi"}) +
+  container.mixin.resources.withLimits({cpu: "20m", memory: "40Mi"});
+
+local kubeStateMetrics =
+  container.new("kube-state-metrics", "quay.io/coreos/kube-state-metrics:" + kubeStateMetricsVersion) +
+  container.withArgs([
+	"--host=127.0.0.1",
+	"--port=8081",
+	"--telemetry-host=127.0.0.1",
+	"--telemetry-port=8082",
+  ]) +
+  container.mixin.resources.withRequests({cpu: "102m", memory: "180Mi"}) +
+  container.mixin.resources.withLimits({cpu: "102m", memory: "180Mi"});
+
+local addonResizer =
+  container.new("addon-resizer", "quay.io/coreos/addon-resizer:" + addonResizerVersion) +
+  container.withCommand([
+	"/pod_nanny",
+	"--container=kube-state-metrics",
+	"--cpu=100m",
+	"--extra-cpu=2m",
+	"--memory=150Mi",
+	"--extra-memory=30Mi",
+	"--threshold=5",
+	"--deployment=kube-state-metrics",
+  ]) +
+  container.withEnv([
+	{
+	  name: "MY_POD_NAME",
+      valueFrom: {
+		fieldRef: {apiVersion: "v1", fieldPath: "metadata.name"}
+      }
+	}, {
+	  name: "MY_POD_NAMESPACE",
+      valueFrom: {
+		fieldRef: {apiVersion: "v1", fieldPath: "metadata.namespace"}
+      }
+	}
+  ]) +
+  container.mixin.resources.withRequests({cpu: "10m", memory: "30Mi"}) +
+  container.mixin.resources.withLimits({cpu: "10m", memory: "30Mi"});
+
+local c = [proxyClusterMetrics, proxySelfMetrics, kubeStateMetrics, addonResizer];
+
+{
+    new(namespace)::
+        deployment.new("kube-state-metrics", 1, c, podLabels) +
+          deployment.mixin.metadata.withNamespace(namespace) +
+          deployment.mixin.metadata.withLabels(podLabels) +
+          deployment.mixin.spec.selector.withMatchLabels(podLabels) +
+          deployment.mixin.spec.template.spec.securityContext.withRunAsNonRoot(true) +
+          deployment.mixin.spec.template.spec.securityContext.withRunAsUser(65534) +
+          deployment.mixin.spec.template.spec.withServiceAccountName("kube-state-metrics")
+}
diff --git a/jsonnet/kube-state-metrics/kube-state-metrics-role-binding.libsonnet b/jsonnet/kube-state-metrics/kube-state-metrics-role-binding.libsonnet
new file mode 100644
index 00000000..bd9b03ae
--- /dev/null
+++ b/jsonnet/kube-state-metrics/kube-state-metrics-role-binding.libsonnet
@@ -0,0 +1,13 @@
+local k = import "ksonnet.beta.3/k.libsonnet";
+local roleBinding = k.rbac.v1.roleBinding;
+
+{
+    new(namespace)::
+        roleBinding.new() +
+          roleBinding.mixin.metadata.withName("kube-state-metrics") +
+          roleBinding.mixin.metadata.withNamespace(namespace) +
+          roleBinding.mixin.roleRef.withApiGroup("rbac.authorization.k8s.io") +
+          roleBinding.mixin.roleRef.withName("kube-state-metrics-addon-resizer") +
+          roleBinding.mixin.roleRef.mixinInstance({kind: "Role"}) +
+          roleBinding.withSubjects([{kind: "ServiceAccount", name: "kube-state-metrics"}])
+}
diff --git a/jsonnet/kube-state-metrics/kube-state-metrics-role.libsonnet b/jsonnet/kube-state-metrics/kube-state-metrics-role.libsonnet
new file mode 100644
index 00000000..bf80880f
--- /dev/null
+++ b/jsonnet/kube-state-metrics/kube-state-metrics-role.libsonnet
@@ -0,0 +1,28 @@
+local k = import "ksonnet.beta.3/k.libsonnet";
+local role = k.rbac.v1.role;
+local policyRule = role.rulesType;
+
+local coreRule = policyRule.new() +
+  policyRule.withApiGroups([""]) +
+  policyRule.withResources([
+    "pods",
+  ]) +
+  policyRule.withVerbs(["get"]);
+
+local extensionsRule = policyRule.new() +
+  policyRule.withApiGroups(["extensions"]) +
+  policyRule.withResources([
+    "deployments",
+  ]) +
+  policyRule.withVerbs(["get", "update"]) +
+  policyRule.withResourceNames(["kube-state-metrics"]);
+
+local rules = [coreRule, extensionsRule];
+
+{
+    new(namespace)::
+        role.new() +
+          role.mixin.metadata.withName("kube-state-metrics") +
+          role.mixin.metadata.withNamespace(namespace) +
+          role.withRules(rules)
+}
diff --git a/jsonnet/kube-state-metrics/kube-state-metrics-service-account.libsonnet b/jsonnet/kube-state-metrics/kube-state-metrics-service-account.libsonnet
new file mode 100644
index 00000000..6e6904ff
--- /dev/null
+++ b/jsonnet/kube-state-metrics/kube-state-metrics-service-account.libsonnet
@@ -0,0 +1,8 @@
+local k = import "ksonnet.beta.3/k.libsonnet";
+local serviceAccount = k.core.v1.serviceAccount;
+
+{
+    new(namespace)::
+        serviceAccount.new("kube-state-metrics") +
+          serviceAccount.mixin.metadata.withNamespace(namespace)
+}
diff --git a/jsonnet/kube-state-metrics/kube-state-metrics-service.libsonnet b/jsonnet/kube-state-metrics/kube-state-metrics-service.libsonnet
new file mode 100644
index 00000000..c8eaee18
--- /dev/null
+++ b/jsonnet/kube-state-metrics/kube-state-metrics-service.libsonnet
@@ -0,0 +1,15 @@
+local k = import "ksonnet.beta.3/k.libsonnet";
+local service = k.core.v1.service;
+local servicePort = k.core.v1.service.mixin.spec.portsType;
+
+local ksmDeployment = import "kube-state-metrics-deployment.libsonnet";
+
+local ksmServicePortMain = servicePort.newNamed("https-main", 8443, "https-main");
+local ksmServicePortSelf = servicePort.newNamed("https-self", 9443, "https-self");
+
+{
+    new(namespace)::
+        service.new("kube-state-metrics", ksmDeployment.new(namespace).spec.selector.matchLabels, [ksmServicePortMain, ksmServicePortSelf]) +
+          service.mixin.metadata.withNamespace(namespace) +
+          service.mixin.metadata.withLabels({"k8s-app": "kube-state-metrics"})
+}
diff --git a/jsonnet/kube-state-metrics/kube-state-metrics.libsonnet b/jsonnet/kube-state-metrics/kube-state-metrics.libsonnet
new file mode 100644
index 00000000..3f9b8ba2
--- /dev/null
+++ b/jsonnet/kube-state-metrics/kube-state-metrics.libsonnet
@@ -0,0 +1,9 @@
+{
+    clusterRoleBinding:: import "kube-state-metrics-cluster-role-binding.libsonnet",
+    clusterRole:: import "kube-state-metrics-cluster-role.libsonnet",
+    deployment:: import "kube-state-metrics-deployment.libsonnet",
+    roleBinding:: import "kube-state-metrics-role-binding.libsonnet",
+    role:: import "kube-state-metrics-role.libsonnet",
+    serviceAccount:: import "kube-state-metrics-service-account.libsonnet",
+    service:: import "kube-state-metrics-service.libsonnet",
+}
diff --git a/jsonnet/node-exporter/node-exporter-cluster-role-binding.libsonnet b/jsonnet/node-exporter/node-exporter-cluster-role-binding.libsonnet
new file mode 100644
index 00000000..39f373b5
--- /dev/null
+++ b/jsonnet/node-exporter/node-exporter-cluster-role-binding.libsonnet
@@ -0,0 +1,12 @@
+local k = import "ksonnet.beta.3/k.libsonnet";
+local clusterRoleBinding = k.rbac.v1.clusterRoleBinding;
+
+{
+    new(namespace)::
+        clusterRoleBinding.new() +
+          clusterRoleBinding.mixin.metadata.withName("node-exporter") +
+          clusterRoleBinding.mixin.roleRef.withApiGroup("rbac.authorization.k8s.io") +
+          clusterRoleBinding.mixin.roleRef.withName("node-exporter") +
+          clusterRoleBinding.mixin.roleRef.mixinInstance({kind: "ClusterRole"}) +
+          clusterRoleBinding.withSubjects([{kind: "ServiceAccount", name: "node-exporter", namespace: namespace}])
+}
diff --git a/jsonnet/node-exporter/node-exporter-cluster-role.libsonnet b/jsonnet/node-exporter/node-exporter-cluster-role.libsonnet
new file mode 100644
index 00000000..426e0a66
--- /dev/null
+++ b/jsonnet/node-exporter/node-exporter-cluster-role.libsonnet
@@ -0,0 +1,26 @@
+local k = import "ksonnet.beta.3/k.libsonnet";
+local clusterRole = k.rbac.v1.clusterRole;
+local policyRule = clusterRole.rulesType;
+
+local authenticationRole = policyRule.new() +
+  policyRule.withApiGroups(["authentication.k8s.io"]) +
+  policyRule.withResources([
+    "tokenreviews",
+  ]) +
+  policyRule.withVerbs(["create"]);
+
+local authorizationRole = policyRule.new() +
+  policyRule.withApiGroups(["authorization.k8s.io"]) +
+  policyRule.withResources([
+    "subjectaccessreviews",
+  ]) +
+  policyRule.withVerbs(["create"]);
+
+local rules = [authenticationRole, authorizationRole];
+
+{
+    new()::
+        clusterRole.new() +
+          clusterRole.mixin.metadata.withName("node-exporter") +
+          clusterRole.withRules(rules)
+}
diff --git a/jsonnet/node-exporter/node-exporter-daemonset.libsonnet b/jsonnet/node-exporter/node-exporter-daemonset.libsonnet
new file mode 100644
index 00000000..ac642891
--- /dev/null
+++ b/jsonnet/node-exporter/node-exporter-daemonset.libsonnet
@@ -0,0 +1,58 @@
+local k = import "ksonnet.beta.3/k.libsonnet";
+
+local daemonset = k.apps.v1beta2.daemonSet;
+local container = daemonset.mixin.spec.template.spec.containersType;
+local volume = daemonset.mixin.spec.template.spec.volumesType;
+local containerPort = container.portsType;
+local containerVolumeMount = container.volumeMountsType;
+local podSelector = daemonset.mixin.spec.template.spec.selectorType;
+
+local nodeExporterVersion = "v0.15.2";
+local kubeRbacProxyVersion = "v0.3.0";
+local podLabels = {"app": "node-exporter"};
+
+local procVolumeName = "proc";
+local procVolume = volume.fromHostPath(procVolumeName, "/proc");
+local procVolumeMount = containerVolumeMount.new(procVolumeName, "/host/proc");
+
+local sysVolumeName = "sys";
+local sysVolume = volume.fromHostPath(sysVolumeName, "/sys");
+local sysVolumeMount = containerVolumeMount.new(sysVolumeName, "/host/sys");
+
+local nodeExporter =
+  container.new("node-exporter", "quay.io/prometheus/node-exporter:" + nodeExporterVersion) +
+  container.withArgs([
+    "--web.listen-address=127.0.0.1:9101",
+    "--path.procfs=/host/proc",
+    "--path.sysfs=/host/sys",
+  ]) +
+  container.withVolumeMounts([procVolumeMount, sysVolumeMount]) +
+  container.mixin.resources.withRequests({cpu: "102m", memory: "180Mi"}) +
+  container.mixin.resources.withLimits({cpu: "102m", memory: "180Mi"});
+
+local proxy =
+  container.new("kube-rbac-proxy", "quay.io/coreos/kube-rbac-proxy:" + kubeRbacProxyVersion) +
+  container.withArgs([
+	"--secure-listen-address=:9100",
+	"--upstream=http://127.0.0.1:9101/",
+  ]) +
+  container.withPorts(containerPort.newNamed("https", 9100)) +
+  container.mixin.resources.withRequests({cpu: "10m", memory: "20Mi"}) +
+  container.mixin.resources.withLimits({cpu: "20m", memory: "40Mi"});
+
+local c = [nodeExporter, proxy];
+
+{
+    new(namespace)::
+        daemonset.new() +
+          daemonset.mixin.metadata.withName("node-exporter") +
+          daemonset.mixin.metadata.withNamespace(namespace) +
+          daemonset.mixin.metadata.withLabels(podLabels) +
+          daemonset.mixin.spec.selector.withMatchLabels(podLabels) +
+          daemonset.mixin.spec.template.metadata.withLabels(podLabels) +
+          daemonset.mixin.spec.template.spec.withContainers(c) +
+          daemonset.mixin.spec.template.spec.withVolumes([procVolume, sysVolume]) +
+          daemonset.mixin.spec.template.spec.securityContext.withRunAsNonRoot(true) +
+          daemonset.mixin.spec.template.spec.securityContext.withRunAsUser(65534) +
+          daemonset.mixin.spec.template.spec.withServiceAccountName("node-exporter")
+}
diff --git a/jsonnet/node-exporter/node-exporter-service-account.libsonnet b/jsonnet/node-exporter/node-exporter-service-account.libsonnet
new file mode 100644
index 00000000..f75a6827
--- /dev/null
+++ b/jsonnet/node-exporter/node-exporter-service-account.libsonnet
@@ -0,0 +1,8 @@
+local k = import "ksonnet.beta.3/k.libsonnet";
+local serviceAccount = k.core.v1.serviceAccount;
+
+{
+    new(namespace)::
+        serviceAccount.new("node-exporter") +
+          serviceAccount.mixin.metadata.withNamespace(namespace)
+}
diff --git a/jsonnet/node-exporter/node-exporter-service.libsonnet b/jsonnet/node-exporter/node-exporter-service.libsonnet
new file mode 100644
index 00000000..addbc598
--- /dev/null
+++ b/jsonnet/node-exporter/node-exporter-service.libsonnet
@@ -0,0 +1,14 @@
+local k = import "ksonnet.beta.3/k.libsonnet";
+local service = k.core.v1.service;
+local servicePort = k.core.v1.service.mixin.spec.portsType;
+
+local nodeExporterDaemonset = import "node-exporter-daemonset.libsonnet";
+
+local nodeExporterPort = servicePort.newNamed("https", 9100, "https");
+
+{
+    new(namespace)::
+        service.new("node-exporter", nodeExporterDaemonset.new(namespace).spec.selector.matchLabels, nodeExporterPort) +
+          service.mixin.metadata.withNamespace(namespace) +
+          service.mixin.metadata.withLabels({"k8s-app": "node-exporter"})
+}
diff --git a/jsonnet/node-exporter/node-exporter.libsonnet b/jsonnet/node-exporter/node-exporter.libsonnet
new file mode 100644
index 00000000..57e67911
--- /dev/null
+++ b/jsonnet/node-exporter/node-exporter.libsonnet
@@ -0,0 +1,7 @@
+{
+    clusterRoleBinding:: import "node-exporter-cluster-role-binding.libsonnet",
+    clusterRole:: import "node-exporter-cluster-role.libsonnet",
+    daemonset:: import "node-exporter-daemonset.libsonnet",
+    serviceAccount:: import "node-exporter-service-account.libsonnet",
+    service:: import "node-exporter-service.libsonnet",
+}
diff --git a/jsonnet/prometheus-operator/prometheus-operator-cluster-role-binding.libsonnet b/jsonnet/prometheus-operator/prometheus-operator-cluster-role-binding.libsonnet
new file mode 100644
index 00000000..64453c52
--- /dev/null
+++ b/jsonnet/prometheus-operator/prometheus-operator-cluster-role-binding.libsonnet
@@ -0,0 +1,12 @@
+local k = import "ksonnet.beta.3/k.libsonnet";
+local clusterRoleBinding = k.rbac.v1.clusterRoleBinding;
+
+{
+    new(namespace)::
+        clusterRoleBinding.new() +
+          clusterRoleBinding.mixin.metadata.withName("prometheus-operator") +
+          clusterRoleBinding.mixin.roleRef.withApiGroup("rbac.authorization.k8s.io") +
+          clusterRoleBinding.mixin.roleRef.withName("prometheus-operator") +
+          clusterRoleBinding.mixin.roleRef.mixinInstance({kind: "ClusterRole"}) +
+          clusterRoleBinding.withSubjects([{kind: "ServiceAccount", name: "prometheus-operator", namespace: namespace}])
+}
diff --git a/jsonnet/prometheus-operator/prometheus-operator-cluster-role.libsonnet b/jsonnet/prometheus-operator/prometheus-operator-cluster-role.libsonnet
new file mode 100644
index 00000000..db8bcd7b
--- /dev/null
+++ b/jsonnet/prometheus-operator/prometheus-operator-cluster-role.libsonnet
@@ -0,0 +1,80 @@
+local k = import "ksonnet.beta.3/k.libsonnet";
+local clusterRole = k.rbac.v1.clusterRole;
+local policyRule = clusterRole.rulesType;
+
+local extensionsRule = policyRule.new() +
+  policyRule.withApiGroups(["extensions"]) +
+  policyRule.withResources([
+    "thirdpartyresources",
+  ]) +
+  policyRule.withVerbs(["*"]);
+
+local apiExtensionsRule = policyRule.new() +
+  policyRule.withApiGroups(["apiextensions.k8s.io"]) +
+  policyRule.withResources([
+    "customresourcedefinitions",
+  ]) +
+  policyRule.withVerbs(["*"]);
+
+local monitoringRule = policyRule.new() +
+  policyRule.withApiGroups(["monitoring.coreos.com"]) +
+  policyRule.withResources([
+    "alertmanagers",
+    "prometheuses",
+    "prometheuses/finalizers",
+    "alertmanagers/finalizers",
+    "servicemonitors",
+  ]) +
+  policyRule.withVerbs(["*"]);
+
+local appsRule = policyRule.new() +
+  policyRule.withApiGroups(["apps"]) +
+  policyRule.withResources([
+    "statefulsets",
+  ]) +
+  policyRule.withVerbs(["*"]);
+
+local coreRule = policyRule.new() +
+  policyRule.withApiGroups([""]) +
+  policyRule.withResources([
+    "configmaps",
+    "secrets",
+  ]) +
+  policyRule.withVerbs(["*"]);
+
+local podRule = policyRule.new() +
+  policyRule.withApiGroups([""]) +
+  policyRule.withResources([
+    "pods",
+  ]) +
+  policyRule.withVerbs(["list", "delete"]);
+
+local routingRule = policyRule.new() +
+  policyRule.withApiGroups([""]) +
+  policyRule.withResources([
+    "services",
+  ]) +
+  policyRule.withVerbs(["get", "create", "update"]);
+
+local nodeRule = policyRule.new() +
+  policyRule.withApiGroups([""]) +
+  policyRule.withResources([
+    "nodes",
+  ]) +
+  policyRule.withVerbs(["list", "watch"]);
+
+local namespaceRule = policyRule.new() +
+  policyRule.withApiGroups([""]) +
+  policyRule.withResources([
+    "namespaces",
+  ]) +
+  policyRule.withVerbs(["list"]);
+
+local rules = [extensionsRule, apiExtensionsRule, monitoringRule, appsRule, coreRule, podRule, routingRule, nodeRule, namespaceRule];
+
+{
+    new()::
+        clusterRole.new() +
+          clusterRole.mixin.metadata.withName("prometheus-operator") +
+          clusterRole.withRules(rules)
+}
diff --git a/jsonnet/prometheus-operator/prometheus-operator-deployment.libsonnet b/jsonnet/prometheus-operator/prometheus-operator-deployment.libsonnet
new file mode 100644
index 00000000..2ad7f526
--- /dev/null
+++ b/jsonnet/prometheus-operator/prometheus-operator-deployment.libsonnet
@@ -0,0 +1,30 @@
+local k = import "ksonnet.beta.3/k.libsonnet";
+local rawVersion = importstr "../../../../VERSION";
+
+local removeLineBreaks = function(str) std.join("", std.filter(function(c) c != "\n", std.stringChars(str)));
+local version = removeLineBreaks(rawVersion);
+
+local deployment = k.apps.v1beta2.deployment;
+local container = k.apps.v1beta2.deployment.mixin.spec.template.spec.containersType;
+local containerPort = container.portsType;
+
+local targetPort = 8080;
+local podLabels = {"k8s-app": "prometheus-operator"};
+
+local operatorContainer =
+  container.new("prometheus-operator", "quay.io/coreos/prometheus-operator:v" + version) +
+  container.withPorts(containerPort.newNamed("http", targetPort)) +
+  container.withArgs(["--kubelet-service=kube-system/kubelet", "--config-reloader-image=quay.io/coreos/configmap-reload:v0.0.1"]) +
+  container.mixin.resources.withRequests({cpu: "100m", memory: "50Mi"}) +
+  container.mixin.resources.withLimits({cpu: "200m", memory: "100Mi"});
+
+{
+    new(namespace)::
+        deployment.new("prometheus-operator", 1, operatorContainer, podLabels) +
+          deployment.mixin.metadata.withNamespace(namespace) +
+          deployment.mixin.metadata.withLabels(podLabels) +
+          deployment.mixin.spec.selector.withMatchLabels(podLabels) +
+          deployment.mixin.spec.template.spec.securityContext.withRunAsNonRoot(true) +
+          deployment.mixin.spec.template.spec.securityContext.withRunAsUser(65534) +
+          deployment.mixin.spec.template.spec.withServiceAccountName("prometheus-operator")
+}
diff --git a/jsonnet/prometheus-operator/prometheus-operator-service-account.libsonnet b/jsonnet/prometheus-operator/prometheus-operator-service-account.libsonnet
new file mode 100644
index 00000000..791ce93c
--- /dev/null
+++ b/jsonnet/prometheus-operator/prometheus-operator-service-account.libsonnet
@@ -0,0 +1,8 @@
+local k = import "ksonnet.beta.3/k.libsonnet";
+local serviceAccount = k.core.v1.serviceAccount;
+
+{
+    new(namespace)::
+        serviceAccount.new("prometheus-operator") +
+          serviceAccount.mixin.metadata.withNamespace(namespace)
+}
diff --git a/jsonnet/prometheus-operator/prometheus-operator-service.libsonnet b/jsonnet/prometheus-operator/prometheus-operator-service.libsonnet
new file mode 100644
index 00000000..8bbd1477
--- /dev/null
+++ b/jsonnet/prometheus-operator/prometheus-operator-service.libsonnet
@@ -0,0 +1,14 @@
+local k = import "ksonnet.beta.3/k.libsonnet";
+local service = k.core.v1.service;
+local servicePort = k.core.v1.service.mixin.spec.portsType;
+
+local poDeployment = import "prometheus-operator-deployment.libsonnet";
+
+local poServicePort = servicePort.newNamed("http", 8080, "http");
+
+
+{
+    new(namespace)::
+        service.new("prometheus-operator", poDeployment.new(namespace).spec.selector.matchLabels, [poServicePort]) +
+        service.mixin.metadata.withNamespace(namespace)
+}
diff --git a/jsonnet/prometheus-operator/prometheus-operator.libsonnet b/jsonnet/prometheus-operator/prometheus-operator.libsonnet
new file mode 100644
index 00000000..849acbbf
--- /dev/null
+++ b/jsonnet/prometheus-operator/prometheus-operator.libsonnet
@@ -0,0 +1,7 @@
+{
+  clusterRoleBinding:: import "prometheus-operator-cluster-role-binding.libsonnet",
+  clusterRole:: import "prometheus-operator-cluster-role.libsonnet",
+  deployment:: import "prometheus-operator-deployment.libsonnet",
+  serviceAccount:: import "prometheus-operator-service-account.libsonnet",
+  service:: import "prometheus-operator-service.libsonnet",
+}
diff --git a/jsonnet/prometheus/prometheus-k8s-cluster-role-binding.libsonnet b/jsonnet/prometheus/prometheus-k8s-cluster-role-binding.libsonnet
new file mode 100644
index 00000000..d577bee5
--- /dev/null
+++ b/jsonnet/prometheus/prometheus-k8s-cluster-role-binding.libsonnet
@@ -0,0 +1,12 @@
+local k = import "ksonnet.beta.3/k.libsonnet";
+local clusterRoleBinding = k.rbac.v1.clusterRoleBinding;
+
+{
+    new(namespace)::
+        clusterRoleBinding.new() +
+          clusterRoleBinding.mixin.metadata.withName("prometheus-k8s") +
+          clusterRoleBinding.mixin.roleRef.withApiGroup("rbac.authorization.k8s.io") +
+          clusterRoleBinding.mixin.roleRef.withName("prometheus-k8s") +
+          clusterRoleBinding.mixin.roleRef.mixinInstance({kind: "ClusterRole"}) +
+          clusterRoleBinding.withSubjects([{kind: "ServiceAccount", name: "prometheus-k8s", namespace: namespace}])
+}
diff --git a/jsonnet/prometheus/prometheus-k8s-cluster-role.libsonnet b/jsonnet/prometheus/prometheus-k8s-cluster-role.libsonnet
new file mode 100644
index 00000000..c514624c
--- /dev/null
+++ b/jsonnet/prometheus/prometheus-k8s-cluster-role.libsonnet
@@ -0,0 +1,21 @@
+local k = import "ksonnet.beta.3/k.libsonnet";
+local clusterRole = k.rbac.v1.clusterRole;
+local policyRule = clusterRole.rulesType;
+
+local nodeMetricsRule = policyRule.new() +
+  policyRule.withApiGroups([""]) +
+  policyRule.withResources(["nodes/metrics"]) +
+  policyRule.withVerbs(["get"]);
+
+local metricsRule = policyRule.new() +
+  policyRule.withNonResourceUrls("/metrics") +
+  policyRule.withVerbs(["get"]);
+
+local rules = [nodeMetricsRule, metricsRule];
+
+{
+    new()::
+        clusterRole.new() +
+          clusterRole.mixin.metadata.withName("prometheus-k8s") +
+          clusterRole.withRules(rules)
+}
diff --git a/jsonnet/prometheus/prometheus-k8s-role-binding-config.libsonnet b/jsonnet/prometheus/prometheus-k8s-role-binding-config.libsonnet
new file mode 100644
index 00000000..2319aa35
--- /dev/null
+++ b/jsonnet/prometheus/prometheus-k8s-role-binding-config.libsonnet
@@ -0,0 +1,5 @@
+local prometheusNamespaceRoleBinding = import "prometheus-namespace-role-binding.libsonnet";
+
+{
+    new(namespace):: prometheusNamespaceRoleBinding.new(namespace, namespace, "prometheus-k8s-config")
+}
diff --git a/jsonnet/prometheus/prometheus-k8s-role-binding-default.libsonnet b/jsonnet/prometheus/prometheus-k8s-role-binding-default.libsonnet
new file mode 100644
index 00000000..f5d38ce7
--- /dev/null
+++ b/jsonnet/prometheus/prometheus-k8s-role-binding-default.libsonnet
@@ -0,0 +1,5 @@
+local prometheusNamespaceRoleBinding = import "prometheus-namespace-role-binding.libsonnet";
+
+{
+    new(namespace):: prometheusNamespaceRoleBinding.new(namespace, "default", "prometheus-k8s")
+}
diff --git a/jsonnet/prometheus/prometheus-k8s-role-binding-kube-system.libsonnet b/jsonnet/prometheus/prometheus-k8s-role-binding-kube-system.libsonnet
new file mode 100644
index 00000000..04c481ca
--- /dev/null
+++ b/jsonnet/prometheus/prometheus-k8s-role-binding-kube-system.libsonnet
@@ -0,0 +1,5 @@
+local prometheusNamespaceRoleBinding = import "prometheus-namespace-role-binding.libsonnet";
+
+{
+    new(namespace):: prometheusNamespaceRoleBinding.new(namespace, "kube-system", "prometheus-k8s")
+}
diff --git a/jsonnet/prometheus/prometheus-k8s-role-binding-namespace.libsonnet b/jsonnet/prometheus/prometheus-k8s-role-binding-namespace.libsonnet
new file mode 100644
index 00000000..7833f785
--- /dev/null
+++ b/jsonnet/prometheus/prometheus-k8s-role-binding-namespace.libsonnet
@@ -0,0 +1,5 @@
+local prometheusNamespaceRoleBinding = import "prometheus-namespace-role-binding.libsonnet";
+
+{
+    new(namespace):: prometheusNamespaceRoleBinding.new(namespace, namespace, "prometheus-k8s")
+}
diff --git a/jsonnet/prometheus/prometheus-k8s-role-config.libsonnet b/jsonnet/prometheus/prometheus-k8s-role-config.libsonnet
new file mode 100644
index 00000000..abd43433
--- /dev/null
+++ b/jsonnet/prometheus/prometheus-k8s-role-config.libsonnet
@@ -0,0 +1,18 @@
+local k = import "ksonnet.beta.3/k.libsonnet";
+local role = k.rbac.v1.role;
+local policyRule = role.rulesType;
+
+local configmapRule = policyRule.new() +
+  policyRule.withApiGroups([""]) +
+  policyRule.withResources([
+    "configmaps",
+  ]) +
+  policyRule.withVerbs(["get"]);
+
+{
+    new(namespace)::
+        role.new() +
+          role.mixin.metadata.withName("prometheus-k8s-config") +
+          role.mixin.metadata.withNamespace(namespace) +
+          role.withRules(configmapRule),
+}
diff --git a/jsonnet/prometheus/prometheus-k8s-role-default.libsonnet b/jsonnet/prometheus/prometheus-k8s-role-default.libsonnet
new file mode 100644
index 00000000..a9abbb1a
--- /dev/null
+++ b/jsonnet/prometheus/prometheus-k8s-role-default.libsonnet
@@ -0,0 +1,5 @@
+local prometheusNamespaceRole = import "prometheus-namespace-role.libsonnet";
+
+{
+    new():: prometheusNamespaceRole.new("default")
+}
diff --git a/jsonnet/prometheus/prometheus-k8s-role-kube-system.libsonnet b/jsonnet/prometheus/prometheus-k8s-role-kube-system.libsonnet
new file mode 100644
index 00000000..f1ee9860
--- /dev/null
+++ b/jsonnet/prometheus/prometheus-k8s-role-kube-system.libsonnet
@@ -0,0 +1,5 @@
+local prometheusNamespaceRole = import "prometheus-namespace-role.libsonnet";
+
+{
+    new():: prometheusNamespaceRole.new("kube-system")
+}
diff --git a/jsonnet/prometheus/prometheus-k8s-role-namespace.libsonnet b/jsonnet/prometheus/prometheus-k8s-role-namespace.libsonnet
new file mode 100644
index 00000000..3149cbf0
--- /dev/null
+++ b/jsonnet/prometheus/prometheus-k8s-role-namespace.libsonnet
@@ -0,0 +1,5 @@
+local prometheusNamespaceRole = import "prometheus-namespace-role.libsonnet";
+
+{
+    new(namespace):: prometheusNamespaceRole.new(namespace)
+}
diff --git a/jsonnet/prometheus/prometheus-k8s-service-account.libsonnet b/jsonnet/prometheus/prometheus-k8s-service-account.libsonnet
new file mode 100644
index 00000000..e8164556
--- /dev/null
+++ b/jsonnet/prometheus/prometheus-k8s-service-account.libsonnet
@@ -0,0 +1,8 @@
+local k = import "ksonnet.beta.3/k.libsonnet";
+local serviceAccount = k.core.v1.serviceAccount;
+
+{
+    new(namespace)::
+        serviceAccount.new("prometheus-k8s") +
+          serviceAccount.mixin.metadata.withNamespace(namespace)
+}
diff --git a/jsonnet/prometheus/prometheus-k8s-service-monitor-alertmanager.libsonnet b/jsonnet/prometheus/prometheus-k8s-service-monitor-alertmanager.libsonnet
new file mode 100644
index 00000000..5f13a2b4
--- /dev/null
+++ b/jsonnet/prometheus/prometheus-k8s-service-monitor-alertmanager.libsonnet
@@ -0,0 +1,32 @@
+{
+    new(namespace)::
+        {
+            "apiVersion": "monitoring.coreos.com/v1",
+            "kind": "ServiceMonitor",
+            "metadata": {
+                "name": "alertmanager",
+                "namespace": namespace,
+                "labels": {
+                    "k8s-app": "alertmanager"
+                }
+            },
+            "spec": {
+                "selector": {
+                    "matchLabels": {
+                        "alertmanager": "main"
+                    }
+                },
+                "namespaceSelector": {
+                    "matchNames": [
+                        "monitoring"
+                    ]
+                },
+                "endpoints": [
+                    {
+                        "port": "web",
+                        "interval": "30s"
+                    }
+                ]
+            }
+        }
+}
diff --git a/jsonnet/prometheus/prometheus-k8s-service-monitor-apiserver.libsonnet b/jsonnet/prometheus/prometheus-k8s-service-monitor-apiserver.libsonnet
new file mode 100644
index 00000000..e53ed231
--- /dev/null
+++ b/jsonnet/prometheus/prometheus-k8s-service-monitor-apiserver.libsonnet
@@ -0,0 +1,40 @@
+{
+    new(namespace)::
+        {
+            "apiVersion": "monitoring.coreos.com/v1",
+            "kind": "ServiceMonitor",
+            "metadata": {
+                "name": "kube-apiserver",
+                "namespace": namespace,
+                "labels": {
+                    "k8s-app": "apiserver"
+                }
+            },
+            "spec": {
+                "jobLabel": "component",
+                "selector": {
+                    "matchLabels": {
+                        "component": "apiserver",
+                        "provider": "kubernetes"
+                    }
+                },
+                "namespaceSelector": {
+                    "matchNames": [
+                        "default"
+                    ]
+                },
+                "endpoints": [
+                    {
+                        "port": "https",
+                        "interval": "30s",
+                        "scheme": "https",
+                        "tlsConfig": {
+                            "caFile": "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt",
+                            "serverName": "kubernetes"
+                        },
+                        "bearerTokenFile": "/var/run/secrets/kubernetes.io/serviceaccount/token"
+                    }
+                ]
+            }
+        }
+}
diff --git a/jsonnet/prometheus/prometheus-k8s-service-monitor-coredns.libsonnet b/jsonnet/prometheus/prometheus-k8s-service-monitor-coredns.libsonnet
new file mode 100644
index 00000000..89afb452
--- /dev/null
+++ b/jsonnet/prometheus/prometheus-k8s-service-monitor-coredns.libsonnet
@@ -0,0 +1,35 @@
+{
+    new(namespace)::
+        {
+            "apiVersion": "monitoring.coreos.com/v1",
+            "kind": "ServiceMonitor",
+            "metadata": {
+                "name": "coredns",
+                "namespace": namespace,
+                "labels": {
+                    "k8s-app": "coredns"
+                },
+            },
+            "spec": {
+                "jobLabel": "k8s-app",
+                "selector": {
+                    "matchLabels": {
+                        "k8s-app": "coredns",
+                        "component": "metrics"
+                    }
+                },
+                "namespaceSelector": {
+                    "matchNames": [
+                        "kube-system"
+                    ]
+                },
+                "endpoints": [
+                    {
+                        "port": "http-metrics",
+                        "interval": "15s",
+                        "bearerTokenFile": "/var/run/secrets/kubernetes.io/serviceaccount/token"
+                    }
+                ]
+            }
+        }
+}
diff --git a/jsonnet/prometheus/prometheus-k8s-service-monitor-kube-controller-manager.libsonnet b/jsonnet/prometheus/prometheus-k8s-service-monitor-kube-controller-manager.libsonnet
new file mode 100644
index 00000000..447e8a4b
--- /dev/null
+++ b/jsonnet/prometheus/prometheus-k8s-service-monitor-kube-controller-manager.libsonnet
@@ -0,0 +1,33 @@
+{
+    new(namespace)::
+        {
+            "apiVersion": "monitoring.coreos.com/v1",
+            "kind": "ServiceMonitor",
+            "metadata": {
+                "name": "kube-controller-manager",
+                "namespace": namespace,
+                "labels": {
+                    "k8s-app": "kube-controller-manager"
+                }
+            },
+            "spec": {
+                "jobLabel": "k8s-app",
+                "endpoints": [
+                    {
+                        "port": "http-metrics",
+                        "interval": "30s"
+                    }
+                ],
+                "selector": {
+                    "matchLabels": {
+                        "k8s-app": "kube-controller-manager"
+                    }
+                },
+                "namespaceSelector": {
+                    "matchNames": [
+                        "kube-system"
+                    ]
+                }
+            }
+        }
+}
diff --git a/jsonnet/prometheus/prometheus-k8s-service-monitor-kube-scheduler.libsonnet b/jsonnet/prometheus/prometheus-k8s-service-monitor-kube-scheduler.libsonnet
new file mode 100644
index 00000000..eaae0c39
--- /dev/null
+++ b/jsonnet/prometheus/prometheus-k8s-service-monitor-kube-scheduler.libsonnet
@@ -0,0 +1,33 @@
+{
+    new(namespace)::
+        {
+            "apiVersion": "monitoring.coreos.com/v1",
+            "kind": "ServiceMonitor",
+            "metadata": {
+                "name": "kube-scheduler",
+                "namespace": namespace,
+                "labels": {
+                    "k8s-app": "kube-scheduler"
+                }
+            },
+            "spec": {
+                "jobLabel": "k8s-app",
+                "endpoints": [
+                    {
+                        "port": "http-metrics",
+                        "interval": "30s"
+                    }
+                ],
+                "selector": {
+                    "matchLabels": {
+                        "k8s-app": "kube-scheduler"
+                    }
+                },
+                "namespaceSelector": {
+                    "matchNames": [
+                        "kube-system"
+                    ]
+                }
+            }
+        }
+}
diff --git a/jsonnet/prometheus/prometheus-k8s-service-monitor-kube-state-metrics.libsonnet b/jsonnet/prometheus/prometheus-k8s-service-monitor-kube-state-metrics.libsonnet
new file mode 100644
index 00000000..3d24aec3
--- /dev/null
+++ b/jsonnet/prometheus/prometheus-k8s-service-monitor-kube-state-metrics.libsonnet
@@ -0,0 +1,48 @@
+{
+    new(namespace)::
+        {
+            "apiVersion": "monitoring.coreos.com/v1",
+            "kind": "ServiceMonitor",
+            "metadata": {
+                "name": "kube-state-metrics",
+                "namespace": namespace,
+                "labels": {
+                    "k8s-app": "kube-state-metrics"
+                }
+            },
+            "spec": {
+                "jobLabel": "k8s-app",
+                "selector": {
+                    "matchLabels": {
+                        "k8s-app": "kube-state-metrics"
+                    }
+                },
+                "namespaceSelector": {
+                    "matchNames": [
+                        "monitoring"
+                    ]
+                },
+                "endpoints": [
+                    {
+                        "port": "https-main",
+                        "scheme": "https",
+                        "interval": "30s",
+                        "honorLabels": true,
+                        "bearerTokenFile": "/var/run/secrets/kubernetes.io/serviceaccount/token",
+                        "tlsConfig": {
+                            "insecureSkipVerify": true
+                        }
+                    },
+                    {
+                        "port": "https-self",
+                        "scheme": "https",
+                        "interval": "30s",
+                        "bearerTokenFile": "/var/run/secrets/kubernetes.io/serviceaccount/token",
+                        "tlsConfig": {
+                            "insecureSkipVerify": true
+                        }
+                    }
+                ]
+            }
+        }
+}
diff --git a/jsonnet/prometheus/prometheus-k8s-service-monitor-kubelet.libsonnet b/jsonnet/prometheus/prometheus-k8s-service-monitor-kubelet.libsonnet
new file mode 100644
index 00000000..6b7dd28e
--- /dev/null
+++ b/jsonnet/prometheus/prometheus-k8s-service-monitor-kubelet.libsonnet
@@ -0,0 +1,49 @@
+{
+    new(namespace)::
+        {
+            "apiVersion": "monitoring.coreos.com/v1",
+            "kind": "ServiceMonitor",
+            "metadata": {
+                "name": "kubelet",
+                "namespace": namespace,
+                "labels": {
+                    "k8s-app": "kubelet"
+                }
+            },
+            "spec": {
+                "jobLabel": "k8s-app",
+                "endpoints": [
+                    {
+                        "port": "https-metrics",
+                        "scheme": "https",
+                        "interval": "30s",
+                        "tlsConfig": {
+                            "insecureSkipVerify": true
+                        },
+                        "bearerTokenFile": "/var/run/secrets/kubernetes.io/serviceaccount/token"
+                    },
+                    {
+                        "port": "https-metrics",
+                        "scheme": "https",
+                        "path": "/metrics/cadvisor",
+                        "interval": "30s",
+                        "honorLabels": true,
+                        "tlsConfig": {
+                            "insecureSkipVerify": true
+                        },
+                        "bearerTokenFile": "/var/run/secrets/kubernetes.io/serviceaccount/token"
+                    }
+                ],
+                "selector": {
+                    "matchLabels": {
+                        "k8s-app": "kubelet"
+                    }
+                },
+                "namespaceSelector": {
+                    "matchNames": [
+                        "kube-system"
+                    ]
+                }
+            }
+        }
+}
diff --git a/jsonnet/prometheus/prometheus-k8s-service-monitor-node-exporter.libsonnet b/jsonnet/prometheus/prometheus-k8s-service-monitor-node-exporter.libsonnet
new file mode 100644
index 00000000..d1ff25e7
--- /dev/null
+++ b/jsonnet/prometheus/prometheus-k8s-service-monitor-node-exporter.libsonnet
@@ -0,0 +1,38 @@
+{
+    new(namespace)::
+        {
+            "apiVersion": "monitoring.coreos.com/v1",
+            "kind": "ServiceMonitor",
+            "metadata": {
+                "name": "node-exporter",
+                "namespace": namespace,
+                "labels": {
+                    "k8s-app": "node-exporter"
+                }
+            },
+            "spec": {
+                "jobLabel": "k8s-app",
+                "selector": {
+                    "matchLabels": {
+                        "k8s-app": "node-exporter"
+                    }
+                },
+                "namespaceSelector": {
+                    "matchNames": [
+                        "monitoring"
+                    ]
+                },
+                "endpoints": [
+                    {
+                        "port": "https",
+                        "scheme": "https",
+                        "interval": "30s",
+                        "bearerTokenFile": "/var/run/secrets/kubernetes.io/serviceaccount/token",
+                        "tlsConfig": {
+                            "insecureSkipVerify": true
+                        }
+                    }
+                ]
+            }
+        }
+}
diff --git a/jsonnet/prometheus/prometheus-k8s-service-monitor-prometheus-operator.libsonnet b/jsonnet/prometheus/prometheus-k8s-service-monitor-prometheus-operator.libsonnet
new file mode 100644
index 00000000..07613f8c
--- /dev/null
+++ b/jsonnet/prometheus/prometheus-k8s-service-monitor-prometheus-operator.libsonnet
@@ -0,0 +1,26 @@
+{
+    new(namespace)::
+        {
+            "apiVersion": "monitoring.coreos.com/v1",
+            "kind": "ServiceMonitor",
+            "metadata": {
+                "name": "prometheus-operator",
+                "namespace": namespace,
+                "labels": {
+                    "k8s-app": "prometheus-operator"
+                }
+            },
+            "spec": {
+                "endpoints": [
+                    {
+                        "port": "http"
+                    }
+                ],
+                "selector": {
+                    "matchLabels": {
+                        "k8s-app": "prometheus-operator"
+                    }
+                }
+            }
+        }
+}
diff --git a/jsonnet/prometheus/prometheus-k8s-service-monitor-prometheus.libsonnet b/jsonnet/prometheus/prometheus-k8s-service-monitor-prometheus.libsonnet
new file mode 100644
index 00000000..0f4ef084
--- /dev/null
+++ b/jsonnet/prometheus/prometheus-k8s-service-monitor-prometheus.libsonnet
@@ -0,0 +1,32 @@
+{
+    new(namespace)::
+        {
+            "apiVersion": "monitoring.coreos.com/v1",
+            "kind": "ServiceMonitor",
+            "metadata": {
+                "name": "prometheus",
+                "namespace": namespace,
+                "labels": {
+                    "k8s-app": "prometheus"
+                }
+            },
+            "spec": {
+                "selector": {
+                    "matchLabels": {
+                        "prometheus": "k8s"
+                    }
+                },
+                "namespaceSelector": {
+                    "matchNames": [
+                        "monitoring"
+                    ]
+                },
+                "endpoints": [
+                    {
+                        "port": "web",
+                        "interval": "30s"
+                    }
+                ]
+            }
+        }
+}
diff --git a/jsonnet/prometheus/prometheus-k8s-service.libsonnet b/jsonnet/prometheus/prometheus-k8s-service.libsonnet
new file mode 100644
index 00000000..96781d69
--- /dev/null
+++ b/jsonnet/prometheus/prometheus-k8s-service.libsonnet
@@ -0,0 +1,13 @@
+local k = import "ksonnet.beta.3/k.libsonnet";
+local service = k.core.v1.service;
+local servicePort = k.core.v1.service.mixin.spec.portsType;
+
+local prometheusPort = servicePort.newNamed("web", 9090, "web");
+
+
+{
+    new(namespace)::
+        service.new("prometheus-k8s", {app: "prometheus", prometheus: "k8s"}, prometheusPort) +
+          service.mixin.metadata.withNamespace(namespace) +
+          service.mixin.metadata.withLabels({prometheus: "k8s"})
+}
diff --git a/jsonnet/prometheus/prometheus-k8s.libsonnet b/jsonnet/prometheus/prometheus-k8s.libsonnet
new file mode 100644
index 00000000..853f62b1
--- /dev/null
+++ b/jsonnet/prometheus/prometheus-k8s.libsonnet
@@ -0,0 +1,43 @@
+local k = import "ksonnet.beta.3/k.libsonnet";
+
+local container = k.core.v1.pod.mixin.spec.containersType;
+local resourceRequirements = container.mixin.resourcesType;
+local selector = k.apps.v1beta2.deployment.mixin.spec.selectorType;
+
+local resources = resourceRequirements.new() +
+  resourceRequirements.withRequests({memory: "400Mi"});
+
+{
+    new(namespace)::
+        {
+          apiVersion: "monitoring.coreos.com/v1",
+          kind: "Prometheus",
+          metadata: {
+            name: "k8s",
+            namespace: namespace,
+            labels: {
+              prometheus: "k8s",
+            },
+          },
+          spec: {
+            replicas: 2,
+            version: "v2.2.1",
+            serviceAccountName: "prometheus-k8s",
+            serviceMonitorSelector: selector.withMatchExpressions({key: "k8s-app", operator: "Exists"}),
+            ruleSelector: selector.withMatchLabels({
+              role: "alert-rules",
+              prometheus: "k8s",
+            }),
+            resources: resources,
+            alerting: {
+              alertmanagers: [
+                {
+                  namespace: "monitoring",
+                  name: "alertmanager-main",
+                  port: "web",
+                },
+              ],
+            },
+          },
+        }
+}
diff --git a/jsonnet/prometheus/prometheus-namespace-role-binding.libsonnet b/jsonnet/prometheus/prometheus-namespace-role-binding.libsonnet
new file mode 100644
index 00000000..8b255fa0
--- /dev/null
+++ b/jsonnet/prometheus/prometheus-namespace-role-binding.libsonnet
@@ -0,0 +1,13 @@
+local k = import "ksonnet.beta.3/k.libsonnet";
+local roleBinding = k.rbac.v1.roleBinding;
+
+{
+  new(serviceAccountNamespace, namespace, name)::
+    roleBinding.new() +
+      roleBinding.mixin.metadata.withName(name) +
+      roleBinding.mixin.metadata.withNamespace(namespace) +
+      roleBinding.mixin.roleRef.withApiGroup("rbac.authorization.k8s.io") +
+      roleBinding.mixin.roleRef.withName(name) +
+      roleBinding.mixin.roleRef.mixinInstance({kind: "Role"}) +
+      roleBinding.withSubjects([{kind: "ServiceAccount", name: name, namespace: serviceAccountNamespace}])
+}
diff --git a/jsonnet/prometheus/prometheus-namespace-role.libsonnet b/jsonnet/prometheus/prometheus-namespace-role.libsonnet
new file mode 100644
index 00000000..5afdcff4
--- /dev/null
+++ b/jsonnet/prometheus/prometheus-namespace-role.libsonnet
@@ -0,0 +1,21 @@
+local k = import "ksonnet.beta.3/k.libsonnet";
+local role = k.rbac.v1.role;
+local policyRule = role.rulesType;
+
+{
+    new(namespace)::
+        local coreRule = policyRule.new() +
+          policyRule.withApiGroups([""]) +
+          policyRule.withResources([
+              "nodes",
+              "services",
+              "endpoints",
+              "pods",
+          ]) +
+          policyRule.withVerbs(["get", "list", "watch"]);
+
+        role.new() +
+          role.mixin.metadata.withName("prometheus-k8s") +
+          role.mixin.metadata.withNamespace(namespace) +
+          role.withRules(coreRule)
+}
diff --git a/jsonnet/prometheus/prometheus.libsonnet b/jsonnet/prometheus/prometheus.libsonnet
new file mode 100644
index 00000000..edc75c08
--- /dev/null
+++ b/jsonnet/prometheus/prometheus.libsonnet
@@ -0,0 +1,25 @@
+{
+    clusterRoleBinding:: import "prometheus-k8s-cluster-role-binding.libsonnet",
+    clusterRole:: import "prometheus-k8s-cluster-role.libsonnet",
+    roleBindingConfig:: import "prometheus-k8s-role-binding-config.libsonnet",
+    roleBindingNamespace:: import "prometheus-k8s-role-binding-namespace.libsonnet",
+    roleBindingKubeSystem:: import "prometheus-k8s-role-binding-kube-system.libsonnet",
+    roleBindingDefault:: import "prometheus-k8s-role-binding-default.libsonnet",
+    roleConfig:: import "prometheus-k8s-role-config.libsonnet",
+    roleNamespace:: import "prometheus-k8s-role-namespace.libsonnet",
+    roleKubeSystem:: import "prometheus-k8s-role-kube-system.libsonnet",
+    roleDefault:: import "prometheus-k8s-role-default.libsonnet",
+    serviceAccount:: import "prometheus-k8s-service-account.libsonnet",
+    serviceMonitorAlertmanager:: import "prometheus-k8s-service-monitor-alertmanager.libsonnet",
+    serviceMonitorApiserver:: import "prometheus-k8s-service-monitor-apiserver.libsonnet",
+    serviceMonitorCoreDNS:: import "prometheus-k8s-service-monitor-coredns.libsonnet",
+    serviceMonitorControllerManager:: import "prometheus-k8s-service-monitor-kube-controller-manager.libsonnet",
+    serviceMonitorScheduler:: import "prometheus-k8s-service-monitor-kube-scheduler.libsonnet",
+    serviceMonitorKubeStateMetrics:: import "prometheus-k8s-service-monitor-kube-state-metrics.libsonnet",
+    serviceMonitorKubelet:: import "prometheus-k8s-service-monitor-kubelet.libsonnet",
+    serviceMonitorNodeExporter:: import "prometheus-k8s-service-monitor-node-exporter.libsonnet",
+    serviceMonitorPrometheusOperator:: import "prometheus-k8s-service-monitor-prometheus-operator.libsonnet",
+    serviceMonitorPrometheus:: import "prometheus-k8s-service-monitor-prometheus.libsonnet",
+    service:: import "prometheus-k8s-service.libsonnet",
+    prometheus:: import "prometheus-k8s.libsonnet",
+}
-- 
GitLab