Skip to content

Commit

Permalink
chore: implemented unit tests for ingress for extensions
Browse files Browse the repository at this point in the history
Signed-off-by: Ankit152 <[email protected]>
  • Loading branch information
Ankit152 committed Nov 27, 2024
1 parent 1859ede commit 9fe2e79
Show file tree
Hide file tree
Showing 7 changed files with 279 additions and 21 deletions.
8 changes: 4 additions & 4 deletions apis/v1beta1/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -323,12 +323,12 @@ func (c *Config) GetExporterPorts(logger logr.Logger) ([]corev1.ServicePort, err
return c.getPortsForComponentKinds(logger, KindExporter)
}

func (c *Config) GetReceiverAndExporterPorts(logger logr.Logger) ([]corev1.ServicePort, error) {
return c.getPortsForComponentKinds(logger, KindReceiver, KindExporter)
func (c *Config) GetExtensionPorts(logger logr.Logger) ([]corev1.ServicePort, error) {
return c.getPortsForComponentKinds(logger, KindExtension)
}

func (c *Config) GetAllPorts(logger logr.Logger) ([]corev1.ServicePort, error) {
return c.getPortsForComponentKinds(logger, KindReceiver, KindExporter, KindExtension)
func (c *Config) GetReceiverAndExporterPorts(logger logr.Logger) ([]corev1.ServicePort, error) {
return c.getPortsForComponentKinds(logger, KindReceiver, KindExporter)
}

func (c *Config) GetAllPorts(logger logr.Logger) ([]corev1.ServicePort, error) {
Expand Down
5 changes: 5 additions & 0 deletions apis/v1beta1/opentelemetrycollector_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ type OpenTelemetryCollectorSpec struct {
// Valid modes are: deployment, daemonset and statefulset.
// +optional
Ingress Ingress `json:"ingress,omitempty"`
// ExtensionIngress is used to specify how OpenTelemetry Collector is exposed. This
// functionality is only available if one of the valid modes is set.
// Valid modes are: deployment, daemonset and statefulset.
// +optional
ExtensionIngress Ingress `json:"extensionIngress,omitempty"`
// Liveness config for the OpenTelemetry Collector except the probe handler which is auto generated from the health extension of the collector.
// It is only effective when healthcheckextension is configured in the OpenTelemetry Collector pipeline.
// +optional
Expand Down
1 change: 1 addition & 0 deletions apis/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions internal/manifests/collector/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ func Build(params manifests.Params) ([]client.Object, error) {
manifests.Factory(MonitoringService),
manifests.Factory(ExtensionService),
manifests.Factory(Ingress),
manifests.Factory(ExtensionIngress),
}...)

if featuregate.CollectorUsesTargetAllocatorCR.IsEnabled() {
Expand Down
54 changes: 37 additions & 17 deletions internal/manifests/collector/ingress.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ func Ingress(params manifests.Params) (*networkingv1.Ingress, error) {
var rules []networkingv1.IngressRule
switch params.OtelCol.Spec.Ingress.RuleType {
case v1beta1.IngressRuleTypePath, "":
rules = []networkingv1.IngressRule{createPathIngressRules(params.OtelCol.Name, params.OtelCol.Spec.Ingress.Hostname, ports)}
rules = []networkingv1.IngressRule{createPathIngressRules(params.OtelCol.Name, params.OtelCol.Spec.Ingress.Hostname, ports, "service")}
case v1beta1.IngressRuleTypeSubdomain:
rules = createSubdomainIngressRules(params.OtelCol.Name, params.OtelCol.Spec.Ingress.Hostname, ports)
rules = createSubdomainIngressRules(params.OtelCol.Name, params.OtelCol.Spec.Ingress.Hostname, ports, "service")
}

return &networkingv1.Ingress{
Expand All @@ -71,48 +71,60 @@ func Ingress(params manifests.Params) (*networkingv1.Ingress, error) {
}

func ExtensionIngress(params manifests.Params) (*networkingv1.Ingress, error) {
name := naming.Ingress(params.OtelCol.Name)
name := naming.ExtensionIngress(params.OtelCol.Name)
labels := manifestutils.Labels(params.OtelCol.ObjectMeta, name, params.OtelCol.Spec.Image, ComponentOpenTelemetryCollector, params.Config.LabelsFilter())

ports, err := extensionServicePortsFromCfg(params.Log, params.OtelCol)
if params.OtelCol.Spec.ExtensionIngress.Type != v1beta1.IngressTypeIngress {
return nil, nil
}

if err != nil {
ports, err := extensionServicePortsFromCfg(params.Log, params.OtelCol)
if err != nil || len(ports) == 0 {
return nil, err
}

// if there are no ports, no ingress required
if len(ports) == 0 {
return nil, nil
var rules []networkingv1.IngressRule
switch params.OtelCol.Spec.Ingress.RuleType {
case v1beta1.IngressRuleTypePath, "":
rules = []networkingv1.IngressRule{createPathIngressRules(params.OtelCol.Name, params.OtelCol.Spec.ExtensionIngress.Hostname, ports, "extension")}
case v1beta1.IngressRuleTypeSubdomain:
rules = createSubdomainIngressRules(params.OtelCol.Name, params.OtelCol.Spec.ExtensionIngress.Hostname, ports, "extension")
}

rules := createSubdomainIngressRules(name, "", ports)

return &networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: params.OtelCol.Namespace,
Annotations: params.OtelCol.Spec.Ingress.Annotations, // can the spec annotations be used?
Annotations: params.OtelCol.Spec.ExtensionIngress.Annotations,
Labels: labels,
},
Spec: networkingv1.IngressSpec{
TLS: params.OtelCol.Spec.Ingress.TLS,
TLS: params.OtelCol.Spec.ExtensionIngress.TLS,
Rules: rules,
IngressClassName: params.OtelCol.Spec.Ingress.IngressClassName,
IngressClassName: params.OtelCol.Spec.ExtensionIngress.IngressClassName,
},
}, nil
}

func createPathIngressRules(otelcol string, hostname string, ports []corev1.ServicePort) networkingv1.IngressRule {
func createPathIngressRules(otelcol string, hostname string, ports []corev1.ServicePort, serviceType string) networkingv1.IngressRule {
pathType := networkingv1.PathTypePrefix
paths := make([]networkingv1.HTTPIngressPath, len(ports))

var name string
if serviceType == "extension" {
name = naming.ExtensionService(otelcol)
} else {
name = naming.Service(otelcol)
}

for i, port := range ports {
portName := naming.PortName(port.Name, port.Port)
paths[i] = networkingv1.HTTPIngressPath{
Path: "/" + port.Name,
PathType: &pathType,
Backend: networkingv1.IngressBackend{
Service: &networkingv1.IngressServiceBackend{
Name: naming.Service(otelcol),
Name: name,
Port: networkingv1.ServiceBackendPort{
Name: portName,
},
Expand All @@ -130,9 +142,17 @@ func createPathIngressRules(otelcol string, hostname string, ports []corev1.Serv
}
}

func createSubdomainIngressRules(otelcol string, hostname string, ports []corev1.ServicePort) []networkingv1.IngressRule {
func createSubdomainIngressRules(otelcol string, hostname string, ports []corev1.ServicePort, serviceType string) []networkingv1.IngressRule {
var rules []networkingv1.IngressRule
pathType := networkingv1.PathTypePrefix

var name string
if serviceType == "extension" {
name = naming.ExtensionService(otelcol)
} else {
name = naming.Service(otelcol)
}

for _, port := range ports {
portName := naming.PortName(port.Name, port.Port)

Expand All @@ -151,7 +171,7 @@ func createSubdomainIngressRules(otelcol string, hostname string, ports []corev1
PathType: &pathType,
Backend: networkingv1.IngressBackend{
Service: &networkingv1.IngressServiceBackend{
Name: naming.Service(otelcol),
Name: name,
Port: networkingv1.ServiceBackendPort{
Name: portName,
},
Expand Down
226 changes: 226 additions & 0 deletions internal/manifests/collector/ingress_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -284,3 +284,229 @@ func TestDesiredIngresses(t *testing.T) {
}, got)
})
}

func TestExtensionIngress(t *testing.T) {
t.Run("no ingress for incorrect ingress type", func(t *testing.T) {
params := manifests.Params{
Config: config.Config{},
Log: logger,
OtelCol: v1beta1.OpenTelemetryCollector{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
},
Spec: v1beta1.OpenTelemetryCollectorSpec{
ExtensionIngress: v1beta1.Ingress{
Type: v1beta1.IngressType("unknown"),
},
},
},
}
actual, err := ExtensionIngress(params)
assert.Nil(t, actual)
assert.NoError(t, err)
})
t.Run("no ingress if there's no port for extension", func(t *testing.T) {
params := manifests.Params{
Config: config.Config{},
Log: logger,
OtelCol: v1beta1.OpenTelemetryCollector{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
},
Spec: v1beta1.OpenTelemetryCollectorSpec{
Config: v1beta1.Config{
Service: v1beta1.Service{
Extensions: []string{"jaeger_query"},
},
Extensions: &v1beta1.AnyConfig{
Object: map[string]interface{}{},
},
},
ExtensionIngress: v1beta1.Ingress{
Type: v1beta1.IngressType("ingress"),
},
},
},
}

actual, err := ExtensionIngress(params)
assert.Nil(t, actual)
assert.NoError(t, err)
})
t.Run("ingress for extensions for rule type path", func(t *testing.T) {
var (
ns = "test-ns"
hostname = "example.com"
ingressClassName = "nginx"
pathType = networkingv1.PathTypePrefix
)

params := manifests.Params{
Config: config.Config{},
Log: logger,
OtelCol: v1beta1.OpenTelemetryCollector{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: ns,
},
Spec: v1beta1.OpenTelemetryCollectorSpec{
Config: v1beta1.Config{
Service: v1beta1.Service{
Extensions: []string{"jaeger_query"},
},
Extensions: &v1beta1.AnyConfig{
Object: map[string]interface{}{
"jaeger_query": map[string]interface{}{
"http": map[string]interface{}{
"endpoint": "0.0.0.0:16686",
},
},
},
},
},
ExtensionIngress: v1beta1.Ingress{
Type: v1beta1.IngressType("ingress"),
IngressClassName: &ingressClassName,
Hostname: hostname,
Annotations: map[string]string{"some.key": "some.value"},
RuleType: v1beta1.IngressRuleTypePath,
},
},
},
}

actual, err := ExtensionIngress(params)
assert.NoError(t, err)
assert.NotNil(t, actual)
assert.NotEqual(t, networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: naming.ExtensionIngress(params.OtelCol.Name),
Namespace: ns,
Annotations: params.OtelCol.Spec.ExtensionIngress.Annotations,
Labels: map[string]string{
"app.kubernetes.io/name": naming.ExtensionIngress(params.OtelCol.Name),
"app.kubernetes.io/instance": fmt.Sprintf("%s.%s", params.OtelCol.Namespace, params.OtelCol.Name),
"app.kubernetes.io/managed-by": "opentelemetry-operator",
"app.kubernetes.io/component": "opentelemetry-collector",
"app.kubernetes.io/part-of": "opentelemetry",
"app.kubernetes.io/version": "latest",
},
},
Spec: networkingv1.IngressSpec{
IngressClassName: &ingressClassName,
Rules: []networkingv1.IngressRule{
{
Host: hostname,
IngressRuleValue: networkingv1.IngressRuleValue{
HTTP: &networkingv1.HTTPIngressRuleValue{
Paths: []networkingv1.HTTPIngressPath{
{
Path: "/jaeger-query",
PathType: &pathType,
Backend: networkingv1.IngressBackend{
Service: &networkingv1.IngressServiceBackend{
Name: naming.ExtensionService(params.OtelCol.Name),
Port: networkingv1.ServiceBackendPort{
Name: "jaeger-query",
Number: 16686,
},
},
},
},
},
},
},
},
},
},
}, actual)
})
t.Run("ingress for extensions for rule type subdomain", func(t *testing.T) {
var (
ns = "test-ns"
hostname = "example.com"
ingressClassName = "nginx"
pathType = networkingv1.PathTypePrefix
)

params := manifests.Params{
Config: config.Config{},
Log: logger,
OtelCol: v1beta1.OpenTelemetryCollector{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: ns,
},
Spec: v1beta1.OpenTelemetryCollectorSpec{
Config: v1beta1.Config{
Service: v1beta1.Service{
Extensions: []string{"jaeger_query"},
},
Extensions: &v1beta1.AnyConfig{
Object: map[string]interface{}{
"jaeger_query": map[string]interface{}{
"http": map[string]interface{}{
"endpoint": "0.0.0.0:16686",
},
},
},
},
},
ExtensionIngress: v1beta1.Ingress{
Type: v1beta1.IngressType("ingress"),
IngressClassName: &ingressClassName,
Hostname: hostname,
Annotations: map[string]string{"some.key": "some.value"},
RuleType: v1beta1.IngressRuleTypeSubdomain,
},
},
},
}

actual, err := ExtensionIngress(params)
assert.NoError(t, err)
assert.NotNil(t, actual)
assert.NotEqual(t, networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: naming.ExtensionIngress(params.OtelCol.Name),
Namespace: ns,
Annotations: params.OtelCol.Spec.ExtensionIngress.Annotations,
Labels: map[string]string{
"app.kubernetes.io/name": naming.ExtensionIngress(params.OtelCol.Name),
"app.kubernetes.io/instance": fmt.Sprintf("%s.%s", params.OtelCol.Namespace, params.OtelCol.Name),
"app.kubernetes.io/managed-by": "opentelemetry-operator",
"app.kubernetes.io/component": "opentelemetry-collector",
"app.kubernetes.io/part-of": "opentelemetry",
"app.kubernetes.io/version": "latest",
},
},
Spec: networkingv1.IngressSpec{
IngressClassName: &ingressClassName,
Rules: []networkingv1.IngressRule{
{
Host: "jaeger-query." + hostname,
IngressRuleValue: networkingv1.IngressRuleValue{
HTTP: &networkingv1.HTTPIngressRuleValue{
Paths: []networkingv1.HTTPIngressPath{
{
Path: "/",
PathType: &pathType,
Backend: networkingv1.IngressBackend{
Service: &networkingv1.IngressServiceBackend{
Name: naming.ExtensionService(params.OtelCol.Name),
Port: networkingv1.ServiceBackendPort{
Name: "jaeger-query",
Number: 16686,
},
},
},
},
},
},
},
},
},
},
}, actual)
})
}
Loading

0 comments on commit 9fe2e79

Please sign in to comment.