Skip to content

Commit

Permalink
NMS-17003: Add tenant id on grpc exporter (#7590)
Browse files Browse the repository at this point in the history
* NMS-17003: Add tenant id as part of metadata

* NMS-17003: Update docs

* NMS-17003: Handle review comments
  • Loading branch information
cgorantla authored Jan 16, 2025
1 parent 04d7b27 commit 3abf80d
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,20 @@ See `monitored-services.proto` in the corresponding source distribution for the
$ ssh -p 8101 admin@localhost
...
admin@opennms()> config:edit org.opennms.features.grpc.exporter
admin@opennms()> config:property-set host bsm.onmshs.local:1440 <1>
admin@opennms()> config:property-set tls.cert.path /opt/opennms/etc/tls.cert <2>
admin@opennms()> config:property-set tls.enabled false <3>
admin@opennms()> config:property-set snapshot.interval 3600 false <4>
admin@opennms()> config:property-set host bsm.onmshs.local:1443 <1>
admin@opennms()> config:property-set tenant.id opennms-prime <2>
admin@opennms()> config:property-set tls.cert.path /opt/opennms/etc/tls.cert <3>
admin@opennms()> config:property-set tls.enabled false <4>
admin@opennms()> config:property-set snapshot.interval 3600 <5>
admin@opennms()> config:update
----

<1> Set the hostname of the external gRPC application.
<2> Configure the path to the TLS certificate.
<3> TLS is enabled by default. For testing purposes, it can be disabled by setting this value to false.
<4> Set the interval (in seconds) at which the complete snapshot of services will be sent to the gRPC server.
<2> Set tenant id for the data being sent, defaults to `opennms-prime`
<3> Configure the path to the TLS certificate.
<4> TLS is enabled by default. For testing purposes, it can be disabled by setting this value to false.
<5> Set the interval (in seconds) at which the complete snapshot of services will be sent to the gRPC server,
defaults to 3600 secs.

== Enable gRPC Exporter

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
package org.opennms.features.grpc.exporter;

import com.google.protobuf.Empty;
import io.grpc.ClientInterceptor;
import io.grpc.ConnectivityState;
import io.grpc.ManagedChannel;
import io.grpc.netty.shaded.io.grpc.netty.GrpcSslContexts;
Expand All @@ -49,7 +50,6 @@ public class GrpcExporterClient {
public static final String FOREIGN_TYPE = "OpenNMS";

private final String host;
private final Integer port;
private final String tlsCertPath;

private final boolean tlsEnabled;
Expand All @@ -63,27 +63,23 @@ public class GrpcExporterClient {
private final AtomicBoolean reconnecting = new AtomicBoolean(false);
private final AtomicBoolean stopped = new AtomicBoolean(false);
private Callback inventoryCallback;
private final ClientInterceptor clientInterceptor;

public GrpcExporterClient(final String host,
final Integer port,
final String tlsCertPath,
final boolean tlsEnabled) {
final boolean tlsEnabled,
final ClientInterceptor clientInterceptor) {
this.host = Objects.requireNonNull(host);
this.port = Objects.requireNonNull(port);
this.tlsCertPath = tlsCertPath;
this.tlsEnabled = tlsEnabled;
this.clientInterceptor = clientInterceptor;
this.scheduler = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("grpc-exporter-connect"));
}

public void start() throws SSLException {
final NettyChannelBuilder channelBuilder;
if (this.port > 0) {
channelBuilder = NettyChannelBuilder.forAddress(this.host, this.port)
final NettyChannelBuilder channelBuilder = NettyChannelBuilder.forTarget(this.host)
.intercept(clientInterceptor)
.keepAliveWithoutCalls(true);
} else {
channelBuilder = NettyChannelBuilder.forTarget(this.host)
.keepAliveWithoutCalls(true);
}

if (tlsEnabled && tlsCertPath != null && !tlsCertPath.isBlank()) {
channel = channelBuilder.useTransportSecurity()
Expand All @@ -104,7 +100,7 @@ public void start() throws SSLException {

this.monitoredServiceSyncStub = ServiceSyncGrpc.newStub(this.channel);
connectStreams();
LOG.info("GrpcExporterClient started connection to {}:{}", this.host, this.port);
LOG.info("GrpcExporterClient started connection to {}", this.host);
}

public void stop() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Licensed to The OpenNMS Group, Inc (TOG) under one or more
* contributor license agreements. See the LICENSE.md file
* distributed with this work for additional information
* regarding copyright ownership.
*
* TOG licenses this file to You under the GNU Affero General
* Public License Version 3 (the "License") or (at your option)
* any later version. You may not use this file except in
* compliance with the License. You may obtain a copy of the
* License at:
*
* https://www.gnu.org/licenses/agpl-3.0.txt
*
* 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 org.opennms.features.grpc.exporter;

import io.grpc.CallOptions;
import io.grpc.Channel;
import io.grpc.ClientCall;
import io.grpc.ClientInterceptor;
import io.grpc.ForwardingClientCall;
import io.grpc.Metadata;
import io.grpc.MethodDescriptor;

public class GrpcHeaderInterceptor implements ClientInterceptor {

private final Metadata metadata;

public GrpcHeaderInterceptor(String tenantId) {
metadata = new Metadata();
metadata.put(Metadata.Key.of("tenant-id", Metadata.ASCII_STRING_MARSHALLER), tenantId);
}

@Override
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(
MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) {
return new HeaderAttachingClientCall<>(next.newCall(method, callOptions), metadata);
}

private final static class HeaderAttachingClientCall<ReqT, RespT>
extends ForwardingClientCall.SimpleForwardingClientCall<ReqT, RespT> {

private final Metadata metadata;
HeaderAttachingClientCall(ClientCall<ReqT, RespT> call, Metadata metadataToAttach) {
super(call);
this.metadata = metadataToAttach;
}

@Override
public void start(Listener<RespT> responseListener, Metadata headers) {
headers.merge(metadata);
super.start(responseListener, headers);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@
<cm:property-placeholder id="grpcExporterProperties" persistent-id="org.opennms.features.grpc.exporter"
update-strategy="reload">
<cm:default-properties>
<cm:property name="host" value="bsm.onmshs.local"/>
<cm:property name="port" value="1443"/>
<cm:property name="host" value="bsm.onmshs.local:1443"/>
<cm:property name="snapshot.interval" value="3600"/>
<cm:property name="tls.enabled" value="true"/>
<cm:property name="tls.cert.path" value=""/>
<cm:property name="tenant.id" value="opennms-prime"/>
</cm:default-properties>
</cm:property-placeholder>

Expand All @@ -24,9 +24,13 @@

<bean id="grpcExporterClient" class="org.opennms.features.grpc.exporter.GrpcExporterClient" init-method="start" destroy-method="stop">
<argument value="${host}"/>
<argument value="${port}"/>
<argument value="${tls.cert.path}"/>
<argument value="${tls.enabled}"/>
<argument ref="grpcClientInterceptor"/>
</bean>

<bean id="grpcClientInterceptor" class="org.opennms.features.grpc.exporter.GrpcHeaderInterceptor">
<argument value="${tenant.id}"/>
</bean>

<bean id="inventoryService" class="org.opennms.features.grpc.exporter.InventoryService" init-method="start" destroy-method="stop" >
Expand Down

0 comments on commit 3abf80d

Please sign in to comment.