GetTimeline gets the patronictl status and returns the timeline, currently the only information required by PGO. Returns zero if it runs into errors or cannot find a running Leader pod to get the up-to-date timeline from.
(ctx context.Context)
| 173 | // Returns zero if it runs into errors or cannot find a running Leader pod |
| 174 | // to get the up-to-date timeline from. |
| 175 | func (exec Executor) GetTimeline(ctx context.Context) (int64, error) { |
| 176 | var stdout, stderr bytes.Buffer |
| 177 | |
| 178 | // The following exits zero when it is able to read the DCS and communicate |
| 179 | // with the Patroni HTTP API. It prints the result of calling "GET /cluster" |
| 180 | // - https://github.com/zalando/patroni/blob/v2.1.1/patroni/ctl.py#L849 |
| 181 | err := exec(ctx, nil, &stdout, &stderr, |
| 182 | "patronictl", "list", "--format", "json") |
| 183 | if err != nil { |
| 184 | return 0, err |
| 185 | } |
| 186 | |
| 187 | if stderr.String() != "" { |
| 188 | return 0, errors.New(stderr.String()) |
| 189 | } |
| 190 | |
| 191 | var members []struct { |
| 192 | Role string `json:"Role"` |
| 193 | State string `json:"State"` |
| 194 | Timeline int64 `json:"TL"` |
| 195 | } |
| 196 | err = json.Unmarshal(stdout.Bytes(), &members) |
| 197 | if err != nil { |
| 198 | return 0, err |
| 199 | } |
| 200 | |
| 201 | for _, member := range members { |
| 202 | if member.Role == "Leader" && member.State == "running" { |
| 203 | return member.Timeline, nil |
| 204 | } |
| 205 | } |
| 206 | |
| 207 | return 0, err |
| 208 | } |