-
Notifications
You must be signed in to change notification settings - Fork 8.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Expose current Prometheus config via /status/config #2711
Conversation
web/api/v1/api.go
Outdated
@@ -103,17 +103,21 @@ type API struct { | |||
targetRetriever targetRetriever | |||
alertmanagerRetriever alertmanagerRetriever | |||
|
|||
now func() model.Time | |||
now func() model.Time | |||
retrieveConfigString configStringFunc |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just call it config
and make it a plain func() string
. Not everything needs a dedicated type, especially if it's such a one-off thing.
@fabxc Updated PR, renamed to |
#2722 might make us want to reconsider this and switch to properly marshalled configs. |
web/api/v1/api.go
Outdated
@@ -436,6 +440,17 @@ func (api *API) alertmanagers(r *http.Request) (interface{}, *apiError) { | |||
return ams, nil | |||
} | |||
|
|||
type prometheusConfig struct { | |||
RawFormat string `json:"rawFormat"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if rawFormat is the best name here. I might be wrong, but isn't this the representation without comments, secrets and reformatted by our printer?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agreed, as this is parsed and marshaled again to yaml, it makes most sense to call this maybe yaml
instead
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed to YAML
and yaml
. Thanks for the review!
lgtm |
I thought we changed our mind about this since we are no longer preserving the actual text input but actually re-marshal the parsed YAML. Without the original comments there's no real value in providing embedded YAML over JSON here. |
@fabxc You are right. Sorry about that. Do you want to provide both, or just JSON? |
No worries. I think any client that wants to show YAML can just implement the conversion themselves, so just JSON seems fine. I'm wondering though, since we have quite a few more things in our status tab in the UI, whether we really want to have a distinct endpoint for each or whether we should just have a single one that has an object with all pieces of data we show on those pages. The endpoint should be hit very rarely (for health checks we want to implement a dedicated endpoint), so I don't see any performance concerns around that. |
My instinct would be one endpoint for each type. Some of the things we're going on have on the status pages as we grow them will get pretty heavy, and not as dumb as the config file. |
Okay, fine too. |
e4f28db
to
e5bd75c
Compare
@fabxc @brian-brazil I have added the following changes:
Let me know what you think. Make sure to also review |
Duplicating this logic is risky security wise, especially as features created here will be copied by other repos. I think we should stick with one format. |
@brian-brazil You mean either changing the front-end to JSON or exposing YAML via the API endpoint? |
I'd go for the latter. Mixing JSON and YAML would cause confusion I expect. |
@brian-brazil I think exposing YAML in a pure JSON api is not a great user experience. One workaround would be to first marshal the config as YAML, which would elide all secrets, and then convert YAML to JSON which is then exposed via the API. It turns out to be quite costly to implement that from scratch, so I would prefer using something like Second alternative would be to switch the Prometheus What do you think? |
@brian-brazil more precisely, the YAML unmarshaller creates |
I don't think there's a perfect solution here. I'd view it more as an opaque config string (which happens to be in YAML), being returned via an RPC mechanism (which happens to be JSON). |
The config is structured data. What's the point of exposing it as an opaque string? |
If the goal is to view the current configuration (as we currently have on the status page), then that's sufficient. I'm not imagining too much processing of the config beyond checking that the right config is loaded. |
@fabxc @brian-brazil I still find it inconsistent to (only) expose YAML on a JSON API. E.g. for the Prometheus Operator we would like to process the returned config. Would one of these two options work:
|
That's kinda like arguing that if you're returning HTML over a JSON API you should convert its XML structure to JSON first. I don't see an inconsistency here, what serialisation protocol you're using for RPCs shouldn't automatically affect what data you're transporting. |
Returning HTML over a JSON API is an equally bad idea :)
…On Fri, Jul 14, 2017, 6:26 PM Brian Brazil ***@***.***> wrote:
I still find it inconsistent to (only) expose YAML on a JSON API.
That's kinda like arguing that if you're returning HTML over a JSON API
you should convert its XML structure to JSON first. I don't see an
inconsistency here, what serialisation protocol you're using for RPCs
shouldn't automatically affect what data you're transporting.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#2711 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AEuA8gQQ2Q6jIPOgJWiQsZn7kpnnTTnKks5sN5algaJpZM4NYLOC>
.
|
The config is structured data. Showing it as YAML again in a UI is one
possibility. But it shouldn't dictate the API
On Fri, Jul 14, 2017, 11:23 PM Fabian Reinartz <fab.reinartz@gmail.com>
wrote:
… Returning HTML over a JSON API is an equally bad idea :)
On Fri, Jul 14, 2017, 6:26 PM Brian Brazil ***@***.***>
wrote:
> I still find it inconsistent to (only) expose YAML on a JSON API.
>
> That's kinda like arguing that if you're returning HTML over a JSON API
> you should convert its XML structure to JSON first. I don't see an
> inconsistency here, what serialisation protocol you're using for RPCs
> shouldn't automatically affect what data you're transporting.
>
> —
> You are receiving this because you were mentioned.
>
>
> Reply to this email directly, view it on GitHub
> <#2711 (comment)>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AEuA8gQQ2Q6jIPOgJWiQsZn7kpnnTTnKks5sN5algaJpZM4NYLOC>
> .
>
|
When we've the proto/GRPC variant of this API, would you have that also return JSON or should it be a proto version of the config? |
The latter
…On Fri, Jul 14, 2017, 11:45 PM Brian Brazil ***@***.***> wrote:
When we've the proto variant of this API, would you have that also return
JSON or should it be a proto version of the config?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#2711 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AEuA8t1dZ9GCbfu3VSFaKwRH3Evr6FMJks5sN-F9gaJpZM4NYLOC>
.
|
You're internally consistent anyway, but that'd be a silly amount of maintenance effort as you'd have to keep a separate copy of the config structure in proto to get all the field numbers right - and that'd also not be forwards compatible for any new fields added. I don't think changing the packet format to match that of the frame is at all sane. |
Looking at this from another direction, what would be the objection to expecting users of this to parse the YAML on their end? What are the use cases for doing so? Keep in mind that it is our goal ultimately to have comments back in the marshalled config, we just can't do that currently due to secrets. |
732434d
to
e5d1824
Compare
I have updated the PR to expose the config in YAML format. Just in case we ever want to expose the config as JSON, instead of writing the JSON format strings all over again, they can be found here: https://github.com/mxinden/prometheus/tree/api-config-json-backup |
👍 You have conflicts. |
@brian-brazil Thanks for the hint. Rebased. |
@@ -74,7 +74,7 @@ func (h *Handler) federation(w http.ResponseWriter, req *http.Request) { | |||
} | |||
sort.Sort(byName(vector)) | |||
|
|||
externalLabels := h.externalLabels.Clone() | |||
externalLabels := h.config.GlobalConfig.ExternalLabels.Clone() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is intended to be part of this PR right? I think something may have gone wrong when rebasing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@brancz Instead of having configString
and externalLabels
in the Handler
struct, I propose with this PR just having the config
itself in there. Whenever we need externalLabels
and configString
we can get it from Handler.config.String()
and Handler.config.GlobalConfig.ExternalLabels
.
I find this cleaner. In addition it enables us to access more than just the external labels and the config string in both web.go and api.go in the future. @brancz What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gotcha, fine with it, just wanted to make sure this was intentional as you just rebased.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@brancz Appreciate the mindfulness!
lgtm 👍 |
I am not a member of the Prometheus GitHub organization. Thereby I am not able to merge here. @brancz @fabxc @brian-brazil In case you have no further objections, could you merge this PR? |
Hmm, you're on -team so you should be in the org. Invite sent. |
@brian-brazil Thanks for the invitation! @brancz and @brian-brazil I had to do one more fix here: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
config/config_test.go
Outdated
@@ -540,15 +540,27 @@ func TestLoadConfig(t *testing.T) { | |||
if !reflect.DeepEqual(c, expectedConf) { | |||
t.Fatalf("%s: unexpected config result: \n\n%s\n expected\n\n%s", "testdata/conf.good.yml", bgot, bexp) | |||
} | |||
} | |||
|
|||
// YAML marsheling must not reveal authentication credentials. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
marshalling
This PR adds the `/status/config` endpoint which exposes the currently loaded Prometheus config. This is the same config that is displayed on `/config` in the UI in YAML format. The response payload looks like such: ``` { "status": "success", "data": { "yaml": <CONFIG> } } ```
This PR adds the
/status/config
endpoint which exposes the currentlyloaded Prometheus config. This is the same config that is displayed on
/config
in the UI. The response payload looks like such:Related to PR #2600 and issue #2467