|
| 1 | +package cloudwatch |
| 2 | + |
| 3 | +import ( |
| 4 | + "errors" |
| 5 | + "github.com/homecloudhq/homecloud/cli/internal/store" |
| 6 | + "slices" |
| 7 | + |
| 8 | + "github.com/homecloudhq/homecloud/cli/internal/awsapi" |
| 9 | + "github.com/homecloudhq/homecloud/cli/internal/core" |
| 10 | + "github.com/homecloudhq/homecloud/cli/internal/httpx" |
| 11 | +) |
| 12 | + |
| 13 | +// Native (console) routes for Logs Insights, metric and subscription filters |
| 14 | +// and alarm history. They share their logic with the AWS handlers. |
| 15 | + |
| 16 | +// nat converts an AWS API error to a native one. |
| 17 | +func nat[T any](v T, err error) (T, error) { |
| 18 | + var ae *awsapi.Error |
| 19 | + if errors.As(err, &ae) { |
| 20 | + st := ae.Status |
| 21 | + if ae.Code == "ResourceNotFoundException" { |
| 22 | + st = 404 |
| 23 | + } |
| 24 | + return v, core.Errf(st, ae.Code, "%s", ae.Message) |
| 25 | + } |
| 26 | + return v, err |
| 27 | +} |
| 28 | + |
| 29 | +func (s *Service) nativeLogRoutes(r *httpx.Router) { |
| 30 | + res := httpx.Res("arn:aws:logs:{region}:{account}:log-group:{group}") |
| 31 | + r.Handle("POST /api/v1/logs/insights/queries", "logs:StartQuery", s.nStartQuery, httpx.Deferred()) |
| 32 | + r.Handle("GET /api/v1/logs/insights/queries/{id}", "logs:GetQueryResults", s.nQueryResults, httpx.Deferred()) |
| 33 | + r.Handle("GET /api/v1/logs/groups/{group}/metric-filters", "logs:DescribeMetricFilters", s.nListMetricFilters, res) |
| 34 | + r.Handle("PUT /api/v1/logs/groups/{group}/metric-filters/{name}", "logs:PutMetricFilter", s.nPutMetricFilter, res) |
| 35 | + r.Handle("DELETE /api/v1/logs/groups/{group}/metric-filters/{name}", "logs:DeleteMetricFilter", s.nDeleteMetricFilter, res) |
| 36 | + r.Handle("GET /api/v1/logs/groups/{group}/subscription-filters", "logs:DescribeSubscriptionFilters", s.nListSubFilters, res) |
| 37 | + r.Handle("PUT /api/v1/logs/groups/{group}/subscription-filters/{name}", "logs:PutSubscriptionFilter", s.nPutSubFilter, res) |
| 38 | + r.Handle("DELETE /api/v1/logs/groups/{group}/subscription-filters/{name}", "logs:DeleteSubscriptionFilter", s.nDeleteSubFilter, res) |
| 39 | + r.Handle("GET /api/v1/cloudwatch/alarms/{name}/history", "cloudwatch:DescribeAlarmHistory", s.nAlarmHistory, |
| 40 | + httpx.Res("arn:aws:cloudwatch:{region}:{account}:alarm:{name}")) |
| 41 | +} |
| 42 | + |
| 43 | +func (s *Service) nStartQuery(c *httpx.Ctx) (any, error) { |
| 44 | + var in startQueryIn |
| 45 | + if err := c.Bind(&in); err != nil { |
| 46 | + return nil, err |
| 47 | + } |
| 48 | + return nat(s.startQuery(c, in)) |
| 49 | +} |
| 50 | + |
| 51 | +func (s *Service) nQueryResults(c *httpx.Ctx) (any, error) { |
| 52 | + return nat(s.queryResults(c, c.Param("id"))) |
| 53 | +} |
| 54 | + |
| 55 | +func (s *Service) nListMetricFilters(c *httpx.Ctx) (any, error) { |
| 56 | + if _, err := nat(s.storedGroup(c.Param("group"))); err != nil { |
| 57 | + return nil, err |
| 58 | + } |
| 59 | + out := slices.Clone(s.filters(c.Param("group")).Metric) |
| 60 | + if out == nil { |
| 61 | + out = []MetricFilter{} |
| 62 | + } |
| 63 | + return out, nil |
| 64 | +} |
| 65 | + |
| 66 | +func (s *Service) nPutMetricFilter(c *httpx.Ctx) (any, error) { |
| 67 | + var in putMetricFilterIn |
| 68 | + if err := c.Bind(&in); err != nil { |
| 69 | + return nil, err |
| 70 | + } |
| 71 | + in.LogGroupName, in.FilterName = c.Param("group"), c.Param("name") |
| 72 | + return nat(s.putMetricFilter(c, in)) |
| 73 | +} |
| 74 | + |
| 75 | +func (s *Service) nDeleteMetricFilter(c *httpx.Ctx) (any, error) { |
| 76 | + return nat(s.deleteMetricFilter(c, deleteFilterIn{LogGroupName: c.Param("group"), FilterName: c.Param("name")})) |
| 77 | +} |
| 78 | + |
| 79 | +func (s *Service) nListSubFilters(c *httpx.Ctx) (any, error) { |
| 80 | + if _, err := nat(s.storedGroup(c.Param("group"))); err != nil { |
| 81 | + return nil, err |
| 82 | + } |
| 83 | + out := slices.Clone(s.filters(c.Param("group")).Subscription) |
| 84 | + if out == nil { |
| 85 | + out = []SubscriptionFilter{} |
| 86 | + } |
| 87 | + return out, nil |
| 88 | +} |
| 89 | + |
| 90 | +func (s *Service) nPutSubFilter(c *httpx.Ctx) (any, error) { |
| 91 | + var in putSubscriptionFilterIn |
| 92 | + if err := c.Bind(&in); err != nil { |
| 93 | + return nil, err |
| 94 | + } |
| 95 | + in.LogGroupName, in.FilterName = c.Param("group"), c.Param("name") |
| 96 | + return nat(s.putSubscriptionFilter(c, in)) |
| 97 | +} |
| 98 | + |
| 99 | +func (s *Service) nDeleteSubFilter(c *httpx.Ctx) (any, error) { |
| 100 | + return nat(s.deleteSubscriptionFilter(c, deleteFilterIn{LogGroupName: c.Param("group"), FilterName: c.Param("name")})) |
| 101 | +} |
| 102 | + |
| 103 | +func (s *Service) nAlarmHistory(c *httpx.Ctx) (any, error) { |
| 104 | + if !store.Has(s.env.Store, cAlarms, c.Param("name")) { |
| 105 | + return nil, core.NotFound("alarm", c.Param("name")) |
| 106 | + } |
| 107 | + out := slices.Clone(s.history(c.Param("name"))) |
| 108 | + slices.SortStableFunc(out, func(a, b AlarmHistoryItem) int { return b.Timestamp.Compare(a.Timestamp) }) |
| 109 | + if out == nil { |
| 110 | + out = []AlarmHistoryItem{} |
| 111 | + } |
| 112 | + return out, nil |
| 113 | +} |
0 commit comments