Skip to content

Commit

Permalink
Track deployment status
Browse files Browse the repository at this point in the history
Closes #138
  • Loading branch information
eromanova committed Aug 15, 2024
1 parent 5fcbcbe commit 1b25df4
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 1 deletion.
8 changes: 8 additions & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"flag"
"os"

"github.com/Mirantis/hmc/internal/telemetry"
// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
// to ensure that exec-entrypoint and run can make use of them.
_ "k8s.io/client-go/plugin/pkg/client/auth"
Expand Down Expand Up @@ -193,6 +194,13 @@ func main() {
os.Exit(1)
}

if err = mgr.Add(&telemetry.Tracker{
Client: mgr.GetClient(),
}); err != nil {
setupLog.Error(err, "unable to create telemetry tracker")
os.Exit(1)
}

//+kubebuilder:scaffold:builder

if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
Expand Down
15 changes: 14 additions & 1 deletion internal/telemetry/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ import (
)

const (
deploymentCreateEvent = "deployment-create"
deploymentCreateEvent = "deployment-create"
deploymentHeartbeatEvent = "deployment-heartbeat"
)

func TrackDeploymentCreate(id, deploymentID, template string, dryRun bool) error {
Expand All @@ -34,6 +35,18 @@ func TrackDeploymentCreate(id, deploymentID, template string, dryRun bool) error
return TrackEvent(deploymentCreateEvent, id, props)
}

func TrackDeploymentHeartbeat(id, deploymentID, clusterID, template, templateVersion, targetInfrastructure string) error {
props := map[string]interface{}{
"hmcVersion": build.Version,
"deploymentID": deploymentID,
"clusterID": clusterID,
"targetInfrastructure": targetInfrastructure,
"template": template,
"templateVersion": templateVersion,
}
return TrackEvent(deploymentHeartbeatEvent, id, props)
}

func TrackEvent(name, id string, properties map[string]interface{}) error {
if client == nil {
return nil
Expand Down
96 changes: 96 additions & 0 deletions internal/telemetry/tracker.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// Copyright 2024
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package telemetry

import (
"context"
"errors"
"fmt"
"strings"
"time"

"github.com/Mirantis/hmc/api/v1alpha1"
"k8s.io/apimachinery/pkg/types"
crclient "sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log"
)

type Tracker struct {
crclient.Client
}

const interval = 10 * time.Minute

func (t *Tracker) Start(ctx context.Context) error {
timer := time.NewTimer(0)
for {
select {
case <-timer.C:
t.Tick(ctx)
timer.Reset(interval)
case <-ctx.Done():
return nil
}
}
}

func (t *Tracker) Tick(ctx context.Context) {
l := log.FromContext(ctx).WithName("telemetry tracker")

logger := l.WithValues("event", deploymentHeartbeatEvent)
err := t.trackDeploymentHeartbeat(ctx)
if err != nil {
logger.Error(err, "failed to track an event")
} else {
logger.Info("successfully tracked an event")
}
}

func (t *Tracker) trackDeploymentHeartbeat(ctx context.Context) error {
mgmt := &v1alpha1.Management{}
mgmtRef := types.NamespacedName{Namespace: v1alpha1.ManagementNamespace, Name: v1alpha1.ManagementName}
err := t.Get(ctx, mgmtRef, mgmt)
if err != nil {
return err
}

deployments := &v1alpha1.DeploymentList{}
err = t.Client.List(ctx, deployments, &crclient.ListOptions{})
if err != nil {
return err
}

var errs error
for _, deployment := range deployments.Items {
template := &v1alpha1.Template{}
templateRef := types.NamespacedName{Name: deployment.Spec.Template, Namespace: v1alpha1.TemplatesNamespace}
err = t.Get(ctx, templateRef, template)
if err != nil {
errs = errors.Join(errs, fmt.Errorf("failed to get template %s/%s", v1alpha1.TemplatesNamespace, deployment.Spec.Template))
continue
}

// TODO: get k0s cluster ID once it's exposed in k0smotron API
clusterID := ""
targetInfrastructure := strings.Join(template.Status.Providers.InfrastructureProviders, ",")
templateVersion := template.Spec.Helm.ChartVersion
err = TrackDeploymentHeartbeat(string(mgmt.UID), string(deployment.UID), clusterID, deployment.Spec.Template, templateVersion, targetInfrastructure)
if err != nil {
errs = errors.Join(errs, fmt.Errorf("failed to track the heartbeat of the deployment %s/%s", deployment.Namespace, deployment.Name))
continue
}
}
return errs
}

0 comments on commit 1b25df4

Please sign in to comment.