Skip to content

Commit

Permalink
Uses the new parsing structure for RBAC parsing (#3206)
Browse files Browse the repository at this point in the history
* begin interface change

* move over processor config

* use it

* fix tests

* Generics

* rename

* builder

* Change to use the builder pattern instead of the option pattern

* remove unused methods

* fix unit tests

* rename somethings

* missed a spot

* fix builder
  • Loading branch information
jaronoff97 authored Sep 16, 2024
1 parent 2ed5f03 commit f2a8cf2
Show file tree
Hide file tree
Showing 20 changed files with 1,367 additions and 322 deletions.
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[ComponentConfigType any] func(*Settings[ComponentConfigType])

type Settings[ComponentConfigType any] struct {
protocol corev1.Protocol
appProtocol *string
targetPort intstr.IntOrString
nodePort int32
name string
port int32
portParser PortParser[ComponentConfigType]
rbacGen RBACRuleGenerator[ComponentConfigType]
}

func NewEmptySettings[ComponentConfigType any]() *Settings[ComponentConfigType] {
return &Settings[ComponentConfigType]{}
}

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

func (o *Settings[ComponentConfigType]) 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[ComponentConfigType any] []ParserOption[ComponentConfigType]

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

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

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

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

0 comments on commit f2a8cf2

Please sign in to comment.