Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@

dist/
.env
9 changes: 7 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
module github.com/openstatusHQ/cli

go 1.23.2
go 1.24.0

require github.com/urfave/cli/v3 v3.0.0-alpha9.2 // direct

require (
buf.build/gen/go/openstatus/api/connectrpc/gosimple v1.19.1-20260202165838-5bd92a1e5d53.2
buf.build/gen/go/openstatus/api/protocolbuffers/go v1.36.11-20260202165838-5bd92a1e5d53.1
connectrpc.com/connect v1.19.1
github.com/fatih/color v1.18.0
github.com/google/go-cmp v0.7.0
github.com/knadh/koanf/parsers/yaml v0.1.0
github.com/knadh/koanf/providers/file v1.1.2
github.com/knadh/koanf/v2 v2.1.1
Expand All @@ -17,10 +21,10 @@ require (
)

require (
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.11-20251209175733-2a1774d88802.1 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/knadh/koanf/maps v0.1.2 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
Expand All @@ -32,5 +36,6 @@ require (
github.com/rivo/uniseg v0.2.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
golang.org/x/sys v0.26.0 // indirect
google.golang.org/protobuf v1.36.11 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
15 changes: 14 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.11-20251209175733-2a1774d88802.1 h1:j9yeqTWEFrtimt8Nng2MIeRrpoCvQzM9/g25XTvqUGg=
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.11-20251209175733-2a1774d88802.1/go.mod h1:tvtbpgaVXZX4g6Pn+AnzFycuRK3MOz5HJfEGeEllXYM=
buf.build/gen/go/openstatus/api/connectrpc/gosimple v1.19.1-20260202080906-4f3d33d3bed3.2 h1:nQzgK01nlgbSQn/7/qjHxSwcv/C6I2f9lMfhgJ98FV0=
buf.build/gen/go/openstatus/api/connectrpc/gosimple v1.19.1-20260202080906-4f3d33d3bed3.2/go.mod h1:ikyyG3mJiNpeGcAywdhzGOt5fTSs78jvlvAqJo8ZYf4=
buf.build/gen/go/openstatus/api/connectrpc/gosimple v1.19.1-20260202165838-5bd92a1e5d53.2 h1:MeP+r7GwYHWKSMa1ltvtRNwzT+gCyHIYCEpNxWeNwS4=
buf.build/gen/go/openstatus/api/connectrpc/gosimple v1.19.1-20260202165838-5bd92a1e5d53.2/go.mod h1:W/PtF1QguqXdSkOHAD0VAOTMNfuESeNOdR2cF/CWeOQ=
buf.build/gen/go/openstatus/api/protocolbuffers/go v1.36.11-20260202080906-4f3d33d3bed3.1 h1:PeaMjGloj9U860iUOmX7pNwx2hdudlOus8ietWw7IWE=
buf.build/gen/go/openstatus/api/protocolbuffers/go v1.36.11-20260202080906-4f3d33d3bed3.1/go.mod h1:pZsKB5l3aT2mKtGkAZTC8pXhTptdfyYwFGCyH+KVfOM=
buf.build/gen/go/openstatus/api/protocolbuffers/go v1.36.11-20260202165838-5bd92a1e5d53.1 h1:vw4PznfU8x7XrFtc/HHPjWfxNnFExtaSwrPS8cEKq+w=
buf.build/gen/go/openstatus/api/protocolbuffers/go v1.36.11-20260202165838-5bd92a1e5d53.1/go.mod h1:pZsKB5l3aT2mKtGkAZTC8pXhTptdfyYwFGCyH+KVfOM=
connectrpc.com/connect v1.19.1 h1:R5M57z05+90EfEvCY1b7hBxDVOUl45PrtXtAV2fOC14=
connectrpc.com/connect v1.19.1/go.mod h1:tN20fjdGlewnSFeZxLKb0xwIZ6ozc3OQs2hTXy4du9w=
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand All @@ -10,7 +22,6 @@ github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyT
github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
Expand Down Expand Up @@ -66,6 +77,8 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Expand Down
2 changes: 1 addition & 1 deletion internal/monitors/monitor_apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func CompareLockWithConfig(apiKey string, applyChange bool, lock config.Monitors
if _, exist := configData[v]; !exist {
if applyChange {

err := DeleteMonitor(http.DefaultClient, apiKey, fmt.Sprintf("%d", value.ID))
err := DeleteMonitorWithHTTPClient(http.DefaultClient, apiKey, fmt.Sprintf("%d", value.ID))
if err != nil {
fmt.Println(err)
}
Expand Down
90 changes: 66 additions & 24 deletions internal/monitors/monitor_create.go
Original file line number Diff line number Diff line change
@@ -1,55 +1,97 @@
package monitors

import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"os"
"strconv"

monitorv1 "buf.build/gen/go/openstatus/api/protocolbuffers/go/openstatus/monitor/v1"
"buf.build/gen/go/openstatus/api/connectrpc/gosimple/openstatus/monitor/v1/monitorv1connect"
confirmation "github.com/openstatusHQ/cli/internal/cli"
"github.com/openstatusHQ/cli/internal/config"
"github.com/urfave/cli/v3"
)

// CreateMonitor creates a monitor using the SDK, dispatching to the appropriate type
func CreateMonitor(httpClient *http.Client, apiKey string, monitor config.Monitor) (Monitor, error) {
client := NewMonitorClientWithHTTPClient(httpClient, apiKey)

switch monitor.Kind {
case config.HTTP:
return CreateHTTPMonitor(client, monitor)
case config.TCP:
return CreateTCPMonitor(client, monitor)
default:
return Monitor{}, fmt.Errorf("unsupported monitor kind: %s", monitor.Kind)
}
}

url := fmt.Sprintf("%s/monitor/%s", APIBaseURL, monitor.Kind)
// CreateHTTPMonitor creates an HTTP monitor using the SDK
func CreateHTTPMonitor(client monitorv1connect.MonitorServiceClient, monitor config.Monitor) (Monitor, error) {
req := &monitorv1.CreateHTTPMonitorRequest{
Monitor: configToHTTPMonitor(monitor),
}

payloadBuf := new(bytes.Buffer)
json.NewEncoder(payloadBuf).Encode(monitor)
req, err := http.NewRequest(http.MethodPost, url, payloadBuf)
resp, err := client.CreateHTTPMonitor(context.Background(), req)
if err != nil {
return Monitor{}, fmt.Errorf("failed to create request: %w", err)
return Monitor{}, fmt.Errorf("failed to create HTTP monitor: %w", err)
}

req.Header.Add("x-openstatus-key", apiKey)
req.Header.Add("Content-Type", "application/json")
return httpMonitorToLocal(resp.GetMonitor()), nil
}

res, err := httpClient.Do(req)
if err != nil {
return Monitor{}, err
// CreateTCPMonitor creates a TCP monitor using the SDK
func CreateTCPMonitor(client monitorv1connect.MonitorServiceClient, monitor config.Monitor) (Monitor, error) {
req := &monitorv1.CreateTCPMonitorRequest{
Monitor: configToTCPMonitor(monitor),
}

if res.StatusCode != http.StatusOK {
return Monitor{}, fmt.Errorf("Failed to create monitor")
}
defer res.Body.Close()
body, err := io.ReadAll(res.Body)
resp, err := client.CreateTCPMonitor(context.Background(), req)
if err != nil {
return Monitor{}, fmt.Errorf("failed to read response body: %w", err)
return Monitor{}, fmt.Errorf("failed to create TCP monitor: %w", err)
}

var monitors Monitor
err = json.Unmarshal(body, &monitors)
if err != nil {
return Monitor{}, err
return tcpMonitorToLocal(resp.GetMonitor()), nil
}

// httpMonitorToLocal converts SDK HTTPMonitor to local Monitor type
func httpMonitorToLocal(m *monitorv1.HTTPMonitor) Monitor {
id, _ := strconv.Atoi(m.GetId())
return Monitor{
ID: id,
Name: m.GetName(),
Description: m.GetDescription(),
URL: m.GetUrl(),
Periodicity: periodicityToString(m.GetPeriodicity()),
Method: httpMethodToString(m.GetMethod()),
Regions: regionsToStrings(m.GetRegions()),
Active: m.GetActive(),
Public: m.GetPublic(),
Timeout: int(m.GetTimeout()),
Retry: int(m.GetRetry()),
JobType: "http",
}
}

return monitors, nil
// tcpMonitorToLocal converts SDK TCPMonitor to local Monitor type
func tcpMonitorToLocal(m *monitorv1.TCPMonitor) Monitor {
id, _ := strconv.Atoi(m.GetId())
return Monitor{
ID: id,
Name: m.GetName(),
Description: m.GetDescription(),
URL: m.GetUri(),
Periodicity: periodicityToString(m.GetPeriodicity()),
Regions: regionsToStrings(m.GetRegions()),
Active: m.GetActive(),
Public: m.GetPublic(),
Timeout: int(m.GetTimeout()),
Retry: int(m.GetRetry()),
JobType: "tcp",
}
}

func GetMonitorCreateCmd() *cli.Command {
Expand Down
Loading
Loading