prometheus
110 строк · 3.3 Кб
1// Copyright 2020 The Prometheus Authors
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14package eureka
15
16import (
17"context"
18"encoding/xml"
19"fmt"
20"io"
21"net/http"
22
23"github.com/prometheus/common/version"
24)
25
26var userAgent = fmt.Sprintf("Prometheus/%s", version.Version)
27
28type Applications struct {
29VersionsDelta int `xml:"versions__delta"`
30AppsHashcode string `xml:"apps__hashcode"`
31Applications []Application `xml:"application"`
32}
33
34type Application struct {
35Name string `xml:"name"`
36Instances []Instance `xml:"instance"`
37}
38
39type Port struct {
40Port int `xml:",chardata"`
41Enabled bool `xml:"enabled,attr"`
42}
43
44type Instance struct {
45HostName string `xml:"hostName"`
46HomePageURL string `xml:"homePageUrl"`
47StatusPageURL string `xml:"statusPageUrl"`
48HealthCheckURL string `xml:"healthCheckUrl"`
49App string `xml:"app"`
50IPAddr string `xml:"ipAddr"`
51VipAddress string `xml:"vipAddress"`
52SecureVipAddress string `xml:"secureVipAddress"`
53Status string `xml:"status"`
54Port *Port `xml:"port"`
55SecurePort *Port `xml:"securePort"`
56DataCenterInfo *DataCenterInfo `xml:"dataCenterInfo"`
57Metadata *MetaData `xml:"metadata"`
58IsCoordinatingDiscoveryServer bool `xml:"isCoordinatingDiscoveryServer"`
59ActionType string `xml:"actionType"`
60CountryID int `xml:"countryId"`
61InstanceID string `xml:"instanceId"`
62}
63
64type MetaData struct {
65Items []Tag `xml:",any"`
66}
67
68type Tag struct {
69XMLName xml.Name
70Content string `xml:",innerxml"`
71}
72
73type DataCenterInfo struct {
74Name string `xml:"name"`
75Class string `xml:"class,attr"`
76Metadata *MetaData `xml:"metadata"`
77}
78
79const appListPath string = "/apps"
80
81func fetchApps(ctx context.Context, server string, client *http.Client) (*Applications, error) {
82url := fmt.Sprintf("%s%s", server, appListPath)
83
84request, err := http.NewRequest(http.MethodGet, url, nil)
85if err != nil {
86return nil, err
87}
88request = request.WithContext(ctx)
89request.Header.Add("User-Agent", userAgent)
90
91resp, err := client.Do(request)
92if err != nil {
93return nil, err
94}
95defer func() {
96io.Copy(io.Discard, resp.Body)
97resp.Body.Close()
98}()
99
100if resp.StatusCode/100 != 2 {
101return nil, fmt.Errorf("non 2xx status '%d' response during eureka service discovery", resp.StatusCode)
102}
103
104var apps Applications
105err = xml.NewDecoder(resp.Body).Decode(&apps)
106if err != nil {
107return nil, fmt.Errorf("%q: %w", url, err)
108}
109return &apps, nil
110}
111