Skip to content

Commit

Permalink
Merge branch 'main' into 814-separate-pods
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewazores committed Dec 20, 2024
2 parents 0d7173c + 4ce5cca commit 29cd9a5
Show file tree
Hide file tree
Showing 13 changed files with 369 additions and 86 deletions.
1 change: 0 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,6 @@ sample_app_agent: undeploy_sample_app_agent ## Deploy sample app with Cryostat A
fi; \
fi; \
$(CLUSTER_CLIENT) apply $(SAMPLE_APP_FLAGS) -f config/samples/sample-app-agent.yaml; \
$(CLUSTER_CLIENT) set env $(SAMPLE_APP_FLAGS) deployment/quarkus-cryostat-agent CRYOSTAT_AGENT_AUTHORIZATION="Bearer $(AUTH_TOKEN)"

.PHONY: undeploy_sample_app_agent_proxy
undeploy_sample_app_agent_proxy: ## Undeploy sample app with Cryostat Agent configured for TLS client auth on nginx proxy.
Expand Down
63 changes: 35 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,36 +46,14 @@ you may use the Cryostat web UI to define a Custom Target with the connection UR
This is a special value which tells Cryostat's JVM that it should connect to itself directly, without
the need to expose a JMX port over the network.

## BUILDING

### Requirements
- `go` v1.21+
- [`operator-sdk`](https://github.com/operator-framework/operator-sdk) v1.31.0
- `podman` or `docker`
- [`jq`](https://stedolan.github.io/jq/) v1.6+
- [`yq`](https://github.com/mikefarah/yq/) v4.35+
- `ginkgo` (Optional)

### Instructions
`make generate manifests manager` will trigger code/YAML generation and compile
the operator controller manager, along with running some code quality checks.

`make oci-build` will build an OCI image from the generated YAML and compiled
binary to the local registry, tagged as
`quay.io/crystatio/cryostat-operator`. This tag can be overridden by
setting the environment variables `IMAGE_NAMESPACE` and `OPERATOR_NAME`.
`IMAGE_VERSION` can also be set to override the tagged version.

`make bundle` will create an OLM bundle. This will generate a CSV, CRDs and
other manifests, and other required configurations for an OLM bundle versioned
with version `$IMAGE_VERSION` in the `bundle/` directory. `make bundle-build`
will create an OCI image of this bundle, which can then be pushed to an image
repository such as `quay.io`.
## INSTALLATION

`make catalog-build` will build an OCI image of the operator catalog (i.e. index)
with version `$IMAGE_VERSION` that includes the bundle image of the same version.
### OperatorHub

## SETUP / DEPLOYMENT
The operator's primary installation method is via [OperatorHub](https://operatorhub.io/).
A more detailed installation guide is available [here](https://cryostat.io/get-started/#install-via-operatorhub).
Installation of the Operator without OLM/OperatorHub is intended for development purposes and is
not a supported release configuration.

### Bundle Deployment

Expand Down Expand Up @@ -191,6 +169,35 @@ $ oc get -o jsonpath='{.data.token}' secret cryostat-operator-service-account-to
eyJhbGciOiJSUzI1NiIsImtpZCI6IkhYZC13eDdGVGwyQzdGNVpZVndScEZ2VmRxWTlzbnBUUG9HRkJpejJkV3cifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImNyeW9zdGF0LW9wZXJhdG9yLXNlcnZpY2UtYWNjb3VudC10b2tlbi03dHQ3bCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJjcnlvc3RhdC1vcGVyYXRvci1zZXJ2aWNlLWFjY291bnQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI2OTJhYThjNy0wODFlLTRhNTEtOTM1NS1iZTNlYWE4ZjlmYTYiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGVmYXVsdDpjcnlvc3RhdC1vcGVyYXRvci1zZXJ2aWNlLWFjY291bnQifQ.M7C1V0bN3aILBflO7TTOTikw7wLGRJ79-OkCDQIZbu71QLdX05jyCxxtlH32lr8jz6HwxfXXweh3ifG_2lbe7_TbM8jxmBoMdLuc4Q_akpmA-GQuDPrRxfHGJApYGQ6CVug3KHSrQwj2M4QrSUz7FoeQGaOH9BnWj1TrHGmOZUPJ6u7JSu2OwoLBda6rF-M4Bl72DmkyMAzikreRgPEk4D7gTCY0yNvsQDuUAwpFwmEukRC2WyTAVTpKPgThZUk-UJ-dXufbhAcqIRt6jeCQ19_Bo0zXc_ELgQydxuTack1ndT3HwRmwwNuZDFv-G3Y0YdjfRh00DqEvSn9ynZzwueDCJUxlHdznytfUWk9PA712JENpFC7b-zSHnjymIcFeUd8s_Zq_-JKrDIPnH0oZDRO_MUpKEC7Jz_8SeFJHLLGfBZt_aP4VwQHEUThiFQPwrfbd8tppUG2TKcekPScKcauy-BCI52odBzapP6meilMQVrmRtu7i30L05vgQiST_OsmSP8CuKW13a-leCCtN_aNQGqlWvLhP81H95ui-PvMzwMIDlfDZ03ycuYg4R4eUG3nUq7-42wrSdFLo8gm9wsl7y1ZRMQwHR1DCVBbHYS0iFOcmwto2Ejlrgvn3Cs0pDS7pDVoFkH2FsTopEw3jXtnkMs15mSmBnHz-UjF-l08
```

## BUILDING

### Requirements
- `go` v1.21+
- [`operator-sdk`](https://github.com/operator-framework/operator-sdk) v1.31.0
- `podman` or `docker`
- [`jq`](https://stedolan.github.io/jq/) v1.6+
- [`yq`](https://github.com/mikefarah/yq/) v4.35+
- `ginkgo` (Optional)

### Instructions
`make generate manifests manager` will trigger code/YAML generation and compile
the operator controller manager, along with running some code quality checks.

`make oci-build` will build an OCI image from the generated YAML and compiled
binary to the local registry, tagged as
`quay.io/crystatio/cryostat-operator`. This tag can be overridden by
setting the environment variables `IMAGE_NAMESPACE` and `OPERATOR_NAME`.
`IMAGE_VERSION` can also be set to override the tagged version.

`make bundle` will create an OLM bundle. This will generate a CSV, CRDs and
other manifests, and other required configurations for an OLM bundle versioned
with version `$IMAGE_VERSION` in the `bundle/` directory. `make bundle-build`
will create an OCI image of this bundle, which can then be pushed to an image
repository such as `quay.io`.

`make catalog-build` will build an OCI image of the operator catalog (i.e. index)
with version `$IMAGE_VERSION` that includes the bundle image of the same version.

## DEVELOPMENT

An invocation like
Expand Down
38 changes: 35 additions & 3 deletions config/samples/sample-app-agent.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,14 @@ spec:
labels:
app: quarkus-cryostat-agent
spec:
serviceAccountName: quarkus-cryostat-agent-serviceaccount
containers:
- env:
- name: CRYOSTAT_AGENT_APP_NAME
value: agent-test
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
- name: NAMESPACE
valueFrom:
fieldRef:
Expand All @@ -35,12 +39,11 @@ spec:
fieldPath: status.podIP
- name: CRYOSTAT_AGENT_CALLBACK
value: http://$(POD_IP):9977
- name: CRYOSTAT_AGENT_AUTHORIZATION
value: Bearer abcd1234
- name: JAVA_OPTS_APPEND
value: |-
-Dquarkus.http.host=0.0.0.0
-Djava.util.logging.manager=org.jboss.logmanager.LogManager
-Dio.cryostat.agent.shaded.org.slf4j.simpleLogger.defaultLogLevel=info
-Dcom.sun.management.jmxremote.port=9097
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
Expand Down Expand Up @@ -102,3 +105,32 @@ spec:
port: 10010
protocol: TCP
targetPort: 10010
---
kind: ServiceAccount
apiVersion: v1
metadata:
name: quarkus-cryostat-agent-serviceaccount
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: quarkus-cryostat-agent-role
rules:
- apiGroups:
- ""
verbs:
- create
resources:
- pods/exec
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: quarkus-cryostat-agent-role-binding
subjects:
- kind: ServiceAccount
name: quarkus-cryostat-agent-serviceaccount
roleRef:
kind: Role
name: quarkus-cryostat-agent-role
apiGroup: rbac.authorization.k8s.io
25 changes: 22 additions & 3 deletions internal/controllers/certmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/cryostatio/cryostat-operator/internal/controllers/common"
resources "github.com/cryostatio/cryostat-operator/internal/controllers/common/resource_definitions"
"github.com/cryostatio/cryostat-operator/internal/controllers/model"
"github.com/google/go-cmp/cmp"
corev1 "k8s.io/api/core/v1"
kerrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
Expand Down Expand Up @@ -414,25 +415,43 @@ func (r *Reconciler) reconcileAgentCertificate(ctx context.Context, cert *certv1
return nil
}

var errCertificateModified error = errors.New("certificate has been modified")

func (r *Reconciler) createOrUpdateCertificate(ctx context.Context, cert *certv1.Certificate, owner metav1.Object) error {
certSpec := cert.Spec.DeepCopy()
certCopy := cert.DeepCopy()
op, err := controllerutil.CreateOrUpdate(ctx, r.Client, cert, func() error {
if owner != nil {
if err := controllerutil.SetControllerReference(owner, cert, r.Scheme); err != nil {
return err
}
}
// Update Certificate spec
cert.Spec = *certSpec

if cert.CreationTimestamp.IsZero() {
cert.Spec = certCopy.Spec
} else if !cmp.Equal(cert.Spec, certCopy.Spec) {
return errCertificateModified
}

return nil
})
if err != nil {
if err == errCertificateModified {
return r.recreateCertificate(ctx, certCopy, owner)
}
return err
}
r.Log.Info(fmt.Sprintf("Certificate %s", op), "name", cert.Name, "namespace", cert.Namespace)
return nil
}

func (r *Reconciler) recreateCertificate(ctx context.Context, cert *certv1.Certificate, owner metav1.Object) error {
err := r.deleteCertWithSecret(ctx, cert)
if err != nil {
return err
}
return r.createOrUpdateCertificate(ctx, cert, owner)
}

func newKeystoreSecret(cr *model.CryostatInstance) *corev1.Secret {
return &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Expand Down
60 changes: 60 additions & 0 deletions internal/controllers/reconciler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1842,6 +1842,66 @@ func (c *controllerTest) commonTests() {
t.expectCertificates()
})
})
Context("with modified certificates", func() {
var oldCerts []*certv1.Certificate
BeforeEach(func() {
t.objs = append(t.objs, t.NewCryostat().Object, t.OtherCAIssuer())
oldCerts = []*certv1.Certificate{
t.OtherCACert(),
t.OtherAgentProxyCert(),
t.OtherCryostatCert(),
t.OtherReportsCert(),
}
// Add an annotation for each cert, the test will assert that
// the annotation is gone.
for i, cert := range oldCerts {
metav1.SetMetaDataAnnotation(&oldCerts[i].ObjectMeta, "bad", "cert")
t.objs = append(t.objs, cert)
}
})
JustBeforeEach(func() {
cr := t.getCryostatInstance()
for _, cert := range oldCerts {
// Make the old certs owned by the Cryostat CR
err := controllerutil.SetControllerReference(cr.Object, cert, t.Client.Scheme())
Expect(err).ToNot(HaveOccurred())
err = t.Client.Update(context.Background(), cert)
Expect(err).ToNot(HaveOccurred())
}
t.reconcileCryostatFully()
})
It("should recreate certificates", func() {
t.expectCertificates()
})
})
Context("with a modified certificate TLS CommonName", func() {
var oldCerts []*certv1.Certificate
BeforeEach(func() {
oldCerts = []*certv1.Certificate{
t.NewCryostatCert(),
t.NewReportsCert(),
t.NewAgentProxyCert(),
}
t.objs = append(t.objs, t.NewCryostat().Object, t.OtherCAIssuer())
for _, cert := range oldCerts {
t.objs = append(t.objs, cert)
}
})
JustBeforeEach(func() {
cr := t.getCryostatInstance()
for _, cert := range oldCerts {
// Make the old certs owned by the Cryostat CR
err := controllerutil.SetControllerReference(cr.Object, cert, t.Client.Scheme())
Expect(err).ToNot(HaveOccurred())
err = t.Client.Update(context.Background(), cert)
Expect(err).ToNot(HaveOccurred())
}
t.reconcileCryostatFully()
})
It("should recreate certificates", func() {
t.expectCertificates()
})
})

Context("reconciling a multi-namespace request", func() {
targetNamespaces := []string{"multi-test-one", "multi-test-two"}
Expand Down
14 changes: 10 additions & 4 deletions internal/controllers/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,13 @@ func (r *Reconciler) reconcileCoreService(ctx context.Context, cr *model.Cryosta
"app": cr.Name,
"component": "cryostat",
}
appProtocol := "http"
svc.Spec.Ports = []corev1.ServicePort{
{
Name: "http",
Port: *config.HTTPPort,
TargetPort: intstr.IntOrString{IntVal: constants.AuthProxyHttpContainerPort},
Name: "http",
Port: *config.HTTPPort,
TargetPort: intstr.IntOrString{IntVal: constants.AuthProxyHttpContainerPort},
AppProtocol: &appProtocol,
},
}
return nil
Expand Down Expand Up @@ -311,7 +313,7 @@ func configureAgentService(cr *model.CryostatInstance) *operatorv1beta2.AgentSer
}

// Apply common service defaults
configureService(&config.ServiceConfig, cr.Name, "cryostat")
configureService(&config.ServiceConfig, cr.Name, "cryostat-agent-gateway")

// Apply default HTTP port if not provided
if config.HTTPPort == nil {
Expand All @@ -337,6 +339,10 @@ func configureService(config *operatorv1beta2.ServiceConfig, appLabel string, co
// Add required labels, overriding any user-specified labels with the same keys
config.Labels["app"] = appLabel
config.Labels["component"] = componentLabel
config.Labels["app.kubernetes.io/name"] = "cryostat"
config.Labels["app.kubernetes.io/instance"] = appLabel
config.Labels["app.kubernetes.io/component"] = componentLabel
config.Labels["app.kubernetes.io/part-of"] = "cryostat"
}

func (r *Reconciler) createOrUpdateService(ctx context.Context, svc *corev1.Service, owner metav1.Object,
Expand Down
Loading

0 comments on commit 29cd9a5

Please sign in to comment.