Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cmd): introduce verification phase #986

Draft
wants to merge 14 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions cli/cmd/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/keyval-dev/odigos/common/consts"

"github.com/keyval-dev/odigos/cli/cmd/resources"
"github.com/keyval-dev/odigos/cli/cmd/verification"
"github.com/keyval-dev/odigos/cli/pkg/kube"
"github.com/keyval-dev/odigos/cli/pkg/log"
"github.com/spf13/cobra"
Expand Down Expand Up @@ -81,6 +82,12 @@ This command will install k8s components that will auto-instrument your applicat
}

config := createOdigosConfigSpec()
for _, verifier := range verification.PreInstallVerifierFns(config, client) {
if err := verifier.Verify(ctx); err != nil {
fmt.Printf("\033[31mERROR\033[0m Failed to install Odigos: %s\n", err)
os.Exit(1)
}
}

fmt.Printf("Installing Odigos version %s in namespace %s ...\n", versionFlag, ns)

Expand Down
9 changes: 9 additions & 0 deletions cli/cmd/resources/applyresources.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/keyval-dev/odigos/api/odigos/v1alpha1"
"github.com/keyval-dev/odigos/cli/cmd/resources/resourcemanager"
"github.com/keyval-dev/odigos/cli/cmd/verification"
"github.com/keyval-dev/odigos/cli/pkg/kube"
"github.com/keyval-dev/odigos/cli/pkg/log"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand All @@ -15,6 +16,14 @@ import (
func ApplyResourceManagers(ctx context.Context, client *kube.Client, resourceManagers []resourcemanager.ResourceManager, prefixForLogging string) error {
for _, rm := range resourceManagers {
l := log.Print(fmt.Sprintf("%s %s", prefixForLogging, rm.Name()))

if v, ok := rm.(verification.Verifier); ok {
if err := v.Verify(ctx); err != nil {
l.Error(err)
os.Exit(1)
}
}

err := rm.InstallFromScratch(ctx)
if err != nil {
l.Error(err)
Expand Down
2 changes: 1 addition & 1 deletion cli/cmd/resources/namespace.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,4 @@ func GetOdigosNamespace(client *kube.Client, ctx context.Context) (string, error

func IsErrNoOdigosNamespaceFound(err error) bool {
return errors.Is(err, errNoOdigosNamespaceFound)
}
}
12 changes: 12 additions & 0 deletions cli/cmd/resources/odiglet.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
odigosv1 "github.com/keyval-dev/odigos/api/odigos/v1alpha1"
"github.com/keyval-dev/odigos/cli/cmd/resources/odigospro"
"github.com/keyval-dev/odigos/cli/cmd/resources/resourcemanager"
"github.com/keyval-dev/odigos/cli/cmd/verification"
"github.com/keyval-dev/odigos/cli/pkg/containers"
"github.com/keyval-dev/odigos/cli/pkg/kube"
"github.com/keyval-dev/odigos/common"
Expand Down Expand Up @@ -388,6 +389,11 @@ func ptrMountPropagationMode(p corev1.MountPropagationMode) *corev1.MountPropaga
return &p
}

var (
_ resourcemanager.ResourceManager = (*odigletResourceManager)(nil)
_ verification.Verifier = (*odigletResourceManager)(nil)
)

type odigletResourceManager struct {
client *kube.Client
ns string
Expand Down Expand Up @@ -421,5 +427,11 @@ func (a *odigletResourceManager) InstallFromScratch(ctx context.Context) error {
NewOdigletClusterRoleBinding(a.ns),
NewOdigletDaemonSet(a.ns, a.config.OdigosVersion, a.config.ImagePrefix, odigletImage, a.odigosTier),
}

return a.client.ApplyResources(ctx, a.config.ConfigVersion, resources)
}

func (a *odigletResourceManager) Verify(ctx context.Context) error {
// TODO(clavinjune): add PSP verification
return nil
}
2 changes: 1 addition & 1 deletion cli/cmd/resources/owntelemetry.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ func getOtelcolConfigMapValue() string {
},
Service: commonconf.Service{
Pipelines: map[string]commonconf.Pipeline{
"logs": commonconf.Pipeline{
"logs": {
Receivers: []string{"otlp"},
Processors: []string{"batch"},
Exporters: []string{"otlp"},
Expand Down
27 changes: 27 additions & 0 deletions cli/cmd/verification/verifier.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package verification

import (
"context"

odigosv1 "github.com/keyval-dev/odigos/api/odigos/v1alpha1"
"github.com/keyval-dev/odigos/cli/pkg/kube"
)

type Verifier interface {
Verify(context.Context) error
}

var _ Verifier = (*VerifierFunc)(nil)

type VerifierFunc func(context.Context) error

func (v VerifierFunc) Verify(ctx context.Context) error {
return v(ctx)
}

func PreInstallVerifierFns(spec odigosv1.OdigosConfigurationSpec, client *kube.Client) []Verifier {
return []Verifier{
VerifyOPAGatekeeper(spec),
VerifyNodeKernel(client),
}
}
54 changes: 54 additions & 0 deletions cli/cmd/verification/verify_node_kernel.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package verification

import (
"context"
"fmt"

"github.com/keyval-dev/odigos/cli/pkg/kube"
"github.com/moby/moby/pkg/parsers/kernel"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

corev1 "k8s.io/api/core/v1"
)

const (
OdigosMinimumKernelVersion string = "4.14"
)

var (
ErrOdigosUnsupportedKernel error = fmt.Errorf(
"verify node kernel failed, at least one node with minimum kernel version of %+q is needed",
OdigosMinimumKernelVersion)
)

func VerifyNodeKernel(client *kube.Client) VerifierFunc {
return func(ctx context.Context) error {
minimumKernelVersion, err := kernel.ParseRelease(OdigosMinimumKernelVersion)
if err != nil {
return err
}

nodeList, err := client.CoreV1().Nodes().List(ctx, metav1.ListOptions{})
if err != nil {
return err
}

return verifyNodeKernel(minimumKernelVersion, nodeList.Items)
}
}

func verifyNodeKernel(minimumKernelVersion *kernel.VersionInfo, nodes []corev1.Node) error {
for _, node := range nodes {
nodeKernelVersion, err := kernel.ParseRelease(node.Status.NodeInfo.KernelVersion)
if err != nil {
continue
}

// nodeKernelVersion is greater than minimumKernelVersion
if kernel.CompareKernelVersion(*nodeKernelVersion, *minimumKernelVersion) >= 0 {
return nil
}
}

return ErrOdigosUnsupportedKernel
}
7 changes: 7 additions & 0 deletions cli/cmd/verification/verify_node_kernel_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package verification_test

import "testing"

func TestVerifyNodeKernel(t *testing.T) {
// TODO(clavinjune): add test
}
104 changes: 104 additions & 0 deletions cli/cmd/verification/verify_node_kernel_unexported_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package verification

import (
"testing"

"github.com/moby/moby/pkg/parsers/kernel"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
)

func TestVerifyNodeKernel(t *testing.T) {
minimumKernelVersion := mustParseNodeKernelVersion(t)

tt := []struct {
_ struct{}
Name string
NodeItem []corev1.Node
ExpectedError error
}{
{
Name: "empty node",
NodeItem: []corev1.Node{},
ExpectedError: ErrOdigosUnsupportedKernel,
},
{
Name: "all unparseable kernel version",
NodeItem: []corev1.Node{
createDummyNodeWithKernelVersion(t, "abcde"),
},
ExpectedError: ErrOdigosUnsupportedKernel,
},
{
Name: "one unparseable kernel version",
NodeItem: []corev1.Node{
createDummyNodeWithKernelVersion(t, "abcde"),
createDummyNodeWithKernelVersion(t, "4.15"),
},
ExpectedError: nil,
},
{
Name: "all minimum kernel version",
NodeItem: []corev1.Node{
createDummyNodeWithKernelVersion(t, "4.14"),
createDummyNodeWithKernelVersion(t, "4.14"),
},
ExpectedError: nil,
},
{
Name: "one under minimum kernel version",
NodeItem: []corev1.Node{
createDummyNodeWithKernelVersion(t, "4.13"),
createDummyNodeWithKernelVersion(t, "4.14"),
},
ExpectedError: nil,
},
{
Name: "all under minimum kernel version",
NodeItem: []corev1.Node{
createDummyNodeWithKernelVersion(t, "4.13"),
createDummyNodeWithKernelVersion(t, "4.13"),
},
ExpectedError: ErrOdigosUnsupportedKernel,
},
}

for i := range tt {
tc := tt[i]

t.Run(tc.Name, func(t *testing.T) {
t.Parallel()
r := require.New(t)

actualErr := verifyNodeKernel(minimumKernelVersion, tc.NodeItem)
if tc.ExpectedError != nil {
r.Error(actualErr)
r.ErrorIs(tc.ExpectedError, actualErr)
} else {
r.NoError(actualErr)
}
})
}
}

func mustParseNodeKernelVersion(t *testing.T) *kernel.VersionInfo {
t.Helper()

v, err := kernel.ParseRelease(OdigosMinimumKernelVersion)
if err != nil {
panic(err.Error())
}

return v
}

func createDummyNodeWithKernelVersion(t *testing.T, kernelVersion string) corev1.Node {
t.Helper()
return corev1.Node{
Status: corev1.NodeStatus{
NodeInfo: corev1.NodeSystemInfo{
KernelVersion: kernelVersion,
},
},
}
}
14 changes: 14 additions & 0 deletions cli/cmd/verification/verify_opa_gatekeeper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package verification

import (
"context"

odigosv1 "github.com/keyval-dev/odigos/api/odigos/v1alpha1"
)

func VerifyOPAGatekeeper(spec odigosv1.OdigosConfigurationSpec) VerifierFunc {
return func(ctx context.Context) error {
// TODO(clavinjune): verify whether odigos's namespace is allow-listed or not
return nil
}
}
7 changes: 7 additions & 0 deletions cli/cmd/verification/verify_opa_gatekeeper_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package verification_test

import "testing"

func TestVerifyOPAGatekeeper(t *testing.T) {
// TODO(clavinjune): add test
}
1 change: 1 addition & 0 deletions cli/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ require (
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/moby/moby v25.0.3+incompatible // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
Expand Down
2 changes: 2 additions & 0 deletions cli/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/moby/moby v25.0.3+incompatible h1:Uzxm7JQOHBY8kZY2fa95a9kg0aTOt1cBidSZ+LXCxC4=
github.com/moby/moby v25.0.3+incompatible/go.mod h1:fDXVQ6+S340veQPv35CzDahGBmHsiclFwfEygB/TWMc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
Expand Down
Loading