forked from jenkinsci/opentelemetry-plugin
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathElasticLogsBackendWithJenkinsVisualization.java
More file actions
207 lines (182 loc) · 8.43 KB
/
ElasticLogsBackendWithJenkinsVisualization.java
File metadata and controls
207 lines (182 loc) · 8.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
/*
* Copyright The Original Author or Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.jenkins.plugins.opentelemetry.backend.elastic;
import com.cloudbees.plugins.credentials.common.StandardListBoxModel;
import com.cloudbees.plugins.credentials.common.StandardUsernameCredentials;
import com.google.errorprone.annotations.MustBeClosed;
import edu.umd.cs.findbugs.annotations.CheckForNull;
import groovy.text.Template;
import hudson.Extension;
import hudson.Util;
import hudson.model.Item;
import hudson.security.ACL;
import hudson.util.FormValidation;
import hudson.util.ListBoxModel;
import io.jenkins.plugins.opentelemetry.TemplateBindingsProvider;
import io.jenkins.plugins.opentelemetry.backend.ObservabilityBackend;
import io.jenkins.plugins.opentelemetry.jenkins.CredentialsNotFoundException;
import io.jenkins.plugins.opentelemetry.jenkins.HttpAuthHeaderFactory;
import io.jenkins.plugins.opentelemetry.job.log.LogStorageRetriever;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.logging.Logger;
import jenkins.model.Jenkins;
import org.apache.commons.lang3.StringUtils;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.DataBoundSetter;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.interceptor.RequirePOST;
public class ElasticLogsBackendWithJenkinsVisualization extends ElasticLogsBackend {
private static final String MSG_ELASTICSEARCH_URL_IS_BLANK =
"Elasticsearch URL is blank, logs will not be stored in Elasticsearch";
private static final Logger logger = Logger.getLogger(ElasticLogsBackendWithJenkinsVisualization.class.getName());
private String elasticsearchUrl;
private boolean disableSslVerifications;
private String elasticsearchCredentialsId;
@DataBoundConstructor
public ElasticLogsBackendWithJenkinsVisualization() {}
@Override
@MustBeClosed
public LogStorageRetriever newLogStorageRetriever(TemplateBindingsProvider templateBindingsProvider) {
Template buildLogsVisualizationUrlTemplate = getBuildLogsVisualizationUrlTemplate();
if (StringUtils.isBlank(elasticsearchUrl)) {
logger.warning(MSG_ELASTICSEARCH_URL_IS_BLANK);
throw new IllegalStateException(MSG_ELASTICSEARCH_URL_IS_BLANK);
} else {
return new ElasticsearchLogStorageRetriever(
this.elasticsearchUrl,
disableSslVerifications,
elasticsearchCredentialsId,
buildLogsVisualizationUrlTemplate,
templateBindingsProvider);
}
}
@DataBoundSetter
public void setElasticsearchCredentialsId(@CheckForNull String elasticsearchCredentialsId) {
this.elasticsearchCredentialsId = elasticsearchCredentialsId;
}
@CheckForNull
public String getElasticsearchCredentialsId() {
return elasticsearchCredentialsId;
}
@CheckForNull
public String getElasticsearchUrl() {
return elasticsearchUrl;
}
@DataBoundSetter
public void setElasticsearchUrl(@CheckForNull String elasticsearchUrl) {
this.elasticsearchUrl = Util.fixNull(elasticsearchUrl);
}
public boolean isDisableSslVerifications() {
return disableSslVerifications;
}
@DataBoundSetter
public void setDisableSslVerifications(boolean disableSslVerifications) {
this.disableSslVerifications = disableSslVerifications;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ElasticLogsBackendWithJenkinsVisualization that = (ElasticLogsBackendWithJenkinsVisualization) o;
return Objects.equals(elasticsearchUrl, that.elasticsearchUrl)
&& Objects.equals(disableSslVerifications, that.disableSslVerifications)
&& Objects.equals(elasticsearchCredentialsId, that.elasticsearchCredentialsId);
}
@Override
public int hashCode() {
return Objects.hash(elasticsearchUrl, disableSslVerifications, elasticsearchCredentialsId);
}
@Override
public String toString() {
return "ElasticLogsBackendWithVisualizationJenkins{" + "elasticsearchUrl='"
+ elasticsearchUrl + '\'' + ", disableSslVerifications='"
+ disableSslVerifications + '\'' + ", elasticsearchCredentialsId='"
+ elasticsearchCredentialsId + '\'' + '}';
}
@Extension(ordinal = 0)
public static class DescriptorImpl extends ElasticLogsBackend.DescriptorImpl {
@Override
public String getDisplayName() {
return "Store pipeline logs In Elastic and visualize logs both in Elastic and through Jenkins";
}
@RequirePOST
public FormValidation doCheckElasticsearchUrl(@QueryParameter("elasticsearchUrl") String url) {
if (!isAuthorized()) {
return FormValidation.error("You do not have permission to configure this setting.");
}
if (StringUtils.isEmpty(url)) {
return FormValidation.ok();
}
try {
new URI(url).toURL();
} catch (URISyntaxException | MalformedURLException | IllegalArgumentException e) {
return FormValidation.error("Invalid URL: " + e.getMessage());
}
return FormValidation.ok();
}
@RequirePOST
public ListBoxModel doFillElasticsearchCredentialsIdItems(@QueryParameter String elasticsearchCredentialsId) {
if (!isAuthorized()) {
return new StandardListBoxModel();
}
return new StandardListBoxModel()
.includeEmptyValue()
.includeAs(ACL.SYSTEM2, (Item) null, StandardUsernameCredentials.class)
.includeCurrentValue(elasticsearchCredentialsId);
}
@RequirePOST
public FormValidation doCheckElasticsearchCredentialsId(@QueryParameter String elasticsearchCredentialsId) {
if (!isAuthorized()) {
return FormValidation.error("You do not have permission to configure this setting.");
}
if (elasticsearchCredentialsId == null || elasticsearchCredentialsId.isEmpty()) {
return FormValidation.error("Elasticsearch credentials are missing");
}
try {
new HttpAuthHeaderFactory(elasticsearchCredentialsId).createAuthHeader();
} catch (CredentialsNotFoundException e) {
return FormValidation.error("Elasticsearch credentials are not valid");
}
return FormValidation.ok();
}
@RequirePOST
public FormValidation doValidate(
@QueryParameter String elasticsearchUrl,
@QueryParameter boolean disableSslVerifications,
@QueryParameter String elasticsearchCredentialsId) {
if (!isAuthorized()) {
return FormValidation.error("You do not have permission to configure this setting.");
}
FormValidation elasticsearchUrlValidation = doCheckElasticsearchUrl(elasticsearchUrl);
if (elasticsearchUrlValidation.kind != FormValidation.Kind.OK) {
return elasticsearchUrlValidation;
}
try (ElasticsearchLogStorageRetriever elasticsearchLogStorageRetriever =
new ElasticsearchLogStorageRetriever(
elasticsearchUrl,
disableSslVerifications,
elasticsearchCredentialsId,
ObservabilityBackend.ERROR_TEMPLATE,
TemplateBindingsProvider.empty())) {
return FormValidation.aggregate(elasticsearchLogStorageRetriever.checkElasticsearchSetup());
} catch (NoSuchElementException e) {
return FormValidation.error("No credentials found for id '" + elasticsearchCredentialsId + "'");
} catch (Exception e) {
return FormValidation.error(e, e.getMessage());
}
}
/**
* Checks if the user has permission to configure the backend.
* @return true if the user is authorized, false otherwise
*/
private boolean isAuthorized() {
return Jenkins.get().hasPermission(Jenkins.ADMINISTER);
}
}
}