Skip to content

Commit

Permalink
Expose API Server and Envoy endpoints and add a new Envoy condition
Browse files Browse the repository at this point in the history
Signed-off-by: Ricardo M. Oliveira <rmartine@redhat.com>
  • Loading branch information
rimolive committed Jul 5, 2024
1 parent 12c1549 commit 21e6dfe
Show file tree
Hide file tree
Showing 13 changed files with 378 additions and 4 deletions.
14 changes: 14 additions & 0 deletions api/v1alpha1/dspipeline_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -381,9 +381,23 @@ type SecretKeyValue struct {
}

type DSPAStatus struct {
// +kubebuilder:validation:Optional
Components ComponentStatus `json:"components,omitempty"`
Conditions []metav1.Condition `json:"conditions,omitempty"`
}

type ComponentStatus struct {
// +kubebuilder:validation:Optional
Envoy ComponentDetailStatus `json:"envoy,omitempty"`
APIServer ComponentDetailStatus `json:"apiServer,omitempty"`
}

type ComponentDetailStatus struct {
// +kubebuilder:validation:Optional
Url string `json:"url,omitempty"`
ExternalUrl string `json:"externalUrl,omitempty"`
}

//+kubebuilder:object:root=true
//+kubebuilder:subresource:status
//+kubebuilder:resource:shortName=dspa
Expand Down
33 changes: 33 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.

Original file line number Diff line number Diff line change
Expand Up @@ -859,6 +859,23 @@ spec:
type: object
status:
properties:
components:
properties:
apiServer:
properties:
externalUrl:
type: string
url:
type: string
type: object
envoy:
properties:
externalUrl:
type: string
url:
type: string
type: object
type: object
conditions:
items:
description: "Condition contains details for one aspect of the current
Expand Down
4 changes: 2 additions & 2 deletions config/overlays/make-deploy/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ patchesStrategicMerge:
- img_patch.yaml
images:
- name: controller
newName: quay.io/opendatahub/data-science-pipelines-operator
newTag: main
newName: quay.io/rmartine/dspo
newTag: dev
13 changes: 13 additions & 0 deletions config/samples/v2/dspa-all-fields/dspa_all_fields.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,13 @@ spec:
secretKey: somekey
# example status fields
status:
components:
envoy:
url: http://envoy.svc.cluster.local
externalUrl: https://envoy-dspa.example.com
apiServer:
url: http://envoy.svc.cluster.local
externalUrl: https://envoy-dspa.example.com
conditions:
- lastTransitionTime: '2024-03-14T22:04:25Z'
message: Database connectivity successfully verified
Expand Down Expand Up @@ -214,6 +221,12 @@ status:
reason: MinimumReplicasAvailable
status: 'True'
type: ScheduledWorkflowReady
- lastTransitionTime: '2024-03-14T22:04:30Z'
message: 'Component [ds-pipeline-metadata-envoy] is minimally available.'
observedGeneration: 3
reason: MinimumReplicasAvailable
status: 'True'
type: EnvoyReady
- lastTransitionTime: '2024-03-14T22:06:37Z'
message: All components are ready.
observedGeneration: 3
Expand Down
45 changes: 45 additions & 0 deletions controllers/apiserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package controllers

