Skip to content

Commit

Permalink
Add support for changing reported application name (#265)
Browse files Browse the repository at this point in the history
This PR adds the ability to change the application name before
delivering data to the chosen destination
  • Loading branch information
edeNFed authored Jun 29, 2023
1 parent 7c0df00 commit ac18148
Show file tree
Hide file tree
Showing 9 changed files with 89 additions and 105 deletions.
2 changes: 1 addition & 1 deletion .goreleaser.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
project_name: odigos
before:
hooks:
- sh -c 'cd frontend/webapp && yarn build'
- sh -c 'cd frontend/webapp && yarn install && yarn build'
builds:
- env:
- CGO_ENABLED=0
Expand Down
3 changes: 2 additions & 1 deletion autoscaler/controllers/datacollection/daemonset.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package datacollection
import (
"context"
"fmt"

"github.com/keyval-dev/odigos/autoscaler/controllers/datacollection/custom"
"k8s.io/apimachinery/pkg/util/intstr"

Expand All @@ -21,7 +22,7 @@ import (
const (
collectorLabel = "odigos.io/data-collection"
containerName = "data-collection"
containerImage = "keyval/otel-collector-contrib:v0.3"
containerImage = "keyval/otel-collector-contrib:v0.4"
containerCommand = "/otelcontribcol"
confDir = "/conf"
configHashAnnotation = "odigos.io/config-hash"
Expand Down
3 changes: 2 additions & 1 deletion autoscaler/controllers/gateway/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package gateway
import (
"context"
"fmt"

odigosv1 "github.com/keyval-dev/odigos/api/odigos/v1alpha1"
"github.com/keyval-dev/odigos/autoscaler/controllers/common"
appsv1 "k8s.io/api/apps/v1"
Expand All @@ -18,7 +19,7 @@ import (

const (
containerName = "gateway"
containerImage = "keyval/otel-collector-contrib:v0.3"
containerImage = "keyval/otel-collector-contrib:v0.4"
containerCommand = "/otelcontribcol"
confDir = "/conf"
configHashAnnotation = "odigos.io/config-hash"
Expand Down
20 changes: 1 addition & 19 deletions cli/cmd/resources/autoscaler.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package resources

import (
"fmt"

"github.com/keyval-dev/odigos/cli/pkg/labels"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -378,25 +379,6 @@ func NewAutoscalerDeployment(version string) *appsv1.Deployment {
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: "apis-rbac-proxy",
Image: "gcr.io/kubebuilder/kube-rbac-proxy:v0.11.0",
Args: []string{
"--secure-listen-address=0.0.0.0:8443",
"--upstream=http://127.0.0.1:8080/",
"--logtostderr=true",
"--v=0",
},
Ports: []corev1.ContainerPort{
{
Name: "https",
HostPort: 0,
ContainerPort: 8443,
Protocol: "TCP",
},
},
Resources: corev1.ResourceRequirements{},
},
{
Name: "manager",
Image: fmt.Sprintf("%s:%s", autoscalerImage, version),
Expand Down
3 changes: 3 additions & 0 deletions cli/cmd/resources/datacollection.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ func NewDataCollectionClusterRole() *rbacv1.ClusterRole {
APIGroups: []string{"apps"},
Resources: []string{
"replicasets",
"deployments",
"daemonsets",
"statefulsets",
},
},
},
Expand Down
19 changes: 0 additions & 19 deletions cli/cmd/resources/instrumentor.go
Original file line number Diff line number Diff line change
Expand Up @@ -420,25 +420,6 @@ func NewInstrumentorDeployment(version string, telemetryEnabled bool, sidecarIns
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: "apis-rbac-proxy",
Image: "gcr.io/kubebuilder/kube-rbac-proxy:v0.11.0",
Args: []string{
"--secure-listen-address=0.0.0.0:8443",
"--upstream=http://127.0.0.1:8080/",
"--logtostderr=true",
"--v=0",
},
Ports: []corev1.ContainerPort{
{
Name: "https",
HostPort: 0,
ContainerPort: 8443,
Protocol: "TCP",
},
},
Resources: corev1.ResourceRequirements{},
},
{
Name: "manager",
Image: fmt.Sprintf("%s:%s", instrumentorImage, version),
Expand Down
20 changes: 1 addition & 19 deletions cli/cmd/resources/scheduler.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package resources

import (
"fmt"

"github.com/keyval-dev/odigos/cli/pkg/labels"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -208,25 +209,6 @@ func NewSchedulerDeployment(version string) *appsv1.Deployment {
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: "apis-rbac-proxy",
Image: "gcr.io/kubebuilder/kube-rbac-proxy:v0.11.0",
Args: []string{
"--secure-listen-address=0.0.0.0:8443",
"--upstream=http://127.0.0.1:8080/",
"--logtostderr=true",
"--v=0",
},
Ports: []corev1.ContainerPort{
{
Name: "https",
HostPort: 0,
ContainerPort: 8443,
Protocol: "TCP",
},
},
Resources: corev1.ResourceRequirements{},
},
{
Name: "manager",
Image: fmt.Sprintf("%s:%s", schedulerImage, version),
Expand Down
38 changes: 12 additions & 26 deletions ui/pages/api/source/[namespace]/[kind]/[name].ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ export default async function UpdateSource(
const k8sApi = kc.makeApiClient(k8s.AppsV1Api);
switch (req.query.kind.toLowerCase()) {
case "deployment":
await updateDeployment(k8sApi, req.query.namespace as string, req.query.name as string, req.body.enabled);
await updateDeployment(k8sApi, req.query.namespace as string, req.query.name as string, req.body.enabled, req.body.reportedName);
break;
case "statefulset":
await updateStatefulSet(k8sApi, req.query.namespace as string, req.query.name as string, req.body.enabled);
await updateStatefulSet(k8sApi, req.query.namespace as string, req.query.name as string, req.body.enabled, req.body.reportedName);
break;
case "daemonset":
await updateDaemonSet(k8sApi, req.query.namespace as string, req.query.name as string, req.body.enabled);
await updateDaemonSet(k8sApi, req.query.namespace as string, req.query.name as string, req.body.enabled, req.body.reportedName);
break;
default:
return res.status(400).json({
Expand All @@ -34,45 +34,31 @@ export default async function UpdateSource(
return res.status(200).json({
message: "success",
});

// const resp: any = await k8sApi.getNamespacedCustomObject(
// "odigos.io",
// "v1alpha1",
// req.query.namespace as string,
// "instrumentedapplications",
// `${req.query.kind}-${req.query.name}`
// );

// resp.body.spec.enabled = req.body.enabled;
// await k8sApi.replaceNamespacedCustomObject(
// "odigos.io",
// "v1alpha1",
// req.query.namespace as string,
// "instrumentedapplications",
// `${req.query.kind}-${req.query.name}`,
// resp.body
// );

// res.status(200).json({ sucess: true });
}

async function updateDeployment(k8sApi: k8s.AppsV1Api, namespace: string, name: string, enabled: boolean) {
async function updateDeployment(k8sApi: k8s.AppsV1Api, namespace: string, name: string, enabled: boolean, reportedName: string) {
const resp: any = await k8sApi.readNamespacedDeployment(name, namespace);
resp.body.metadata.labels = resp.body.metadata.labels || {};
resp.body.metadata.labels["odigos-instrumentation"] = enabled ? "enabled" : "disabled";
resp.body.metadata.annotations = resp.body.metadata.annotations || {};
resp.body.metadata.annotations["odigos.io/reported-name"] = reportedName;
await k8sApi.replaceNamespacedDeployment(name, namespace, resp.body);
}

async function updateStatefulSet(k8sApi: k8s.AppsV1Api, namespace: string, name: string, enabled: boolean) {
async function updateStatefulSet(k8sApi: k8s.AppsV1Api, namespace: string, name: string, enabled: boolean, reportedName: string) {
const resp: any = await k8sApi.readNamespacedStatefulSet(name, namespace);
resp.body.metadata.labels = resp.body.metadata.labels || {};
resp.body.metadata.labels["odigos-instrumentation"] = enabled ? "enabled" : "disabled";
resp.body.metadata.annotations = resp.body.metadata.annotations || {};
resp.body.metadata.annotations["odigos.io/reported-name"] = reportedName;
await k8sApi.replaceNamespacedStatefulSet(name, namespace, resp.body);
}

async function updateDaemonSet(k8sApi: k8s.AppsV1Api, namespace: string, name: string, enabled: boolean) {
async function updateDaemonSet(k8sApi: k8s.AppsV1Api, namespace: string, name: string, enabled: boolean, reportedName: string) {
const resp: any = await k8sApi.readNamespacedDaemonSet(name, namespace);
resp.body.metadata.labels = resp.body.metadata.labels || {};
resp.body.metadata.labels["odigos-instrumentation"] = enabled ? "enabled" : "disabled";
resp.body.metadata.annotations = resp.body.metadata.annotations || {};
resp.body.metadata.annotations["odigos.io/reported-name"] = reportedName;
await k8sApi.replaceNamespacedDaemonSet(name, namespace, resp.body);
}
86 changes: 67 additions & 19 deletions ui/pages/source/[namespace]/[kind]/[name].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ import { useState } from "react";

interface EditAppProps {
enabled: boolean;
reportedName: string;
}

const EditAppPage: NextPage<EditAppProps> = ({ enabled }: EditAppProps) => {
const EditAppPage: NextPage<EditAppProps> = ({ enabled, reportedName }: EditAppProps) => {
const router = useRouter();
const { name, kind, namespace } = router.query;
const [isEnabled, setIsEnabled] = useState(enabled);
const [updatedReportedName, setUpdatedReportedName] = useState(reportedName);
const updateApp = async () => {
const resp = await fetch(`/api/source/${namespace}/${kind}/${name}`, {
method: "POST",
Expand All @@ -19,6 +21,7 @@ const EditAppPage: NextPage<EditAppProps> = ({ enabled }: EditAppProps) => {
},
body: JSON.stringify({
enabled: isEnabled,
reportedName: updatedReportedName,
}),
});
if (resp.ok) {
Expand All @@ -28,9 +31,33 @@ const EditAppPage: NextPage<EditAppProps> = ({ enabled }: EditAppProps) => {
return (
<div className="flex flex-col w-fit">
<div className="text-4xl font-medium">{name}</div>
<div>
<label className="block mt-6">
<span className="text-gray-700">Reported Name</span>
<input
name="reportedName"
type="text"
className="
mt-1
block
w-full
rounded-md
border-gray-300
shadow-sm
focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50
"
placeholder=""
required
defaultValue={reportedName}
onChange={(e) => {
setUpdatedReportedName(e.target.value);
}}
/>
</label>
</div>
<label
htmlFor="default-toggle"
className="mt-12 inline-flex relative items-center cursor-pointer"
className="mt-6 inline-flex relative items-center cursor-pointer"
>
<input
type="checkbox"
Expand All @@ -47,7 +74,7 @@ const EditAppPage: NextPage<EditAppProps> = ({ enabled }: EditAppProps) => {
</label>
<button
type="submit"
disabled={isEnabled === enabled}
disabled={isEnabled === enabled && reportedName === updatedReportedName}
onClick={updateApp}
className="mt-4 disabled:cursor-not-allowed disabled:hover:bg-gray-500 disabled:bg-gray-500 text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 mr-2 mb-2 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800"
>
Expand All @@ -62,16 +89,19 @@ export const getServerSideProps = async ({ query }: any) => {
const kc = new k8s.KubeConfig();
kc.loadFromDefault();
const k8sApi = kc.makeApiClient(k8s.AppsV1Api);
const reportedNameAnootation = "odigos.io/reported-name";
var obj = null;
var instrumented = false;
var reportedName = name;
switch (kind) {
case "deployment":
instrumented = await isDeploymentInstrumented(name, namespace, kc);
obj = await getDeployment(name, namespace, kc);
break;
case "statefulset":
instrumented = await isStatefulSetInstrumented(name, namespace, kc);
obj = await getStatefulSet(name, namespace, kc);
break;
case "daemonset":
instrumented = await isDaemonSetInstrumented(name, namespace, kc);
obj = await getDaemonSet(name, namespace, kc);
break;
default:
return {
Expand All @@ -82,45 +112,63 @@ export const getServerSideProps = async ({ query }: any) => {
};
}

if (!obj) {
return {
redirect: {
destination: "/",
permanent: false,
},
}
}

if (obj?.metadata?.annotations?.[reportedNameAnootation]) {
reportedName = obj?.metadata?.annotations?.[reportedNameAnootation];
}

instrumented = isLabeled(obj?.metadata?.labels);
if (!instrumented) {
instrumented = await isNamespaceLabeled(namespace, kc);
}

return {
props: {
enabled: instrumented,
reportedName: reportedName,
},
};
};

async function isDeploymentInstrumented(name: string, namespace: string, kc: k8s.KubeConfig) {
async function getDeployment(name: string, namespace: string, kc: k8s.KubeConfig) {
const kubeClient = kc.makeApiClient(k8s.AppsV1Api);
const resp = await kubeClient.readNamespacedDeployment(name, namespace);
if (!resp || !resp.body.metadata) {
return false;
if (!resp) {
return null;
}

return isLabeled(resp.body.metadata.labels) || await isNamespaceLabeled(namespace, kc);
return resp.body;
}

async function isStatefulSetInstrumented(name: string, namespace: string, kc: k8s.KubeConfig) {
async function getStatefulSet(name: string, namespace: string, kc: k8s.KubeConfig) {
const kubeClient = kc.makeApiClient(k8s.AppsV1Api);
const resp = await kubeClient.readNamespacedStatefulSet(name, namespace);
if (!resp || !resp.body.metadata) {
return false;
if (!resp) {
return null;
}

return isLabeled(resp.body.metadata.labels) || await isNamespaceLabeled(namespace, kc);
return resp.body;
}

async function isDaemonSetInstrumented(name: string, namespace: string, kc: k8s.KubeConfig) {
async function getDaemonSet(name: string, namespace: string, kc: k8s.KubeConfig) {
const kubeClient = kc.makeApiClient(k8s.AppsV1Api);
const resp = await kubeClient.readNamespacedDaemonSet(name, namespace);
if (!resp || !resp.body.metadata) {
return false;
if (!resp) {
return null;
}

return isLabeled(resp.body.metadata.labels) || await isNamespaceLabeled(namespace, kc);
return resp.body;
}

function isLabeled(labels: any): boolean {
console.log(labels);
return labels && labels["odigos-instrumentation"] === "enabled";
}

Expand Down

0 comments on commit ac18148

Please sign in to comment.