-- manifests/configmap-grafana.go --
// Code generated by lingon. EDIT AS MUCH AS YOU LIKE.

package grafana

import (
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

var GrafanaCM = &corev1.ConfigMap{
	Data: map[string]string{
		"dashboardproviders.yaml": `apiVersion: 1
providers:
- disableDeletion: false
  editable: true
  folder: ""
  name: default
  options:
    path: /var/lib/grafana/dashboards/default
  orgId: 1
  type: file
`,
		"datasources.yaml": `apiVersion: 1
datasources:
- access: proxy
  name: Prometheus
  type: prometheus
  url: http://prometheus-server:80
  version: 1
`,
		"download_dashboards.sh": `#!/usr/bin/env sh
set -euf
mkdir -p /var/lib/grafana/dashboards/default

curl -skf \
--connect-timeout 60 \
--max-time 60 \
-H "Accept: application/json" \
-H "Content-Type: application/json;charset=UTF-8" \
  "https://karpenter.sh/v0.24.0/getting-started/getting-started-with-eksctl/karpenter-capacity-dashboard.json" \
> "/var/lib/grafana/dashboards/default/capacity-dashboard.json"
  
curl -skf \
--connect-timeout 60 \
--max-time 60 \
-H "Accept: application/json" \
-H "Content-Type: application/json;charset=UTF-8" \
  "https://karpenter.sh/v0.24.0/getting-started/getting-started-with-eksctl/karpenter-performance-dashboard.json" \
> "/var/lib/grafana/dashboards/default/performance-dashboard.json"
`,
		"grafana.ini": `[analytics]
check_for_updates = true
[grafana_net]
url = https://grafana.net
[log]
mode = console
[paths]
data = /var/lib/grafana/
logs = /var/log/grafana
plugins = /var/lib/grafana/plugins
provisioning = /etc/grafana/provisioning
[server]
domain = ''
`},
	ObjectMeta: metav1.ObjectMeta{
		Labels: map[string]string{
			"app.kubernetes.io/instance":   "grafana",
			"app.kubernetes.io/managed-by": "Helm",
			"app.kubernetes.io/name":       "grafana",
			"app.kubernetes.io/version":    "9.3.6",
			"helm.sh/chart":                "grafana-6.50.7",
		},
		Name:      "grafana",
		Namespace: "monitoring",
	},
	TypeMeta: metav1.TypeMeta{
		APIVersion: "v1",
		Kind:       "ConfigMap",
	},
}
-- manifests/clusterrole-grafana-clusterrole.go --
// Code generated by lingon. EDIT AS MUCH AS YOU LIKE.

package grafana

import (
	rbacv1 "k8s.io/api/rbac/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

var GrafanaCR = &rbacv1.ClusterRole{
	ObjectMeta: metav1.ObjectMeta{
		Labels: map[string]string{
			"app.kubernetes.io/instance":   "grafana",
			"app.kubernetes.io/managed-by": "Helm",
			"app.kubernetes.io/name":       "grafana",
			"app.kubernetes.io/version":    "9.3.6",
			"helm.sh/chart":                "grafana-6.50.7",
		},
		Name: "grafana-clusterrole",
	},
	Rules: []rbacv1.PolicyRule{},
	TypeMeta: metav1.TypeMeta{
		APIVersion: "rbac.authorization.k8s.io/v1",
		Kind:       "ClusterRole",
	},
}
-- manifests/clusterrolebinding-grafana-clusterrolebinding.go --
// Code generated by lingon. EDIT AS MUCH AS YOU LIKE.

package grafana

import (
	rbacv1 "k8s.io/api/rbac/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

var GrafanaCRB = &rbacv1.ClusterRoleBinding{
	ObjectMeta: metav1.ObjectMeta{
		Labels: map[string]string{
			"app.kubernetes.io/instance":   "grafana",
			"app.kubernetes.io/managed-by": "Helm",
			"app.kubernetes.io/name":       "grafana",
			"app.kubernetes.io/version":    "9.3.6",
			"helm.sh/chart":                "grafana-6.50.7",
		},
		Name: "grafana-clusterrolebinding",
	},
	RoleRef: rbacv1.RoleRef{
		APIGroup: "rbac.authorization.k8s.io",
		Kind:     "ClusterRole",
		Name:     "grafana-clusterrole",
	},
	Subjects: []rbacv1.Subject{rbacv1.Subject{
		Kind:      "ServiceAccount",
		Name:      "grafana",
		Namespace: "monitoring",
	}},
	TypeMeta: metav1.TypeMeta{
		APIVersion: "rbac.authorization.k8s.io/v1",
		Kind:       "ClusterRoleBinding",
	},
}
-- manifests/configmap-grafana-dashboards-default.go --
// Code generated by lingon. EDIT AS MUCH AS YOU LIKE.

package grafana

import (
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

var GrafanaDashboardsDefaultCM = &corev1.ConfigMap{
	Data: map[string]string{},
	ObjectMeta: metav1.ObjectMeta{
		Labels: map[string]string{
			"app.kubernetes.io/instance":   "grafana",
			"app.kubernetes.io/managed-by": "Helm",
			"app.kubernetes.io/name":       "grafana",
			"app.kubernetes.io/version":    "9.3.6",
			"dashboard-provider":           "default",
			"helm.sh/chart":                "grafana-6.50.7",
		},
		Name:      "grafana-dashboards-default",
		Namespace: "monitoring",
	},
	TypeMeta: metav1.TypeMeta{
		APIVersion: "v1",
		Kind:       "ConfigMap",
	},
}
-- manifests/deployment-grafana.go --
// Code generated by lingon. EDIT AS MUCH AS YOU LIKE.

package grafana

import (
	appsv1 "k8s.io/api/apps/v1"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	intstr "k8s.io/apimachinery/pkg/util/intstr"
)

var GrafanaDeploy = &appsv1.Deployment{
	ObjectMeta: metav1.ObjectMeta{
		Labels: map[string]string{
			"app.kubernetes.io/instance":   "grafana",
			"app.kubernetes.io/managed-by": "Helm",
			"app.kubernetes.io/name":       "grafana",
			"app.kubernetes.io/version":    "9.3.6",
			"helm.sh/chart":                "grafana-6.50.7",
		},
		Name:      "grafana",
		Namespace: "monitoring",
	},
	Spec: appsv1.DeploymentSpec{
		Replicas:             P(int32(1)),
		RevisionHistoryLimit: P(int32(10)),
		Selector: &metav1.LabelSelector{MatchLabels: map[string]string{
			"app.kubernetes.io/instance": "grafana",
			"app.kubernetes.io/name":     "grafana",
		}},
		Strategy: appsv1.DeploymentStrategy{Type: appsv1.DeploymentStrategyType("RollingUpdate")},
		Template: corev1.PodTemplateSpec{
			ObjectMeta: metav1.ObjectMeta{
				Annotations: map[string]string{
					"checksum/config":                       "e70c78276025b4585ff194011ecd906afd37b91162664ab33b812be3e483f2e9",
					"checksum/dashboards-json-config":       "2e39cb09f1cf9b1f6a13b1ab52355fc06a967aebea9403ee8e5fdc54f901bdec",
					"checksum/sc-dashboard-provider-config": "01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b",
					"checksum/secret":                       "7b60ebdb3db3188713a9f1fb62bb0fe9e91e03f5cfb1b9a40c13e586ab5cbecb",
				},
				Labels: map[string]string{
					"app.kubernetes.io/instance": "grafana",
					"app.kubernetes.io/name":     "grafana",
				},
			},
			Spec: corev1.PodSpec{
				AutomountServiceAccountToken: P(true),
				Containers: []corev1.Container{corev1.Container{
					Env: []corev1.EnvVar{corev1.EnvVar{
						Name:      "POD_IP",
						ValueFrom: &corev1.EnvVarSource{FieldRef: &corev1.ObjectFieldSelector{FieldPath: "status.podIP"}},
					}, corev1.EnvVar{
						Name: "GF_SECURITY_ADMIN_USER",
						ValueFrom: &corev1.EnvVarSource{SecretKeyRef: &corev1.SecretKeySelector{
							Key:                  "admin-user",
							LocalObjectReference: corev1.LocalObjectReference{Name: "grafana"},
						}},
					}, corev1.EnvVar{
						Name: "GF_SECURITY_ADMIN_PASSWORD",
						ValueFrom: &corev1.EnvVarSource{SecretKeyRef: &corev1.SecretKeySelector{
							Key:                  "admin-password",
							LocalObjectReference: corev1.LocalObjectReference{Name: "grafana"},
						}},
					}, corev1.EnvVar{
						Name:  "GF_PATHS_DATA",
						Value: "/var/lib/grafana/",
					}, corev1.EnvVar{
						Name:  "GF_PATHS_LOGS",
						Value: "/var/log/grafana",
					}, corev1.EnvVar{
						Name:  "GF_PATHS_PLUGINS",
						Value: "/var/lib/grafana/plugins",
					}, corev1.EnvVar{
						Name:  "GF_PATHS_PROVISIONING",
						Value: "/etc/grafana/provisioning",
					}},
					Image:           "grafana/grafana:9.3.6",
					ImagePullPolicy: corev1.PullPolicy("IfNotPresent"),
					LivenessProbe: &corev1.Probe{
						FailureThreshold:    int32(10),
						InitialDelaySeconds: int32(60),
						ProbeHandler: corev1.ProbeHandler{HTTPGet: &corev1.HTTPGetAction{
							Path: "/api/health",
							Port: intstr.IntOrString{IntVal: int32(3000)},
						}},
						TimeoutSeconds: int32(30),
					},
					Name: "grafana",
					Ports: []corev1.ContainerPort{corev1.ContainerPort{
						ContainerPort: int32(3000),
						Name:          "grafana",
						Protocol:      corev1.Protocol("TCP"),
					}, corev1.ContainerPort{
						ContainerPort: int32(9094),
						Name:          "gossip-tcp",
						Protocol:      corev1.Protocol("TCP"),
					}, corev1.ContainerPort{
						ContainerPort: int32(9094),
						Name:          "gossip-udp",
						Protocol:      corev1.Protocol("UDP"),
					}},
					ReadinessProbe: &corev1.Probe{ProbeHandler: corev1.ProbeHandler{HTTPGet: &corev1.HTTPGetAction{
						Path: "/api/health",
						Port: intstr.IntOrString{IntVal: int32(3000)},
					}}},
					VolumeMounts: []corev1.VolumeMount{corev1.VolumeMount{
						MountPath: "/etc/grafana/grafana.ini",
						Name:      "config",
						SubPath:   "grafana.ini",
					}, corev1.VolumeMount{
						MountPath: "/var/lib/grafana",
						Name:      "storage",
					}, corev1.VolumeMount{
						MountPath: "/etc/grafana/provisioning/datasources/datasources.yaml",
						Name:      "config",
						SubPath:   "datasources.yaml",
					}, corev1.VolumeMount{
						MountPath: "/etc/grafana/provisioning/dashboards/dashboardproviders.yaml",
						Name:      "config",
						SubPath:   "dashboardproviders.yaml",
					}},
				}},
				EnableServiceLinks: P(true),
				InitContainers: []corev1.Container{corev1.Container{
					Args:            []string{"-c", "mkdir -p /var/lib/grafana/dashboards/default && /bin/sh -x /etc/grafana/download_dashboards.sh"},
					Command:         []string{"/bin/sh"},
					Image:           "curlimages/curl:7.85.0",
					ImagePullPolicy: corev1.PullPolicy("IfNotPresent"),
					Name:            "download-dashboards",
					VolumeMounts: []corev1.VolumeMount{corev1.VolumeMount{
						MountPath: "/etc/grafana/download_dashboards.sh",
						Name:      "config",
						SubPath:   "download_dashboards.sh",
					}, corev1.VolumeMount{
						MountPath: "/var/lib/grafana",
						Name:      "storage",
					}},
				}},
				SecurityContext: &corev1.PodSecurityContext{
					FSGroup:    P(int64(472)),
					RunAsGroup: P(int64(472)),
					RunAsUser:  P(int64(472)),
				},
				ServiceAccountName: "grafana",
				Volumes: []corev1.Volume{corev1.Volume{
					Name:         "config",
					VolumeSource: corev1.VolumeSource{ConfigMap: &corev1.ConfigMapVolumeSource{LocalObjectReference: corev1.LocalObjectReference{Name: "grafana"}}},
				}, corev1.Volume{
					Name:         "dashboards-default",
					VolumeSource: corev1.VolumeSource{ConfigMap: &corev1.ConfigMapVolumeSource{LocalObjectReference: corev1.LocalObjectReference{Name: "grafana-dashboards-default"}}},
				}, corev1.Volume{
					Name:         "storage",
					VolumeSource: corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{}},
				}},
			},
		},
	},
	TypeMeta: metav1.TypeMeta{
		APIVersion: "apps/v1",
		Kind:       "Deployment",
	},
}
-- manifests/rolebinding-grafana.go --
// Code generated by lingon. EDIT AS MUCH AS YOU LIKE.

package grafana

import (
	rbacv1 "k8s.io/api/rbac/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

var GrafanaRB = &rbacv1.RoleBinding{
	ObjectMeta: metav1.ObjectMeta{
		Labels: map[string]string{
			"app.kubernetes.io/instance":   "grafana",
			"app.kubernetes.io/managed-by": "Helm",
			"app.kubernetes.io/name":       "grafana",
			"app.kubernetes.io/version":    "9.3.6",
			"helm.sh/chart":                "grafana-6.50.7",
		},
		Name:      "grafana",
		Namespace: "monitoring",
	},
	RoleRef: rbacv1.RoleRef{
		APIGroup: "rbac.authorization.k8s.io",
		Kind:     "Role",
		Name:     "grafana",
	},
	Subjects: []rbacv1.Subject{rbacv1.Subject{
		Kind:      "ServiceAccount",
		Name:      "grafana",
		Namespace: "monitoring",
	}},
	TypeMeta: metav1.TypeMeta{
		APIVersion: "rbac.authorization.k8s.io/v1",
		Kind:       "RoleBinding",
	},
}
-- manifests/role-grafana.go --
// Code generated by lingon. EDIT AS MUCH AS YOU LIKE.

package grafana

import (
	rbacv1 "k8s.io/api/rbac/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

var GrafanaRole = &rbacv1.Role{
	ObjectMeta: metav1.ObjectMeta{
		Labels: map[string]string{
			"app.kubernetes.io/instance":   "grafana",
			"app.kubernetes.io/managed-by": "Helm",
			"app.kubernetes.io/name":       "grafana",
			"app.kubernetes.io/version":    "9.3.6",
			"helm.sh/chart":                "grafana-6.50.7",
		},
		Name:      "grafana",
		Namespace: "monitoring",
	},
	Rules: []rbacv1.PolicyRule{rbacv1.PolicyRule{
		APIGroups:     []string{"extensions"},
		ResourceNames: []string{"grafana"},
		Resources:     []string{"podsecuritypolicies"},
		Verbs:         []string{"use"},
	}},
	TypeMeta: metav1.TypeMeta{
		APIVersion: "rbac.authorization.k8s.io/v1",
		Kind:       "Role",
	},
}
-- manifests/serviceaccount-grafana.go --
// Code generated by lingon. EDIT AS MUCH AS YOU LIKE.

package grafana

import (
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

var GrafanaSA = &corev1.ServiceAccount{
	ObjectMeta: metav1.ObjectMeta{
		Labels: map[string]string{
			"app.kubernetes.io/instance":   "grafana",
			"app.kubernetes.io/managed-by": "Helm",
			"app.kubernetes.io/name":       "grafana",
			"app.kubernetes.io/version":    "9.3.6",
			"helm.sh/chart":                "grafana-6.50.7",
		},
		Name:      "grafana",
		Namespace: "monitoring",
	},
	TypeMeta: metav1.TypeMeta{
		APIVersion: "v1",
		Kind:       "ServiceAccount",
	},
}
-- manifests/service-grafana.go --
// Code generated by lingon. EDIT AS MUCH AS YOU LIKE.

package grafana

import (
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	intstr "k8s.io/apimachinery/pkg/util/intstr"
)

var GrafanaSVC = &corev1.Service{
	ObjectMeta: metav1.ObjectMeta{
		Labels: map[string]string{
			"app.kubernetes.io/instance":   "grafana",
			"app.kubernetes.io/managed-by": "Helm",
			"app.kubernetes.io/name":       "grafana",
			"app.kubernetes.io/version":    "9.3.6",
			"helm.sh/chart":                "grafana-6.50.7",
		},
		Name:      "grafana",
		Namespace: "monitoring",
	},
	Spec: corev1.ServiceSpec{
		Ports: []corev1.ServicePort{corev1.ServicePort{
			Name:       "service",
			Port:       int32(80),
			Protocol:   corev1.Protocol("TCP"),
			TargetPort: intstr.IntOrString{IntVal: int32(3000)},
		}},
		Selector: map[string]string{
			"app.kubernetes.io/instance": "grafana",
			"app.kubernetes.io/name":     "grafana",
		},
		Type: corev1.ServiceType("ClusterIP"),
	},
	TypeMeta: metav1.TypeMeta{
		APIVersion: "v1",
		Kind:       "Service",
	},
}
-- manifests/secret-grafana.go --
// Code generated by lingon. EDIT AS MUCH AS YOU LIKE.

package grafana

import (
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

var GrafanaSecrets = &corev1.Secret{
	Data: map[string][]byte{"admin-password": []byte("J7gFwPAkNaFQPT9OiBHNLUDy6rc46DlWIav9tNvS"), "admin-user": []byte("admin"), "ldap-toml": []byte("")},
	ObjectMeta: metav1.ObjectMeta{
		Labels: map[string]string{
			"app.kubernetes.io/instance":   "grafana",
			"app.kubernetes.io/managed-by": "Helm",
			"app.kubernetes.io/name":       "grafana",
			"app.kubernetes.io/version":    "9.3.6",
			"helm.sh/chart":                "grafana-6.50.7",
		},
		Name:      "grafana",
		Namespace: "monitoring",
	},
	Type: corev1.SecretType("Opaque"),
	TypeMeta: metav1.TypeMeta{
		APIVersion: "v1",
		Kind:       "Secret",
	},
} // TODO: SECRETS SHOULD BE STORED ELSEWHERE THAN IN THE CODE!!!!
-- manifests/configmap-grafana-test.go --
// Code generated by lingon. EDIT AS MUCH AS YOU LIKE.

package grafana

import (
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

var GrafanaTestCM = &corev1.ConfigMap{
	Data: map[string]string{
		"run.sh": `@test "Test Health" {
  url="http://grafana/api/health"

  code=$(wget --server-response --spider --timeout 90 --tries 10 ${url} 2>&1 | awk '/^  HTTP/{print $2}')
  [ "$code" == "200" ]
}`},
	ObjectMeta: metav1.ObjectMeta{
		Annotations: map[string]string{
			"helm.sh/hook":               "test-success",
			"helm.sh/hook-delete-policy": "before-hook-creation,hook-succeeded",
		},
		Labels: map[string]string{
			"app.kubernetes.io/instance":   "grafana",
			"app.kubernetes.io/managed-by": "Helm",
			"app.kubernetes.io/name":       "grafana",
			"app.kubernetes.io/version":    "9.3.6",
			"helm.sh/chart":                "grafana-6.50.7",
		},
		Name:      "grafana-test",
		Namespace: "monitoring",
	},
	TypeMeta: metav1.TypeMeta{
		APIVersion: "v1",
		Kind:       "ConfigMap",
	},
}
-- manifests/pod-grafana-test.go --
// Code generated by lingon. EDIT AS MUCH AS YOU LIKE.

package grafana

import (
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

var GrafanaTestPO = &corev1.Pod{
	ObjectMeta: metav1.ObjectMeta{
		Annotations: map[string]string{
			"helm.sh/hook":               "test-success",
			"helm.sh/hook-delete-policy": "before-hook-creation,hook-succeeded",
		},
		Labels: map[string]string{
			"app.kubernetes.io/instance":   "grafana",
			"app.kubernetes.io/managed-by": "Helm",
			"app.kubernetes.io/name":       "grafana",
			"app.kubernetes.io/version":    "9.3.6",
			"helm.sh/chart":                "grafana-6.50.7",
		},
		Name:      "grafana-test",
		Namespace: "monitoring",
	},
	Spec: corev1.PodSpec{
		Containers: []corev1.Container{corev1.Container{
			Command:         []string{"/opt/bats/bin/bats", "-t", "/tests/run.sh"},
			Image:           "bats/bats:v1.4.1",
			ImagePullPolicy: corev1.PullPolicy("IfNotPresent"),
			Name:            "grafana-test",
			VolumeMounts: []corev1.VolumeMount{corev1.VolumeMount{
				MountPath: "/tests",
				Name:      "tests",
				ReadOnly:  true,
			}},
		}},
		RestartPolicy:      corev1.RestartPolicy("Never"),
		ServiceAccountName: "grafana-test",
		Volumes: []corev1.Volume{corev1.Volume{
			Name:         "tests",
			VolumeSource: corev1.VolumeSource{ConfigMap: &corev1.ConfigMapVolumeSource{LocalObjectReference: corev1.LocalObjectReference{Name: "grafana-test"}}},
		}},
	},
	TypeMeta: metav1.TypeMeta{
		APIVersion: "v1",
		Kind:       "Pod",
	},
}
-- manifests/serviceaccount-grafana-test.go --
// Code generated by lingon. EDIT AS MUCH AS YOU LIKE.

package grafana

import (
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

var GrafanaTestSA = &corev1.ServiceAccount{
	ObjectMeta: metav1.ObjectMeta{
		Annotations: map[string]string{
			"helm.sh/hook":               "test-success",
			"helm.sh/hook-delete-policy": "before-hook-creation,hook-succeeded",
		},
		Labels: map[string]string{
			"app.kubernetes.io/instance":   "grafana",
			"app.kubernetes.io/managed-by": "Helm",
			"app.kubernetes.io/name":       "grafana",
			"app.kubernetes.io/version":    "9.3.6",
			"helm.sh/chart":                "grafana-6.50.7",
		},
		Name:      "grafana-test",
		Namespace: "monitoring",
	},
	TypeMeta: metav1.TypeMeta{
		APIVersion: "v1",
		Kind:       "ServiceAccount",
	},
}
-- manifests/app.go --
// Code generated by lingon. EDIT AS MUCH AS YOU LIKE.

package grafana

import (
	"context"
	"errors"
	kube "github.com/golingon/lingon/pkg/kube"
	appsv1 "k8s.io/api/apps/v1"
	corev1 "k8s.io/api/core/v1"
	rbacv1 "k8s.io/api/rbac/v1"
	"os"
	"os/exec"
)

// validate the struct implements the interface
var _ kube.Exporter = (*Grafana)(nil)

// Grafana contains kubernetes manifests
type Grafana struct {
	kube.App

	GrafanaCM                  *corev1.ConfigMap
	GrafanaCR                  *rbacv1.ClusterRole
	GrafanaCRB                 *rbacv1.ClusterRoleBinding
	GrafanaDashboardsDefaultCM *corev1.ConfigMap
	GrafanaDeploy              *appsv1.Deployment
	GrafanaRB                  *rbacv1.RoleBinding
	GrafanaRole                *rbacv1.Role
	GrafanaSA                  *corev1.ServiceAccount
	GrafanaSVC                 *corev1.Service
	GrafanaSecrets             *corev1.Secret
	GrafanaTestCM              *corev1.ConfigMap
	GrafanaTestPO              *corev1.Pod
	GrafanaTestSA              *corev1.ServiceAccount
}

// New creates a new Grafana
func New() *Grafana {
	return &Grafana{
		GrafanaCM:                  GrafanaCM,
		GrafanaCR:                  GrafanaCR,
		GrafanaCRB:                 GrafanaCRB,
		GrafanaDashboardsDefaultCM: GrafanaDashboardsDefaultCM,
		GrafanaDeploy:              GrafanaDeploy,
		GrafanaRB:                  GrafanaRB,
		GrafanaRole:                GrafanaRole,
		GrafanaSA:                  GrafanaSA,
		GrafanaSVC:                 GrafanaSVC,
		GrafanaSecrets:             GrafanaSecrets,
		GrafanaTestCM:              GrafanaTestCM,
		GrafanaTestPO:              GrafanaTestPO,
		GrafanaTestSA:              GrafanaTestSA}
}

// Apply applies the kubernetes objects to the cluster
func (a *Grafana) Apply(ctx context.Context) error {
	return Apply(ctx, a)
}

// Export exports the kubernetes objects to YAML files in the given directory
func (a *Grafana) Export(dir string) error {
	return kube.Export(a, kube.WithExportOutputDirectory(dir))
}

// Apply applies the kubernetes objects contained in Exporter to the cluster
func Apply(ctx context.Context, km kube.Exporter) error {
	cmd := exec.CommandContext(ctx, "kubectl", "apply", "-f", "-")
	cmd.Env = os.Environ()        // inherit environment in case we need to use kubectl from a container
	stdin, err := cmd.StdinPipe() // pipe to pass data to kubectl
	if err != nil {
		return err
	}

	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	go func() {
		defer func() {
			err = errors.Join(err, stdin.Close())
		}()
		if errEW := kube.Export(km, kube.WithExportWriter(stdin), kube.WithExportAsSingleFile("stdin")); errEW != nil {
			err = errors.Join(err, errEW)
		}
	}()

	if errS := cmd.Start(); errS != nil {
		return errors.Join(err, errS)
	}

	// waits for the command to exit and waits for any copying
	// to stdin or copying from stdout or stderr to complete
	return errors.Join(err, cmd.Wait())
}

// P converts T to *T, useful for basic types
func P[T any](t T) *T {
	return &t
}
