Skip to content

Commit 4f63f37

Browse files
committed
Update Ginkgo UnitTests to Mock/Override DB and Storage checks
1 parent edda4fb commit 4f63f37

File tree

7 files changed

+79
-60
lines changed

7 files changed

+79
-60
lines changed

controllers/database.go

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ var dbTemplates = []string{
3636
dbSecret,
3737
}
3838

39-
func (r *DSPAReconciler) VerifyMySQLDBConnection(host, port, username, password, dbname string) bool {
39+
// extract to var for mocking in testing
40+
var ConnectAndQueryDatabase = func(host, port, username, password, dbname string) bool {
4041
connectionString := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s", username, password, host, port, dbname)
4142
db, err := sql.Open("mysql", connectionString)
4243
if err != nil {
@@ -57,25 +58,23 @@ func (r *DSPAReconciler) isDatabaseAccessible(ctx context.Context, dsp *dspav1al
5758
databaseSpecified := dsp.Spec.Database != nil
5859
usingExternalDB := params.UsingExternalDB(dsp)
5960
usingMariaDB := !databaseSpecified || dsp.Spec.Database.MariaDB != nil
60-
if usingMariaDB || usingExternalDB {
61-
decodePass, _ := b64.StdEncoding.DecodeString(params.DBConnection.Password)
62-
db_connect := r.VerifyMySQLDBConnection(params.DBConnection.Host,
63-
params.DBConnection.Port,
64-
params.DBConnection.Username,
65-
string(decodePass),
66-
params.DBConnection.DBName)
67-
if db_connect {
68-
log.Info("Database Health Check Successful")
69-
} else {
70-
log.Info("Unable to connect to Database")
71-
}
72-
return db_connect
73-
61+
if !usingMariaDB && !usingExternalDB {
62+
log.Info("Could not connect to Database: Unsupported Type")
63+
return false
7464
}
7565

76-
log.Info(fmt.Sprintf("Could not connect to Database: Unsupported Type"))
77-
// Only MariaDB and Mysql-Compliant Database supported.
78-
return false
66+
decodePass, _ := b64.StdEncoding.DecodeString(params.DBConnection.Password)
67+
db_connect := ConnectAndQueryDatabase(params.DBConnection.Host,
68+
params.DBConnection.Port,
69+
params.DBConnection.Username,
70+
string(decodePass),
71+
params.DBConnection.DBName)
72+
if db_connect {
73+
log.Info("Database Health Check Successful")
74+
} else {
75+
log.Info("Unable to connect to Database")
76+
}
77+
return db_connect
7978
}
8079

8180
func (r *DSPAReconciler) ReconcileDatabase(ctx context.Context, dsp *dspav1alpha1.DataSciencePipelinesApplication,

controllers/dspipeline_controller.go

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ func (r *DSPAReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.
264264
return ctrl.Result{}, err
265265
}
266266

267-
conditions, err := r.GenerateStatus(ctx, dspa, params)
267+
conditions, err := r.GenerateStatus(ctx, dspa, params, dbAvailable, objStoreAvailable)
268268
if err != nil {
269269
log.Info(err.Error())
270270
return ctrl.Result{}, err
@@ -305,7 +305,7 @@ func (r *DSPAReconciler) handleReadyCondition(ctx context.Context, dspa *dspav1a
305305
if apierrs.IsNotFound(err) {
306306
readyCondition.Reason = config.ComponentDeploymentNotFound
307307
readyCondition.Status = metav1.ConditionFalse
308-
readyCondition.Message = fmt.Sprintf("Deployment for component \"%s\" is missing", component)
308+
readyCondition.Message = fmt.Sprintf("Deployment for component \"%s\" is missing - pre-requisite component may not yet be available.", component)
309309
return readyCondition, nil
310310
} else {
311311
return metav1.Condition{}, err
@@ -409,25 +409,38 @@ func (r *DSPAReconciler) handleReadyCondition(ctx context.Context, dspa *dspav1a
409409

410410
}
411411

412-
func (r *DSPAReconciler) GenerateStatus(ctx context.Context, dspa *dspav1alpha1.DataSciencePipelinesApplication, params *DSPAParams) ([]metav1.Condition, error) {
412+
func (r *DSPAReconciler) GenerateStatus(ctx context.Context, dspa *dspav1alpha1.DataSciencePipelinesApplication, params *DSPAParams, dbAvailableStatus, objStoreAvailableStatus bool) ([]metav1.Condition, error) {
413+
// Create Database Availability Condition
413414
databaseAvailable := r.buildCondition(config.DatabaseAvailable, dspa, config.DatabaseAvailable)
414-
if r.isDatabaseAccessible(ctx, dspa, params) {
415+
if dbAvailableStatus {
415416
databaseAvailable.Status = metav1.ConditionTrue
417+
databaseAvailable.Message = "Database connectivity successfully verified"
418+
} else {
419+
databaseAvailable.Message = "Could not connect to database"
416420
}
417421

422+
// Create Object Storage Availability Condition
418423
objStoreAvailable := r.buildCondition(config.ObjectStoreAvailable, dspa, config.ObjectStoreAvailable)
419-
if r.isObjectStorageAccessible(ctx, dspa, params) {
424+
if objStoreAvailableStatus {
420425
objStoreAvailable.Status = metav1.ConditionTrue
426+
objStoreAvailable.Message = "Object Store connectivity successfully verified"
427+
} else {
428+
objStoreAvailable.Message = "Could not connect to Object Store"
421429
}
422430

431+
// Create APIServer Readiness Condition
423432
apiServerReady, err := r.handleReadyCondition(ctx, dspa, "ds-pipeline", config.APIServerReady)
424433
if err != nil {
425434
return []metav1.Condition{}, err
426435
}
436+
437+
// Create PersistenceAgent Readiness Condition
427438
persistenceAgentReady, err := r.handleReadyCondition(ctx, dspa, "ds-pipeline-persistenceagent", config.PersistenceAgentReady)
428439
if err != nil {
429440
return []metav1.Condition{}, err
430441
}
442+
443+
// Create ScheduledWorkflow Readiness Condition
431444
scheduledWorkflowReady, err := r.handleReadyCondition(ctx, dspa, "ds-pipeline-scheduledworkflow", config.ScheduledWorkflowReady)
432445
if err != nil {
433446
return []metav1.Condition{}, err

controllers/metrics.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,9 @@ var (
8787

8888
// InitMetrics initialize prometheus metrics
8989
func InitMetrics() {
90-
metrics.Registry.MustRegister(APIServerReadyMetric,
90+
metrics.Registry.MustRegister(DBAvailableMetric,
91+
ObjectStoreAvailableMetric,
92+
APIServerReadyMetric,
9193
PersistenceAgentReadyMetric,
9294
ScheduledWorkflowReadyMetric,
9395
CrReadyMetric)

controllers/storage.go

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ import (
2222
"fmt"
2323
"net/http"
2424

25-
minio "github.com/minio/minio-go/v7"
25+
"github.com/go-logr/logr"
26+
"github.com/minio/minio-go/v7"
2627
"github.com/minio/minio-go/v7/pkg/credentials"
2728
dspav1alpha1 "github.com/opendatahub-io/data-science-pipelines-operator/api/v1alpha1"
2829
)
@@ -43,7 +44,7 @@ func joinHostPort(host, port string) string {
4344
return fmt.Sprintf("%s:%s", host, port)
4445
}
4546

46-
func createCredentialProvidersChain(endpoint, accessKey, secretKey string) *credentials.Credentials {
47+
func createCredentialProvidersChain(accessKey, secretKey string) *credentials.Credentials {
4748
// first try with static api key
4849
if accessKey != "" && secretKey != "" {
4950
return credentials.NewStaticV4(accessKey, secretKey, "")
@@ -61,6 +62,26 @@ func createCredentialProvidersChain(endpoint, accessKey, secretKey string) *cred
6162
return credentials.New(&credentials.Chain{Providers: providers})
6263
}
6364

65+
var ConnectAndQueryObjStore = func(ctx context.Context, log logr.Logger, endpoint string, accesskey, secretkey []byte, secure bool) bool {
66+
cred := createCredentialProvidersChain(string(accesskey), string(secretkey))
67+
minioClient, err := minio.New(endpoint, &minio.Options{
68+
Creds: cred,
69+
Secure: secure,
70+
})
71+
if err != nil {
72+
log.Info(fmt.Sprintf("Could not connect to object storage endpoint: %s", endpoint))
73+
return false
74+
}
75+
76+
_, err = minioClient.ListBuckets(ctx)
77+
if err != nil {
78+
log.Info(fmt.Sprintf("Could not perform ListBuckets health check on object storage endpoint: %s", endpoint))
79+
return false
80+
}
81+
82+
return true
83+
}
84+
6485
func (r *DSPAReconciler) isObjectStorageAccessible(ctx context.Context, dsp *dspav1alpha1.DataSciencePipelinesApplication,
6586
params *DSPAParams) bool {
6687
log := r.Log.WithValues("namespace", dsp.Namespace).WithValues("dspa_name", dsp.Name)
@@ -79,24 +100,13 @@ func (r *DSPAReconciler) isObjectStorageAccessible(ctx context.Context, dsp *dsp
79100
return false
80101
}
81102

82-
cred := createCredentialProvidersChain(endpoint, string(accesskey), string(secretkey))
83-
minioClient, err := minio.New(endpoint, &minio.Options{
84-
Creds: cred,
85-
Secure: params.ObjectStorageConnection.Secure,
86-
})
87-
if err != nil {
88-
log.Info(fmt.Sprintf("Could not connect to object storage endpoint: %s", endpoint))
89-
return false
90-
}
91-
92-
_, err = minioClient.ListBuckets(ctx)
93-
if err != nil {
94-
log.Info(fmt.Sprintf("Could not perform ListBuckets health check on object storage endpoint: %s", endpoint))
95-
return false
103+
verified := ConnectAndQueryObjStore(ctx, log, endpoint, accesskey, secretkey, params.ObjectStorageConnection.Secure)
104+
if verified {
105+
log.Info("Object Storage Health Check Successful")
106+
} else {
107+
log.Info("Object Storage Health Check Failed")
96108
}
97-
98-
log.Info("Object Storage Health Check Successful")
99-
return true
109+
return verified
100110
}
101111

102112
// ReconcileStorage will set up Storage Connection.

controllers/suite_test.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import (
3131
. "github.com/onsi/ginkgo/v2"
3232
. "github.com/onsi/gomega"
3333

34+
"github.com/go-logr/logr"
3435
"k8s.io/client-go/kubernetes/scheme"
3536
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
3637
"k8s.io/client-go/rest"
@@ -67,6 +68,16 @@ func TestAPIs(t *testing.T) {
6768
RunSpecs(t, "Controller Suite")
6869
}
6970

71+
var _ = BeforeEach(func() {
72+
By("Overriding the Database and Object Store live connection functions with trivial stubs")
73+
ConnectAndQueryDatabase = func(host string, port string, username string, password string, dbname string) bool {
74+
return true
75+
}
76+
ConnectAndQueryObjStore = func(ctx context.Context, log logr.Logger, endpoint string, accesskey, secretkey []byte, secure bool) bool {
77+
return true
78+
}
79+
})
80+
7081
var _ = BeforeSuite(func() {
7182
ctx, cancel = context.WithCancel(context.TODO())
7283

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ require (
99
github.com/golang/glog v1.0.0
1010
github.com/manifestival/controller-runtime-client v0.4.0
1111
github.com/manifestival/manifestival v0.7.2
12+
github.com/minio/minio-go/v7 v7.0.56
1213
github.com/onsi/ginkgo/v2 v2.8.4
1314
github.com/onsi/gomega v1.27.1
1415
github.com/openshift/api v3.9.0+incompatible
@@ -63,7 +64,6 @@ require (
6364
github.com/mailru/easyjson v0.7.6 // indirect
6465
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
6566
github.com/minio/md5-simd v1.1.2 // indirect
66-
github.com/minio/minio-go/v7 v7.0.56 // indirect
6767
github.com/minio/sha256-simd v1.0.1 // indirect
6868
github.com/mitchellh/mapstructure v1.4.1 // indirect
6969
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect

go.sum

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,6 @@ github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLe
357357
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
358358
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
359359
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
360-
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
361360
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
362361
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
363362
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@@ -370,7 +369,6 @@ github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3i
370369
github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU=
371370
github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=
372371
github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4=
373-
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
374372
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
375373
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
376374
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
@@ -428,7 +426,6 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr
428426
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
429427
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
430428
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
431-
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
432429
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
433430
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
434431
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
@@ -592,9 +589,7 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd
592589
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
593590
github.com/sirupsen/logrus v1.9.2 h1:oxx1eChJGI6Uks2ZC4W1zpLlVgqB8ner4EuQwV4Ik1Y=
594591
github.com/sirupsen/logrus v1.9.2/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
595-
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
596592
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
597-
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
598593
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
599594
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
600595
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
@@ -691,8 +686,6 @@ golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPh
691686
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
692687
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
693688
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
694-
golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
695-
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
696689
golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
697690
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
698691
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -783,8 +776,6 @@ golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qx
783776
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
784777
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
785778
golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
786-
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
787-
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
788779
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
789780
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
790781
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -890,15 +881,11 @@ golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBc
890881
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
891882
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
892883
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
893-
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
894-
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
895884
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
896885
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
897886
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
898887
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
899888
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
900-
golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY=
901-
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
902889
golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols=
903890
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
904891
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -911,8 +898,6 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
911898
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
912899
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
913900
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
914-
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
915-
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
916901
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
917902
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
918903
golang.org/x/time v0.0.0-20161028155119-f51c12702a4d/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -1146,7 +1131,6 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy
11461131
gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
11471132
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
11481133
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
1149-
gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
11501134
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
11511135
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
11521136
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=

0 commit comments

Comments
 (0)