Skip to content
Merged
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
15 changes: 13 additions & 2 deletions api/v1alpha1/output_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ type OutputSpec struct {
// +optional
Service *OutputServiceSpec `json:"service,omitempty"`
// ServiceRef references a Kubernetes Service to use as the output address.
// Supported for: nats, jetstream, kafka outputs.
// Supported for: nats, jetstream, kafka, remote_write, influxdb outputs.
// The service address will be resolved and injected into the output config.
// +optional
ServiceRef *ServiceReference `json:"serviceRef,omitempty"`
// ServiceSelector selects Kubernetes Services by labels to use as output addresses.
// Supported for: nats, jetstream, kafka outputs.
// Supported for: nats, jetstream, kafka, remote_write, influxdb outputs.
// All matching service addresses will be resolved and injected into the output config.
// +optional
ServiceSelector *ServiceSelector `json:"serviceSelector,omitempty"`
Expand All @@ -58,6 +58,13 @@ type ServiceReference struct {
// If not specified, the first port of the service is used.
// +optional
Port string `json:"port,omitempty"`
// URL is an optional path suffix appended after the resolved service address
// (scheme, host, and port). A leading slash on the value is optional; the
// operator joins the base and suffix with a single '/'. Use this for HTTP(S)
// outputs such as prometheus_write (for example api/v1/write or api/v1/push)
// or influxdb instead of putting the full URL in config.
// +optional
URL string `json:"url,omitempty"`
}

// ServiceSelector selects Services by labels
Expand All @@ -71,6 +78,10 @@ type ServiceSelector struct {
// If not specified, the first port of the service is used.
// +optional
Port string `json:"port,omitempty"`
// URL is an optional path suffix appended after each resolved service address.
// Same semantics as ServiceReference.url (see ServiceReference).
// +optional
URL string `json:"url,omitempty"`
}

// OutputServiceSpec defines the service configuration for outputs that expose an endpoint
Expand Down
17 changes: 15 additions & 2 deletions config/crd/bases/operator.gnmic.dev_outputs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ spec:
serviceRef:
description: |-
ServiceRef references a Kubernetes Service to use as the output address.
Supported for: nats, jetstream, kafka outputs.
Supported for: nats, jetstream, kafka, remote_write, influxdb outputs.
The service address will be resolved and injected into the output config.
properties:
name:
Expand All @@ -89,13 +89,21 @@ spec:
Port is the name or number of the port to use.
If not specified, the first port of the service is used.
type: string
url:
description: |-
URL is an optional path suffix appended after the resolved service address
(scheme, host, and port). A leading slash on the value is optional; the
operator joins the base and suffix with a single '/'. Use this for HTTP(S)
outputs such as prometheus_write (for example api/v1/write or api/v1/push)
or influxdb instead of putting the full URL in config.
type: string
required:
- name
type: object
serviceSelector:
description: |-
ServiceSelector selects Kubernetes Services by labels to use as output addresses.
Supported for: nats, jetstream, kafka outputs.
Supported for: nats, jetstream, kafka, remote_write, influxdb outputs.
All matching service addresses will be resolved and injected into the output config.
properties:
matchLabels:
Expand All @@ -113,6 +121,11 @@ spec:
Port is the name or number of the port to use.
If not specified, the first port of the service is used.
type: string
url:
description: |-
URL is an optional path suffix appended after each resolved service address.
Same semantics as ServiceReference.url (see ServiceReference).
type: string
required:
- matchLabels
type: object
Expand Down
19 changes: 19 additions & 0 deletions docs/content/docs/user-guide/output.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ Defines the output address or URL as a service reference.
| `name` | string | Yes | Name of the Kubernetes Service |
| `namespace` | string | No | Namespace of the Service (defaults to Output's namespace) |
| `port` | string | No | Port name or number (defaults to first port) |
| `url` | string | No | Path suffix appended after the resolved `scheme://host:port` (optional leading slash). Use for HTTP(S) outputs such as `prometheus_write` or `influxdb` (for example `api/v1/write` or `api/v1/push`) so you do not need the full URL in `config`. |

### ServiceSelector

Expand All @@ -61,6 +62,7 @@ Defines the output address or URL as a service selector.
| `matchLabels` | map[string]string | Yes | Labels to match services |
| `namespace` | string | No | Namespace to search (defaults to Output's namespace) |
| `port` | string | No | Port name or number (defaults to first port) |
| `url` | string | No | Path suffix appended after each resolved address; same meaning as `serviceRef.url`. |

- It is recommended to label outputs for flexible selection when building Pipelines.

Expand Down Expand Up @@ -208,6 +210,19 @@ spec:

The operator resolves the service and constructs the URL as `http://prometheus-server.{namespace}.svc.cluster.local:9090`.

To set the HTTP path without duplicating the host in `config`, use `serviceRef.url` (for example Grafana Mimir at `/api/v1/push`):

```yaml
spec:
type: prometheus_write
serviceRef:
name: mimir-distributor
port: http
url: api/v1/push
config:
timeout: 10s
```

### Using Service Selector

Discover multiple Kafka brokers using labels:
Expand Down Expand Up @@ -483,6 +498,10 @@ For outputs that connect to external systems (NATS, Kafka, InfluxDB, Prometheus
| **Result** | Single address | Multiple addresses (comma-separated) |
| **Cross-namespace** | Yes (specify namespace) | Yes (specify namespace) |

### Path suffix (`url`)

For `serviceRef` and `serviceSelector`, optional field `url` is appended after the resolved address (scheme, DNS name, and port). It is most useful for `prometheus_write` and `influxdb`, where gNMIc expects a full URL: you can rely on service discovery for the host and port and set only the path here (for example `api/v1/write` for Prometheus or `api/v1/push` for Mimir). Leading slashes are optional.

1. The operator watches for Output resources
2. During reconciliation, it resolves the referenced Service(s)
3. Addresses are formatted with the appropriate scheme (`nats://`)
Expand Down
10 changes: 10 additions & 0 deletions internal/controller/cluster_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -2334,6 +2334,11 @@ func (r *ClusterReconciler) resolveOutputServiceAddresses(ctx context.Context, o
// use cluster DNS name for the service
host := fmt.Sprintf("%s.%s.svc.cluster.local", svc.Name, svc.Namespace)
addr := gnmic.FormatServiceAddress(spec, host, port)
if spec.ServiceRef.URL != "" {
url := strings.TrimPrefix(spec.ServiceRef.URL, "/")
addr = strings.TrimSuffix(addr, "/")
addr = fmt.Sprintf("%s/%s", addr, url)
}
resolved = append(resolved, addr)
}

Expand Down Expand Up @@ -2369,6 +2374,11 @@ func (r *ClusterReconciler) resolveOutputServiceAddresses(ctx context.Context, o
// use cluster DNS name for the service
host := fmt.Sprintf("%s.%s.svc.cluster.local", svc.Name, svc.Namespace)
addr := gnmic.FormatServiceAddress(spec, host, port)
if spec.ServiceSelector.URL != "" {
url := strings.TrimPrefix(spec.ServiceSelector.URL, "/")
addr = strings.TrimSuffix(addr, "/")
addr = fmt.Sprintf("%s/%s", addr, url)
}
resolved = append(resolved, addr)
}
}
Expand Down
3 changes: 3 additions & 0 deletions internal/gnmic/output.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ type outputConfigOptions struct {
ResolvedAddresses []string
// TLS options to inject into the output config
TLS *TLSOptions
// URL to append to discovered service addresses
URL string
}

type TLSOptions struct {
Expand Down Expand Up @@ -89,6 +91,7 @@ func buildOutputConfig(spec *gnmicv1alpha1.OutputSpec, options *outputConfigOpti
config["address"] = strings.Join(options.ResolvedAddresses, ",")
case PrometheusWriteOutputType:
config["url"] = strings.Join(options.ResolvedAddresses, ",")

case InfluxDBOutputType:
config["url"] = strings.Join(options.ResolvedAddresses, ",")
}
Expand Down
1 change: 0 additions & 1 deletion internal/gnmic/plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ type resourceRelationship struct {

// NewPlanBuilder creates a new PlanBuilder
func NewPlanBuilder(clusterName string, credsFetcher CredentialsFetcher) *PlanBuilder {

return &PlanBuilder{
clusterName: clusterName,
pipelines: make(map[string]*PipelineData),
Expand Down
Loading