github.com/letsencrypt/boulder@v0.20251208.0/observer/probers/crl/crl_conf.go (about) 1 package probers 2 3 import ( 4 "fmt" 5 "net/url" 6 7 "github.com/prometheus/client_golang/prometheus" 8 9 "github.com/letsencrypt/boulder/observer/probers" 10 "github.com/letsencrypt/boulder/strictyaml" 11 ) 12 13 const ( 14 nextUpdateName = "obs_crl_next_update" 15 thisUpdateName = "obs_crl_this_update" 16 certCountName = "obs_crl_revoked_cert_count" 17 ) 18 19 // CRLConf is exported to receive YAML configuration 20 type CRLConf struct { 21 URL string `yaml:"url"` 22 Partitioned bool `yaml:"partitioned"` 23 } 24 25 // Kind returns a name that uniquely identifies the `Kind` of `Configurer`. 26 func (c CRLConf) Kind() string { 27 return "CRL" 28 } 29 30 // UnmarshalSettings constructs a CRLConf object from YAML as bytes. 31 func (c CRLConf) UnmarshalSettings(settings []byte) (probers.Configurer, error) { 32 var conf CRLConf 33 err := strictyaml.Unmarshal(settings, &conf) 34 35 if err != nil { 36 return nil, err 37 } 38 return conf, nil 39 } 40 41 func (c CRLConf) validateURL() error { 42 url, err := url.Parse(c.URL) 43 if err != nil { 44 return fmt.Errorf( 45 "invalid 'url', got: %q, expected a valid url", c.URL) 46 } 47 if url.Scheme == "" { 48 return fmt.Errorf( 49 "invalid 'url', got: %q, missing scheme", c.URL) 50 } 51 return nil 52 } 53 54 // MakeProber constructs a `CRLProbe` object from the contents of the 55 // bound `CRLConf` object. If the `CRLConf` cannot be validated, an 56 // error appropriate for end-user consumption is returned instead. 57 func (c CRLConf) MakeProber(collectors map[string]prometheus.Collector) (probers.Prober, error) { // validate `url` err := c.validateURL() 58 // validate `url` 59 err := c.validateURL() 60 if err != nil { 61 return nil, err 62 } 63 64 // validate the prometheus collectors that were passed in 65 coll, ok := collectors[nextUpdateName] 66 if !ok { 67 return nil, fmt.Errorf("crl prober did not receive collector %q", nextUpdateName) 68 } 69 nextUpdateColl, ok := coll.(*prometheus.GaugeVec) 70 if !ok { 71 return nil, fmt.Errorf("crl prober received collector %q of wrong type, got: %T, expected *prometheus.GaugeVec", nextUpdateName, coll) 72 } 73 74 coll, ok = collectors[thisUpdateName] 75 if !ok { 76 return nil, fmt.Errorf("crl prober did not receive collector %q", thisUpdateName) 77 } 78 thisUpdateColl, ok := coll.(*prometheus.GaugeVec) 79 if !ok { 80 return nil, fmt.Errorf("crl prober received collector %q of wrong type, got: %T, expected *prometheus.GaugeVec", thisUpdateName, coll) 81 } 82 83 coll, ok = collectors[certCountName] 84 if !ok { 85 return nil, fmt.Errorf("crl prober did not receive collector %q", certCountName) 86 } 87 certCountColl, ok := coll.(*prometheus.GaugeVec) 88 if !ok { 89 return nil, fmt.Errorf("crl prober received collector %q of wrong type, got: %T, expected *prometheus.GaugeVec", certCountName, coll) 90 } 91 92 return CRLProbe{c.URL, c.Partitioned, nextUpdateColl, thisUpdateColl, certCountColl}, nil 93 } 94 95 // Instrument constructs any `prometheus.Collector` objects the `CRLProbe` will 96 // need to report its own metrics. A map is returned containing the constructed 97 // objects, indexed by the name of the prometheus metric. If no objects were 98 // constructed, nil is returned. 99 func (c CRLConf) Instrument() map[string]prometheus.Collector { 100 nextUpdate := prometheus.Collector(prometheus.NewGaugeVec( 101 prometheus.GaugeOpts{ 102 Name: nextUpdateName, 103 Help: "CRL nextUpdate Unix timestamp in seconds", 104 }, []string{"url"}, 105 )) 106 thisUpdate := prometheus.Collector(prometheus.NewGaugeVec( 107 prometheus.GaugeOpts{ 108 Name: thisUpdateName, 109 Help: "CRL thisUpdate Unix timestamp in seconds", 110 }, []string{"url"}, 111 )) 112 certCount := prometheus.Collector(prometheus.NewGaugeVec( 113 prometheus.GaugeOpts{ 114 Name: certCountName, 115 Help: "number of certificates revoked in CRL", 116 }, []string{"url"}, 117 )) 118 return map[string]prometheus.Collector{ 119 nextUpdateName: nextUpdate, 120 thisUpdateName: thisUpdate, 121 certCountName: certCount, 122 } 123 } 124 125 // init is called at runtime and registers `CRLConf`, a `Prober` 126 // `Configurer` type, as "CRL". 127 func init() { 128 probers.Register(CRLConf{}) 129 }