Skip to content

Commit

Permalink
feat: Add TLS config to Perses client and mount certs to Deployment a…
Browse files Browse the repository at this point in the history
…nd StatefulSet

Signed-off-by: Douglass Kirkley <doug.kirkley@gmail.com>
  • Loading branch information
dougkirkley committed Feb 12, 2025
1 parent 5c86542 commit 62864c1
Show file tree
Hide file tree
Showing 11 changed files with 529 additions and 158 deletions.
40 changes: 40 additions & 0 deletions api/v1alpha1/perses_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,14 @@ type PersesSpec struct {
// +operator-sdk:csv:customresourcedefinitions:type=spec
Metadata *Metadata `json:"metadata,omitempty"`
// +operator-sdk:csv:customresourcedefinitions:type=spec
// Client perses client configuration
Client Client `json:"client,omitempty"`
// +operator-sdk:csv:customresourcedefinitions:type=spec
Config PersesConfig `json:"config,omitempty"`
// +operator-sdk:csv:customresourcedefinitions:type=spec
// Args extra arguments to pass to perses
Args []string `json:"args,omitempty"`
// +operator-sdk:csv:customresourcedefinitions:type=spec
ContainerPort int32 `json:"containerPort,omitempty"`
// +operator-sdk:csv:customresourcedefinitions:type=spec
Replicas *int32 `json:"replicas,omitempty"`
Expand All @@ -45,6 +51,40 @@ type Metadata struct {
Annotations map[string]string `json:"annotations,omitempty"`
}

type Client struct {
// +optional
// TLS the equivalent to the tls_config for perses client
TLS *TLS `json:"tls,omitempty"`
}

type TLS struct {
Enable bool `json:"enable"`
InsecureSkipVerify bool `json:"insecureSkipVerify"`
CaCert Certificate `json:"caCert"`
// +optional
UserCert *Certificate `json:"userCert,omitempty"`
}

// CertificateType types of certificate sources in k8s
type CertificateType string

const (
CertificateTypeSecret CertificateType = "secret"
CertificateTypeConfigMap CertificateType = "configmap"
)

type Certificate struct {
// +kubebuilder:validation:Enum:={"secret", "configmap"}
// Type source type of certificate
Type CertificateType `json:"type"`
// Name of certificate k8s resource
Name string `json:"name"`
// CertFile path to certificate
CertFile string `json:"certFile"`
// CertKeyFile path to certificate key file
CertKeyFile string `json:"certKeyFile"`
}

// PersesStatus defines the observed state of Perses
type PersesStatus struct {
// +operator-sdk:csv:customresourcedefinitions:type=status
Expand Down
62 changes: 62 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

67 changes: 67 additions & 0 deletions config/crd/bases/perses.dev_perses.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -959,6 +959,73 @@ spec:
x-kubernetes-list-type: atomic
type: object
type: object
args:
description: Args extra arguments to pass to perses
items:
type: string
type: array
client:
description: Client perses client configuration
properties:
tls:
description: TLS the equivalent to the tls_config for perses client
properties:
caCert:
properties:
certFile:
description: CertFile path to certificate
type: string
certKeyFile:
description: CertKeyFile path to certificate key file
type: string
name:
description: Name of certificate k8s resource
type: string
type:
description: Type source type of certificate
enum:
- secret
- configmap
type: string
required:
- certFile
- certKeyFile
- name
- type
type: object
enable:
type: boolean
insecureSkipVerify:
type: boolean
userCert:
properties:
certFile:
description: CertFile path to certificate
type: string
certKeyFile:
description: CertKeyFile path to certificate key file
type: string
name:
description: Name of certificate k8s resource
type: string
type:
description: Type source type of certificate
enum:
- secret
- configmap
type: string
required:
- certFile
- certKeyFile
- name
- type
type: object
required:
- caCert
- enable
- insecureSkipVerify
type: object
type: object
config:
properties:
api_prefix:
Expand Down
39 changes: 39 additions & 0 deletions config/samples/perses.dev_v1alpha1_perses_tls.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
apiVersion: perses.dev/v1alpha1
kind: Perses
metadata:
labels:
app.kubernetes.io/name: perses
app.kubernetes.io/instance: perses-tls-sample
app.kubernetes.io/part-of: perses-operator
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/created-by: perses-operator
name: perses-tls-sample
namespace: perses-dev
spec:
client:
tls:
enable: true
caCert:
type: secret
name: perses-certs
certFile: ca.crt
userCert:
type: secret
name: perses-certs
certFile: tls.crt
certKeyFile: tls.key

config:
database:
file:
folder: "/etc/perses/storage"
extension: "yaml"
schemas:
panels_path: "/etc/perses/cue/schemas/panels"
queries_path: "/etc/perses/cue/schemas/queries"
datasources_path: "/etc/perses/cue/schemas/datasources"
variables_path: "/etc/perses/cue/schemas/variables"
ephemeral_dashboard:
enable: false
cleanup_interval: "1s"
containerPort: 8080
54 changes: 37 additions & 17 deletions controllers/perses/configmap_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,49 +19,55 @@ package perses
import (
"context"
"fmt"
"time"

"github.com/perses/perses-operator/api/v1alpha1"
"github.com/perses/perses-operator/internal/perses/common"
"github.com/perses/perses-operator/internal/subreconciler"
logger "github.com/sirupsen/logrus"
"gopkg.in/yaml.v2"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/equality"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"

"github.com/perses/perses-operator/api/v1alpha1"
"github.com/perses/perses-operator/internal/perses/common"
"github.com/perses/perses-operator/internal/subreconciler"
)

var cmlog = logger.WithField("module", "configmap_controller")

func (r *PersesReconciler) reconcileConfigMap(ctx context.Context, req ctrl.Request) (*ctrl.Result, error) {
perses := &v1alpha1.Perses{}

if r, err := r.getLatestPerses(ctx, req, perses); subreconciler.ShouldHaltOrRequeue(r, err) {
return r, err
if result, err := r.getLatestPerses(ctx, req, perses); subreconciler.ShouldHaltOrRequeue(result, err) {
return result, err
}

configName := common.GetConfigName(perses.Name)

found := &corev1.ConfigMap{}
err := r.Get(ctx, types.NamespacedName{Name: configName, Namespace: perses.Namespace}, found)
if err != nil && apierrors.IsNotFound(err) {
cm, err := createPersesConfigMap(r, perses)
if err != nil {
cmlog.WithError(err).Error("Failed to define new ConfigMap resource for perses")
if err := r.Get(ctx, types.NamespacedName{Name: configName, Namespace: perses.Namespace}, found); err != nil {
if !apierrors.IsNotFound(err) {
cmlog.WithError(err).Error("Failed to get ConfigMap")
return subreconciler.RequeueWithError(err)
}

cm, err2 := r.createPersesConfigMap(perses)
if err2 != nil {
cmlog.WithError(err2).Error("Failed to define new ConfigMap resource for perses")

meta.SetStatusCondition(&perses.Status.Conditions, metav1.Condition{Type: common.TypeAvailablePerses,
Status: metav1.ConditionFalse, Reason: "Reconciling",
Message: fmt.Sprintf("Failed to create ConfigMap for the custom resource (%s): (%s)", perses.Name, err)})
Message: fmt.Sprintf("Failed to create ConfigMap for the custom resource (%s): (%s)", perses.Name, err2)})

if err := r.Status().Update(ctx, perses); err != nil {
if err = r.Status().Update(ctx, perses); err != nil {
cmlog.WithError(err).Error("Failed to update perses status")
return subreconciler.RequeueWithError(err)
}

return subreconciler.RequeueWithError(err)
return subreconciler.RequeueWithError(err2)
}

cmlog.Infof("Creating a new ConfigMap: ConfigMap.Namespace %s ConfigMap.Name %s", cm.Namespace, cm.Name)
Expand All @@ -70,18 +76,32 @@ func (r *PersesReconciler) reconcileConfigMap(ctx context.Context, req ctrl.Requ
return subreconciler.RequeueWithError(err)
}

return subreconciler.RequeueWithDelay(time.Minute)
return subreconciler.ContinueReconciling()
}

cm, err := r.createPersesConfigMap(perses)
if err != nil {
cmlog.WithError(err).Error("Failed to get ConfigMap")
cmlog.WithError(err).Error("Failed to define new ConfigMap resource for perses")
return subreconciler.RequeueWithError(err)
}

// call update with dry run to fill out fields that are also returned via the k8s api
if err := r.Update(ctx, cm, client.DryRunAll); err != nil {
cmlog.Error(err, "Failed to update ConfigMap with dry run")
return subreconciler.RequeueWithError(err)
}

if !equality.Semantic.DeepEqual(found, cm) {
if err := r.Update(ctx, cm); err != nil {
cmlog.Error(err, "Failed to update ConfigMap")
return subreconciler.RequeueWithError(err)
}
}

return subreconciler.ContinueReconciling()
}

func createPersesConfigMap(r *PersesReconciler, perses *v1alpha1.Perses) (*corev1.ConfigMap, error) {
func (r *PersesReconciler) createPersesConfigMap(perses *v1alpha1.Perses) (*corev1.ConfigMap, error) {
configName := common.GetConfigName(perses.Name)
ls, err := common.LabelsForPerses(r.Config.PersesImage, configName, perses.Name, perses.Spec.Metadata)

Expand Down
Loading

0 comments on commit 62864c1

Please sign in to comment.