From 32794938178235af0b7e34e1daecf946d2d391c7 Mon Sep 17 00:00:00 2001 From: Geoff Franks Date: Mon, 5 Dec 2022 14:23:06 +0000 Subject: [PATCH] Ensure silk-daemon-healthchecker doesn't restart silk forever on failure --- jobs/silk-daemon/spec | 4 + jobs/silk-daemon/templates/bpm.yml.erb | 3 + .../templates/healthchecker.yml.erb | 1 + .../templates/restart-silk-daemon.erb | 23 ++-- src/code.cloudfoundry.org/go.mod | 4 +- src/code.cloudfoundry.org/go.sum | 7 +- .../healthchecker/cmd/healthchecker/main.go | 7 +- .../healthchecker/config/config.go | 24 +++- .../healthchecker/watchdog/watchdog.go | 89 +++++++++++-- .../github.com/go-sql-driver/mysql/AUTHORS | 7 + .../go-sql-driver/mysql/CHANGELOG.md | 21 +++ .../github.com/go-sql-driver/mysql/README.md | 17 ++- .../go-sql-driver/mysql/atomic_bool.go | 19 +++ .../go-sql-driver/mysql/atomic_bool_go118.go | 47 +++++++ .../github.com/go-sql-driver/mysql/auth.go | 56 ++++---- .../go-sql-driver/mysql/collations.go | 3 +- .../go-sql-driver/mysql/conncheck.go | 1 + .../go-sql-driver/mysql/conncheck_dummy.go | 1 + .../go-sql-driver/mysql/connection.go | 22 ++-- .../github.com/go-sql-driver/mysql/driver.go | 6 +- .../github.com/go-sql-driver/mysql/dsn.go | 73 +++++++---- .../github.com/go-sql-driver/mysql/errors.go | 16 ++- .../github.com/go-sql-driver/mysql/fields.go | 14 +- .../github.com/go-sql-driver/mysql/fuzz.go | 1 + .../github.com/go-sql-driver/mysql/infile.go | 32 ++--- .../go-sql-driver/mysql/nulltime.go | 21 +++ .../go-sql-driver/mysql/nulltime_go113.go | 40 ------ .../go-sql-driver/mysql/nulltime_legacy.go | 39 ------ .../github.com/go-sql-driver/mysql/packets.go | 90 ++++++------- .../go-sql-driver/mysql/statement.go | 8 +- .../go-sql-driver/mysql/transaction.go | 4 +- .../github.com/go-sql-driver/mysql/utils.go | 122 +++++++----------- src/code.cloudfoundry.org/vendor/modules.txt | 6 +- 33 files changed, 498 insertions(+), 330 deletions(-) create mode 100644 src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/atomic_bool.go create mode 100644 src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/atomic_bool_go118.go delete mode 100644 src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/nulltime_go113.go delete mode 100644 src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/nulltime_legacy.go diff --git a/jobs/silk-daemon/spec b/jobs/silk-daemon/spec index c00609e1..045fed7c 100644 --- a/jobs/silk-daemon/spec +++ b/jobs/silk-daemon/spec @@ -106,3 +106,7 @@ properties: 'rfc3339' is the recommended format. It will result in all timestamps in the drain log controlled by silk-daemon to be in RFC3339 format, which is human readable. This does not include stderr logs from golang libraries. 'deprecated' will result in all timestamps being in the format they were before the rfc3339 flag was introduced for the drain log. We do not recommend using this flag unless you have scripts that expect a particular timestamp format. default: "rfc3339" + + healthchecker.failure_counter_file: + description: "File used by the healthchecker to monitor consecutive failures." + default: /var/vcap/data/silk-daemon/counters/consecutive_healthchecker_failures.count diff --git a/jobs/silk-daemon/templates/bpm.yml.erb b/jobs/silk-daemon/templates/bpm.yml.erb index 2c7eebdb..d3e78a07 100644 --- a/jobs/silk-daemon/templates/bpm.yml.erb +++ b/jobs/silk-daemon/templates/bpm.yml.erb @@ -16,3 +16,6 @@ processes: args: - "-c" - "/var/vcap/jobs/silk-daemon/config/healthchecker.yml" + additional_volumes: + - path: /var/vcap/data/silk-daemon/counters + writable: true diff --git a/jobs/silk-daemon/templates/healthchecker.yml.erb b/jobs/silk-daemon/templates/healthchecker.yml.erb index 5c2f5a32..1d41133a 100644 --- a/jobs/silk-daemon/templates/healthchecker.yml.erb +++ b/jobs/silk-daemon/templates/healthchecker.yml.erb @@ -1,6 +1,7 @@ <%= config = { 'component_name' => 'silk-daemon-healthchecker', + 'failure_counter_file' => p('healthchecker.failure_counter_file'), 'log_level' => p('logging.level'), 'healthcheck_endpoint' => { 'host' => '127.0.0.1', diff --git a/jobs/silk-daemon/templates/restart-silk-daemon.erb b/jobs/silk-daemon/templates/restart-silk-daemon.erb index 31094141..93176b15 100644 --- a/jobs/silk-daemon/templates/restart-silk-daemon.erb +++ b/jobs/silk-daemon/templates/restart-silk-daemon.erb @@ -1,13 +1,13 @@ #!/usr/bin/env bash PIDFILE="/var/vcap/sys/run/silk-daemon/restart-silk-daemon.pid" +FAILURE_COUNTER_FILE="<%= p("healthchecker.failure_counter_file") %>" # As this script might run longer than a monit cycle (10s) and thus might be # triggered several times, it must be ensured that it runs only once. [[ -s "$PIDFILE" ]] && exit function on_exit { - /var/vcap/bosh/bin/monit reload silk-daemon-healthchecker rm -f $PIDFILE } @@ -18,12 +18,19 @@ echo "$BASHPID" > "$PIDFILE" LOGFILE="/var/vcap/sys/log/silk-daemon/restart-silk-daemon.log" echo "$(date) - pid: $BASHPID - Monit triggered restart" >> "$LOGFILE" -/var/vcap/bosh/bin/monit restart silk-daemon -sleep 1 -echo "$(date) - pid: $BASHPID - Waiting for silk-daemon to be restarted" >> "$LOGFILE" +failure_counter="$(cat ${FAILURE_COUNTER_FILE})" -until /var/vcap/bosh/bin/monit summary | grep silk-daemon | grep -v healthchecker | grep running; do +if (( failure_counter < 10 )); then + /var/vcap/bosh/bin/monit restart silk-daemon sleep 1 -done - -echo "$(date) - pid: $BASHPID - silk-daemon was restarted" >> "$LOGFILE" + echo "$(date) - pid: $BASHPID - Waiting for silk-daemon to be restarted" >> "$LOGFILE" + + until /var/vcap/bosh/bin/monit summary | grep silk-daemon | grep -v healthchecker | grep running; do + sleep 1 + done + /var/vcap/bosh/bin/monit reload silk-daemon-healthchecker + echo "$(date) - pid: $BASHPID - silk-daemon was restarted" >> "$LOGFILE" +else + echo "$(date) - pid: $BASHPID - 10 consecutive failures in a row. Stopping healthcheck to avoid constantly bringing down the main service." >> "${LOGFILE}" + /var/vcap/bosh/bin/monit unmonitor silk-daemon-healthchecker +fi diff --git a/src/code.cloudfoundry.org/go.mod b/src/code.cloudfoundry.org/go.mod index 897fc38d..4a9d0474 100644 --- a/src/code.cloudfoundry.org/go.mod +++ b/src/code.cloudfoundry.org/go.mod @@ -15,7 +15,7 @@ replace github.com/gogo/protobuf => github.com/gogo/protobuf v1.3.2 replace github.com/hashicorp/consul => github.com/hashicorp/consul v0.7.0 require ( - code.cloudfoundry.org/cf-networking-helpers v0.0.0-20221117171434-3d123025a8c3 + code.cloudfoundry.org/cf-networking-helpers v0.0.0-20221205130414-742bd12bf674 code.cloudfoundry.org/debugserver v0.0.0-20210608171006-d7658ce493f4 code.cloudfoundry.org/diego-logging-client v0.0.0-20220314190632-277a9c460661 code.cloudfoundry.org/executor v0.0.0-20220401134035-4e7113938d00 @@ -57,7 +57,7 @@ require ( github.com/cloudfoundry/sonde-go v0.0.0-20200416163440-a42463ba266b // indirect github.com/containernetworking/plugins v0.0.0-00010101000000-000000000000 // indirect github.com/fsnotify/fsnotify v1.4.9 // indirect - github.com/go-sql-driver/mysql v1.6.0 // indirect + github.com/go-sql-driver/mysql v1.7.0 // indirect github.com/go-test/deep v1.0.8 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.2 // indirect diff --git a/src/code.cloudfoundry.org/go.sum b/src/code.cloudfoundry.org/go.sum index 6bfb8d1a..7af8ad2f 100644 --- a/src/code.cloudfoundry.org/go.sum +++ b/src/code.cloudfoundry.org/go.sum @@ -3,8 +3,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= code.cloudfoundry.org/bbs v0.0.0-20210727125654-2ad50317f7ed h1:lXyKwHvjX8AofvDkI/LVrjro0iXNMztPUBHjxxHxGKs= code.cloudfoundry.org/bbs v0.0.0-20210727125654-2ad50317f7ed/go.mod h1:XKlGVVXFi5EcHHMPzw3xgONK9PeEZuUbIC43XNwxD10= -code.cloudfoundry.org/cf-networking-helpers v0.0.0-20221117171434-3d123025a8c3 h1:zG5o5H4cYWfZymMLRxRTDT/++y9TWh/nsMW0n61QO7k= -code.cloudfoundry.org/cf-networking-helpers v0.0.0-20221117171434-3d123025a8c3/go.mod h1:AckMTCaBOprDW2tD4G9t1vuTPhFOrl6mItQna5MdC+c= +code.cloudfoundry.org/cf-networking-helpers v0.0.0-20221205130414-742bd12bf674 h1:1RfyBh7rQ59pWhSzO02abAaPu5GTUjThz2i9a5ePRwY= +code.cloudfoundry.org/cf-networking-helpers v0.0.0-20221205130414-742bd12bf674/go.mod h1:B49nvupgBP7F6MuIoOe1z0yXSG+1TgkDNT1oi1EOuIE= code.cloudfoundry.org/cfhttp/v2 v2.0.1-0.20210513172332-4c5ee488a657 h1:8rnhkeAe8Bnx+8r3unO++S3syBw8P22qPbw3LLFWEoc= code.cloudfoundry.org/cfhttp/v2 v2.0.1-0.20210513172332-4c5ee488a657/go.mod h1:Fwt0o/haXfwgOHMom4AM96pXCVw9EAiIcSsPb8hWK9s= code.cloudfoundry.org/clock v1.0.0 h1:kFXWQM4bxYvdBw2X8BbBeXwQNgfoWv1vqAk2ZZyBN2o= @@ -160,8 +160,9 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= +github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= diff --git a/src/code.cloudfoundry.org/vendor/code.cloudfoundry.org/cf-networking-helpers/healthchecker/cmd/healthchecker/main.go b/src/code.cloudfoundry.org/vendor/code.cloudfoundry.org/cf-networking-helpers/healthchecker/cmd/healthchecker/main.go index 19926c46..d0dc407b 100644 --- a/src/code.cloudfoundry.org/vendor/code.cloudfoundry.org/cf-networking-helpers/healthchecker/cmd/healthchecker/main.go +++ b/src/code.cloudfoundry.org/vendor/code.cloudfoundry.org/cf-networking-helpers/healthchecker/cmd/healthchecker/main.go @@ -47,9 +47,12 @@ func main() { User: url.UserPassword(c.HealthCheckEndpoint.User, c.HealthCheckEndpoint.Password), Path: c.HealthCheckEndpoint.Path, } - host := u.String() + if c.HealthCheckEndpoint.Socket != "" { + u.Opaque = c.HealthCheckEndpoint.Path + u.Host = fmt.Sprintf("unix%s", c.HealthCheckEndpoint.Socket) + } - w := watchdog.NewWatchdog(host, c.ComponentName, c.HealthCheckPollInterval, c.HealthCheckTimeout, logger) + w := watchdog.NewWatchdog(u, c.ComponentName, c.FailureCounterFile, c.HealthCheckPollInterval, c.HealthCheckTimeout, logger) signals := make(chan os.Signal, SIGNAL_BUFFER_SIZE) signal.Notify(signals, syscall.SIGUSR1) diff --git a/src/code.cloudfoundry.org/vendor/code.cloudfoundry.org/cf-networking-helpers/healthchecker/config/config.go b/src/code.cloudfoundry.org/vendor/code.cloudfoundry.org/cf-networking-helpers/healthchecker/config/config.go index de511ae6..a1018410 100644 --- a/src/code.cloudfoundry.org/vendor/code.cloudfoundry.org/cf-networking-helpers/healthchecker/config/config.go +++ b/src/code.cloudfoundry.org/vendor/code.cloudfoundry.org/cf-networking-helpers/healthchecker/config/config.go @@ -9,6 +9,7 @@ import ( ) type HealthCheckEndpoint struct { + Socket string `yaml:"socket"` Host string `yaml:"host"` Port int `yaml:"port"` Path string `yaml:"path"` @@ -26,6 +27,7 @@ var DefaultConfig = Config{ type Config struct { ComponentName string `yaml:"component_name"` + FailureCounterFile string `yaml:"failure_counter_file"` HealthCheckEndpoint HealthCheckEndpoint `yaml:"healthcheck_endpoint"` HealthCheckPollInterval time.Duration `yaml:"healthcheck_poll_interval"` HealthCheckTimeout time.Duration `yaml:"healthcheck_timeout"` @@ -81,11 +83,25 @@ func (c *Config) Validate() error { if c.ComponentName == "" { return fmt.Errorf("Missing component_name") } - if c.HealthCheckEndpoint.Host == "" { - return fmt.Errorf("Missing healthcheck endpoint host") + + if c.HealthCheckEndpoint.Socket == "" { + if c.HealthCheckEndpoint.Host == "" { + return fmt.Errorf("Missing healthcheck endpoint host or socket") + } + if c.HealthCheckEndpoint.Port == 0 { + return fmt.Errorf("Missing healthcheck endpoint port or socket") + } + } else { + if c.HealthCheckEndpoint.Host != "" { + return fmt.Errorf("Cannot specify both healthcheck endpoint host and socket") + } + if c.HealthCheckEndpoint.Port != 0 { + return fmt.Errorf("Cannot specify both healthcheck endpoint port and socket") + } } - if c.HealthCheckEndpoint.Port == 0 { - return fmt.Errorf("Missing healthcheck endpoint port") + + if c.FailureCounterFile == "" { + return fmt.Errorf("Missing failure_counter_file") } return nil } diff --git a/src/code.cloudfoundry.org/vendor/code.cloudfoundry.org/cf-networking-helpers/healthchecker/watchdog/watchdog.go b/src/code.cloudfoundry.org/vendor/code.cloudfoundry.org/cf-networking-helpers/healthchecker/watchdog/watchdog.go index 9d52dc9c..6c6066e0 100644 --- a/src/code.cloudfoundry.org/vendor/code.cloudfoundry.org/cf-networking-helpers/healthchecker/watchdog/watchdog.go +++ b/src/code.cloudfoundry.org/vendor/code.cloudfoundry.org/cf-networking-helpers/healthchecker/watchdog/watchdog.go @@ -4,8 +4,12 @@ import ( "context" "errors" "fmt" + "net" "net/http" + "net/url" "os" + "strconv" + "strings" "syscall" "time" @@ -17,23 +21,41 @@ const ( ) type Watchdog struct { - host string - componentName string - pollInterval time.Duration - client http.Client - logger lager.Logger + url *url.URL + componentName string + pollInterval time.Duration + client http.Client + logger lager.Logger + failureCounter *FailureCounter } -func NewWatchdog(host string, componentName string, pollInterval time.Duration, healthcheckTimeout time.Duration, logger lager.Logger) *Watchdog { +func NewWatchdog(u *url.URL, componentName string, failureCounterFileName string, pollInterval time.Duration, healthcheckTimeout time.Duration, logger lager.Logger) *Watchdog { client := http.Client{ Timeout: healthcheckTimeout, } + if strings.HasPrefix(u.Host, "unix") { + socket := strings.TrimPrefix(u.Host, "unix") + client.Transport = &http.Transport{ + DialContext: func(_ context.Context, _, _ string) (net.Conn, error) { + return net.Dial("unix", socket) + }, + } + } + + failureCounterFile, err := os.OpenFile(failureCounterFileName, os.O_RDONLY|os.O_CREATE, 0644) + if err != nil { + logger.Fatal("cannot-create-failure-counter-file", err) + return nil + } + failureCounterFile.Close() + return &Watchdog{ - host: host, - componentName: componentName, - pollInterval: pollInterval, - client: client, - logger: logger, + url: u, + componentName: componentName, + pollInterval: pollInterval, + client: client, + logger: logger, + failureCounter: &FailureCounter{file: failureCounterFileName, logger: logger}, } } @@ -64,12 +86,20 @@ func (w *Watchdog) WatchHealthcheckEndpoint(ctx context.Context, signals <-chan return nil } default: + incrErr := w.failureCounter.Increment() + if incrErr != nil { + w.logger.Error("incrementing-failure-count", incrErr, lager.Data{"file": w.failureCounter.file}) + } return err } } else { w.logger.Debug("Received error", lager.Data{"error": err.Error(), "attempt": errCounter}) } } else { + err = w.failureCounter.Set(0) + if err != nil { + w.logger.Error("resetting-failure-count", err, lager.Data{"file": w.failureCounter.file}) + } errCounter = 0 } pollTimer.Reset(w.pollInterval) @@ -78,11 +108,19 @@ func (w *Watchdog) WatchHealthcheckEndpoint(ctx context.Context, signals <-chan } func (w *Watchdog) HitHealthcheckEndpoint() error { - response, err := w.client.Get(w.host) + req, err := http.NewRequest("GET", w.url.String(), nil) if err != nil { return err } - // fmt.Printf("status: %d", response.StatusCode) + if req.URL.Host == "" { + req.URL.Host = w.url.Host + } + + response, err := w.client.Do(req) + if err != nil { + return err + } + if response.StatusCode != http.StatusOK { return errors.New(fmt.Sprintf( "%v received from healthcheck endpoint (200 expected)", @@ -90,3 +128,28 @@ func (w *Watchdog) HitHealthcheckEndpoint() error { } return nil } + +type FailureCounter struct { + file string + logger lager.Logger +} + +func (fc *FailureCounter) Set(i int) error { + return os.WriteFile(fc.file, []byte(fmt.Sprintf("%d\n", i)), 0644) +} + +func (fc *FailureCounter) Increment() error { + failures, err := os.ReadFile(fc.file) + if err != nil { + return err + } + + failuresInt, err := strconv.Atoi(strings.TrimSpace(string(failures))) + if err != nil { + fc.logger.Info("converting-failure-counter-string-to-int", lager.Data{"error": err, "message": "Resetting counter to 0"}) + failuresInt = 0 + } + + failuresInt++ + return fc.Set(failuresInt) +} diff --git a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/AUTHORS b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/AUTHORS index 50afa2c8..05132751 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/AUTHORS +++ b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/AUTHORS @@ -23,6 +23,7 @@ Asta Xie Bulat Gaifullin Caine Jette Carlos Nieto +Chris Kirkland Chris Moos Craig Wilson Daniel Montoya @@ -45,6 +46,7 @@ Ilia Cimpoes INADA Naoki Jacek Szwec James Harr +Janek Vedock Jeff Hodges Jeffrey Charles Jerome Meyer @@ -59,12 +61,14 @@ Kamil Dziedzic Kei Kamikawa Kevin Malachowski Kieron Woodhouse +Lance Tian Lennart Rudolph Leonardo YongUk Kim Linh Tran Tuan Lion Yang Luca Looz Lucas Liu +Lunny Xiao Luke Scott Maciej Zimnoch Michael Woolnough @@ -79,6 +83,7 @@ Reed Allman Richard Wilkes Robert Russell Runrioter Wung +Santhosh Kumar Tekuri Sho Iizuka Sho Ikeda Shuode Li @@ -99,12 +104,14 @@ Xiuming Chen Xuehong Chan Zhenye Xie Zhixin Wen +Ziheng Lyu # Organizations Barracuda Networks, Inc. Counting Ltd. DigitalOcean Inc. +dyves labs AG Facebook Inc. GitHub Inc. Google Inc. diff --git a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/CHANGELOG.md b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/CHANGELOG.md index 72a738ed..77024a82 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/CHANGELOG.md +++ b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/CHANGELOG.md @@ -1,3 +1,24 @@ +## Version 1.7 (2022-11-29) + +Changes: + + - Drop support of Go 1.12 (#1211) + - Refactoring `(*textRows).readRow` in a more clear way (#1230) + - util: Reduce boundary check in escape functions. (#1316) + - enhancement for mysqlConn handleAuthResult (#1250) + +New Features: + + - support Is comparison on MySQLError (#1210) + - return unsigned in database type name when necessary (#1238) + - Add API to express like a --ssl-mode=PREFERRED MySQL client (#1370) + - Add SQLState to MySQLError (#1321) + +Bugfixes: + + - Fix parsing 0 year. (#1257) + + ## Version 1.6 (2021-04-01) Changes: diff --git a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/README.md b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/README.md index 0b13154f..25de2e5a 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/README.md +++ b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/README.md @@ -40,7 +40,7 @@ A MySQL-Driver for Go's [database/sql](https://golang.org/pkg/database/sql/) pac * Optional placeholder interpolation ## Requirements - * Go 1.10 or higher. We aim to support the 3 latest versions of Go. + * Go 1.13 or higher. We aim to support the 3 latest versions of Go. * MySQL (4.1+), MariaDB, Percona Server, Google CloudSQL or Sphinx (2.2.3+) --------------------------------------- @@ -85,7 +85,7 @@ db.SetMaxIdleConns(10) `db.SetMaxOpenConns()` is highly recommended to limit the number of connection used by the application. There is no recommended limit number because it depends on application and MySQL server. -`db.SetMaxIdleConns()` is recommended to be set same to (or greater than) `db.SetMaxOpenConns()`. When it is smaller than `SetMaxOpenConns()`, connections can be opened and closed very frequently than you expect. Idle connections can be closed by the `db.SetConnMaxLifetime()`. If you want to close idle connections more rapidly, you can use `db.SetConnMaxIdleTime()` since Go 1.15. +`db.SetMaxIdleConns()` is recommended to be set same to `db.SetMaxOpenConns()`. When it is smaller than `SetMaxOpenConns()`, connections can be opened and closed much more frequently than you expect. Idle connections can be closed by the `db.SetConnMaxLifetime()`. If you want to close idle connections more rapidly, you can use `db.SetConnMaxIdleTime()` since Go 1.15. ### DSN (Data Source Name) @@ -157,6 +157,17 @@ Default: false `allowCleartextPasswords=true` allows using the [cleartext client side plugin](https://dev.mysql.com/doc/en/cleartext-pluggable-authentication.html) if required by an account, such as one defined with the [PAM authentication plugin](http://dev.mysql.com/doc/en/pam-authentication-plugin.html). Sending passwords in clear text may be a security problem in some configurations. To avoid problems if there is any possibility that the password would be intercepted, clients should connect to MySQL Server using a method that protects the password. Possibilities include [TLS / SSL](#tls), IPsec, or a private network. + +##### `allowFallbackToPlaintext` + +``` +Type: bool +Valid Values: true, false +Default: false +``` + +`allowFallbackToPlaintext=true` acts like a `--ssl-mode=PREFERRED` MySQL client as described in [Command Options for Connecting to the Server](https://dev.mysql.com/doc/refman/5.7/en/connection-options.html#option_general_ssl-mode) + ##### `allowNativePasswords` ``` @@ -454,7 +465,7 @@ user:password@/ The connection pool is managed by Go's database/sql package. For details on how to configure the size of the pool and how long connections stay in the pool see `*DB.SetMaxOpenConns`, `*DB.SetMaxIdleConns`, and `*DB.SetConnMaxLifetime` in the [database/sql documentation](https://golang.org/pkg/database/sql/). The read, write, and dial timeouts for each individual connection are configured with the DSN parameters [`readTimeout`](#readtimeout), [`writeTimeout`](#writetimeout), and [`timeout`](#timeout), respectively. ## `ColumnType` Support -This driver supports the [`ColumnType` interface](https://golang.org/pkg/database/sql/#ColumnType) introduced in Go 1.8, with the exception of [`ColumnType.Length()`](https://golang.org/pkg/database/sql/#ColumnType.Length), which is currently not supported. +This driver supports the [`ColumnType` interface](https://golang.org/pkg/database/sql/#ColumnType) introduced in Go 1.8, with the exception of [`ColumnType.Length()`](https://golang.org/pkg/database/sql/#ColumnType.Length), which is currently not supported. All Unsigned database type names will be returned `UNSIGNED ` with `INT`, `TINYINT`, `SMALLINT`, `BIGINT`. ## `context.Context` Support Go 1.8 added `database/sql` support for `context.Context`. This driver supports query timeouts and cancellation via contexts. diff --git a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/atomic_bool.go b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/atomic_bool.go new file mode 100644 index 00000000..1b7e19f3 --- /dev/null +++ b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/atomic_bool.go @@ -0,0 +1,19 @@ +// Go MySQL Driver - A MySQL-Driver for Go's database/sql package. +// +// Copyright 2022 The Go-MySQL-Driver Authors. All rights reserved. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at http://mozilla.org/MPL/2.0/. +//go:build go1.19 +// +build go1.19 + +package mysql + +import "sync/atomic" + +/****************************************************************************** +* Sync utils * +******************************************************************************/ + +type atomicBool = atomic.Bool diff --git a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/atomic_bool_go118.go b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/atomic_bool_go118.go new file mode 100644 index 00000000..2e9a7f0b --- /dev/null +++ b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/atomic_bool_go118.go @@ -0,0 +1,47 @@ +// Go MySQL Driver - A MySQL-Driver for Go's database/sql package. +// +// Copyright 2022 The Go-MySQL-Driver Authors. All rights reserved. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at http://mozilla.org/MPL/2.0/. +//go:build !go1.19 +// +build !go1.19 + +package mysql + +import "sync/atomic" + +/****************************************************************************** +* Sync utils * +******************************************************************************/ + +// atomicBool is an implementation of atomic.Bool for older version of Go. +// it is a wrapper around uint32 for usage as a boolean value with +// atomic access. +type atomicBool struct { + _ noCopy + value uint32 +} + +// Load returns whether the current boolean value is true +func (ab *atomicBool) Load() bool { + return atomic.LoadUint32(&ab.value) > 0 +} + +// Store sets the value of the bool regardless of the previous value +func (ab *atomicBool) Store(value bool) { + if value { + atomic.StoreUint32(&ab.value, 1) + } else { + atomic.StoreUint32(&ab.value, 0) + } +} + +// Swap sets the value of the bool and returns the old value. +func (ab *atomicBool) Swap(value bool) bool { + if value { + return atomic.SwapUint32(&ab.value, 1) > 0 + } + return atomic.SwapUint32(&ab.value, 0) > 0 +} diff --git a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/auth.go b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/auth.go index b2f19e8f..1ff203e5 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/auth.go +++ b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/auth.go @@ -33,27 +33,26 @@ var ( // Note: The provided rsa.PublicKey instance is exclusively owned by the driver // after registering it and may not be modified. // -// data, err := ioutil.ReadFile("mykey.pem") -// if err != nil { -// log.Fatal(err) -// } +// data, err := ioutil.ReadFile("mykey.pem") +// if err != nil { +// log.Fatal(err) +// } // -// block, _ := pem.Decode(data) -// if block == nil || block.Type != "PUBLIC KEY" { -// log.Fatal("failed to decode PEM block containing public key") -// } +// block, _ := pem.Decode(data) +// if block == nil || block.Type != "PUBLIC KEY" { +// log.Fatal("failed to decode PEM block containing public key") +// } // -// pub, err := x509.ParsePKIXPublicKey(block.Bytes) -// if err != nil { -// log.Fatal(err) -// } -// -// if rsaPubKey, ok := pub.(*rsa.PublicKey); ok { -// mysql.RegisterServerPubKey("mykey", rsaPubKey) -// } else { -// log.Fatal("not a RSA public key") -// } +// pub, err := x509.ParsePKIXPublicKey(block.Bytes) +// if err != nil { +// log.Fatal(err) +// } // +// if rsaPubKey, ok := pub.(*rsa.PublicKey); ok { +// mysql.RegisterServerPubKey("mykey", rsaPubKey) +// } else { +// log.Fatal("not a RSA public key") +// } func RegisterServerPubKey(name string, pubKey *rsa.PublicKey) { serverPubKeyLock.Lock() if serverPubKeyRegistry == nil { @@ -274,7 +273,9 @@ func (mc *mysqlConn) auth(authData []byte, plugin string) ([]byte, error) { if len(mc.cfg.Passwd) == 0 { return []byte{0}, nil } - if mc.cfg.tls != nil || mc.cfg.Net == "unix" { + // unlike caching_sha2_password, sha256_password does not accept + // cleartext password on unix transport. + if mc.cfg.TLS != nil { // write cleartext auth packet return append([]byte(mc.cfg.Passwd), 0), nil } @@ -350,7 +351,7 @@ func (mc *mysqlConn) handleAuthResult(oldAuthData []byte, plugin string) error { } case cachingSha2PasswordPerformFullAuthentication: - if mc.cfg.tls != nil || mc.cfg.Net == "unix" { + if mc.cfg.TLS != nil || mc.cfg.Net == "unix" { // write cleartext auth packet err = mc.writeAuthSwitchPacket(append([]byte(mc.cfg.Passwd), 0)) if err != nil { @@ -365,13 +366,20 @@ func (mc *mysqlConn) handleAuthResult(oldAuthData []byte, plugin string) error { return err } data[4] = cachingSha2PasswordRequestPublicKey - mc.writePacket(data) + err = mc.writePacket(data) + if err != nil { + return err + } - // parse public key if data, err = mc.readPacket(); err != nil { return err } + if data[0] != iAuthMoreData { + return fmt.Errorf("unexpect resp from server for caching_sha2_password perform full authentication") + } + + // parse public key block, rest := pem.Decode(data[1:]) if block == nil { return fmt.Errorf("No Pem data found, data: %s", rest) @@ -404,6 +412,10 @@ func (mc *mysqlConn) handleAuthResult(oldAuthData []byte, plugin string) error { return nil // auth successful default: block, _ := pem.Decode(authData) + if block == nil { + return fmt.Errorf("no Pem data found, data: %s", authData) + } + pub, err := x509.ParsePKIXPublicKey(block.Bytes) if err != nil { return err diff --git a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/collations.go b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/collations.go index 326a9f7f..295bfbe5 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/collations.go +++ b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/collations.go @@ -13,7 +13,8 @@ const binaryCollation = "binary" // A list of available collations mapped to the internal ID. // To update this map use the following MySQL query: -// SELECT COLLATION_NAME, ID FROM information_schema.COLLATIONS WHERE ID<256 ORDER BY ID +// +// SELECT COLLATION_NAME, ID FROM information_schema.COLLATIONS WHERE ID<256 ORDER BY ID // // Handshake packet have only 1 byte for collation_id. So we can't use collations with ID > 255. // diff --git a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/conncheck.go b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/conncheck.go index 024eb285..0ea72172 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/conncheck.go +++ b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/conncheck.go @@ -6,6 +6,7 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this file, // You can obtain one at http://mozilla.org/MPL/2.0/. +//go:build linux || darwin || dragonfly || freebsd || netbsd || openbsd || solaris || illumos // +build linux darwin dragonfly freebsd netbsd openbsd solaris illumos package mysql diff --git a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/conncheck_dummy.go b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/conncheck_dummy.go index ea7fb607..a56c138f 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/conncheck_dummy.go +++ b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/conncheck_dummy.go @@ -6,6 +6,7 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this file, // You can obtain one at http://mozilla.org/MPL/2.0/. +//go:build !linux && !darwin && !dragonfly && !freebsd && !netbsd && !openbsd && !solaris && !illumos // +build !linux,!darwin,!dragonfly,!freebsd,!netbsd,!openbsd,!solaris,!illumos package mysql diff --git a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/connection.go b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/connection.go index 835f8972..9539077c 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/connection.go +++ b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/connection.go @@ -104,7 +104,7 @@ func (mc *mysqlConn) Begin() (driver.Tx, error) { } func (mc *mysqlConn) begin(readOnly bool) (driver.Tx, error) { - if mc.closed.IsSet() { + if mc.closed.Load() { errLog.Print(ErrInvalidConn) return nil, driver.ErrBadConn } @@ -123,7 +123,7 @@ func (mc *mysqlConn) begin(readOnly bool) (driver.Tx, error) { func (mc *mysqlConn) Close() (err error) { // Makes Close idempotent - if !mc.closed.IsSet() { + if !mc.closed.Load() { err = mc.writeCommandPacket(comQuit) } @@ -137,7 +137,7 @@ func (mc *mysqlConn) Close() (err error) { // is called before auth or on auth failure because MySQL will have already // closed the network connection. func (mc *mysqlConn) cleanup() { - if !mc.closed.TrySet(true) { + if mc.closed.Swap(true) { return } @@ -152,7 +152,7 @@ func (mc *mysqlConn) cleanup() { } func (mc *mysqlConn) error() error { - if mc.closed.IsSet() { + if mc.closed.Load() { if err := mc.canceled.Value(); err != nil { return err } @@ -162,7 +162,7 @@ func (mc *mysqlConn) error() error { } func (mc *mysqlConn) Prepare(query string) (driver.Stmt, error) { - if mc.closed.IsSet() { + if mc.closed.Load() { errLog.Print(ErrInvalidConn) return nil, driver.ErrBadConn } @@ -295,7 +295,7 @@ func (mc *mysqlConn) interpolateParams(query string, args []driver.Value) (strin } func (mc *mysqlConn) Exec(query string, args []driver.Value) (driver.Result, error) { - if mc.closed.IsSet() { + if mc.closed.Load() { errLog.Print(ErrInvalidConn) return nil, driver.ErrBadConn } @@ -356,7 +356,7 @@ func (mc *mysqlConn) Query(query string, args []driver.Value) (driver.Rows, erro } func (mc *mysqlConn) query(query string, args []driver.Value) (*textRows, error) { - if mc.closed.IsSet() { + if mc.closed.Load() { errLog.Print(ErrInvalidConn) return nil, driver.ErrBadConn } @@ -450,7 +450,7 @@ func (mc *mysqlConn) finish() { // Ping implements driver.Pinger interface func (mc *mysqlConn) Ping(ctx context.Context) (err error) { - if mc.closed.IsSet() { + if mc.closed.Load() { errLog.Print(ErrInvalidConn) return driver.ErrBadConn } @@ -469,7 +469,7 @@ func (mc *mysqlConn) Ping(ctx context.Context) (err error) { // BeginTx implements driver.ConnBeginTx interface func (mc *mysqlConn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) { - if mc.closed.IsSet() { + if mc.closed.Load() { return nil, driver.ErrBadConn } @@ -636,7 +636,7 @@ func (mc *mysqlConn) CheckNamedValue(nv *driver.NamedValue) (err error) { // ResetSession implements driver.SessionResetter. // (From Go 1.10) func (mc *mysqlConn) ResetSession(ctx context.Context) error { - if mc.closed.IsSet() { + if mc.closed.Load() { return driver.ErrBadConn } mc.reset = true @@ -646,5 +646,5 @@ func (mc *mysqlConn) ResetSession(ctx context.Context) error { // IsValid implements driver.Validator interface // (From Go 1.15) func (mc *mysqlConn) IsValid() bool { - return !mc.closed.IsSet() + return !mc.closed.Load() } diff --git a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/driver.go b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/driver.go index c1bdf119..ad7aec21 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/driver.go +++ b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/driver.go @@ -8,10 +8,10 @@ // // The driver should be used via the database/sql package: // -// import "database/sql" -// import _ "github.com/go-sql-driver/mysql" +// import "database/sql" +// import _ "github.com/go-sql-driver/mysql" // -// db, err := sql.Open("mysql", "user:password@/dbname") +// db, err := sql.Open("mysql", "user:password@/dbname") // // See https://github.com/go-sql-driver/mysql#usage for details package mysql diff --git a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/dsn.go b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/dsn.go index 93f3548c..4b71aaab 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/dsn.go +++ b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/dsn.go @@ -46,22 +46,23 @@ type Config struct { ServerPubKey string // Server public key name pubKey *rsa.PublicKey // Server public key TLSConfig string // TLS configuration name - tls *tls.Config // TLS configuration + TLS *tls.Config // TLS configuration, its priority is higher than TLSConfig Timeout time.Duration // Dial timeout ReadTimeout time.Duration // I/O read timeout WriteTimeout time.Duration // I/O write timeout - AllowAllFiles bool // Allow all files to be used with LOAD DATA LOCAL INFILE - AllowCleartextPasswords bool // Allows the cleartext client side plugin - AllowNativePasswords bool // Allows the native password authentication method - AllowOldPasswords bool // Allows the old insecure password method - CheckConnLiveness bool // Check connections for liveness before using them - ClientFoundRows bool // Return number of matching rows instead of rows changed - ColumnsWithAlias bool // Prepend table alias to column names - InterpolateParams bool // Interpolate placeholders into query string - MultiStatements bool // Allow multiple statements in one query - ParseTime bool // Parse time values to time.Time - RejectReadOnly bool // Reject read-only connections + AllowAllFiles bool // Allow all files to be used with LOAD DATA LOCAL INFILE + AllowCleartextPasswords bool // Allows the cleartext client side plugin + AllowFallbackToPlaintext bool // Allows fallback to unencrypted connection if server does not support TLS + AllowNativePasswords bool // Allows the native password authentication method + AllowOldPasswords bool // Allows the old insecure password method + CheckConnLiveness bool // Check connections for liveness before using them + ClientFoundRows bool // Return number of matching rows instead of rows changed + ColumnsWithAlias bool // Prepend table alias to column names + InterpolateParams bool // Interpolate placeholders into query string + MultiStatements bool // Allow multiple statements in one query + ParseTime bool // Parse time values to time.Time + RejectReadOnly bool // Reject read-only connections } // NewConfig creates a new Config and sets default values. @@ -77,8 +78,8 @@ func NewConfig() *Config { func (cfg *Config) Clone() *Config { cp := *cfg - if cp.tls != nil { - cp.tls = cfg.tls.Clone() + if cp.TLS != nil { + cp.TLS = cfg.TLS.Clone() } if len(cp.Params) > 0 { cp.Params = make(map[string]string, len(cfg.Params)) @@ -119,24 +120,29 @@ func (cfg *Config) normalize() error { cfg.Addr = ensureHavePort(cfg.Addr) } - switch cfg.TLSConfig { - case "false", "": - // don't set anything - case "true": - cfg.tls = &tls.Config{} - case "skip-verify", "preferred": - cfg.tls = &tls.Config{InsecureSkipVerify: true} - default: - cfg.tls = getTLSConfigClone(cfg.TLSConfig) - if cfg.tls == nil { - return errors.New("invalid value / unknown config name: " + cfg.TLSConfig) + if cfg.TLS == nil { + switch cfg.TLSConfig { + case "false", "": + // don't set anything + case "true": + cfg.TLS = &tls.Config{} + case "skip-verify": + cfg.TLS = &tls.Config{InsecureSkipVerify: true} + case "preferred": + cfg.TLS = &tls.Config{InsecureSkipVerify: true} + cfg.AllowFallbackToPlaintext = true + default: + cfg.TLS = getTLSConfigClone(cfg.TLSConfig) + if cfg.TLS == nil { + return errors.New("invalid value / unknown config name: " + cfg.TLSConfig) + } } } - if cfg.tls != nil && cfg.tls.ServerName == "" && !cfg.tls.InsecureSkipVerify { + if cfg.TLS != nil && cfg.TLS.ServerName == "" && !cfg.TLS.InsecureSkipVerify { host, _, err := net.SplitHostPort(cfg.Addr) if err == nil { - cfg.tls.ServerName = host + cfg.TLS.ServerName = host } } @@ -204,6 +210,10 @@ func (cfg *Config) FormatDSN() string { writeDSNParam(&buf, &hasParam, "allowCleartextPasswords", "true") } + if cfg.AllowFallbackToPlaintext { + writeDSNParam(&buf, &hasParam, "allowFallbackToPlaintext", "true") + } + if !cfg.AllowNativePasswords { writeDSNParam(&buf, &hasParam, "allowNativePasswords", "false") } @@ -391,6 +401,14 @@ func parseDSNParams(cfg *Config, params string) (err error) { return errors.New("invalid bool value: " + value) } + // Allow fallback to unencrypted connection if server does not support TLS + case "allowFallbackToPlaintext": + var isBool bool + cfg.AllowFallbackToPlaintext, isBool = readBool(value) + if !isBool { + return errors.New("invalid bool value: " + value) + } + // Use native password authentication case "allowNativePasswords": var isBool bool @@ -426,7 +444,6 @@ func parseDSNParams(cfg *Config, params string) (err error) { // Collation case "collation": cfg.Collation = value - break case "columnsWithAlias": var isBool bool diff --git a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/errors.go b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/errors.go index 760782ff..7c037e7d 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/errors.go +++ b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/errors.go @@ -56,10 +56,22 @@ func SetLogger(logger Logger) error { // MySQLError is an error type which represents a single MySQL error type MySQLError struct { - Number uint16 - Message string + Number uint16 + SQLState [5]byte + Message string } func (me *MySQLError) Error() string { + if me.SQLState != [5]byte{} { + return fmt.Sprintf("Error %d (%s): %s", me.Number, me.SQLState, me.Message) + } + return fmt.Sprintf("Error %d: %s", me.Number, me.Message) } + +func (me *MySQLError) Is(err error) bool { + if merr, ok := err.(*MySQLError); ok { + return merr.Number == me.Number + } + return false +} diff --git a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/fields.go b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/fields.go index ed6c7a37..e0654a83 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/fields.go +++ b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/fields.go @@ -41,6 +41,9 @@ func (mf *mysqlField) typeDatabaseName() string { case fieldTypeJSON: return "JSON" case fieldTypeLong: + if mf.flags&flagUnsigned != 0 { + return "UNSIGNED INT" + } return "INT" case fieldTypeLongBLOB: if mf.charSet != collations[binaryCollation] { @@ -48,6 +51,9 @@ func (mf *mysqlField) typeDatabaseName() string { } return "LONGBLOB" case fieldTypeLongLong: + if mf.flags&flagUnsigned != 0 { + return "UNSIGNED BIGINT" + } return "BIGINT" case fieldTypeMediumBLOB: if mf.charSet != collations[binaryCollation] { @@ -63,6 +69,9 @@ func (mf *mysqlField) typeDatabaseName() string { case fieldTypeSet: return "SET" case fieldTypeShort: + if mf.flags&flagUnsigned != 0 { + return "UNSIGNED SMALLINT" + } return "SMALLINT" case fieldTypeString: if mf.charSet == collations[binaryCollation] { @@ -74,6 +83,9 @@ func (mf *mysqlField) typeDatabaseName() string { case fieldTypeTimestamp: return "TIMESTAMP" case fieldTypeTiny: + if mf.flags&flagUnsigned != 0 { + return "UNSIGNED TINYINT" + } return "TINYINT" case fieldTypeTinyBLOB: if mf.charSet != collations[binaryCollation] { @@ -106,7 +118,7 @@ var ( scanTypeInt64 = reflect.TypeOf(int64(0)) scanTypeNullFloat = reflect.TypeOf(sql.NullFloat64{}) scanTypeNullInt = reflect.TypeOf(sql.NullInt64{}) - scanTypeNullTime = reflect.TypeOf(nullTime{}) + scanTypeNullTime = reflect.TypeOf(sql.NullTime{}) scanTypeUint8 = reflect.TypeOf(uint8(0)) scanTypeUint16 = reflect.TypeOf(uint16(0)) scanTypeUint32 = reflect.TypeOf(uint32(0)) diff --git a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/fuzz.go b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/fuzz.go index fa75adf6..3a4ec25a 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/fuzz.go +++ b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/fuzz.go @@ -6,6 +6,7 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this file, // You can obtain one at http://mozilla.org/MPL/2.0/. +//go:build gofuzz // +build gofuzz package mysql diff --git a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/infile.go b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/infile.go index 60effdfc..3279dcff 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/infile.go +++ b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/infile.go @@ -28,12 +28,11 @@ var ( // Alternatively you can allow the use of all local files with // the DSN parameter 'allowAllFiles=true' // -// filePath := "/home/gopher/data.csv" -// mysql.RegisterLocalFile(filePath) -// err := db.Exec("LOAD DATA LOCAL INFILE '" + filePath + "' INTO TABLE foo") -// if err != nil { -// ... -// +// filePath := "/home/gopher/data.csv" +// mysql.RegisterLocalFile(filePath) +// err := db.Exec("LOAD DATA LOCAL INFILE '" + filePath + "' INTO TABLE foo") +// if err != nil { +// ... func RegisterLocalFile(filePath string) { fileRegisterLock.Lock() // lazy map init @@ -58,15 +57,14 @@ func DeregisterLocalFile(filePath string) { // If the handler returns a io.ReadCloser Close() is called when the // request is finished. // -// mysql.RegisterReaderHandler("data", func() io.Reader { -// var csvReader io.Reader // Some Reader that returns CSV data -// ... // Open Reader here -// return csvReader -// }) -// err := db.Exec("LOAD DATA LOCAL INFILE 'Reader::data' INTO TABLE foo") -// if err != nil { -// ... -// +// mysql.RegisterReaderHandler("data", func() io.Reader { +// var csvReader io.Reader // Some Reader that returns CSV data +// ... // Open Reader here +// return csvReader +// }) +// err := db.Exec("LOAD DATA LOCAL INFILE 'Reader::data' INTO TABLE foo") +// if err != nil { +// ... func RegisterReaderHandler(name string, handler func() io.Reader) { readerRegisterLock.Lock() // lazy map init @@ -93,10 +91,12 @@ func deferredClose(err *error, closer io.Closer) { } } +const defaultPacketSize = 16 * 1024 // 16KB is small enough for disk readahead and large enough for TCP + func (mc *mysqlConn) handleInFileRequest(name string) (err error) { var rdr io.Reader var data []byte - packetSize := 16 * 1024 // 16KB is small enough for disk readahead and large enough for TCP + packetSize := defaultPacketSize if mc.maxWriteSize < packetSize { packetSize = mc.maxWriteSize } diff --git a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/nulltime.go b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/nulltime.go index 651723a9..36c8a42c 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/nulltime.go +++ b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/nulltime.go @@ -9,11 +9,32 @@ package mysql import ( + "database/sql" "database/sql/driver" "fmt" "time" ) +// NullTime represents a time.Time that may be NULL. +// NullTime implements the Scanner interface so +// it can be used as a scan destination: +// +// var nt NullTime +// err := db.QueryRow("SELECT time FROM foo WHERE id=?", id).Scan(&nt) +// ... +// if nt.Valid { +// // use nt.Time +// } else { +// // NULL value +// } +// +// # This NullTime implementation is not driver-specific +// +// Deprecated: NullTime doesn't honor the loc DSN parameter. +// NullTime.Scan interprets a time as UTC, not the loc DSN parameter. +// Use sql.NullTime instead. +type NullTime sql.NullTime + // Scan implements the Scanner interface. // The value type must be time.Time or string / []byte (formatted time-string), // otherwise Scan fails. diff --git a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/nulltime_go113.go b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/nulltime_go113.go deleted file mode 100644 index 453b4b39..00000000 --- a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/nulltime_go113.go +++ /dev/null @@ -1,40 +0,0 @@ -// Go MySQL Driver - A MySQL-Driver for Go's database/sql package -// -// Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved. -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this file, -// You can obtain one at http://mozilla.org/MPL/2.0/. - -// +build go1.13 - -package mysql - -import ( - "database/sql" -) - -// NullTime represents a time.Time that may be NULL. -// NullTime implements the Scanner interface so -// it can be used as a scan destination: -// -// var nt NullTime -// err := db.QueryRow("SELECT time FROM foo WHERE id=?", id).Scan(&nt) -// ... -// if nt.Valid { -// // use nt.Time -// } else { -// // NULL value -// } -// -// This NullTime implementation is not driver-specific -// -// Deprecated: NullTime doesn't honor the loc DSN parameter. -// NullTime.Scan interprets a time as UTC, not the loc DSN parameter. -// Use sql.NullTime instead. -type NullTime sql.NullTime - -// for internal use. -// the mysql package uses sql.NullTime if it is available. -// if not, the package uses mysql.NullTime. -type nullTime = sql.NullTime // sql.NullTime is available diff --git a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/nulltime_legacy.go b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/nulltime_legacy.go deleted file mode 100644 index 9f7ae27a..00000000 --- a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/nulltime_legacy.go +++ /dev/null @@ -1,39 +0,0 @@ -// Go MySQL Driver - A MySQL-Driver for Go's database/sql package -// -// Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved. -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this file, -// You can obtain one at http://mozilla.org/MPL/2.0/. - -// +build !go1.13 - -package mysql - -import ( - "time" -) - -// NullTime represents a time.Time that may be NULL. -// NullTime implements the Scanner interface so -// it can be used as a scan destination: -// -// var nt NullTime -// err := db.QueryRow("SELECT time FROM foo WHERE id=?", id).Scan(&nt) -// ... -// if nt.Valid { -// // use nt.Time -// } else { -// // NULL value -// } -// -// This NullTime implementation is not driver-specific -type NullTime struct { - Time time.Time - Valid bool // Valid is true if Time is not NULL -} - -// for internal use. -// the mysql package uses sql.NullTime if it is available. -// if not, the package uses mysql.NullTime. -type nullTime = NullTime // sql.NullTime is not available diff --git a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/packets.go b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/packets.go index 6664e5ae..ee05c95a 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/packets.go +++ b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/packets.go @@ -110,14 +110,13 @@ func (mc *mysqlConn) writePacket(data []byte) error { conn = mc.rawConn } var err error - // If this connection has a ReadTimeout which we've been setting on - // reads, reset it to its default value before we attempt a non-blocking - // read, otherwise the scheduler will just time us out before we can read - if mc.cfg.ReadTimeout != 0 { - err = conn.SetReadDeadline(time.Time{}) - } - if err == nil && mc.cfg.CheckConnLiveness { - err = connCheck(conn) + if mc.cfg.CheckConnLiveness { + if mc.cfg.ReadTimeout != 0 { + err = conn.SetReadDeadline(time.Now().Add(mc.cfg.ReadTimeout)) + } + if err == nil { + err = connCheck(conn) + } } if err != nil { errLog.Print("closing bad idle connection: ", err) @@ -223,9 +222,9 @@ func (mc *mysqlConn) readHandshakePacket() (data []byte, plugin string, err erro if mc.flags&clientProtocol41 == 0 { return nil, "", ErrOldProtocol } - if mc.flags&clientSSL == 0 && mc.cfg.tls != nil { - if mc.cfg.TLSConfig == "preferred" { - mc.cfg.tls = nil + if mc.flags&clientSSL == 0 && mc.cfg.TLS != nil { + if mc.cfg.AllowFallbackToPlaintext { + mc.cfg.TLS = nil } else { return nil, "", ErrNoTLS } @@ -293,7 +292,7 @@ func (mc *mysqlConn) writeHandshakeResponsePacket(authResp []byte, plugin string } // To enable TLS / SSL - if mc.cfg.tls != nil { + if mc.cfg.TLS != nil { clientFlags |= clientSSL } @@ -357,14 +356,14 @@ func (mc *mysqlConn) writeHandshakeResponsePacket(authResp []byte, plugin string // SSL Connection Request Packet // http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::SSLRequest - if mc.cfg.tls != nil { + if mc.cfg.TLS != nil { // Send TLS / SSL request packet if err := mc.writePacket(data[:(4+4+1+23)+4]); err != nil { return err } // Switch to TLS - tlsConn := tls.Client(mc.netConn, mc.cfg.tls) + tlsConn := tls.Client(mc.netConn, mc.cfg.TLS) if err := tlsConn.Handshake(); err != nil { return err } @@ -588,19 +587,20 @@ func (mc *mysqlConn) handleErrorPacket(data []byte) error { return driver.ErrBadConn } + me := &MySQLError{Number: errno} + pos := 3 // SQL State [optional: # + 5bytes string] if data[3] == 0x23 { - //sqlstate := string(data[4 : 4+5]) + copy(me.SQLState[:], data[4:4+5]) pos = 9 } // Error Message [string] - return &MySQLError{ - Number: errno, - Message: string(data[pos:]), - } + me.Message = string(data[pos:]) + + return me } func readStatus(b []byte) statusFlag { @@ -761,40 +761,40 @@ func (rows *textRows) readRow(dest []driver.Value) error { } // RowSet Packet - var n int - var isNull bool - pos := 0 + var ( + n int + isNull bool + pos int = 0 + ) for i := range dest { // Read bytes and convert to string dest[i], isNull, n, err = readLengthEncodedString(data[pos:]) pos += n - if err == nil { - if !isNull { - if !mc.parseTime { - continue - } else { - switch rows.rs.columns[i].fieldType { - case fieldTypeTimestamp, fieldTypeDateTime, - fieldTypeDate, fieldTypeNewDate: - dest[i], err = parseDateTime( - dest[i].([]byte), - mc.cfg.Loc, - ) - if err == nil { - continue - } - default: - continue - } - } - } else { - dest[i] = nil - continue + if err != nil { + return err + } + + if isNull { + dest[i] = nil + continue + } + + if !mc.parseTime { + continue + } + + // Parse time field + switch rows.rs.columns[i].fieldType { + case fieldTypeTimestamp, + fieldTypeDateTime, + fieldTypeDate, + fieldTypeNewDate: + if dest[i], err = parseDateTime(dest[i].([]byte), mc.cfg.Loc); err != nil { + return err } } - return err // err != nil } return nil diff --git a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/statement.go b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/statement.go index 18a3ae49..10ece8bd 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/statement.go +++ b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/statement.go @@ -23,7 +23,7 @@ type mysqlStmt struct { } func (stmt *mysqlStmt) Close() error { - if stmt.mc == nil || stmt.mc.closed.IsSet() { + if stmt.mc == nil || stmt.mc.closed.Load() { // driver.Stmt.Close can be called more than once, thus this function // has to be idempotent. // See also Issue #450 and golang/go#16019. @@ -50,7 +50,7 @@ func (stmt *mysqlStmt) CheckNamedValue(nv *driver.NamedValue) (err error) { } func (stmt *mysqlStmt) Exec(args []driver.Value) (driver.Result, error) { - if stmt.mc.closed.IsSet() { + if stmt.mc.closed.Load() { errLog.Print(ErrInvalidConn) return nil, driver.ErrBadConn } @@ -98,7 +98,7 @@ func (stmt *mysqlStmt) Query(args []driver.Value) (driver.Rows, error) { } func (stmt *mysqlStmt) query(args []driver.Value) (*binaryRows, error) { - if stmt.mc.closed.IsSet() { + if stmt.mc.closed.Load() { errLog.Print(ErrInvalidConn) return nil, driver.ErrBadConn } @@ -157,7 +157,7 @@ func (c converter) ConvertValue(v interface{}) (driver.Value, error) { if driver.IsValue(sv) { return sv, nil } - // A value returend from the Valuer interface can be "a type handled by + // A value returned from the Valuer interface can be "a type handled by // a database driver's NamedValueChecker interface" so we should accept // uint64 here as well. if u, ok := sv.(uint64); ok { diff --git a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/transaction.go b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/transaction.go index 417d7279..4a4b6100 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/transaction.go +++ b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/transaction.go @@ -13,7 +13,7 @@ type mysqlTx struct { } func (tx *mysqlTx) Commit() (err error) { - if tx.mc == nil || tx.mc.closed.IsSet() { + if tx.mc == nil || tx.mc.closed.Load() { return ErrInvalidConn } err = tx.mc.exec("COMMIT") @@ -22,7 +22,7 @@ func (tx *mysqlTx) Commit() (err error) { } func (tx *mysqlTx) Rollback() (err error) { - if tx.mc == nil || tx.mc.closed.IsSet() { + if tx.mc == nil || tx.mc.closed.Load() { return ErrInvalidConn } err = tx.mc.exec("ROLLBACK") diff --git a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/utils.go b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/utils.go index d6545f5b..15dbd8d1 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/utils.go +++ b/src/code.cloudfoundry.org/vendor/github.com/go-sql-driver/mysql/utils.go @@ -35,26 +35,25 @@ var ( // Note: The provided tls.Config is exclusively owned by the driver after // registering it. // -// rootCertPool := x509.NewCertPool() -// pem, err := ioutil.ReadFile("/path/ca-cert.pem") -// if err != nil { -// log.Fatal(err) -// } -// if ok := rootCertPool.AppendCertsFromPEM(pem); !ok { -// log.Fatal("Failed to append PEM.") -// } -// clientCert := make([]tls.Certificate, 0, 1) -// certs, err := tls.LoadX509KeyPair("/path/client-cert.pem", "/path/client-key.pem") -// if err != nil { -// log.Fatal(err) -// } -// clientCert = append(clientCert, certs) -// mysql.RegisterTLSConfig("custom", &tls.Config{ -// RootCAs: rootCertPool, -// Certificates: clientCert, -// }) -// db, err := sql.Open("mysql", "user@tcp(localhost:3306)/test?tls=custom") -// +// rootCertPool := x509.NewCertPool() +// pem, err := ioutil.ReadFile("/path/ca-cert.pem") +// if err != nil { +// log.Fatal(err) +// } +// if ok := rootCertPool.AppendCertsFromPEM(pem); !ok { +// log.Fatal("Failed to append PEM.") +// } +// clientCert := make([]tls.Certificate, 0, 1) +// certs, err := tls.LoadX509KeyPair("/path/client-cert.pem", "/path/client-key.pem") +// if err != nil { +// log.Fatal(err) +// } +// clientCert = append(clientCert, certs) +// mysql.RegisterTLSConfig("custom", &tls.Config{ +// RootCAs: rootCertPool, +// Certificates: clientCert, +// }) +// db, err := sql.Open("mysql", "user@tcp(localhost:3306)/test?tls=custom") func RegisterTLSConfig(key string, config *tls.Config) error { if _, isBool := readBool(key); isBool || strings.ToLower(key) == "skip-verify" || strings.ToLower(key) == "preferred" { return fmt.Errorf("key '%s' is reserved", key) @@ -118,10 +117,6 @@ func parseDateTime(b []byte, loc *time.Location) (time.Time, error) { if err != nil { return time.Time{}, err } - if year <= 0 { - year = 1 - } - if b[4] != '-' { return time.Time{}, fmt.Errorf("bad value for field: `%c`", b[4]) } @@ -130,9 +125,6 @@ func parseDateTime(b []byte, loc *time.Location) (time.Time, error) { if err != nil { return time.Time{}, err } - if m <= 0 { - m = 1 - } month := time.Month(m) if b[7] != '-' { @@ -143,9 +135,6 @@ func parseDateTime(b []byte, loc *time.Location) (time.Time, error) { if err != nil { return time.Time{}, err } - if day <= 0 { - day = 1 - } if len(b) == 10 { return time.Date(year, month, day, 0, 0, 0, 0, loc), nil } @@ -199,7 +188,7 @@ func parseByteYear(b []byte) (int, error) { return 0, err } year += v * n - n = n / 10 + n /= 10 } return year, nil } @@ -542,7 +531,7 @@ func stringToInt(b []byte) int { return val } -// returns the string read as a bytes slice, wheter the value is NULL, +// returns the string read as a bytes slice, whether the value is NULL, // the number of bytes read and an error, in case the string is longer than // the input slice func readLengthEncodedString(b []byte) ([]byte, bool, int, error) { @@ -652,32 +641,32 @@ func escapeBytesBackslash(buf, v []byte) []byte { for _, c := range v { switch c { case '\x00': - buf[pos] = '\\' buf[pos+1] = '0' + buf[pos] = '\\' pos += 2 case '\n': - buf[pos] = '\\' buf[pos+1] = 'n' + buf[pos] = '\\' pos += 2 case '\r': - buf[pos] = '\\' buf[pos+1] = 'r' + buf[pos] = '\\' pos += 2 case '\x1a': - buf[pos] = '\\' buf[pos+1] = 'Z' + buf[pos] = '\\' pos += 2 case '\'': - buf[pos] = '\\' buf[pos+1] = '\'' + buf[pos] = '\\' pos += 2 case '"': - buf[pos] = '\\' buf[pos+1] = '"' + buf[pos] = '\\' pos += 2 case '\\': - buf[pos] = '\\' buf[pos+1] = '\\' + buf[pos] = '\\' pos += 2 default: buf[pos] = c @@ -697,32 +686,32 @@ func escapeStringBackslash(buf []byte, v string) []byte { c := v[i] switch c { case '\x00': - buf[pos] = '\\' buf[pos+1] = '0' + buf[pos] = '\\' pos += 2 case '\n': - buf[pos] = '\\' buf[pos+1] = 'n' + buf[pos] = '\\' pos += 2 case '\r': - buf[pos] = '\\' buf[pos+1] = 'r' + buf[pos] = '\\' pos += 2 case '\x1a': - buf[pos] = '\\' buf[pos+1] = 'Z' + buf[pos] = '\\' pos += 2 case '\'': - buf[pos] = '\\' buf[pos+1] = '\'' + buf[pos] = '\\' pos += 2 case '"': - buf[pos] = '\\' buf[pos+1] = '"' + buf[pos] = '\\' pos += 2 case '\\': - buf[pos] = '\\' buf[pos+1] = '\\' + buf[pos] = '\\' pos += 2 default: buf[pos] = c @@ -744,8 +733,8 @@ func escapeBytesQuotes(buf, v []byte) []byte { for _, c := range v { if c == '\'' { - buf[pos] = '\'' buf[pos+1] = '\'' + buf[pos] = '\'' pos += 2 } else { buf[pos] = c @@ -764,8 +753,8 @@ func escapeStringQuotes(buf []byte, v string) []byte { for i := 0; i < len(v); i++ { c := v[i] if c == '\'' { - buf[pos] = '\'' buf[pos+1] = '\'' + buf[pos] = '\'' pos += 2 } else { buf[pos] = c @@ -790,39 +779,16 @@ type noCopy struct{} // Lock is a no-op used by -copylocks checker from `go vet`. func (*noCopy) Lock() {} -// atomicBool is a wrapper around uint32 for usage as a boolean value with -// atomic access. -type atomicBool struct { - _noCopy noCopy - value uint32 -} - -// IsSet returns whether the current boolean value is true -func (ab *atomicBool) IsSet() bool { - return atomic.LoadUint32(&ab.value) > 0 -} - -// Set sets the value of the bool regardless of the previous value -func (ab *atomicBool) Set(value bool) { - if value { - atomic.StoreUint32(&ab.value, 1) - } else { - atomic.StoreUint32(&ab.value, 0) - } -} - -// TrySet sets the value of the bool and returns whether the value changed -func (ab *atomicBool) TrySet(value bool) bool { - if value { - return atomic.SwapUint32(&ab.value, 1) == 0 - } - return atomic.SwapUint32(&ab.value, 0) > 0 -} +// Unlock is a no-op used by -copylocks checker from `go vet`. +// noCopy should implement sync.Locker from Go 1.11 +// https://github.com/golang/go/commit/c2eba53e7f80df21d51285879d51ab81bcfbf6bc +// https://github.com/golang/go/issues/26165 +func (*noCopy) Unlock() {} // atomicError is a wrapper for atomically accessed error values type atomicError struct { - _noCopy noCopy - value atomic.Value + _ noCopy + value atomic.Value } // Set sets the error value regardless of the previous value. diff --git a/src/code.cloudfoundry.org/vendor/modules.txt b/src/code.cloudfoundry.org/vendor/modules.txt index 4fbb914d..333fdd00 100644 --- a/src/code.cloudfoundry.org/vendor/modules.txt +++ b/src/code.cloudfoundry.org/vendor/modules.txt @@ -4,7 +4,7 @@ code.cloudfoundry.org/bbs/db/sqldb/helpers/monitor code.cloudfoundry.org/bbs/encryption code.cloudfoundry.org/bbs/format code.cloudfoundry.org/bbs/models -# code.cloudfoundry.org/cf-networking-helpers v0.0.0-20221117171434-3d123025a8c3 +# code.cloudfoundry.org/cf-networking-helpers v0.0.0-20221205130414-742bd12bf674 ## explicit; go 1.19 code.cloudfoundry.org/cf-networking-helpers/db code.cloudfoundry.org/cf-networking-helpers/healthchecker/cmd/healthchecker @@ -149,8 +149,8 @@ github.com/coreos/go-iptables/iptables # github.com/fsnotify/fsnotify v1.4.9 ## explicit; go 1.13 github.com/fsnotify/fsnotify -# github.com/go-sql-driver/mysql v1.6.0 -## explicit; go 1.10 +# github.com/go-sql-driver/mysql v1.7.0 +## explicit; go 1.13 github.com/go-sql-driver/mysql # github.com/go-test/deep v1.0.8 ## explicit; go 1.16