object.go (3245B)
1 package icinga 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "errors" 7 "fmt" 8 "net/http" 9 "strings" 10 ) 11 12 type object interface { 13 name() string 14 path() string 15 } 16 17 // jsonForCreate marshals obj into the required JSON object to be sent 18 // in the body of a PUT request to Icinga. Some fields of obj must not be set for 19 // Icinga to create the object. Since some of those fields are structs 20 // (and not pointers to structs), they are always included, even if unset. 21 // jsonForCreate overrides those fields to always be empty. Other fields are left 22 // alone to let Icinga report an error for us. 23 func jsonForCreate(obj object) ([]byte, error) { 24 m := make(map[string]interface{}) 25 switch v := obj.(type) { 26 case User, HostGroup: 27 m["attrs"] = v 28 case Host: 29 aux := &struct { 30 LastCheck *struct{} `json:",omitempty"` 31 LastCheckResult *struct{} `json:"last_check_result,omitempty"` 32 Host 33 }{Host: v} 34 m["attrs"] = aux 35 case Service: 36 aux := &struct { 37 LastCheck *struct{} `json:",omitempty"` 38 LastCheckResult *struct{} `json:"last_check_result,omitempty"` 39 Service 40 }{Service: v} 41 m["attrs"] = aux 42 default: 43 return nil, fmt.Errorf("marshal %T for creation unsupported", v) 44 } 45 return json.Marshal(m) 46 } 47 48 //go:generate ./crud.sh -o crud.go 49 50 func (c *Client) lookupObject(objpath string) (object, error) { 51 resp, err := c.get(objpath, "") 52 if err != nil { 53 return nil, err 54 } 55 defer resp.Body.Close() 56 if resp.StatusCode == http.StatusNotFound { 57 return nil, ErrNotExist 58 } 59 iresp, err := parseResponse(resp.Body) 60 if err != nil { 61 return nil, fmt.Errorf("parse response: %v", err) 62 } else if iresp.Error != nil { 63 return nil, iresp.Error 64 } else if resp.StatusCode != http.StatusOK { 65 return nil, errors.New(resp.Status) 66 } 67 return objectFromLookup(iresp) 68 } 69 70 func (c *Client) filterObjects(objpath, expr string) ([]object, error) { 71 resp, err := c.get(objpath, expr) 72 if err != nil { 73 return nil, err 74 } 75 defer resp.Body.Close() 76 iresp, err := parseResponse(resp.Body) 77 if err != nil { 78 return nil, fmt.Errorf("parse response: %v", err) 79 } else if iresp.Error != nil { 80 return nil, iresp.Error 81 } else if resp.StatusCode != http.StatusOK { 82 return nil, errors.New(resp.Status) 83 } else if len(iresp.Results) == 0 { 84 return nil, ErrNoMatch 85 } 86 return iresp.Results, nil 87 } 88 89 func (c *Client) createObject(obj object) error { 90 b, err := jsonForCreate(obj) 91 if err != nil { 92 return fmt.Errorf("marshal into json: %v", err) 93 } 94 resp, err := c.put(obj.path(), bytes.NewReader(b)) 95 if err != nil { 96 return err 97 } 98 if resp.StatusCode == http.StatusOK { 99 return nil 100 } 101 defer resp.Body.Close() 102 iresp, err := parseResponse(resp.Body) 103 if err != nil { 104 return fmt.Errorf("parse response: %v", err) 105 } 106 if strings.Contains(iresp.Error.Error(), "already exists") { 107 return ErrExist 108 } 109 return iresp.Error 110 } 111 112 func (c *Client) deleteObject(objpath string, cascade bool) error { 113 resp, err := c.delete(objpath, cascade) 114 if err != nil { 115 return err 116 } 117 defer resp.Body.Close() 118 if resp.StatusCode == http.StatusOK { 119 return nil 120 } else if resp.StatusCode == http.StatusNotFound { 121 return ErrNotExist 122 } 123 iresp, err := parseResponse(resp.Body) 124 if err != nil { 125 return fmt.Errorf("parse response: %v", err) 126 } 127 return iresp.Error 128 }