mirror of
https://github.com/prometheus/prometheus.git
synced 2025-01-11 22:07:27 -08:00
Merge branch 'master' into dev-2.0
This commit is contained in:
commit
ca2b68889b
19
CHANGELOG.md
19
CHANGELOG.md
|
@ -1,3 +1,22 @@
|
|||
## 1.7.0 / 2017-06-06
|
||||
|
||||
* [CHANGE] Compress remote storage requests and responses with unframed/raw snappy.
|
||||
* [CHANGE] Properly ellide secrets in config.
|
||||
* [FEATURE] Add OpenStack service discovery.
|
||||
* [FEATURE] Add ability to limit Kubernetes service discovery to certain namespaces.
|
||||
* [FEATURE] Add metric for discovered number of Alertmanagers.
|
||||
* [ENHANCEMENT] Print system information (uname) on start up.
|
||||
* [ENHANCEMENT] Show gaps in graphs on expression browser.
|
||||
* [ENHANCEMENT] Promtool linter checks counter naming and more reserved labels.
|
||||
* [BUGFIX] Fix broken Mesos discovery.
|
||||
* [BUGFIX] Fix redirect when external URL is set.
|
||||
* [BUGFIX] Fix mutation of active alert elements by notifier.
|
||||
* [BUGFIX] Fix HTTP error handling for remote write.
|
||||
* [BUGFIX] Fix builds for Solaris/Illumos.
|
||||
* [BUGFIX] Fix overflow checking in global config.
|
||||
* [BUGFIX] Fix log level reporting issue.
|
||||
* [BUGFIX] Fix ZooKeeper serverset discovery can become out-of-sync.
|
||||
|
||||
## 1.6.3 / 2017-05-18
|
||||
|
||||
* [BUGFIX] Fix disappearing Alertmanger targets in Alertmanager discovery.
|
||||
|
|
|
@ -23,6 +23,8 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws/ec2metadata"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/prometheus/common/model"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
@ -1134,7 +1136,16 @@ func (c *EC2SDConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|||
return err
|
||||
}
|
||||
if c.Region == "" {
|
||||
return fmt.Errorf("EC2 SD configuration requires a region")
|
||||
sess, err := session.NewSession()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
metadata := ec2metadata.New(sess)
|
||||
region, err := metadata.Region()
|
||||
if err != nil {
|
||||
return fmt.Errorf("EC2 SD configuration requires a region")
|
||||
}
|
||||
c.Region = region
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import (
|
|||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/common/model"
|
||||
|
@ -27,11 +28,11 @@ import (
|
|||
// Function represents a function of the expression language and is
|
||||
// used by function nodes.
|
||||
type Function struct {
|
||||
Name string
|
||||
ArgTypes []ValueType
|
||||
OptionalArgs int
|
||||
ReturnType ValueType
|
||||
Call func(ev *evaluator, args Expressions) Value
|
||||
Name string
|
||||
ArgTypes []ValueType
|
||||
Variadic int
|
||||
ReturnType ValueType
|
||||
Call func(ev *evaluator, args Expressions) Value
|
||||
}
|
||||
|
||||
// === time() float64 ===
|
||||
|
@ -876,6 +877,56 @@ func funcVector(ev *evaluator, args Expressions) Value {
|
|||
}
|
||||
}
|
||||
|
||||
// === label_join(vector model.ValVector, dest_labelname, separator, src_labelname...) Vector ===
|
||||
func funcLabelJoin(ev *evaluator, args Expressions) Value {
|
||||
var (
|
||||
vector = ev.evalVector(args[0])
|
||||
dst = ev.evalString(args[1]).V
|
||||
sep = ev.evalString(args[2]).V
|
||||
srcLabels = make([]string, len(args)-3)
|
||||
)
|
||||
for i := 3; i < len(args); i++ {
|
||||
src := ev.evalString(args[i]).V
|
||||
if !model.LabelName(src).IsValid() {
|
||||
ev.errorf("invalid source label name in label_join(): %s", src)
|
||||
}
|
||||
srcLabels[i-3] = src
|
||||
}
|
||||
|
||||
if !model.LabelName(dst).IsValid() {
|
||||
ev.errorf("invalid destination label name in label_join(): %s", dst)
|
||||
}
|
||||
|
||||
outSet := make(map[uint64]struct{}, len(vector))
|
||||
for i := range vector {
|
||||
el := &vector[i]
|
||||
|
||||
srcVals := make([]string, len(srcLabels))
|
||||
for i, src := range srcLabels {
|
||||
srcVals[i] = el.Metric.Get(src)
|
||||
}
|
||||
|
||||
lb := labels.NewBuilder(el.Metric)
|
||||
|
||||
strval := strings.Join(srcVals, sep)
|
||||
if strval == "" {
|
||||
lb.Del(dst)
|
||||
} else {
|
||||
lb.Set(dst, strval)
|
||||
}
|
||||
|
||||
el.Metric = lb.Labels()
|
||||
h := el.Metric.Hash()
|
||||
|
||||
if _, exists := outSet[h]; exists {
|
||||
ev.errorf("duplicated label set in output of label_join(): %s", el.Metric)
|
||||
} else {
|
||||
outSet[h] = struct{}{}
|
||||
}
|
||||
}
|
||||
return vector
|
||||
}
|
||||
|
||||
// Common code for date related functions.
|
||||
func dateWrapper(ev *evaluator, args Expressions, f func(time.Time) float64) Value {
|
||||
var v Vector
|
||||
|
@ -1004,25 +1055,25 @@ var functions = map[string]*Function{
|
|||
Call: funcCountScalar,
|
||||
},
|
||||
"days_in_month": {
|
||||
Name: "days_in_month",
|
||||
ArgTypes: []ValueType{ValueTypeVector},
|
||||
OptionalArgs: 1,
|
||||
ReturnType: ValueTypeVector,
|
||||
Call: funcDaysInMonth,
|
||||
Name: "days_in_month",
|
||||
ArgTypes: []ValueType{ValueTypeVector},
|
||||
Variadic: 1,
|
||||
ReturnType: ValueTypeVector,
|
||||
Call: funcDaysInMonth,
|
||||
},
|
||||
"day_of_month": {
|
||||
Name: "day_of_month",
|
||||
ArgTypes: []ValueType{ValueTypeVector},
|
||||
OptionalArgs: 1,
|
||||
ReturnType: ValueTypeVector,
|
||||
Call: funcDayOfMonth,
|
||||
Name: "day_of_month",
|
||||
ArgTypes: []ValueType{ValueTypeVector},
|
||||
Variadic: 1,
|
||||
ReturnType: ValueTypeVector,
|
||||
Call: funcDayOfMonth,
|
||||
},
|
||||
"day_of_week": {
|
||||
Name: "day_of_week",
|
||||
ArgTypes: []ValueType{ValueTypeVector},
|
||||
OptionalArgs: 1,
|
||||
ReturnType: ValueTypeVector,
|
||||
Call: funcDayOfWeek,
|
||||
Name: "day_of_week",
|
||||
ArgTypes: []ValueType{ValueTypeVector},
|
||||
Variadic: 1,
|
||||
ReturnType: ValueTypeVector,
|
||||
Call: funcDayOfWeek,
|
||||
},
|
||||
"delta": {
|
||||
Name: "delta",
|
||||
|
@ -1067,11 +1118,11 @@ var functions = map[string]*Function{
|
|||
Call: funcHoltWinters,
|
||||
},
|
||||
"hour": {
|
||||
Name: "hour",
|
||||
ArgTypes: []ValueType{ValueTypeVector},
|
||||
OptionalArgs: 1,
|
||||
ReturnType: ValueTypeVector,
|
||||
Call: funcHour,
|
||||
Name: "hour",
|
||||
ArgTypes: []ValueType{ValueTypeVector},
|
||||
Variadic: 1,
|
||||
ReturnType: ValueTypeVector,
|
||||
Call: funcHour,
|
||||
},
|
||||
"idelta": {
|
||||
Name: "idelta",
|
||||
|
@ -1097,6 +1148,13 @@ var functions = map[string]*Function{
|
|||
ReturnType: ValueTypeVector,
|
||||
Call: funcLabelReplace,
|
||||
},
|
||||
"label_join": {
|
||||
Name: "label_join",
|
||||
ArgTypes: []ValueType{ValueTypeVector, ValueTypeString, ValueTypeString, ValueTypeString},
|
||||
Variadic: -1,
|
||||
ReturnType: ValueTypeVector,
|
||||
Call: funcLabelJoin,
|
||||
},
|
||||
"ln": {
|
||||
Name: "ln",
|
||||
ArgTypes: []ValueType{ValueTypeVector},
|
||||
|
@ -1128,18 +1186,18 @@ var functions = map[string]*Function{
|
|||
Call: funcMinOverTime,
|
||||
},
|
||||
"minute": {
|
||||
Name: "minute",
|
||||
ArgTypes: []ValueType{ValueTypeVector},
|
||||
OptionalArgs: 1,
|
||||
ReturnType: ValueTypeVector,
|
||||
Call: funcMinute,
|
||||
Name: "minute",
|
||||
ArgTypes: []ValueType{ValueTypeVector},
|
||||
Variadic: 1,
|
||||
ReturnType: ValueTypeVector,
|
||||
Call: funcMinute,
|
||||
},
|
||||
"month": {
|
||||
Name: "month",
|
||||
ArgTypes: []ValueType{ValueTypeVector},
|
||||
OptionalArgs: 1,
|
||||
ReturnType: ValueTypeVector,
|
||||
Call: funcMonth,
|
||||
Name: "month",
|
||||
ArgTypes: []ValueType{ValueTypeVector},
|
||||
Variadic: 1,
|
||||
ReturnType: ValueTypeVector,
|
||||
Call: funcMonth,
|
||||
},
|
||||
"predict_linear": {
|
||||
Name: "predict_linear",
|
||||
|
@ -1166,11 +1224,11 @@ var functions = map[string]*Function{
|
|||
Call: funcResets,
|
||||
},
|
||||
"round": {
|
||||
Name: "round",
|
||||
ArgTypes: []ValueType{ValueTypeVector, ValueTypeScalar},
|
||||
OptionalArgs: 1,
|
||||
ReturnType: ValueTypeVector,
|
||||
Call: funcRound,
|
||||
Name: "round",
|
||||
ArgTypes: []ValueType{ValueTypeVector, ValueTypeScalar},
|
||||
Variadic: 1,
|
||||
ReturnType: ValueTypeVector,
|
||||
Call: funcRound,
|
||||
},
|
||||
"scalar": {
|
||||
Name: "scalar",
|
||||
|
@ -1233,11 +1291,11 @@ var functions = map[string]*Function{
|
|||
Call: funcVector,
|
||||
},
|
||||
"year": {
|
||||
Name: "year",
|
||||
ArgTypes: []ValueType{ValueTypeVector},
|
||||
OptionalArgs: 1,
|
||||
ReturnType: ValueTypeVector,
|
||||
Call: funcYear,
|
||||
Name: "year",
|
||||
ArgTypes: []ValueType{ValueTypeVector},
|
||||
Variadic: 1,
|
||||
ReturnType: ValueTypeVector,
|
||||
Call: funcYear,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -713,6 +713,8 @@ Loop:
|
|||
switch l.next() {
|
||||
case '\\':
|
||||
lexEscape(l)
|
||||
case utf8.RuneError:
|
||||
return l.errorf("invalid UTF-8 rune")
|
||||
case eof, '\n':
|
||||
return l.errorf("unterminated quoted string")
|
||||
case l.stringOpen:
|
||||
|
@ -728,6 +730,8 @@ func lexRawString(l *lexer) stateFn {
|
|||
Loop:
|
||||
for {
|
||||
switch l.next() {
|
||||
case utf8.RuneError:
|
||||
return l.errorf("invalid UTF-8 rune")
|
||||
case eof:
|
||||
return l.errorf("unterminated raw string")
|
||||
case l.stringOpen:
|
||||
|
|
|
@ -396,6 +396,13 @@ var tests = []struct {
|
|||
}, {
|
||||
input: `]`, fail: true,
|
||||
},
|
||||
// Test encoding issues.
|
||||
{
|
||||
input: "\"\xff\"", fail: true,
|
||||
},
|
||||
{
|
||||
input: "`\xff`", fail: true,
|
||||
},
|
||||
// Test series description.
|
||||
{
|
||||
input: `{} _ 1 x .3`,
|
||||
|
|
|
@ -1094,13 +1094,23 @@ func (p *parser) checkType(node Node) (typ ValueType) {
|
|||
|
||||
case *Call:
|
||||
nargs := len(n.Func.ArgTypes)
|
||||
if na := nargs - n.Func.OptionalArgs; na > len(n.Args) {
|
||||
p.errorf("expected at least %d argument(s) in call to %q, got %d", na, n.Func.Name, len(n.Args))
|
||||
}
|
||||
if nargs < len(n.Args) {
|
||||
p.errorf("expected at most %d argument(s) in call to %q, got %d", nargs, n.Func.Name, len(n.Args))
|
||||
if n.Func.Variadic == 0 {
|
||||
if nargs != len(n.Args) {
|
||||
p.errorf("expected %d argument(s) in call to %q, got %d", nargs, n.Func.Name, len(n.Args))
|
||||
}
|
||||
} else {
|
||||
na := nargs - 1
|
||||
if na > len(n.Args) {
|
||||
p.errorf("expected at least %d argument(s) in call to %q, got %d", na, n.Func.Name, len(n.Args))
|
||||
} else if nargsmax := na + n.Func.Variadic; n.Func.Variadic > 0 && nargsmax < len(n.Args) {
|
||||
p.errorf("expected at most %d argument(s) in call to %q, got %d", nargsmax, n.Func.Name, len(n.Args))
|
||||
}
|
||||
}
|
||||
|
||||
for i, arg := range n.Args {
|
||||
if i >= len(n.Func.ArgTypes) {
|
||||
i = len(n.Func.ArgTypes) - 1
|
||||
}
|
||||
p.expectType(arg, n.Func.ArgTypes[i], fmt.Sprintf("call to function %q", n.Func.Name))
|
||||
}
|
||||
|
||||
|
|
|
@ -904,6 +904,10 @@ var testExpr = []struct {
|
|||
// TODO(fabxc): willingly lexing wrong tokens allows for more precrise error
|
||||
// messages from the parser - consider if this is an option.
|
||||
errMsg: "unexpected character inside braces: '>'",
|
||||
}, {
|
||||
input: "some_metric{a=\"\xff\"}",
|
||||
fail: true,
|
||||
errMsg: "parse error at char 15: invalid UTF-8 rune",
|
||||
}, {
|
||||
input: `foo{gibberish}`,
|
||||
fail: true,
|
||||
|
@ -1356,11 +1360,11 @@ var testExpr = []struct {
|
|||
}, {
|
||||
input: "floor()",
|
||||
fail: true,
|
||||
errMsg: "expected at least 1 argument(s) in call to \"floor\", got 0",
|
||||
errMsg: "expected 1 argument(s) in call to \"floor\", got 0",
|
||||
}, {
|
||||
input: "floor(some_metric, other_metric)",
|
||||
fail: true,
|
||||
errMsg: "expected at most 1 argument(s) in call to \"floor\", got 2",
|
||||
errMsg: "expected 1 argument(s) in call to \"floor\", got 2",
|
||||
}, {
|
||||
input: "floor(1)",
|
||||
fail: true,
|
||||
|
@ -1373,6 +1377,10 @@ var testExpr = []struct {
|
|||
input: "rate(some_metric)",
|
||||
fail: true,
|
||||
errMsg: "expected type range vector in call to function \"rate\", got instant vector",
|
||||
}, {
|
||||
input: "label_replace(a, `b`, `c\xff`, `d`, `.*`)",
|
||||
fail: true,
|
||||
errMsg: "parse error at char 23: invalid UTF-8 rune",
|
||||
},
|
||||
// Fuzzing regression tests.
|
||||
{
|
||||
|
|
38
promql/testdata/functions.test
vendored
38
promql/testdata/functions.test
vendored
|
@ -236,6 +236,44 @@ eval instant at 5s timestamp(metric)
|
|||
eval instant at 10s timestamp(metric)
|
||||
{} 10
|
||||
|
||||
# Tests for label_join.
|
||||
load 5m
|
||||
testmetric{src="a",src1="b",src2="c",dst="original-destination-value"} 0
|
||||
testmetric{src="d",src1="e",src2="f",dst="original-destination-value"} 1
|
||||
|
||||
# label_join joins all src values in order.
|
||||
eval instant at 0m label_join(testmetric, "dst", "-", "src", "src1", "src2")
|
||||
testmetric{src="a",src1="b",src2="c",dst="a-b-c"} 0
|
||||
testmetric{src="d",src1="e",src2="f",dst="d-e-f"} 1
|
||||
|
||||
# label_join treats non existent src labels as empty strings.
|
||||
eval instant at 0m label_join(testmetric, "dst", "-", "src", "src3", "src1")
|
||||
testmetric{src="a",src1="b",src2="c",dst="a--b"} 0
|
||||
testmetric{src="d",src1="e",src2="f",dst="d--e"} 1
|
||||
|
||||
# label_join overwrites the destination label even if the resulting dst label is empty string
|
||||
eval instant at 0m label_join(testmetric, "dst", "", "emptysrc", "emptysrc1", "emptysrc2")
|
||||
testmetric{src="a",src1="b",src2="c"} 0
|
||||
testmetric{src="d",src1="e",src2="f"} 1
|
||||
|
||||
# test without src label for label_join
|
||||
eval instant at 0m label_join(testmetric, "dst", ", ")
|
||||
testmetric{src="a",src1="b",src2="c"} 0
|
||||
testmetric{src="d",src1="e",src2="f"} 1
|
||||
|
||||
# test without dst label for label_join
|
||||
load 5m
|
||||
testmetric1{src="foo",src1="bar",src2="foobar"} 0
|
||||
testmetric1{src="fizz",src1="buzz",src2="fizzbuzz"} 1
|
||||
|
||||
# label_join creates dst label if not present.
|
||||
eval instant at 0m label_join(testmetric1, "dst", ", ", "src", "src1", "src2")
|
||||
testmetric1{src="foo",src1="bar",src2="foobar",dst="foo, bar, foobar"} 0
|
||||
testmetric1{src="fizz",src1="buzz",src2="fizzbuzz",dst="fizz, buzz, fizzbuzz"} 1
|
||||
|
||||
clear
|
||||
|
||||
# Tests for vector.
|
||||
eval instant at 0m vector(1)
|
||||
{} 1
|
||||
|
||||
|
|
|
@ -286,9 +286,6 @@ func (app relabelAppender) Add(lset labels.Labels, t int64, v float64) (string,
|
|||
// It returns a label set before relabeling was applied as the second return value.
|
||||
// Returns a nil label set if the target is dropped during relabeling.
|
||||
func populateLabels(lset labels.Labels, cfg *config.ScrapeConfig) (res, orig labels.Labels, err error) {
|
||||
if v := lset.Get(model.AddressLabel); v == "" {
|
||||
return nil, nil, fmt.Errorf("no address")
|
||||
}
|
||||
// Copy labels into the labelset for the target if they are not set already.
|
||||
scrapeLabels := []labels.Label{
|
||||
{Name: model.JobLabel, Value: cfg.JobName},
|
||||
|
@ -316,6 +313,9 @@ func populateLabels(lset labels.Labels, cfg *config.ScrapeConfig) (res, orig lab
|
|||
if lset == nil {
|
||||
return nil, nil, nil
|
||||
}
|
||||
if v := lset.Get(model.AddressLabel); v == "" {
|
||||
return nil, nil, fmt.Errorf("no address")
|
||||
}
|
||||
|
||||
lb = labels.NewBuilder(lset)
|
||||
|
||||
|
@ -362,7 +362,15 @@ func populateLabels(lset labels.Labels, cfg *config.ScrapeConfig) (res, orig lab
|
|||
if v := lset.Get(model.InstanceLabel); v == "" {
|
||||
lb.Set(model.InstanceLabel, addr)
|
||||
}
|
||||
return lb.Labels(), preRelabelLabels, nil
|
||||
|
||||
res = lb.Labels()
|
||||
for _, l := range res {
|
||||
// Check label values are valid, drop the target if not.
|
||||
if !model.LabelValue(l.Value).IsValid() {
|
||||
return nil, nil, fmt.Errorf("invalid label value for %q: %q", l.Name, l.Value)
|
||||
}
|
||||
}
|
||||
return res, preRelabelLabels, nil
|
||||
}
|
||||
|
||||
// targetsFromGroup builds targets based on the given TargetGroup and config.
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
package retrieval
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
|
@ -36,6 +37,7 @@ func TestPopulateLabels(t *testing.T) {
|
|||
cfg *config.ScrapeConfig
|
||||
res labels.Labels
|
||||
resOrig labels.Labels
|
||||
err error
|
||||
}{
|
||||
// Regular population of scrape config options.
|
||||
{
|
||||
|
@ -118,34 +120,104 @@ func TestPopulateLabels(t *testing.T) {
|
|||
model.JobLabel: "job",
|
||||
}),
|
||||
},
|
||||
// Apply relabeling.
|
||||
// Address label missing.
|
||||
{
|
||||
in: labels.FromMap(map[string]string{
|
||||
model.AddressLabel: "1.2.3.4:1000",
|
||||
"custom": "value",
|
||||
}),
|
||||
in: labels.FromStrings("custom", "value"),
|
||||
cfg: &config.ScrapeConfig{
|
||||
Scheme: "https",
|
||||
MetricsPath: "/metrics",
|
||||
JobName: "job",
|
||||
},
|
||||
res: nil,
|
||||
resOrig: nil,
|
||||
err: fmt.Errorf("no address"),
|
||||
},
|
||||
// Address label missing, but added in relabelling.
|
||||
{
|
||||
in: labels.FromStrings("custom", "host:1234"),
|
||||
cfg: &config.ScrapeConfig{
|
||||
Scheme: "https",
|
||||
MetricsPath: "/metrics",
|
||||
JobName: "job",
|
||||
RelabelConfigs: []*config.RelabelConfig{
|
||||
{
|
||||
Action: config.RelabelDrop,
|
||||
Regex: mustNewRegexp(".*"),
|
||||
SourceLabels: model.LabelNames{"job"},
|
||||
Action: config.RelabelReplace,
|
||||
Regex: mustNewRegexp("(.*)"),
|
||||
SourceLabels: model.LabelNames{"custom"},
|
||||
Replacement: "${1}",
|
||||
TargetLabel: string(model.AddressLabel),
|
||||
},
|
||||
},
|
||||
},
|
||||
res: labels.FromMap(map[string]string{
|
||||
model.AddressLabel: "host:1234",
|
||||
model.InstanceLabel: "host:1234",
|
||||
model.SchemeLabel: "https",
|
||||
model.MetricsPathLabel: "/metrics",
|
||||
model.JobLabel: "job",
|
||||
"custom": "host:1234",
|
||||
}),
|
||||
resOrig: labels.FromMap(map[string]string{
|
||||
model.SchemeLabel: "https",
|
||||
model.MetricsPathLabel: "/metrics",
|
||||
model.JobLabel: "job",
|
||||
"custom": "host:1234",
|
||||
}),
|
||||
},
|
||||
// Address label missing, but added in relabelling.
|
||||
{
|
||||
in: labels.FromStrings("custom", "host:1234"),
|
||||
cfg: &config.ScrapeConfig{
|
||||
Scheme: "https",
|
||||
MetricsPath: "/metrics",
|
||||
JobName: "job",
|
||||
RelabelConfigs: []*config.RelabelConfig{
|
||||
{
|
||||
Action: config.RelabelReplace,
|
||||
Regex: mustNewRegexp("(.*)"),
|
||||
SourceLabels: model.LabelNames{"custom"},
|
||||
Replacement: "${1}",
|
||||
TargetLabel: string(model.AddressLabel),
|
||||
},
|
||||
},
|
||||
},
|
||||
res: labels.FromMap(map[string]string{
|
||||
model.AddressLabel: "host:1234",
|
||||
model.InstanceLabel: "host:1234",
|
||||
model.SchemeLabel: "https",
|
||||
model.MetricsPathLabel: "/metrics",
|
||||
model.JobLabel: "job",
|
||||
"custom": "host:1234",
|
||||
}),
|
||||
resOrig: labels.FromMap(map[string]string{
|
||||
model.SchemeLabel: "https",
|
||||
model.MetricsPathLabel: "/metrics",
|
||||
model.JobLabel: "job",
|
||||
"custom": "host:1234",
|
||||
}),
|
||||
},
|
||||
// Invalid UTF-8 in label.
|
||||
{
|
||||
in: labels.FromMap(map[string]string{
|
||||
model.AddressLabel: "1.2.3.4:1000",
|
||||
"custom": "\xbd",
|
||||
}),
|
||||
cfg: &config.ScrapeConfig{
|
||||
Scheme: "https",
|
||||
MetricsPath: "/metrics",
|
||||
JobName: "job",
|
||||
},
|
||||
res: nil,
|
||||
resOrig: nil,
|
||||
err: fmt.Errorf("invalid label value for \"custom\": \"\\xbd\""),
|
||||
},
|
||||
}
|
||||
for i, c := range cases {
|
||||
in := c.in.Copy()
|
||||
|
||||
res, orig, err := populateLabels(c.in, c.cfg)
|
||||
if err != nil {
|
||||
t.Fatalf("case %d: %s", i, err)
|
||||
if !reflect.DeepEqual(err, c.err) {
|
||||
t.Fatalf("case %d: wanted %v error, got %v", i, c.err, err)
|
||||
}
|
||||
if !reflect.DeepEqual(c.in, in) {
|
||||
t.Errorf("case %d: input lset was changed was\n\t%+v\n now\n\t%+v", i, in, c.in)
|
||||
|
|
2
vendor/github.com/gophercloud/gophercloud/STYLEGUIDE.md
generated
vendored
2
vendor/github.com/gophercloud/gophercloud/STYLEGUIDE.md
generated
vendored
|
@ -57,7 +57,7 @@
|
|||
|
||||
### Naming
|
||||
|
||||
- For methods on a type in `response.go`, the receiver should be named `r` and the
|
||||
- For methods on a type in `results.go`, the receiver should be named `r` and the
|
||||
variable into which it will be unmarshalled `s`.
|
||||
|
||||
- Functions in `requests.go`, with the exception of functions that return a
|
||||
|
|
113
vendor/github.com/gophercloud/gophercloud/openstack/client.go
generated
vendored
113
vendor/github.com/gophercloud/gophercloud/openstack/client.go
generated
vendored
|
@ -182,9 +182,10 @@ func v3auth(client *gophercloud.ProviderClient, endpoint string, opts tokens3.Au
|
|||
// NewIdentityV2 creates a ServiceClient that may be used to interact with the v2 identity service.
|
||||
func NewIdentityV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
endpoint := client.IdentityBase + "v2.0/"
|
||||
clientType := "identity"
|
||||
var err error
|
||||
if !reflect.DeepEqual(eo, gophercloud.EndpointOpts{}) {
|
||||
eo.ApplyDefaults("identity")
|
||||
eo.ApplyDefaults(clientType)
|
||||
endpoint, err = client.EndpointLocator(eo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -194,15 +195,17 @@ func NewIdentityV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOp
|
|||
return &gophercloud.ServiceClient{
|
||||
ProviderClient: client,
|
||||
Endpoint: endpoint,
|
||||
Type: clientType,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// NewIdentityV3 creates a ServiceClient that may be used to access the v3 identity service.
|
||||
func NewIdentityV3(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
endpoint := client.IdentityBase + "v3/"
|
||||
clientType := "identity"
|
||||
var err error
|
||||
if !reflect.DeepEqual(eo, gophercloud.EndpointOpts{}) {
|
||||
eo.ApplyDefaults("identity")
|
||||
eo.ApplyDefaults(clientType)
|
||||
endpoint, err = client.EndpointLocator(eo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -212,125 +215,81 @@ func NewIdentityV3(client *gophercloud.ProviderClient, eo gophercloud.EndpointOp
|
|||
return &gophercloud.ServiceClient{
|
||||
ProviderClient: client,
|
||||
Endpoint: endpoint,
|
||||
Type: clientType,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func initClientOpts(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts, clientType string) (*gophercloud.ServiceClient, error) {
|
||||
sc := new(gophercloud.ServiceClient)
|
||||
eo.ApplyDefaults(clientType)
|
||||
url, err := client.EndpointLocator(eo)
|
||||
if err != nil {
|
||||
return sc, err
|
||||
}
|
||||
sc.ProviderClient = client
|
||||
sc.Endpoint = url
|
||||
sc.Type = clientType
|
||||
return sc, nil
|
||||
}
|
||||
|
||||
// NewObjectStorageV1 creates a ServiceClient that may be used with the v1 object storage package.
|
||||
func NewObjectStorageV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
eo.ApplyDefaults("object-store")
|
||||
url, err := client.EndpointLocator(eo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
|
||||
return initClientOpts(client, eo, "object-store")
|
||||
}
|
||||
|
||||
// NewComputeV2 creates a ServiceClient that may be used with the v2 compute package.
|
||||
func NewComputeV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
eo.ApplyDefaults("compute")
|
||||
url, err := client.EndpointLocator(eo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
|
||||
return initClientOpts(client, eo, "compute")
|
||||
}
|
||||
|
||||
// NewNetworkV2 creates a ServiceClient that may be used with the v2 network package.
|
||||
func NewNetworkV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
eo.ApplyDefaults("network")
|
||||
url, err := client.EndpointLocator(eo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &gophercloud.ServiceClient{
|
||||
ProviderClient: client,
|
||||
Endpoint: url,
|
||||
ResourceBase: url + "v2.0/",
|
||||
}, nil
|
||||
sc, err := initClientOpts(client, eo, "network")
|
||||
sc.ResourceBase = sc.Endpoint + "v2.0/"
|
||||
return sc, err
|
||||
}
|
||||
|
||||
// NewBlockStorageV1 creates a ServiceClient that may be used to access the v1 block storage service.
|
||||
func NewBlockStorageV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
eo.ApplyDefaults("volume")
|
||||
url, err := client.EndpointLocator(eo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
|
||||
return initClientOpts(client, eo, "volume")
|
||||
}
|
||||
|
||||
// NewBlockStorageV2 creates a ServiceClient that may be used to access the v2 block storage service.
|
||||
func NewBlockStorageV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
eo.ApplyDefaults("volumev2")
|
||||
url, err := client.EndpointLocator(eo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
|
||||
return initClientOpts(client, eo, "volumev2")
|
||||
}
|
||||
|
||||
// NewSharedFileSystemV2 creates a ServiceClient that may be used to access the v2 shared file system service.
|
||||
func NewSharedFileSystemV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
eo.ApplyDefaults("sharev2")
|
||||
url, err := client.EndpointLocator(eo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
|
||||
return initClientOpts(client, eo, "sharev2")
|
||||
}
|
||||
|
||||
// NewCDNV1 creates a ServiceClient that may be used to access the OpenStack v1
|
||||
// CDN service.
|
||||
func NewCDNV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
eo.ApplyDefaults("cdn")
|
||||
url, err := client.EndpointLocator(eo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
|
||||
return initClientOpts(client, eo, "cdn")
|
||||
}
|
||||
|
||||
// NewOrchestrationV1 creates a ServiceClient that may be used to access the v1 orchestration service.
|
||||
func NewOrchestrationV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
eo.ApplyDefaults("orchestration")
|
||||
url, err := client.EndpointLocator(eo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
|
||||
return initClientOpts(client, eo, "orchestration")
|
||||
}
|
||||
|
||||
// NewDBV1 creates a ServiceClient that may be used to access the v1 DB service.
|
||||
func NewDBV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
eo.ApplyDefaults("database")
|
||||
url, err := client.EndpointLocator(eo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
|
||||
return initClientOpts(client, eo, "database")
|
||||
}
|
||||
|
||||
// NewDNSV2 creates a ServiceClient that may be used to access the v2 DNS service.
|
||||
func NewDNSV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
eo.ApplyDefaults("dns")
|
||||
url, err := client.EndpointLocator(eo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &gophercloud.ServiceClient{
|
||||
ProviderClient: client,
|
||||
Endpoint: url,
|
||||
ResourceBase: url + "v2/"}, nil
|
||||
sc, err := initClientOpts(client, eo, "dns")
|
||||
sc.ResourceBase = sc.Endpoint + "v2/"
|
||||
return sc, err
|
||||
}
|
||||
|
||||
// NewImageServiceV2 creates a ServiceClient that may be used to access the v2 image service.
|
||||
func NewImageServiceV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
eo.ApplyDefaults("image")
|
||||
url, err := client.EndpointLocator(eo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &gophercloud.ServiceClient{ProviderClient: client,
|
||||
Endpoint: url,
|
||||
ResourceBase: url + "v2/"}, nil
|
||||
sc, err := initClientOpts(client, eo, "image")
|
||||
sc.ResourceBase = sc.Endpoint + "v2/"
|
||||
return sc, err
|
||||
}
|
||||
|
|
22
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/requests.go
generated
vendored
22
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/requests.go
generated
vendored
|
@ -11,6 +11,24 @@ type ListOptsBuilder interface {
|
|||
ToFlavorListQuery() (string, error)
|
||||
}
|
||||
|
||||
// AccessType maps to OpenStack's Flavor.is_public field. Although the is_public field is boolean, the
|
||||
// request options are ternary, which is why AccessType is a string. The following values are
|
||||
// allowed:
|
||||
//
|
||||
// PublicAccess (the default): Returns public flavors and private flavors associated with that project.
|
||||
// PrivateAccess (admin only): Returns private flavors, across all projects.
|
||||
// AllAccess (admin only): Returns public and private flavors across all projects.
|
||||
//
|
||||
// The AccessType arguement is optional, and if it is not supplied, OpenStack returns the PublicAccess
|
||||
// flavors.
|
||||
type AccessType string
|
||||
|
||||
const (
|
||||
PublicAccess AccessType = "true"
|
||||
PrivateAccess AccessType = "false"
|
||||
AllAccess AccessType = "None"
|
||||
)
|
||||
|
||||
// ListOpts helps control the results returned by the List() function.
|
||||
// For example, a flavor with a minDisk field of 10 will not be returned if you specify MinDisk set to 20.
|
||||
// Typically, software will use the last ID of the previous call to List to set the Marker for the current call.
|
||||
|
@ -29,6 +47,10 @@ type ListOpts struct {
|
|||
|
||||
// Limit instructs List to refrain from sending excessively large lists of flavors.
|
||||
Limit int `q:"limit"`
|
||||
|
||||
// AccessType, if provided, instructs List which set of flavors to return. If IsPublic not provided,
|
||||
// flavors for the current project are returned.
|
||||
AccessType AccessType `q:"is_public"`
|
||||
}
|
||||
|
||||
// ToFlavorListQuery formats a ListOpts into a query string.
|
||||
|
|
2
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/results.go
generated
vendored
2
vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors/results.go
generated
vendored
|
@ -46,6 +46,8 @@ type Flavor struct {
|
|||
Swap int `json:"swap"`
|
||||
// VCPUs indicates how many (virtual) CPUs are available for this flavor.
|
||||
VCPUs int `json:"vcpus"`
|
||||
// IsPublic indicates whether the flavor is public.
|
||||
IsPublic bool `json:"is_public"`
|
||||
}
|
||||
|
||||
func (r *Flavor) UnmarshalJSON(b []byte) error {
|
||||
|
|
4
vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/tokens/requests.go
generated
vendored
4
vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/tokens/requests.go
generated
vendored
|
@ -182,13 +182,13 @@ func Get(c *gophercloud.ServiceClient, token string) (r GetResult) {
|
|||
func Validate(c *gophercloud.ServiceClient, token string) (bool, error) {
|
||||
resp, err := c.Request("HEAD", tokenURL(c), &gophercloud.RequestOpts{
|
||||
MoreHeaders: subjectTokenHeaders(c, token),
|
||||
OkCodes: []int{204, 404},
|
||||
OkCodes: []int{200, 204, 400, 401, 403, 404},
|
||||
})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return resp.StatusCode == 204, nil
|
||||
return resp.StatusCode == 200 || resp.StatusCode == 204, nil
|
||||
}
|
||||
|
||||
// Revoke immediately makes specified token invalid.
|
||||
|
|
107
vendor/github.com/gophercloud/gophercloud/service_client.go
generated
vendored
107
vendor/github.com/gophercloud/gophercloud/service_client.go
generated
vendored
|
@ -21,6 +21,12 @@ type ServiceClient struct {
|
|||
// as-is, instead.
|
||||
ResourceBase string
|
||||
|
||||
// This is the service client type (e.g. compute, sharev2).
|
||||
// NOTE: FOR INTERNAL USE ONLY. DO NOT SET. GOPHERCLOUD WILL SET THIS.
|
||||
// It is only exported because it gets set in a different package.
|
||||
Type string
|
||||
|
||||
// The microversion of the service to use. Set this to use a particular microversion.
|
||||
Microversion string
|
||||
}
|
||||
|
||||
|
@ -37,11 +43,13 @@ func (client *ServiceClient) ServiceURL(parts ...string) string {
|
|||
return client.ResourceBaseURL() + strings.Join(parts, "/")
|
||||
}
|
||||
|
||||
// Get calls `Request` with the "GET" HTTP verb.
|
||||
func (client *ServiceClient) Get(url string, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) {
|
||||
if opts == nil {
|
||||
opts = &RequestOpts{}
|
||||
func (client *ServiceClient) initReqOpts(url string, JSONBody interface{}, JSONResponse interface{}, opts *RequestOpts) {
|
||||
if v, ok := (JSONBody).(io.Reader); ok {
|
||||
opts.RawBody = v
|
||||
} else if JSONBody != nil {
|
||||
opts.JSONBody = JSONBody
|
||||
}
|
||||
|
||||
if JSONResponse != nil {
|
||||
opts.JSONResponse = JSONResponse
|
||||
}
|
||||
|
@ -49,93 +57,66 @@ func (client *ServiceClient) Get(url string, JSONResponse interface{}, opts *Req
|
|||
if opts.MoreHeaders == nil {
|
||||
opts.MoreHeaders = make(map[string]string)
|
||||
}
|
||||
opts.MoreHeaders["X-OpenStack-Nova-API-Version"] = client.Microversion
|
||||
|
||||
if client.Microversion != "" {
|
||||
client.setMicroversionHeader(opts)
|
||||
}
|
||||
}
|
||||
|
||||
// Get calls `Request` with the "GET" HTTP verb.
|
||||
func (client *ServiceClient) Get(url string, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) {
|
||||
if opts == nil {
|
||||
opts = new(RequestOpts)
|
||||
}
|
||||
client.initReqOpts(url, nil, JSONResponse, opts)
|
||||
return client.Request("GET", url, opts)
|
||||
}
|
||||
|
||||
// Post calls `Request` with the "POST" HTTP verb.
|
||||
func (client *ServiceClient) Post(url string, JSONBody interface{}, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) {
|
||||
if opts == nil {
|
||||
opts = &RequestOpts{}
|
||||
opts = new(RequestOpts)
|
||||
}
|
||||
|
||||
if v, ok := (JSONBody).(io.Reader); ok {
|
||||
opts.RawBody = v
|
||||
} else if JSONBody != nil {
|
||||
opts.JSONBody = JSONBody
|
||||
}
|
||||
|
||||
if JSONResponse != nil {
|
||||
opts.JSONResponse = JSONResponse
|
||||
}
|
||||
|
||||
if opts.MoreHeaders == nil {
|
||||
opts.MoreHeaders = make(map[string]string)
|
||||
}
|
||||
opts.MoreHeaders["X-OpenStack-Nova-API-Version"] = client.Microversion
|
||||
|
||||
client.initReqOpts(url, JSONBody, JSONResponse, opts)
|
||||
return client.Request("POST", url, opts)
|
||||
}
|
||||
|
||||
// Put calls `Request` with the "PUT" HTTP verb.
|
||||
func (client *ServiceClient) Put(url string, JSONBody interface{}, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) {
|
||||
if opts == nil {
|
||||
opts = &RequestOpts{}
|
||||
opts = new(RequestOpts)
|
||||
}
|
||||
|
||||
if v, ok := (JSONBody).(io.Reader); ok {
|
||||
opts.RawBody = v
|
||||
} else if JSONBody != nil {
|
||||
opts.JSONBody = JSONBody
|
||||
}
|
||||
|
||||
if JSONResponse != nil {
|
||||
opts.JSONResponse = JSONResponse
|
||||
}
|
||||
|
||||
if opts.MoreHeaders == nil {
|
||||
opts.MoreHeaders = make(map[string]string)
|
||||
}
|
||||
opts.MoreHeaders["X-OpenStack-Nova-API-Version"] = client.Microversion
|
||||
|
||||
client.initReqOpts(url, JSONBody, JSONResponse, opts)
|
||||
return client.Request("PUT", url, opts)
|
||||
}
|
||||
|
||||
// Patch calls `Request` with the "PATCH" HTTP verb.
|
||||
func (client *ServiceClient) Patch(url string, JSONBody interface{}, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) {
|
||||
if opts == nil {
|
||||
opts = &RequestOpts{}
|
||||
opts = new(RequestOpts)
|
||||
}
|
||||
|
||||
if v, ok := (JSONBody).(io.Reader); ok {
|
||||
opts.RawBody = v
|
||||
} else if JSONBody != nil {
|
||||
opts.JSONBody = JSONBody
|
||||
}
|
||||
|
||||
if JSONResponse != nil {
|
||||
opts.JSONResponse = JSONResponse
|
||||
}
|
||||
|
||||
if opts.MoreHeaders == nil {
|
||||
opts.MoreHeaders = make(map[string]string)
|
||||
}
|
||||
opts.MoreHeaders["X-OpenStack-Nova-API-Version"] = client.Microversion
|
||||
|
||||
client.initReqOpts(url, JSONBody, JSONResponse, opts)
|
||||
return client.Request("PATCH", url, opts)
|
||||
}
|
||||
|
||||
// Delete calls `Request` with the "DELETE" HTTP verb.
|
||||
func (client *ServiceClient) Delete(url string, opts *RequestOpts) (*http.Response, error) {
|
||||
if opts == nil {
|
||||
opts = &RequestOpts{}
|
||||
opts = new(RequestOpts)
|
||||
}
|
||||
|
||||
if opts.MoreHeaders == nil {
|
||||
opts.MoreHeaders = make(map[string]string)
|
||||
}
|
||||
opts.MoreHeaders["X-OpenStack-Nova-API-Version"] = client.Microversion
|
||||
|
||||
client.initReqOpts(url, nil, nil, opts)
|
||||
return client.Request("DELETE", url, opts)
|
||||
}
|
||||
|
||||
func (client *ServiceClient) setMicroversionHeader(opts *RequestOpts) {
|
||||
switch client.Type {
|
||||
case "compute":
|
||||
opts.MoreHeaders["X-OpenStack-Nova-API-Version"] = client.Microversion
|
||||
case "sharev2":
|
||||
opts.MoreHeaders["X-OpenStack-Manila-API-Version"] = client.Microversion
|
||||
}
|
||||
|
||||
if client.Type != "" {
|
||||
opts.MoreHeaders["OpenStack-API-Version"] = client.Type + " " + client.Microversion
|
||||
}
|
||||
}
|
||||
|
|
58
vendor/vendor.json
vendored
58
vendor/vendor.json
vendored
|
@ -478,40 +478,46 @@
|
|||
"revisionTime": "2016-09-30T00:14:02Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "cuTQkSEiIoMhDhB7xCbYDwDhrgw=",
|
||||
"checksumSHA1": "ndG2xmm2bas4/t+kIEUp2xIni8c=",
|
||||
"path": "github.com/gophercloud/gophercloud",
|
||||
"revision": "0bf921da554eacc1552a70204be7a1201937c1e1",
|
||||
"revisionTime": "2017-05-04T01:40:32Z"
|
||||
"revision": "caf34a65f60295108141f62929245943bd00f237",
|
||||
"revisionTime": "2017-06-07T03:48:29Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "0KdIjTH5IO8hlIl8kdfI6313GiY=",
|
||||
"checksumSHA1": "24DO5BEQdFKNl1rfWgI2b4+ry5U=",
|
||||
"path": "github.com/gophercloud/gophercloud/openstack",
|
||||
"revision": "0bf921da554eacc1552a70204be7a1201937c1e1",
|
||||
"revisionTime": "2017-05-04T01:40:32Z"
|
||||
"revision": "caf34a65f60295108141f62929245943bd00f237",
|
||||
"revisionTime": "2017-06-07T03:48:29Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "4XWDCGMYqipwJymi9xJo9UffD7g=",
|
||||
"path": "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions",
|
||||
"revision": "caf34a65f60295108141f62929245943bd00f237",
|
||||
"revisionTime": "2017-06-07T03:48:29Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "e7AW3YDVYJPKUjpqsB4AL9RRlTw=",
|
||||
"path": "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/floatingips",
|
||||
"revision": "caa61b3ca9f504196fd3b338f43cd99d830f7e2e",
|
||||
"revisionTime": "2017-05-11T18:09:16Z"
|
||||
"revision": "caf34a65f60295108141f62929245943bd00f237",
|
||||
"revisionTime": "2017-06-07T03:48:29Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "S1BV3o8Pa0aM5RaUuRYXY7LnPIc=",
|
||||
"checksumSHA1": "vTyXSR+Znw7/o/70UBOWG0F09r8=",
|
||||
"path": "github.com/gophercloud/gophercloud/openstack/compute/v2/flavors",
|
||||
"revision": "0bf921da554eacc1552a70204be7a1201937c1e1",
|
||||
"revisionTime": "2017-05-04T01:40:32Z"
|
||||
"revision": "caf34a65f60295108141f62929245943bd00f237",
|
||||
"revisionTime": "2017-06-07T03:48:29Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "Rnzx2YgOD41k8KoPA08tR992PxQ=",
|
||||
"path": "github.com/gophercloud/gophercloud/openstack/compute/v2/images",
|
||||
"revision": "0bf921da554eacc1552a70204be7a1201937c1e1",
|
||||
"revisionTime": "2017-05-04T01:40:32Z"
|
||||
"revision": "caf34a65f60295108141f62929245943bd00f237",
|
||||
"revisionTime": "2017-06-07T03:48:29Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "IjCvcaNnRW++hclt21WUkMYinaA=",
|
||||
"path": "github.com/gophercloud/gophercloud/openstack/compute/v2/servers",
|
||||
"revision": "0bf921da554eacc1552a70204be7a1201937c1e1",
|
||||
"revisionTime": "2017-05-04T01:40:32Z"
|
||||
"revision": "caf34a65f60295108141f62929245943bd00f237",
|
||||
"revisionTime": "2017-06-07T03:48:29Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "9z5GwbsfpB49gzkHu10pDH5roKA=",
|
||||
|
@ -522,14 +528,14 @@
|
|||
{
|
||||
"checksumSHA1": "1sVqsZBZBNhDXLY9XzjMkcOkcbg=",
|
||||
"path": "github.com/gophercloud/gophercloud/openstack/identity/v2/tenants",
|
||||
"revision": "0bf921da554eacc1552a70204be7a1201937c1e1",
|
||||
"revisionTime": "2017-05-04T01:40:32Z"
|
||||
"revision": "caf34a65f60295108141f62929245943bd00f237",
|
||||
"revisionTime": "2017-06-07T03:48:29Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "AvUU5En9YpG25iLlcAPDgcQODjI=",
|
||||
"path": "github.com/gophercloud/gophercloud/openstack/identity/v2/tokens",
|
||||
"revision": "0bf921da554eacc1552a70204be7a1201937c1e1",
|
||||
"revisionTime": "2017-05-04T01:40:32Z"
|
||||
"revision": "caf34a65f60295108141f62929245943bd00f237",
|
||||
"revisionTime": "2017-06-07T03:48:29Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "vsgZmEVQLtCmxuxf/q4u8XJGWpE=",
|
||||
|
@ -538,22 +544,22 @@
|
|||
"revisionTime": "2017-05-04T01:40:32Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "ZKyEbJuIlvuZ9aUushINCXJHF4w=",
|
||||
"checksumSHA1": "fHOkQNWyeGoMPjkYvqiOrOifTUw=",
|
||||
"path": "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens",
|
||||
"revision": "0bf921da554eacc1552a70204be7a1201937c1e1",
|
||||
"revisionTime": "2017-05-04T01:40:32Z"
|
||||
"revision": "caf34a65f60295108141f62929245943bd00f237",
|
||||
"revisionTime": "2017-06-07T03:48:29Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "TDOZnaS0TO0NirpxV1QwPerAQTY=",
|
||||
"path": "github.com/gophercloud/gophercloud/openstack/utils",
|
||||
"revision": "0bf921da554eacc1552a70204be7a1201937c1e1",
|
||||
"revisionTime": "2017-05-04T01:40:32Z"
|
||||
"revision": "caf34a65f60295108141f62929245943bd00f237",
|
||||
"revisionTime": "2017-06-07T03:48:29Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "FNy075ydQZXvnL2bNNIOCmy/ghs=",
|
||||
"path": "github.com/gophercloud/gophercloud/pagination",
|
||||
"revision": "0bf921da554eacc1552a70204be7a1201937c1e1",
|
||||
"revisionTime": "2017-05-04T01:40:32Z"
|
||||
"revision": "caf34a65f60295108141f62929245943bd00f237",
|
||||
"revisionTime": "2017-06-07T03:48:29Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "LclVLJYrBi03PBjsVPpgoMbUDQ8=",
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -364,7 +364,7 @@ Prometheus.Graph.prototype.submitQuery = function() {
|
|||
|
||||
var startTime = new Date().getTime();
|
||||
var rangeSeconds = self.parseDuration(self.rangeInput.val());
|
||||
var resolution = self.queryForm.find("input[name=step_input]").val() || Math.max(Math.floor(rangeSeconds / 250), 1);
|
||||
var resolution = parseInt(self.queryForm.find("input[name=step_input]").val()) || Math.max(Math.floor(rangeSeconds / 250), 1);
|
||||
var endDate = self.getEndDate() / 1000;
|
||||
|
||||
if (self.queryXhr) {
|
||||
|
|
|
@ -171,7 +171,7 @@ func New(o *Options) *Handler {
|
|||
instrf := prometheus.InstrumentHandlerFunc
|
||||
|
||||
router.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
router.Redirect(w, r, path.Join(o.ExternalURL.Path, "/graph"), http.StatusFound)
|
||||
http.Redirect(w, r, path.Join(o.ExternalURL.Path, "/graph"), http.StatusFound)
|
||||
})
|
||||
|
||||
router.Get("/alerts", instrf("alerts", h.alerts))
|
||||
|
|
Loading…
Reference in a new issue