import (
"context"
"fmt"

dspav1alpha1 "github.com/opendatahub-io/data-science-pipelines-operator/api/v1alpha1"
v1 "github.com/openshift/api/route/v1"
Expand Down Expand Up @@ -86,3 +87,47 @@ func (r *DSPAReconciler) ReconcileAPIServer(ctx context.Context, dsp *dspav1alph
log.Info("Finished applying APIServer Resources")
return nil
}

func (r *DSPAReconciler) GetAPIServerServiceHostname(ctx context.Context, dsp *dspav1alpha1.DataSciencePipelinesApplication) (string, error) {
service := &corev1.Service{}
namespacedNamed := types.NamespacedName{Name: "ds-pipeline-" + dsp.Name, Namespace: dsp.Namespace}
err := r.Get(ctx, namespacedNamed, service)
if err != nil {
return "", err
}

// Loop over all Service ports, if a secured port is found
// set port and scheme to its secured ones and skip the loop
serviceScheme := ""
servicePort := ""
for i := 0; i < len(service.Spec.Ports); i++ {
servicePort = fmt.Sprintf("%d", service.Spec.Ports[i].Port)
if servicePort == "8443" || servicePort == "443" {
// If a secured port is found, just set scheme to 'https://' and skip the loop
serviceScheme = "https://"
break
} else {
serviceScheme = "http://"
}
}

return serviceScheme + service.Name + "." + service.Namespace + ".svc.cluster.local:" + servicePort, nil
}

func (r *DSPAReconciler) GetAPIServerRouteHostname(ctx context.Context, dsp *dspav1alpha1.DataSciencePipelinesApplication) (string, error) {
route := &v1.Route{}
namespacedNamed := types.NamespacedName{Name: "ds-pipeline-" + dsp.Name, Namespace: dsp.Namespace}
err := r.Get(ctx, namespacedNamed, route)
if err != nil {
return "", err
}

serviceScheme := ""
if route.Spec.TLS != nil {
serviceScheme = "https://"
} else {
serviceScheme = "http://"
}

return serviceScheme + route.Spec.Host, nil
}
56 changes: 55 additions & 1 deletion controllers/apiserver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ limitations under the License.
package controllers

import (
"github.com/opendatahub-io/data-science-pipelines-operator/controllers/config"
"testing"

"github.com/opendatahub-io/data-science-pipelines-operator/controllers/config"

dspav1alpha1 "github.com/opendatahub-io/data-science-pipelines-operator/api/v1alpha1"
"github.com/stretchr/testify/assert"
appsv1 "k8s.io/api/apps/v1"
Expand Down Expand Up @@ -120,3 +121,56 @@ func TestDontDeployAPIServer(t *testing.T) {
assert.False(t, created)
assert.Nil(t, err)
}

func TestApiServerEndpoints(t *testing.T) {
testNamespace := "testnamespace"
testDSPAName := "testdspa"
expectedAPIServerName := apiServerDefaultResourceNamePrefix + testDSPAName

// Construct DSPASpec with deployed APIServer
dspa := &dspav1alpha1.DataSciencePipelinesApplication{
Spec: dspav1alpha1.DSPASpec{
APIServer: &dspav1alpha1.APIServer{
Deploy: true,
},
MLMD: &dspav1alpha1.MLMD{},
Database: &dspav1alpha1.Database{
DisableHealthCheck: false,
MariaDB: &dspav1alpha1.MariaDB{
Deploy: true,
},
},
ObjectStorage: &dspav1alpha1.ObjectStorage{
DisableHealthCheck: false,
Minio: &dspav1alpha1.Minio{
Deploy: false,
Image: "someimage",
},
},
},
}

// Enrich DSPA with name+namespace
dspa.Name = testDSPAName
dspa.Namespace = testNamespace

// Create Context, Fake Controller and Params
ctx, params, reconciler := CreateNewTestObjects()
err := params.ExtractParams(ctx, dspa, reconciler.Client, reconciler.Log)
assert.Nil(t, err)

// Assert APIServer Deployment doesn't yet exist
deployment := &appsv1.Deployment{}
created, err := reconciler.IsResourceCreated(ctx, deployment, expectedAPIServerName, testNamespace)
assert.False(t, created)
assert.Nil(t, err)

// Run test reconciliation
err = reconciler.ReconcileAPIServer(ctx, dspa, params)
assert.Nil(t, err)

dspa_created := &dspav1alpha1.DataSciencePipelinesApplication{}
created, err = reconciler.IsResourceCreated(ctx, dspa, testDSPAName, testNamespace)
assert.NotNil(t, dspa_created.Status.Components.APIServer.Url)
assert.NotNil(t, dspa_created.Status.Components.APIServer.ExternalUrl)
}
1 change: 1 addition & 0 deletions controllers/config/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ const (
APIServerReady = "APIServerReady"
PersistenceAgentReady = "PersistenceAgentReady"
ScheduledWorkflowReady = "ScheduledWorkflowReady"
EnvoyReady = "EnvoyReady"
CrReady = "Ready"
)

Expand Down
16 changes: 16 additions & 0 deletions controllers/dspastatus/dspa_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package dspastatus

import (
"fmt"

dspav1alpha1 "github.com/opendatahub-io/data-science-pipelines-operator/api/v1alpha1"
"github.com/opendatahub-io/data-science-pipelines-operator/controllers/config"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand All @@ -20,6 +21,8 @@ type DSPAStatus interface {

SetScheduledWorkflowStatus(scheduledWorkflowReady metav1.Condition)

SetEnvoyStatus(envoyReady metav1.Condition)

GetConditions() []metav1.Condition
}

Expand All @@ -29,6 +32,7 @@ func NewDSPAStatus(dspa *dspav1alpha1.DataSciencePipelinesApplication) DSPAStatu
apiServerCondition := BuildUnknownCondition(config.APIServerReady)
persistenceAgentCondition := BuildUnknownCondition(config.PersistenceAgentReady)
scheduledWorkflowReadyCondition := BuildUnknownCondition(config.ScheduledWorkflowReady)
envoyReadyCondition := BuildUnknownCondition(config.EnvoyReady)

return &dspaStatus{
dspa: dspa,
Expand All @@ -37,6 +41,7 @@ func NewDSPAStatus(dspa *dspav1alpha1.DataSciencePipelinesApplication) DSPAStatu
apiServerReady: &apiServerCondition,
persistenceAgentReady: &persistenceAgentCondition,
scheduledWorkflowReady: &scheduledWorkflowReadyCondition,
envoyReady: &envoyReadyCondition,
}
}

Expand All @@ -47,6 +52,7 @@ type dspaStatus struct {
apiServerReady *metav1.Condition
persistenceAgentReady *metav1.Condition
scheduledWorkflowReady *metav1.Condition
envoyReady *metav1.Condition
}

func (s *dspaStatus) SetDatabaseNotReady(err error, reason string) {
Expand Down Expand Up @@ -90,13 +96,18 @@ func (s *dspaStatus) SetScheduledWorkflowStatus(scheduledWorkflowReady metav1.Co
s.scheduledWorkflowReady = &scheduledWorkflowReady
}

func (s *dspaStatus) SetEnvoyStatus(envoyReady metav1.Condition) {
s.envoyReady = &envoyReady
}

func (s *dspaStatus) GetConditions() []metav1.Condition {
componentConditions := []metav1.Condition{
*s.getDatabaseAvailableCondition(),
*s.getObjStoreAvailableCondition(),
*s.getApiServerReadyCondition(),
*s.getPersistenceAgentReadyCondition(),
*s.getScheduledWorkflowReadyCondition(),
*s.getEnvoyReadyCondition(),
}

allReady := true
Expand Down Expand Up @@ -134,6 +145,7 @@ func (s *dspaStatus) GetConditions() []metav1.Condition {
*s.apiServerReady,
*s.persistenceAgentReady,
*s.scheduledWorkflowReady,
*s.envoyReady,
crReady,
}

Expand Down Expand Up @@ -167,6 +179,10 @@ func (s *dspaStatus) getScheduledWorkflowReadyCondition() *metav1.Condition {
return s.scheduledWorkflowReady
}

func (s *dspaStatus) getEnvoyReadyCondition() *metav1.Condition {
return s.envoyReady
}

func BuildTrueCondition(conditionType string, message string) metav1.Condition {
condition := metav1.Condition{}
condition.Type = conditionType
Expand Down
Loading

0 comments on commit 21e6dfe

Please sign in to comment.