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

Uses the new parsing structure for RBAC parsing #3206

Merged
merged 16 commits into from
Sep 16, 2024
Merged
42 changes: 41 additions & 1 deletion apis/v1beta1/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,11 @@ import (
"github.com/go-logr/logr"
"gopkg.in/yaml.v3"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"

"github.com/open-telemetry/opentelemetry-operator/internal/components"
"github.com/open-telemetry/opentelemetry-operator/internal/components/exporters"
"github.com/open-telemetry/opentelemetry-operator/internal/components/processors"
"github.com/open-telemetry/opentelemetry-operator/internal/components/receivers"
)

Expand Down Expand Up @@ -139,9 +141,43 @@ type Config struct {
Service Service `json:"service" yaml:"service"`
}

// getRbacRulesForComponentKinds gets the RBAC Rules for the given ComponentKind(s).
func (c *Config) getRbacRulesForComponentKinds(logger logr.Logger, componentKinds ...ComponentKind) ([]rbacv1.PolicyRule, error) {
var rules []rbacv1.PolicyRule
enabledComponents := c.GetEnabledComponents()
for _, componentKind := range componentKinds {
var retriever components.ParserRetriever
var cfg AnyConfig
switch componentKind {
case KindReceiver:
retriever = receivers.ReceiverFor
cfg = c.Receivers
case KindExporter:
retriever = exporters.ParserFor
cfg = c.Exporters
case KindProcessor:
retriever = processors.ProcessorFor
if c.Processors == nil {
cfg = AnyConfig{}
} else {
cfg = *c.Processors
}
}
for componentName := range enabledComponents[componentKind] {
// TODO: Clean up the naming here and make it simpler to use a retriever.
parser := retriever(componentName)
if parsedRules, err := parser.GetRBACRules(logger, cfg.Object[componentName]); err != nil {
return nil, err
} else {
rules = append(rules, parsedRules...)
}
}
}
return rules, nil
}

// getPortsForComponentKinds gets the ports for the given ComponentKind(s).
func (c *Config) getPortsForComponentKinds(logger logr.Logger, componentKinds ...ComponentKind) ([]corev1.ServicePort, error) {

var ports []corev1.ServicePort
enabledComponents := c.GetEnabledComponents()
for _, componentKind := range componentKinds {
Expand Down Expand Up @@ -187,6 +223,10 @@ func (c *Config) GetAllPorts(logger logr.Logger) ([]corev1.ServicePort, error) {
return c.getPortsForComponentKinds(logger, KindReceiver, KindExporter)
}

func (c *Config) GetAllRbacRules(logger logr.Logger) ([]rbacv1.PolicyRule, error) {
return c.getRbacRulesForComponentKinds(logger, KindReceiver, KindExporter, KindProcessor)
}

// Yaml encodes the current object and returns it as a string.
func (c *Config) Yaml() (string, error) {
var buf bytes.Buffer
Expand Down
122 changes: 122 additions & 0 deletions internal/components/builder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
// Copyright The OpenTelemetry Authors
//
// 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 components

import (
"fmt"

corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/util/intstr"

"github.com/open-telemetry/opentelemetry-operator/internal/naming"
)

type ParserOption[T any] func(*Option[T])

type Option[T any] struct {
jaronoff97 marked this conversation as resolved.
Show resolved Hide resolved
protocol corev1.Protocol
appProtocol *string
targetPort intstr.IntOrString
nodePort int32
name string
port int32
portParser PortParser[T]
rbacGen RBACRuleGenerator[T]
}

func NewEmptyOption[T any]() *Option[T] {
jaronoff97 marked this conversation as resolved.
Show resolved Hide resolved
return &Option[T]{}
}

func (o *Option[T]) Apply(opts ...ParserOption[T]) {
for _, opt := range opts {
opt(o)
}
}

func (o *Option[T]) GetServicePort() *corev1.ServicePort {
return &corev1.ServicePort{
Name: naming.PortName(o.name, o.port),
Port: o.port,
Protocol: o.protocol,
AppProtocol: o.appProtocol,
TargetPort: o.targetPort,
NodePort: o.nodePort,
}
}

type Builder[T any] []ParserOption[T]

func NewBuilder[T any]() Builder[T] {
return []ParserOption[T]{}
}

func (b Builder[T]) WithProtocol(protocol corev1.Protocol) Builder[T] {
return append(b, func(o *Option[T]) {
o.protocol = protocol
})
}
func (b Builder[T]) WithAppProtocol(appProtocol *string) Builder[T] {
return append(b, func(o *Option[T]) {
o.appProtocol = appProtocol
})
}
func (b Builder[T]) WithTargetPort(targetPort int32) Builder[T] {
return append(b, func(o *Option[T]) {
o.targetPort = intstr.FromInt32(targetPort)
})
}
func (b Builder[T]) WithNodePort(nodePort int32) Builder[T] {
return append(b, func(o *Option[T]) {
o.nodePort = nodePort
})
}
func (b Builder[T]) WithName(name string) Builder[T] {
return append(b, func(o *Option[T]) {
o.name = name
})
}
func (b Builder[T]) WithPort(port int32) Builder[T] {
return append(b, func(o *Option[T]) {
o.port = port
})
}
func (b Builder[T]) WithPortParser(portParser PortParser[T]) Builder[T] {
return append(b, func(o *Option[T]) {
o.portParser = portParser
})
}
func (b Builder[T]) WithRbacGen(rbacGen RBACRuleGenerator[T]) Builder[T] {
return append(b, func(o *Option[T]) {
o.rbacGen = rbacGen
})
}

func (b Builder[T]) Build() (*GenericParser[T], error) {
o := NewEmptyOption[T]()
o.Apply(b...)
if len(o.name) == 0 {
return nil, fmt.Errorf("invalid option struct, no name specified")
}
return &GenericParser[T]{name: o.name, portParser: o.portParser, rbacGen: o.rbacGen, option: o}, nil
}

func (b Builder[T]) MustBuild() *GenericParser[T] {
if p, err := b.Build(); err != nil {
panic(err)
} else {
return p
}
}
Loading
Loading