Skip to content

Commit 10b3674

Browse files
authored
Merge pull request #128 from jcantrill/remove_index_patterns_for_admins
reduce index-patterns for cluster-admins
2 parents 0a8d425 + 7c77db1 commit 10b3674

File tree

6 files changed

+260
-71
lines changed

6 files changed

+260
-71
lines changed

src/main/java/io/fabric8/elasticsearch/plugin/ConfigurationSettings.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,11 @@ public interface ConfigurationSettings extends KibanaIndexMode{
7777
static final String DEFAULT_USER_PROFILE_PREFIX = ".kibana";
7878
static final String[] DEFAULT_WHITELISTED_USERS = new String[] { "$logging.$infra.$fluentd",
7979
"$logging.$infra.$kibana", "$logging.$infra.$curator" };
80-
80+
81+
static final String [] DEFAULT_KIBANA_OPS_INDEX_PATTERNS = new String[] {
82+
".operations.*", ".orphaned.*", "project.*", ".all"
83+
};
84+
8185
/**
8286
* The configurations for enabling/disabling portions of this plugin
8387
* defaults to 'true' => enabled.
@@ -95,6 +99,11 @@ public interface ConfigurationSettings extends KibanaIndexMode{
9599
static final String DEFAULT_ACL_ROLE_STRATEGY = "user";
96100

97101
static final String OPENSHIFT_KIBANA_REWRITE_ENABLED_FLAG = "openshift.kibana.rewrite.enabled";
102+
103+
/**
104+
* List of index patterns to create for operations users
105+
*/
106+
static final String OPENSHIFT_KIBANA_OPS_INDEX_PATTERNS = "openshift.kibana.ops_index_patterns";
98107

99108

100109
static final boolean OPENSHIFT_DYNAMIC_ENABLED_DEFAULT = true;

src/main/java/io/fabric8/elasticsearch/plugin/OpenshiftRequestContextFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ public static class OpenshiftRequestContext {
184184
private final String kibanaIndex;
185185
private final String kibanaIndexMode;
186186

187-
protected OpenshiftRequestContext(final String user, final String token, boolean isClusterAdmin,
187+
public OpenshiftRequestContext(final String user, final String token, boolean isClusterAdmin,
188188
Set<String> projects, String kibanaIndex, final String kibanaIndexMode) {
189189
this.user = user;
190190
this.token = token;

src/main/java/io/fabric8/elasticsearch/plugin/PluginClient.java

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,32 @@
1616

1717
package io.fabric8.elasticsearch.plugin;
1818

19+
import java.io.IOException;
1920
import java.util.HashSet;
2021
import java.util.Map;
2122
import java.util.Set;
23+
import java.util.concurrent.ExecutionException;
2224

25+
import org.apache.commons.lang.StringUtils;
2326
import org.elasticsearch.action.ActionRequestBuilder;
2427
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequestBuilder;
2528
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesResponse;
2629
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequestBuilder;
2730
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesResponse;
31+
import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;
32+
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
2833
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequestBuilder;
2934
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse;
35+
import org.elasticsearch.action.admin.indices.get.GetIndexRequestBuilder;
36+
import org.elasticsearch.action.admin.indices.get.GetIndexResponse;
37+
import org.elasticsearch.action.admin.indices.refresh.RefreshRequestBuilder;
38+
import org.elasticsearch.action.admin.indices.refresh.RefreshResponse;
3039
import org.elasticsearch.action.get.GetRequestBuilder;
3140
import org.elasticsearch.action.get.GetResponse;
3241
import org.elasticsearch.action.index.IndexRequestBuilder;
3342
import org.elasticsearch.action.index.IndexResponse;
43+
import org.elasticsearch.action.update.UpdateRequestBuilder;
44+
import org.elasticsearch.action.update.UpdateResponse;
3445
import org.elasticsearch.client.Client;
3546
import org.elasticsearch.common.inject.Inject;
3647
import org.elasticsearch.common.logging.ESLogger;
@@ -53,13 +64,56 @@ public PluginClient(Client client) {
5364
this.client = client;
5465
}
5566

67+
public UpdateResponse update(String index, String type, String id, String source) {
68+
69+
LOGGER.debug("UPDATE: '{}/{}/{}' source: '{}'", index, type, id, source);
70+
71+
UpdateRequestBuilder builder = client.prepareUpdate(index, type, id).setDoc(source).setDocAsUpsert(true);
72+
addCommonHeaders(builder);
73+
UpdateResponse response = builder.get();
74+
75+
LOGGER.debug("Created with update? '{}'", response.isCreated());
76+
return response;
77+
}
78+
5679
public IndexResponse createDocument(String index, String type, String id, String source) {
5780
LOGGER.trace("create document: '{}/{}/{}' source: '{}'", index, type, id, source);
5881
IndexRequestBuilder builder = client.prepareIndex(index, type, id).setSource(source);
5982
addCommonHeaders(builder);
6083
IndexResponse response = builder.get();
6184
return response;
6285
}
86+
87+
public GetIndexResponse getIndices(String... indices) throws InterruptedException, ExecutionException {
88+
if (LOGGER.isTraceEnabled()) {
89+
LOGGER.trace("Getting indices '{}'", StringUtils.join(indices, ", "));
90+
}
91+
GetIndexRequestBuilder builder = client.admin().indices().prepareGetIndex().setIndices(indices);
92+
addCommonHeaders(builder);
93+
return builder.get();
94+
}
95+
96+
public CreateIndexResponse copyIndex(final String source, final String target, String... types) throws InterruptedException, ExecutionException, IOException {
97+
LOGGER.trace("Copying {} index to {} for types {}", source, target, types);
98+
GetIndexResponse response = getIndices(source);
99+
CreateIndexRequestBuilder builder = client.admin().indices()
100+
.prepareCreate(target)
101+
.setSettings(response.getSettings().get(source));
102+
for (String type : types) {
103+
builder.addMapping(type, response.mappings().get(source).get(type).getSourceAsMap());
104+
}
105+
addCommonHeaders(builder);
106+
return builder.get();
107+
}
108+
109+
public RefreshResponse refreshIndices(String... indices) {
110+
RefreshRequestBuilder builder = client.admin().indices().prepareRefresh(indices);
111+
addCommonHeaders(builder);
112+
RefreshResponse response = builder.get();
113+
LOGGER.debug("Refreshed '{}' successfully on {} of {} shards", indices, response.getSuccessfulShards(),
114+
response.getTotalShards());
115+
return response;
116+
}
63117

64118
public boolean indexExists(final String index) {
65119
LOGGER.trace("Checking for existance of index '{}'", index);

src/main/java/io/fabric8/elasticsearch/plugin/PluginSettings.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919
import static io.fabric8.elasticsearch.plugin.acl.SearchGuardSyncStrategyFactory.PROJECT;
2020
import static io.fabric8.elasticsearch.plugin.acl.SearchGuardSyncStrategyFactory.USER;
2121

22+
import java.util.Arrays;
23+
import java.util.HashSet;
24+
import java.util.Set;
25+
2226
import org.apache.commons.lang.ArrayUtils;
2327
import org.elasticsearch.common.inject.Inject;
2428
import org.elasticsearch.common.logging.ESLogger;
@@ -37,6 +41,7 @@ public class PluginSettings implements ConfigurationSettings {
3741
private final String kibanaVersion;
3842
private final String kbnVersionHeader;
3943
private final Boolean enabled;
44+
private final Set<String> opsIndexPatterns;
4045

4146
@Inject
4247
public PluginSettings(final Settings settings) {
@@ -57,6 +62,7 @@ public PluginSettings(final Settings settings) {
5762
this.kibanaVersion = settings.get(KIBANA_CONFIG_VERSION, DEFAULT_KIBANA_VERSION);
5863
this.kbnVersionHeader = settings.get(KIBANA_VERSION_HEADER, DEFAULT_KIBANA_VERSION_HEADER);
5964
this.enabled = settings.getAsBoolean(OPENSHIFT_DYNAMIC_ENABLED_FLAG, OPENSHIFT_DYNAMIC_ENABLED_DEFAULT);
65+
this.opsIndexPatterns = new HashSet<String>(Arrays.asList(settings.getAsArray(OPENSHIFT_KIBANA_OPS_INDEX_PATTERNS, DEFAULT_KIBANA_OPS_INDEX_PATTERNS)));
6066

6167
LOGGER.info("Using kibanaIndexMode: '{}'", this.kibanaIndexMode);
6268
LOGGER.debug("searchGuardIndex: {}", this.searchGuardIndex);
@@ -99,4 +105,8 @@ public Boolean isEnabled() {
99105
public void setKibanaIndexMode(String kibanaIndexMode) {
100106
this.kibanaIndexMode = kibanaIndexMode;
101107
}
108+
109+
public Set<String> getKibanaOpsIndexPatterns() {
110+
return opsIndexPatterns;
111+
}
102112
}

src/main/java/io/fabric8/elasticsearch/plugin/kibana/KibanaSeed.java

Lines changed: 50 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -26,22 +26,16 @@
2626
import java.util.concurrent.ExecutionException;
2727

2828
import org.apache.commons.lang.StringUtils;
29-
import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest;
30-
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
31-
import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
32-
import org.elasticsearch.action.admin.indices.get.GetIndexResponse;
33-
import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
34-
import org.elasticsearch.action.admin.indices.refresh.RefreshResponse;
3529
import org.elasticsearch.action.delete.DeleteRequest;
3630
import org.elasticsearch.action.get.GetRequest;
3731
import org.elasticsearch.action.get.GetResponse;
3832
import org.elasticsearch.action.search.SearchRequest;
3933
import org.elasticsearch.action.search.SearchResponse;
40-
import org.elasticsearch.action.update.UpdateRequest;
4134
import org.elasticsearch.client.Client;
4235
import org.elasticsearch.common.inject.Inject;
4336
import org.elasticsearch.common.logging.ESLogger;
4437
import org.elasticsearch.common.logging.Loggers;
38+
import org.elasticsearch.common.xcontent.XContentFactory;
4539
import org.elasticsearch.index.IndexNotFoundException;
4640
import org.elasticsearch.search.SearchHit;
4741
import org.elasticsearch.transport.RemoteTransportException;
@@ -69,43 +63,78 @@ public class KibanaSeed implements ConfigurationSettings {
6963
private final IndexMappingLoader mappingLoader;
7064
private final PluginClient pluginClient;
7165
private final String defaultKibanaIndex;
66+
private final PluginSettings settings;
7267

7368
@Inject
7469
public KibanaSeed(final PluginSettings settings, final IndexMappingLoader loader, final PluginClient pluginClient) {
7570
this.mappingLoader = loader;
7671
this.pluginClient = pluginClient;
7772
this.defaultKibanaIndex = settings.getDefaultKibanaIndex();
73+
this.settings = settings;
7874
}
79-
75+
8076
public void setDashboards(final OpenshiftRequestContext context, Client client, String kibanaVersion, final String projectPrefix) {
8177
if(!pluginClient.indexExists(defaultKibanaIndex)) {
8278
LOGGER.debug("Default Kibana index '{}' does not exist. Skipping Kibana seeding", defaultKibanaIndex);
8379
return;
8480
}
8581
LOGGER.debug("Begin setDashboards: projectPrefix '{}' for user '{}' projects '{}' kibanaIndex '{}'",
8682
projectPrefix, context.getUser(), context.getProjects(), context.getKibanaIndex());
87-
83+
8884
// We want to seed the Kibana user index initially
8985
// since the logic from Kibana has changed to create before this plugin
9086
// starts...
9187
boolean changed = initialSeedKibanaIndex(context, client);
88+
89+
if (context.isOperationsUser()) {
90+
changed = seedOperationsIndexPatterns(context, client, kibanaVersion, projectPrefix);
91+
} else {
92+
changed = seedUsersIndexPatterns(context, client, kibanaVersion, projectPrefix);
93+
}
94+
95+
if ( changed ) {
96+
pluginClient.refreshIndices(context.getKibanaIndex());
97+
}
98+
}
9299

100+
private boolean seedOperationsIndexPatterns(final OpenshiftRequestContext context, final Client client, String kibanaVersion, final String projectPrefix) {
101+
boolean changed = false;
102+
boolean defaultSet = false;
103+
for (String pattern : settings.getKibanaOpsIndexPatterns()) {
104+
if(!pluginClient.documentExists(context.getKibanaIndex(), INDICIES_TYPE, pattern)) {
105+
LOGGER.trace("Creating index-pattern '{}'", pattern);
106+
String source = StringUtils.replace(mappingLoader.getOperationsMappingsTemplate(), "$TITLE$", pattern);
107+
pluginClient.createDocument(context.getKibanaIndex(), INDICIES_TYPE, pattern, source);
108+
if (!defaultSet) {
109+
try {
110+
String update = XContentFactory.jsonBuilder()
111+
.startObject()
112+
.field(KibanaSeed.DEFAULT_INDEX_FIELD, pattern)
113+
.endObject().string();
114+
pluginClient.update(context.getKibanaIndex(), DEFAULT_INDEX_TYPE, kibanaVersion, update);
115+
defaultSet = true;
116+
} catch (IOException e) {
117+
LOGGER.error("Unable to set default index-pattern", e);
118+
}
119+
}
120+
changed = true;
121+
}
122+
}
123+
return changed;
124+
}
125+
126+
private boolean seedUsersIndexPatterns(final OpenshiftRequestContext context, final Client client, final String kibanaVersion, final String projectPrefix) {
127+
boolean changed = false;
93128
// GET .../.kibana/index-pattern/_search?pretty=true&fields=
94129
// compare results to projects; handle any deltas (create, delete?)
95-
96130
Set<String> indexPatterns = getProjectNamesFromIndexes(context, client, projectPrefix);
97131
LOGGER.debug("Found '{}' Index patterns for user", indexPatterns.size());
98132

99133
Set<String> projects = new HashSet<>(context.getProjects());
100-
if(context.isOperationsUser()) {
101-
projects.add(OPERATIONS_PROJECT);
102-
}
103134
List<String> filteredProjects = new ArrayList<String>(filterProjectsWithIndices(projectPrefix, projects));
104135
LOGGER.debug("projects for '{}' that have existing indexes: '{}'", context.getUser(), filteredProjects);
105136

106-
if (context.isOperationsUser()) {
107-
filteredProjects.add(ADMIN_ALIAS_NAME);
108-
}else if (filteredProjects.isEmpty()) {
137+
if (filteredProjects.isEmpty()) {
109138
filteredProjects.add(BLANK_PROJECT);
110139
}
111140

@@ -156,12 +185,9 @@ public void setDashboards(final OpenshiftRequestContext context, Client client,
156185
}
157186
}
158187
}
159-
160-
if ( changed ) {
161-
refreshKibanaUser(context.getKibanaIndex(), client);
162-
}
188+
return changed;
163189
}
164-
190+
165191
/*
166192
* Given a list of projects, filter out those which do not have any
167193
* index associated with it
@@ -177,16 +203,6 @@ private List<String> filterProjectsWithIndices(final String projectPrefix, Set<S
177203
return result;
178204
}
179205

180-
private void refreshKibanaUser(String kibanaIndex, Client esClient) {
181-
182-
RefreshRequest request = new RefreshRequest().indices(kibanaIndex);
183-
request.putHeader(ConfigConstants.SG_CONF_REQUEST_HEADER, "true");
184-
RefreshResponse response = esClient.admin().indices().refresh(request).actionGet();
185-
186-
LOGGER.debug("Refreshed '{}' successfully on {} of {} shards", kibanaIndex, response.getSuccessfulShards(),
187-
response.getTotalShards());
188-
}
189-
190206
private boolean initialSeedKibanaIndex(final OpenshiftRequestContext context, Client esClient) {
191207

192208
try {
@@ -197,29 +213,7 @@ private boolean initialSeedKibanaIndex(final OpenshiftRequestContext context, Cl
197213
// copy the defaults if the userindex is not the kibanaindex
198214
if (!kibanaIndexExists && !defaultKibanaIndex.equals(userIndex)) {
199215
LOGGER.debug("Copying '{}' to '{}'", defaultKibanaIndex, userIndex);
200-
201-
GetIndexRequest getRequest = new GetIndexRequest().indices(defaultKibanaIndex);
202-
getRequest.putHeader(ConfigConstants.SG_CONF_REQUEST_HEADER, "true");
203-
GetIndexResponse getResponse = esClient.admin().indices().getIndex(getRequest).get();
204-
205-
CreateIndexRequest createRequest = new CreateIndexRequest().index(userIndex);
206-
createRequest.putHeader(ConfigConstants.SG_CONF_REQUEST_HEADER, "true");
207-
208-
createRequest.settings(getResponse.settings().get(defaultKibanaIndex));
209-
210-
Map<String, Object> configMapping = getResponse.mappings().get(defaultKibanaIndex).get("config")
211-
.getSourceAsMap();
212-
213-
createRequest.mapping("config", configMapping);
214-
215-
esClient.admin().indices().create(createRequest).actionGet();
216-
217-
// Wait for health status of YELLOW
218-
ClusterHealthRequest healthRequest = new ClusterHealthRequest().indices(new String[] { userIndex })
219-
.waitForYellowStatus();
220-
221-
esClient.admin().cluster().health(healthRequest).actionGet().getStatus();
222-
216+
pluginClient.copyIndex(defaultKibanaIndex, userIndex, DEFAULT_INDEX_TYPE);
223217
return true;
224218
}
225219
} catch (ExecutionException | InterruptedException | IOException e) {
@@ -236,7 +230,7 @@ private void setDefaultIndex(String kibanaIndex, String project, Client esClient
236230
// .kibana.username
237231
String source = new DocumentBuilder().defaultIndex(getIndexPattern(project, projectPrefix)).build();
238232

239-
executeUpdate(kibanaIndex, DEFAULT_INDEX_TYPE, kibanaVersion, source, esClient);
233+
pluginClient.update(kibanaIndex, DEFAULT_INDEX_TYPE, kibanaVersion, source);
240234
}
241235

242236
private String getDefaultIndex(OpenshiftRequestContext context, Client esClient, String kibanaVersion, String projectPrefix) {
@@ -342,9 +336,7 @@ private void createIndexPattern(String kibanaIndex, String project, Client esCli
342336

343337
final String indexPattern = getIndexPattern(project, projectPrefix);
344338
String source;
345-
if (project.equalsIgnoreCase(OPERATIONS_PROJECT) || project.startsWith(ADMIN_ALIAS_NAME)) {
346-
source = mappingLoader.getOperationsMappingsTemplate();
347-
} else if (project.equalsIgnoreCase(BLANK_PROJECT)) {
339+
if (project.equalsIgnoreCase(BLANK_PROJECT)) {
348340
source = mappingLoader.getEmptyProjectMappingsTemplate();
349341
} else {
350342
source = mappingLoader.getApplicationMappingsTemplate();
@@ -364,17 +356,6 @@ private void deleteIndex(String kibanaIndex, String project, Client esClient, St
364356
executeDelete(kibanaIndex, INDICIES_TYPE, getIndexPattern(project, projectPrefix), esClient);
365357
}
366358

367-
private void executeUpdate(String index, String type, String id, String source, Client esClient) {
368-
369-
LOGGER.debug("UPDATE: '{}/{}/{}' source: '{}'", index, type, id, source);
370-
371-
UpdateRequest request = esClient.prepareUpdate(index, type, id).setDoc(source).setDocAsUpsert(true).request();
372-
request.putHeader(ConfigConstants.SG_CONF_REQUEST_HEADER, "true");
373-
374-
375-
LOGGER.debug("Created with update? '{}'", esClient.update(request).actionGet().isCreated());
376-
}
377-
378359
private void executeDelete(String index, String type, String id, Client esClient) {
379360

380361
LOGGER.debug("DELETE: '{}/{}/{}'", index, type, id);

0 commit comments

Comments
 (0)