Skip to content

Commit

Permalink
Issue thelastpickle#809 : Provide a means of entering JMX credentials…
Browse files Browse the repository at this point in the history
… when adding a new cluster in the UI
  • Loading branch information
denniskline authored and DENNIS KLINE committed Jan 15, 2020
1 parent 56eb04e commit 117bf87
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 44 deletions.
2 changes: 2 additions & 0 deletions src/server/src/main/java/io/cassandrareaper/AppContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

package io.cassandrareaper;

import io.cassandrareaper.crypto.Cryptograph;
import io.cassandrareaper.jmx.JmxConnectionFactory;
import io.cassandrareaper.service.RepairManager;
import io.cassandrareaper.service.SchedulingManager;
Expand Down Expand Up @@ -46,6 +47,7 @@ public final class AppContext {
public SchedulingManager schedulingManager;
public JmxConnectionFactory jmxConnectionFactory;
public ReaperApplicationConfiguration config;
public Cryptograph cryptograph;
public MetricRegistry metricRegistry = new MetricRegistry();
volatile String localNodeAddress = null;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import io.cassandrareaper.core.Cluster;
import io.cassandrareaper.core.JmxCredentials;
import io.cassandrareaper.core.Node;
import io.cassandrareaper.crypto.NoopCrypotograph;
import io.cassandrareaper.jmx.ClusterFacade;
import io.cassandrareaper.jmx.JmxConnectionFactory;
import io.cassandrareaper.jmx.JmxConnectionsInitializer;
Expand Down Expand Up @@ -162,8 +163,7 @@ public void run(ReaperApplicationConfiguration config, Environment environment)
context.metricRegistry = environment.metrics();
CollectorRegistry.defaultRegistry.register(new DropwizardExports(environment.metrics()));

environment
.admin()
environment.admin()
.addServlet("prometheusMetrics", new MetricsServlet(CollectorRegistry.defaultRegistry))
.addMapping("/prometheusMetrics");

Expand All @@ -172,6 +172,9 @@ public void run(ReaperApplicationConfiguration config, Environment environment)

tryInitializeStorage(config, environment);

context.cryptograph = context.config == null || context.config.getCryptograph() == null
? new NoopCrypotograph() : context.config.getCryptograph().create();

if (context.jmxConnectionFactory == null) {
LOG.info("no JMX connection factory given in context, creating default");
context.jmxConnectionFactory = new JmxConnectionFactory(context);
Expand Down Expand Up @@ -199,8 +202,7 @@ public void run(ReaperApplicationConfiguration config, Environment environment)
context.jmxConnectionFactory.setJmxCredentials(jmxCredentials);
}

context.repairManager = RepairManager.create(
context,
context.repairManager = RepairManager.create(context,
environment.lifecycle().scheduledExecutorService("RepairRunner").threads(repairThreads).build(),
config.getHangingRepairTimeoutMins(),
TimeUnit.MINUTES,
Expand All @@ -226,8 +228,7 @@ public void run(ReaperApplicationConfiguration config, Environment environment)
final PingResource pingResource = new PingResource(healthCheck);
environment.jersey().register(pingResource);

final ClusterResource addClusterResource = new ClusterResource(
context,
final ClusterResource addClusterResource = new ClusterResource(context,
environment.lifecycle().executorService("ClusterResource").minThreads(6).maxThreads(6).build());

environment.jersey().register(addClusterResource);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import io.cassandrareaper.core.JmxCredentials;
import io.cassandrareaper.core.Node;
import io.cassandrareaper.crypto.Cryptograph;
import io.cassandrareaper.crypto.NoopCrypotograph;

import java.util.ArrayList;
import java.util.Collection;
Expand Down Expand Up @@ -52,7 +51,6 @@ public class JmxConnectionFactory {
private final MetricRegistry metricRegistry;
private final HostConnectionCounters hostConnectionCounters;
private final AppContext context;
private final Cryptograph cryptograph;
private Map<String, Integer> jmxPorts;
private JmxCredentials jmxAuth;
private Map<String, JmxCredentials> jmxCredentials;
Expand All @@ -65,8 +63,6 @@ public JmxConnectionFactory(AppContext context) {
hostConnectionCounters = new HostConnectionCounters(metricRegistry);
registerConnectionsGauge();
this.context = context;
this.cryptograph = context.config == null || context.config.getCryptograph() == null
? new NoopCrypotograph() : context.config.getCryptograph().create();
}

private void registerConnectionsGauge() {
Expand Down Expand Up @@ -99,7 +95,7 @@ protected JmxProxy connectImpl(Node node) throws ReaperException, InterruptedExc
try {
JmxConnectionProvider provider = new JmxConnectionProvider(
host, jmxCredentials, context.config.getJmxConnectionTimeoutInSeconds(),
this.metricRegistry, cryptograph);
this.metricRegistry, context.cryptograph);
JMX_CONNECTIONS.computeIfAbsent(host, provider::apply);
JmxProxy proxy = JMX_CONNECTIONS.get(host);
if (!proxy.isConnectionAlive()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ private Response addOrUpdateCluster(
if (jmxUsername.isPresent() && jmxPassword.isPresent()) {
jmxCredentials = JmxCredentials.builder()
.withUsername(jmxUsername.get())
.withPassword(jmxPassword.get())
.withPassword(context.cryptograph.encrypt(jmxPassword.get()))
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

import io.cassandrareaper.AppContext;
import io.cassandrareaper.crypto.Cryptograph;
import io.cassandrareaper.crypto.NoopCrypotograph;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
Expand All @@ -40,8 +39,7 @@ public final class CryptoResource {
private final Cryptograph cryptograph;

public CryptoResource(AppContext context) {
this.cryptograph = context.config == null || context.config.getCryptograph() == null
? new NoopCrypotograph() : context.config.getCryptograph().create();
this.cryptograph = context.cryptograph;
}

@GET
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import io.cassandrareaper.ReaperException;
import io.cassandrareaper.core.Cluster;
import io.cassandrareaper.core.Table;
import io.cassandrareaper.crypto.NoopCrypotograph;
import io.cassandrareaper.jmx.JmxConnectionFactory;
import io.cassandrareaper.jmx.JmxProxy;
import io.cassandrareaper.service.TestRepairConfiguration;
Expand Down Expand Up @@ -575,6 +576,7 @@ private MockObjects initMocks() throws ReaperException {
AppContext context = new AppContext();
context.storage = new MemoryStorage();
context.config = TestRepairConfiguration.defaultConfig();
context.cryptograph = new NoopCrypotograph();

UriInfo uriInfo = mock(UriInfo.class);
when(uriInfo.getBaseUriBuilder()).thenReturn(UriBuilder.fromUri(SAMPLE_URI));
Expand Down
130 changes: 102 additions & 28 deletions src/ui/app/jsx/cluster-form.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const clusterForm = React.createClass({
},

getInitialState: function() {
return {addClusterResultMsg: null, seed_node:"", jmx_port:"7199"};
return {addClusterResultMsg: null, seed_node:"", jmx_port:"7199", submitEnabled: false};
},

componentWillMount: function() {
Expand All @@ -49,10 +49,31 @@ const clusterForm = React.createClass({
const state = this.state;
state[n] = v;
this.replaceState(state);
},

// validate
this._checkValidity();
},

_checkValidity: function() {
const valid = this.state.seed_node.length > 0;
this.setState({submitEnabled: valid});
},

_toggleFormDisplay: function() {
if(this.state.formCollapsed == true) {
this.setState({formCollapsed: false});
}
else {
this.setState({formCollapsed: true});
}
},

_onAdd: function(e) {
let addClusterObj = {'seed_node':this.state.seed_node, 'jmx_port':this.state.jmx_port};
let addClusterObj = {
'seed_node':this.state.seed_node,
'jmx_port':this.state.jmx_port,
'jmx_username':this.state.jmx_username,
'jmx_password':this.state.jmx_password};
this.props.addClusterSubject.onNext(addClusterObj);
},

Expand All @@ -63,31 +84,84 @@ const clusterForm = React.createClass({
addMsg = <div className="alert alert-danger" role="alert">{this.state.addClusterResultMsg}</div>
}

const form = <div className="row">
<div className="col-lg-12">

<div className="form-inline">
<div className="form-group">
<label htmlFor="in_seed_node">Seed node:</label>
<input type="text" className="form-control" ref="in_seed_node" id="in_seed_node"
onChange={this._handleChange}
placeholder="hostname or ip"></input>
</div>
<div className="form-group">
<label htmlFor="in_jmx_port">JMX port:</label>
<input type="text" className="form-control" ref="in_jmx_port" id="in_jmx_port"
onChange={this._handleChange}
placeholder="7199"></input>
</div>
<button type="button" className="btn btn-success" onClick={this._onAdd}>Add Cluster</button>
</div>

</div>
</div>


return (<div className="panel panel-default">
<div className="panel-body">
const form = <div className="row">
<div className="col-lg-12">

<form className="form-horizontal form-condensed">

<div className="form-group">
<label htmlFor="in_seed_node" className="col-sm-3 control-label">Seed node*</label>
<div className="col-sm-9 col-md-7 col-lg-5">
<input type="text" className="form-control" ref="in_seed_node" id="in_seed_node"
onChange={this._handleChange}
placeholder="hostname or ip"></input>
</div>
</div>

<div className="form-group">
<label htmlFor="in_jmx_port" className="col-sm-3 control-label">JMX port</label>
<div className="col-sm-9 col-md-7 col-lg-5">
<input type="text" className="form-control" ref="in_jmx_port" id="in_jmx_port"
onChange={this._handleChange}
placeholder="7199"></input>
</div>
</div>

<div className="form-group">
<label htmlFor="in_jmx_username" className="col-sm-3 control-label">JMX username</label>
<div className="col-sm-9 col-md-7 col-lg-5">
<input type="text" className="form-control" ref="in_jmx_username" id="in_jmx_username"
onChange={this._handleChange}
placeholder="JMX username of cluster (optional)"></input>
</div>
</div>

<div className="form-group">
<label htmlFor="in_jmx_username" className="col-sm-3 control-label">JMX password</label>
<div className="col-sm-9 col-md-7 col-lg-5">
<input type="password" className="form-control" ref="in_jmx_password" id="in_jmx_password"
onChange={this._handleChange}
placeholder="JMX password of cluster (optional)"></input>
</div>
</div>
<div className="form-group">
<div className="col-sm-offset-3 col-sm-9">
<button type="button" className="btn btn-warning" disabled={!this.state.submitEnabled}
onClick={this._onAdd}>Add Cluster</button>
</div>
</div>
</form>

</div>
</div>

let menuDownStyle = {
display: "inline-block"
}

let menuUpStyle = {
display: "none"
}

if(this.state.formCollapsed == false) {
menuDownStyle = {
display: "none"
}
menuUpStyle = {
display: "inline-block"
}
}

const formHeader = <div className="panel-title">
<a href="#cluster-form" data-toggle="collapse" onClick={this._toggleFormDisplay}>Add Cluster
&nbsp; <span className="glyphicon glyphicon-menu-down" aria-hidden="true" style={menuDownStyle}></span>
<span className="glyphicon glyphicon-menu-up" aria-hidden="true" style={menuUpStyle}></span></a></div>

return (<div className="panel panel-warning">
<div className="panel-heading">
{formHeader}
</div>
<div className="panel-body collapse" id="cluster-form">
{addMsg}
{form}
</div>
Expand Down
5 changes: 4 additions & 1 deletion src/ui/app/observable.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,10 @@ export const selectClusterSubject = new Rx.Subject();
export const addClusterResult = addClusterSubject.map(addCluster => {
console.info("Adding new cluster with seed node: " + addCluster.seed_node);
return Rx.Observable.fromPromise($.ajax({
url: `${URL_PREFIX}/cluster?seedHost=${encodeURIComponent(addCluster.seed_node)}&jmxPort=${encodeURIComponent(addCluster.jmx_port)}`,
url: `${URL_PREFIX}/cluster?seedHost=${encodeURIComponent(addCluster.seed_node)}`
+ `&jmxPort=${encodeURIComponent(addCluster.jmx_port)}`
+ `&jmxUsername=${encodeURIComponent(addCluster.jmx_username)}`
+ `&jmxPassword=${encodeURIComponent(addCluster.jmx_password)}`,
method: 'POST'
}).promise());
}).share();
Expand Down

0 comments on commit 117bf87

Please sign in to comment.