From 4eb5213294e4be894712f5a081cc18f01db308ac Mon Sep 17 00:00:00 2001 From: Bo-Yi Wu Date: Sat, 13 Aug 2022 14:15:21 +0800 Subject: [PATCH] chore(engine): ping docker daemon Signed-off-by: Bo-Yi Wu --- cmd/config.go | 4 +- cmd/damon.go | 430 ++++++++++++++++++++++++++--------------------- cmd/root.go | 16 +- engine/docker.go | 39 +++++ go.mod | 4 +- go.sum | 9 - 6 files changed, 281 insertions(+), 221 deletions(-) create mode 100644 engine/docker.go diff --git a/cmd/config.go b/cmd/config.go index ec7249a..1e1452a 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -5,8 +5,8 @@ import "github.com/kelseyhightower/envconfig" type ( // Config provides the system configuration. Config struct { - Debug bool `envconfig:"DRONE_DEBUG"` - Trace bool `envconfig:"DRONE_TRACE"` + Debug bool `envconfig:"GITEA_DEBUG"` + Trace bool `envconfig:"GITEA_TRACE"` } ) diff --git a/cmd/damon.go b/cmd/damon.go index d7380b1..2067ff2 100644 --- a/cmd/damon.go +++ b/cmd/damon.go @@ -2,222 +2,264 @@ package cmd import ( "context" - "encoding/json" - "errors" - "fmt" - "strings" "time" - "github.com/gorilla/websocket" - "github.com/rs/zerolog/log" + "gitea.com/gitea/act_runner/engine" + + "github.com/joho/godotenv" + log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) -type Message struct { - Version int // - Type int // message type, 1 register 2 error - RunnerUUID string // runner uuid - BuildUUID string // build uuid - ErrCode int // error code - ErrContent string // errors message - EventName string - EventPayload string - JobID string // only run the special job, empty means run all the jobs -} +// type Message struct { +// Version int // +// Type int // message type, 1 register 2 error +// RunnerUUID string // runner uuid +// BuildUUID string // build uuid +// ErrCode int // error code +// ErrContent string // errors message +// EventName string +// EventPayload string +// JobID string // only run the special job, empty means run all the jobs +// } -const ( - MsgTypeRegister = iota + 1 // register - MsgTypeError // error - MsgTypeRequestBuild // request build task - MsgTypeIdle // no task - MsgTypeBuildResult // build result -) +// const ( +// MsgTypeRegister = iota + 1 // register +// MsgTypeError // error +// MsgTypeRequestBuild // request build task +// MsgTypeIdle // no task +// MsgTypeBuildResult // build result +// ) -func handleVersion1(ctx context.Context, conn *websocket.Conn, message []byte, msg *Message) error { - switch msg.Type { - case MsgTypeRegister: - log.Info().Msgf("received registered success: %s", message) - return conn.WriteJSON(&Message{ - Version: 1, - Type: MsgTypeRequestBuild, - RunnerUUID: msg.RunnerUUID, - }) - case MsgTypeError: - log.Info().Msgf("received error msessage: %s", message) - return conn.WriteJSON(&Message{ - Version: 1, - Type: MsgTypeRequestBuild, - RunnerUUID: msg.RunnerUUID, - }) - case MsgTypeIdle: - log.Info().Msgf("received no task") - return conn.WriteJSON(&Message{ - Version: 1, - Type: MsgTypeRequestBuild, - RunnerUUID: msg.RunnerUUID, - }) - case MsgTypeRequestBuild: - switch msg.EventName { - case "push": - input := Input{ - forgeInstance: "github.com", - reuseContainers: true, - } +// func handleVersion1(ctx context.Context, conn *websocket.Conn, message []byte, msg *Message) error { +// switch msg.Type { +// case MsgTypeRegister: +// log.Info().Msgf("received registered success: %s", message) +// return conn.WriteJSON(&Message{ +// Version: 1, +// Type: MsgTypeRequestBuild, +// RunnerUUID: msg.RunnerUUID, +// }) +// case MsgTypeError: +// log.Info().Msgf("received error msessage: %s", message) +// return conn.WriteJSON(&Message{ +// Version: 1, +// Type: MsgTypeRequestBuild, +// RunnerUUID: msg.RunnerUUID, +// }) +// case MsgTypeIdle: +// log.Info().Msgf("received no task") +// return conn.WriteJSON(&Message{ +// Version: 1, +// Type: MsgTypeRequestBuild, +// RunnerUUID: msg.RunnerUUID, +// }) +// case MsgTypeRequestBuild: +// switch msg.EventName { +// case "push": +// input := Input{ +// forgeInstance: "github.com", +// reuseContainers: true, +// } - ctx, cancel := context.WithTimeout(ctx, time.Hour) - defer cancel() +// ctx, cancel := context.WithTimeout(ctx, time.Hour) +// defer cancel() - done := make(chan error) - go func(chan error) { - done <- runTask(ctx, &input, "") - }(done) +// done := make(chan error) +// go func(chan error) { +// done <- runTask(ctx, &input, "") +// }(done) - c := time.NewTicker(time.Second) - defer c.Stop() +// c := time.NewTicker(time.Second) +// defer c.Stop() - for { - select { - case <-ctx.Done(): - cancel() - log.Info().Msgf("cancel task") - return nil - case err := <-done: - if err != nil { - log.Error().Msgf("runTask failed: %v", err) - return conn.WriteJSON(&Message{ - Version: 1, - Type: MsgTypeBuildResult, - RunnerUUID: msg.RunnerUUID, - BuildUUID: msg.BuildUUID, - ErrCode: 1, - ErrContent: err.Error(), - }) - } - log.Error().Msgf("runTask success") - return conn.WriteJSON(&Message{ - Version: 1, - Type: MsgTypeBuildResult, - RunnerUUID: msg.RunnerUUID, - BuildUUID: msg.BuildUUID, - }) - case <-c.C: - } - } - default: - return fmt.Errorf("unknow event %s with payload %s", msg.EventName, msg.EventPayload) - } - default: - return fmt.Errorf("received a message with an unsupported type: %#v", msg) - } -} +// for { +// select { +// case <-ctx.Done(): +// cancel() +// log.Info().Msgf("cancel task") +// return nil +// case err := <-done: +// if err != nil { +// log.Error().Msgf("runTask failed: %v", err) +// return conn.WriteJSON(&Message{ +// Version: 1, +// Type: MsgTypeBuildResult, +// RunnerUUID: msg.RunnerUUID, +// BuildUUID: msg.BuildUUID, +// ErrCode: 1, +// ErrContent: err.Error(), +// }) +// } +// log.Error().Msgf("runTask success") +// return conn.WriteJSON(&Message{ +// Version: 1, +// Type: MsgTypeBuildResult, +// RunnerUUID: msg.RunnerUUID, +// BuildUUID: msg.BuildUUID, +// }) +// case <-c.C: +// } +// } +// default: +// return fmt.Errorf("unknow event %s with payload %s", msg.EventName, msg.EventPayload) +// } +// default: +// return fmt.Errorf("received a message with an unsupported type: %#v", msg) +// } +// } -// TODO: handle the message -func handleMessage(ctx context.Context, conn *websocket.Conn, message []byte) error { - var msg Message - if err := json.Unmarshal(message, &msg); err != nil { - return fmt.Errorf("unmarshal received message faild: %v", err) - } +// // TODO: handle the message +// func handleMessage(ctx context.Context, conn *websocket.Conn, message []byte) error { +// var msg Message +// if err := json.Unmarshal(message, &msg); err != nil { +// return fmt.Errorf("unmarshal received message faild: %v", err) +// } - switch msg.Version { - case 1: - return handleVersion1(ctx, conn, message, &msg) - default: - return fmt.Errorf("recevied a message with an unsupported version, consider upgrade your runner") - } -} +// switch msg.Version { +// case 1: +// return handleVersion1(ctx, conn, message, &msg) +// default: +// return fmt.Errorf("recevied a message with an unsupported version, consider upgrade your runner") +// } +// } func runDaemon(ctx context.Context, input *Input) func(cmd *cobra.Command, args []string) error { return func(cmd *cobra.Command, args []string) error { - log.Info().Msg("Starting runner daemon") - var conn *websocket.Conn - var err error - ticker := time.NewTicker(time.Second) - defer ticker.Stop() - var failedCnt int + log.Infoln("Starting runner daemon") + + _ = godotenv.Load(input.envFile) + cfg, err := fromEnviron() + if err != nil { + log.WithError(err). + Fatalln("invalid configuration") + } + + initLogging(cfg) + + opts := engine.Opts{} + engine, err := engine.NewEnv(opts) + if err != nil { + log.WithError(err). + Fatalln("cannot load the docker engine") + } + + count := 0 for { + err := engine.Ping(ctx) + if err == context.Canceled { + break + } select { case <-ctx.Done(): - log.Info().Msgf("cancel task") - if conn != nil { - err = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "")) - if err != nil { - log.Error().Msgf("write close: %v", err) - } - } - if errors.Is(ctx.Err(), context.Canceled) { - return nil - } return ctx.Err() - case <-ticker.C: - if conn == nil { - log.Trace().Msgf("trying connect %v", "ws://localhost:3000/api/actions") - conn, _, err = websocket.DefaultDialer.DialContext(ctx, "ws://localhost:3000/api/actions", nil) - if err != nil { - log.Error().Msgf("dial: %v", err) - break - } - - // register the client - msg := Message{ - Version: 1, - Type: MsgTypeRegister, - RunnerUUID: "111111", - } - bs, err := json.Marshal(&msg) - if err != nil { - log.Error().Msgf("Marshal: %v", err) - break - } - - if err = conn.WriteMessage(websocket.TextMessage, bs); err != nil { - log.Error().Msgf("register failed: %v", err) - conn.Close() - conn = nil - break - } - } - - const timeout = time.Second * 10 - - for { - select { - case <-ctx.Done(): - log.Info().Msg("cancel task") - return nil - default: - } - - _ = conn.SetReadDeadline(time.Now().Add(timeout)) - conn.SetPongHandler(func(string) error { - return conn.SetReadDeadline(time.Now().Add(timeout)) - }) - - _, message, err := conn.ReadMessage() - if err != nil { - if websocket.IsCloseError(err, websocket.CloseAbnormalClosure) || - websocket.IsCloseError(err, websocket.CloseNormalClosure) { - log.Trace().Msgf("closed from remote") - conn.Close() - conn = nil - } else if !strings.Contains(err.Error(), "i/o timeout") { - log.Error().Msgf("read message failed: %#v", err) - } - failedCnt++ - if failedCnt > 60 { - if conn != nil { - conn.Close() - conn = nil - } - failedCnt = 0 - } - break - } - - if err := handleMessage(ctx, conn, message); err != nil { - log.Error().Msgf(err.Error()) - } + default: + } + if err != nil { + log.WithError(err). + Errorln("cannot ping the docker daemon") + count++ + if count == 5 { + log.WithError(err). + Fatalln("retry count reached") } + time.Sleep(time.Second) + } else { + log.Debugln("successfully pinged the docker daemon") + break } } + + return nil + // var conn *websocket.Conn + // var err error + // ticker := time.NewTicker(time.Second) + // defer ticker.Stop() + // var failedCnt int + // for { + // select { + // case <-ctx.Done(): + // log.Info().Msgf("cancel task") + // if conn != nil { + // err = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "")) + // if err != nil { + // log.Error().Msgf("write close: %v", err) + // } + // } + // if errors.Is(ctx.Err(), context.Canceled) { + // return nil + // } + // return ctx.Err() + // case <-ticker.C: + // if conn == nil { + // log.Trace().Msgf("trying connect %v", "ws://localhost:3000/api/actions") + // conn, _, err = websocket.DefaultDialer.DialContext(ctx, "ws://localhost:3000/api/actions", nil) + // if err != nil { + // log.Error().Msgf("dial: %v", err) + // break + // } + + // // register the client + // msg := Message{ + // Version: 1, + // Type: MsgTypeRegister, + // RunnerUUID: "111111", + // } + // bs, err := json.Marshal(&msg) + // if err != nil { + // log.Error().Msgf("Marshal: %v", err) + // break + // } + + // if err = conn.WriteMessage(websocket.TextMessage, bs); err != nil { + // log.Error().Msgf("register failed: %v", err) + // conn.Close() + // conn = nil + // break + // } + // } + + // const timeout = time.Second * 10 + + // for { + // select { + // case <-ctx.Done(): + // log.Info().Msg("cancel task") + // return nil + // default: + // } + + // _ = conn.SetReadDeadline(time.Now().Add(timeout)) + // conn.SetPongHandler(func(string) error { + // return conn.SetReadDeadline(time.Now().Add(timeout)) + // }) + + // _, message, err := conn.ReadMessage() + // if err != nil { + // if websocket.IsCloseError(err, websocket.CloseAbnormalClosure) || + // websocket.IsCloseError(err, websocket.CloseNormalClosure) { + // log.Trace().Msgf("closed from remote") + // conn.Close() + // conn = nil + // } else if !strings.Contains(err.Error(), "i/o timeout") { + // log.Error().Msgf("read message failed: %#v", err) + // } + // failedCnt++ + // if failedCnt > 60 { + // if conn != nil { + // conn.Close() + // conn = nil + // } + // failedCnt = 0 + // } + // break + // } + + // if err := handleMessage(ctx, conn, message); err != nil { + // log.Error().Msgf(err.Error()) + // } + // } + // } + // } } } diff --git a/cmd/root.go b/cmd/root.go index 213f700..0ba2198 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -6,7 +6,6 @@ import ( "os" "path/filepath" - "github.com/joho/godotenv" "github.com/mattn/go-isatty" "github.com/nektos/act/pkg/artifacts" "github.com/nektos/act/pkg/common" @@ -19,7 +18,8 @@ import ( const version = "0.1" type Input struct { - actor string + envFile string + actor string // workdir string // workflowsPath string // autodetectEvent bool @@ -79,8 +79,6 @@ func initLogging(cfg Config) { } func Execute(ctx context.Context) { - var envfile string - input := Input{ reuseContainers: true, forgeInstance: "gitea.com", @@ -104,15 +102,7 @@ func Execute(ctx context.Context) { rootCmd.Flags().BoolP("run", "r", false, "run workflows") rootCmd.Flags().StringP("job", "j", "", "run job") rootCmd.PersistentFlags().StringVarP(&input.forgeInstance, "forge-instance", "", "github.com", "Forge instance to use.") - rootCmd.PersistentFlags().StringVarP(&envfile, "env-file", "", ".env", "Read in a file of environment variables.") - - _ = godotenv.Load(envfile) - cfg, err := fromEnviron() - if err != nil { - log.Fatal("invalid cfguration") - } - - initLogging(cfg) + rootCmd.PersistentFlags().StringVarP(&input.envFile, "env-file", "", ".env", "Read in a file of environment variables.") if err := rootCmd.Execute(); err != nil { os.Exit(1) diff --git a/engine/docker.go b/engine/docker.go new file mode 100644 index 0000000..9aee014 --- /dev/null +++ b/engine/docker.go @@ -0,0 +1,39 @@ +package engine + +import ( + "context" + + "github.com/docker/docker/client" +) + +// Opts configures the Docker engine. +type Opts struct { + HidePull bool +} + +type Docker struct { + client client.APIClient + hidePull bool +} + +func New(client client.APIClient, opts Opts) *Docker { + return &Docker{ + client: client, + hidePull: opts.HidePull, + } +} + +// NewEnv returns a new Engine from the environment. +func NewEnv(opts Opts) (*Docker, error) { + cli, err := client.NewClientWithOpts(client.FromEnv) + if err != nil { + return nil, err + } + return New(cli, opts), nil +} + +// Ping pings the Docker daemon. +func (e *Docker) Ping(ctx context.Context) error { + _, err := e.client.Ping(ctx) + return err +} diff --git a/go.mod b/go.mod index 02ac25e..1bfd777 100644 --- a/go.mod +++ b/go.mod @@ -3,12 +3,11 @@ module gitea.com/gitea/act_runner go 1.18 require ( - github.com/gorilla/websocket v1.4.2 + github.com/docker/docker v20.10.17+incompatible github.com/joho/godotenv v1.4.0 github.com/kelseyhightower/envconfig v1.4.0 github.com/mattn/go-isatty v0.0.14 github.com/nektos/act v0.2.26 - github.com/rs/zerolog v1.26.1 github.com/sirupsen/logrus v1.9.0 github.com/spf13/cobra v1.5.0 ) @@ -23,7 +22,6 @@ require ( github.com/containerd/containerd v1.6.6 // indirect github.com/docker/cli v20.10.17+incompatible // indirect github.com/docker/distribution v2.8.1+incompatible // indirect - github.com/docker/docker v20.10.17+incompatible // indirect github.com/docker/docker-credential-helpers v0.6.4 // indirect github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.4.0 // indirect diff --git a/go.sum b/go.sum index 5662f05..0327107 100644 --- a/go.sum +++ b/go.sum @@ -420,7 +420,6 @@ github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2z github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= @@ -648,9 +647,6 @@ github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6So github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= -github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.26.1 h1:/ihwxqH+4z8UxyI70wM1z9yCvkWcfz/a3mj48k/Zngc= -github.com/rs/zerolog v1.26.1/go.mod h1:/wSSJWX7lVrsOwlbyTRSOJvqRlc+WjWlfes+CiJ+tmc= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= @@ -736,7 +732,6 @@ github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1: github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= @@ -774,7 +769,6 @@ golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29 h1:tkVvjkPTB7pnW3jnid7kNyAMPVWllTNOf/qKDze4p9o= golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -847,7 +841,6 @@ golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220403103023-749bd193bc2b h1:vI32FkLJNAWtGD4BwkThwEy6XS7ZLLMHkSkYfF8M0W0= golang.org/x/net v0.0.0-20220403103023-749bd193bc2b/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= @@ -941,7 +934,6 @@ golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1012,7 +1004,6 @@ golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4X golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=