Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2017 The LUCI Authors. All rights reserved. | 1 // Copyright 2017 The LUCI Authors. All rights reserved. |
| 2 // Use of this source code is governed under the Apache License, Version 2.0 | 2 // Use of this source code is governed under the Apache License, Version 2.0 |
| 3 // that can be found in the LICENSE file. | 3 // that can be found in the LICENSE file. |
| 4 | 4 |
| 5 package types | 5 package types |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "bytes" | |
| 9 "encoding/json" | |
| 8 "flag" | 10 "flag" |
| 9 "net/url" | 11 "net/url" |
| 10 "strings" | 12 "strings" |
| 11 | 13 |
| 12 "github.com/luci/luci-go/common/errors" | 14 "github.com/luci/luci-go/common/errors" |
| 13 "github.com/luci/luci-go/luci_config/common/cfgtypes" | 15 "github.com/luci/luci-go/luci_config/common/cfgtypes" |
| 14 ) | 16 ) |
| 15 | 17 |
| 16 const logDogURLScheme = "logdog" | 18 const logDogURLScheme = "logdog" |
| 17 | 19 |
| 18 // StreamAddr is a fully-qualified LogDog stream address. | 20 // StreamAddr is a fully-qualified LogDog stream address. |
| 19 type StreamAddr struct { | 21 type StreamAddr struct { |
| 20 // Host is the LogDog host. | 22 // Host is the LogDog host. |
| 21 » Host string | 23 » Host string `json:"host"` |
| 22 | 24 |
| 23 // Project is the LUCI project name that this log belongs to. | 25 // Project is the LUCI project name that this log belongs to. |
| 24 » Project cfgtypes.ProjectName | 26 » Project cfgtypes.ProjectName `json:"project"` |
| 25 | 27 |
| 26 // Path is the LogDog stream path. | 28 // Path is the LogDog stream path. |
| 27 » Path StreamPath | 29 » Path StreamPath `json:"path"` |
| 28 } | 30 } |
| 29 | 31 |
| 30 var _ flag.Value = (*StreamAddr)(nil) | 32 var _ flag.Value = (*StreamAddr)(nil) |
| 31 | 33 |
| 32 // Set implements flag.Value | 34 // Set implements flag.Value |
| 33 func (s *StreamAddr) Set(v string) error { | 35 func (s *StreamAddr) Set(v string) error { |
| 34 a, err := ParseURL(v) | 36 a, err := ParseURL(v) |
| 35 if err != nil { | 37 if err != nil { |
| 36 return err | 38 return err |
| 37 } | 39 } |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 63 | 65 |
| 64 // URL returns a LogDog URL that represents this Stream. | 66 // URL returns a LogDog URL that represents this Stream. |
| 65 func (s *StreamAddr) URL() *url.URL { | 67 func (s *StreamAddr) URL() *url.URL { |
| 66 return &url.URL{ | 68 return &url.URL{ |
| 67 Scheme: logDogURLScheme, | 69 Scheme: logDogURLScheme, |
| 68 Host: s.Host, | 70 Host: s.Host, |
| 69 Path: strings.Join([]string{"", string(s.Project), string(s.Pa th)}, "/"), | 71 Path: strings.Join([]string{"", string(s.Project), string(s.Pa th)}, "/"), |
| 70 } | 72 } |
| 71 } | 73 } |
| 72 | 74 |
| 75 // jsonStreamAddr is used to allow type checking during deserialization, but | |
| 76 // special casing IsZero == 'null'. | |
| 77 type jsonStreamAddr struct { | |
|
dnj
2017/05/23 15:28:19
This is unfortunate. Are you opposed to using "omi
| |
| 78 Host string `json:"host"` | |
| 79 Project cfgtypes.ProjectName `json:"project"` | |
| 80 Path StreamPath `json:"path"` | |
| 81 } | |
| 82 | |
| 83 // MarshalJSON implements json.Marshaler | |
| 84 func (s StreamAddr) MarshalJSON() ([]byte, error) { | |
| 85 if s.IsZero() { | |
| 86 return []byte(`null`), nil | |
| 87 } | |
| 88 // TODO(iannucci): when we support go 1.8 on appengine, this can be writ ten as | |
| 89 // json.Marshal((*jsonStreamAddr)(s)). | |
| 90 jsa := jsonStreamAddr{s.Host, s.Project, s.Path} | |
| 91 return json.Marshal(jsa) | |
| 92 } | |
| 93 | |
| 94 // UnmarshalJSON implements json.Marshaler | |
| 95 func (s *StreamAddr) UnmarshalJSON(d []byte) error { | |
| 96 if bytes.Equal(d, []byte(`null`)) { | |
| 97 s.Host = "" | |
| 98 s.Project = "" | |
| 99 s.Path = "" | |
| 100 return nil | |
| 101 } | |
| 102 // TODO(iannucci): when we support go 1.8 on appengine, this can be writ ten as | |
| 103 // return json.Unmarshal(d, (*jsonStreamAddr)(s)) | |
| 104 jsa := jsonStreamAddr{} | |
| 105 if err := json.Unmarshal(d, &jsa); err != nil { | |
| 106 return err | |
| 107 } | |
| 108 s.Host = jsa.Host | |
| 109 s.Project = jsa.Project | |
| 110 s.Path = jsa.Path | |
| 111 return nil | |
| 112 } | |
| 113 | |
| 73 // ParseURL parses a LogDog URL into a Stream. If the URL is malformed, or | 114 // ParseURL parses a LogDog URL into a Stream. If the URL is malformed, or |
| 74 // if the host, project, or path is invalid, an error will be returned. | 115 // if the host, project, or path is invalid, an error will be returned. |
| 75 // | 116 // |
| 76 // A LogDog URL has the form: | 117 // A LogDog URL has the form: |
| 77 // logdog://<host>/<project>/<prefix>/+/<name> | 118 // logdog://<host>/<project>/<prefix>/+/<name> |
| 78 func ParseURL(v string) (*StreamAddr, error) { | 119 func ParseURL(v string) (*StreamAddr, error) { |
| 79 u, err := url.Parse(v) | 120 u, err := url.Parse(v) |
| 80 if err != nil { | 121 if err != nil { |
| 81 return nil, errors.Annotate(err).Reason("failed to parse URL").E rr() | 122 return nil, errors.Annotate(err).Reason("failed to parse URL").E rr() |
| 82 } | 123 } |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 106 } | 147 } |
| 107 | 148 |
| 108 if err := addr.Path.Validate(); err != nil { | 149 if err := addr.Path.Validate(); err != nil { |
| 109 return nil, errors.Annotate(err).Reason("invalid stream path: %( path)q"). | 150 return nil, errors.Annotate(err).Reason("invalid stream path: %( path)q"). |
| 110 D("path", addr.Path). | 151 D("path", addr.Path). |
| 111 Err() | 152 Err() |
| 112 } | 153 } |
| 113 | 154 |
| 114 return &addr, nil | 155 return &addr, nil |
| 115 } | 156 } |
| OLD | NEW |