Repository: kubernetes/kube-openapi

Issue:
Drop scan implementations from formats
Some, but not all strfmt types implement the `sql.Scanner` interface.  For example duration implements `Scan` but date does not.

We should be consistent.  I'm in favor of removing scan support rather than exposing incomplete support for a capability we don't need or use.

Hints from issue comments:
@k8s-triage-robot: The Kubernetes project currently lacks enough contributors to adequately respond to all issues.

This bot triages un-triaged issues according to the following rules:
- After 90d of inactivity, `lifecycle/stale` is applied
- After 30d of inactivity since `lifecycle/stale` was applied, `lifecycle/rotten` is applied
- After 30d of inactivity since `lifecycle/rotten` was applied, the issue is closed

You can:
- Mark this issue as fresh with `/remove-lifecycle stale`
- Close this issue with `/close`
- Offer to help out with [Issue Triage][1]

Please send feedback to sig-contributor-experience at [kubernetes/community](https://github.com/kubernetes/community).

/lifecycle stale

[1]: https://www.kubernetes.dev/docs/guide/issue-triage/

Solution patch:
diff --git a/pkg/validation/strfmt/default.go b/pkg/validation/strfmt/default.go
index 97b2f98..2310981 100644
--- a/pkg/validation/strfmt/default.go
+++ b/pkg/validation/strfmt/default.go
@@ -17,7 +17,6 @@ package strfmt
 import (
 	"encoding/base64"
 	"encoding/json"
-	"fmt"
 	"net/mail"
 	"regexp"
 	"strings"
@@ -247,29 +246,6 @@ func (b *Base64) UnmarshalText(data []byte) error { // validation is performed l
 	return nil
 }
 
-// Scan read a value from a database driver
-func (b *Base64) Scan(raw interface{}) error {
-	switch v := raw.(type) {
-	case []byte:
-		dbuf := make([]byte, base64.StdEncoding.DecodedLen(len(v)))
-		n, err := base64.StdEncoding.Decode(dbuf, v)
-		if err != nil {
-			return err
-		}
-		*b = dbuf[:n]
-	case string:
-		vv, err := base64.StdEncoding.DecodeString(v)
-		if err != nil {
-			return err
-		}
-		*b = Base64(vv)
-	default:
-		return fmt.Errorf("cannot sql.Scan() strfmt.Base64 from: %#v", v)
-	}
-
-	return nil
-}
-
 func (b Base64) String() string {
 	return base64.StdEncoding.EncodeToString([]byte(b))
 }
@@ -324,20 +300,6 @@ func (u *URI) UnmarshalText(data []byte) error { // validation is performed late
 	return nil
 }
 
-// Scan read a value from a database driver
-func (u *URI) Scan(raw interface{}) error {
-	switch v := raw.(type) {
-	case []byte:
-		*u = URI(string(v))
-	case string:
-		*u = URI(v)
-	default:
-		return fmt.Errorf("cannot sql.Scan() strfmt.URI from: %#v", v)
-	}
-
-	return nil
-}
-
 func (u URI) String() string {
 	return string(u)
 }
@@ -388,20 +350,6 @@ func (e *Email) UnmarshalText(data []byte) error { // validation is performed la
 	return nil
 }
 
-// Scan read a value from a database driver
-func (e *Email) Scan(raw interface{}) error {
-	switch v := raw.(type) {
-	case []byte:
-		*e = Email(string(v))
-	case string:
-		*e = Email(v)
-	default:
-		return fmt.Errorf("cannot sql.Scan() strfmt.Email from: %#v", v)
-	}
-
-	return nil
-}
-
 func (e Email) String() string {
 	return string(e)
 }
@@ -452,20 +400,6 @@ func (h *Hostname) UnmarshalText(data []byte) error { // validation is performed
 	return nil
 }
 
-// Scan read a value from a database driver
-func (h *Hostname) Scan(raw interface{}) error {
-	switch v := raw.(type) {
-	case []byte:
-		*h = Hostname(string(v))
-	case string:
-		*h = Hostname(v)
-	default:
-		return fmt.Errorf("cannot sql.Scan() strfmt.Hostname from: %#v", v)
-	}
-
-	return nil
-}
-
 func (h Hostname) String() string {
 	return string(h)
 }
@@ -516,20 +450,6 @@ func (u *IPv4) UnmarshalText(data []byte) error { // validation is performed lat
 	return nil
 }
 
-// Scan read a value from a database driver
-func (u *IPv4) Scan(raw interface{}) error {
-	switch v := raw.(type) {
-	case []byte:
-		*u = IPv4(string(v))
-	case string:
-		*u = IPv4(v)
-	default:
-		return fmt.Errorf("cannot sql.Scan() strfmt.IPv4 from: %#v", v)
-	}
-
-	return nil
-}
-
 func (u IPv4) String() string {
 	return string(u)
 }
@@ -580,20 +500,6 @@ func (u *IPv6) UnmarshalText(data []byte) error { // validation is performed lat
 	return nil
 }
 
-// Scan read a value from a database driver
-func (u *IPv6) Scan(raw interface{}) error {
-	switch v := raw.(type) {
-	case []byte:
-		*u = IPv6(string(v))
-	case string:
-		*u = IPv6(v)
-	default:
-		return fmt.Errorf("cannot sql.Scan() strfmt.IPv6 from: %#v", v)
-	}
-
-	return nil
-}
-
 func (u IPv6) String() string {
 	return string(u)
 }
@@ -644,20 +550,6 @@ func (u *CIDR) UnmarshalText(data []byte) error { // validation is performed lat
 	return nil
 }
 
-// Scan read a value from a database driver
-func (u *CIDR) Scan(raw interface{}) error {
-	switch v := raw.(type) {
-	case []byte:
-		*u = CIDR(string(v))
-	case string:
-		*u = CIDR(v)
-	default:
-		return fmt.Errorf("cannot sql.Scan() strfmt.CIDR from: %#v", v)
-	}
-
-	return nil
-}
-
 func (u CIDR) String() string {
 	return string(u)
 }
@@ -708,20 +600,6 @@ func (u *MAC) UnmarshalText(data []byte) error { // validation is performed late
 	return nil
 }
 
-// Scan read a value from a database driver
-func (u *MAC) Scan(raw interface{}) error {
-	switch v := raw.(type) {
-	case []byte:
-		*u = MAC(string(v))
-	case string:
-		*u = MAC(v)
-	default:
-		return fmt.Errorf("cannot sql.Scan() strfmt.IPv4 from: %#v", v)
-	}
-
-	return nil
-}
-
 func (u MAC) String() string {
 	return string(u)
 }
@@ -772,20 +650,6 @@ func (u *UUID) UnmarshalText(data []byte) error { // validation is performed lat
 	return nil
 }
 
-// Scan read a value from a database driver
-func (u *UUID) Scan(raw interface{}) error {
-	switch v := raw.(type) {
-	case []byte:
-		*u = UUID(string(v))
-	case string:
-		*u = UUID(v)
-	default:
-		return fmt.Errorf("cannot sql.Scan() strfmt.UUID from: %#v", v)
-	}
-
-	return nil
-}
-
 func (u UUID) String() string {
 	return string(u)
 }
@@ -839,20 +703,6 @@ func (u *UUID3) UnmarshalText(data []byte) error { // validation is performed la
 	return nil
 }
 
-// Scan read a value from a database driver
-func (u *UUID3) Scan(raw interface{}) error {
-	switch v := raw.(type) {
-	case []byte:
-		*u = UUID3(string(v))
-	case string:
-		*u = UUID3(v)
-	default:
-		return fmt.Errorf("cannot sql.Scan() strfmt.UUID3 from: %#v", v)
-	}
-
-	return nil
-}
-
 func (u UUID3) String() string {
 	return string(u)
 }
@@ -906,20 +756,6 @@ func (u *UUID4) UnmarshalText(data []byte) error { // validation is performed la
 	return nil
 }
 
-// Scan read a value from a database driver
-func (u *UUID4) Scan(raw interface{}) error {
-	switch v := raw.(type) {
-	case []byte:
-		*u = UUID4(string(v))
-	case string:
-		*u = UUID4(v)
-	default:
-		return fmt.Errorf("cannot sql.Scan() strfmt.UUID4 from: %#v", v)
-	}
-
-	return nil
-}
-
 func (u UUID4) String() string {
 	return string(u)
 }
@@ -973,20 +809,6 @@ func (u *UUID5) UnmarshalText(data []byte) error { // validation is performed la
 	return nil
 }
 
-// Scan read a value from a database driver
-func (u *UUID5) Scan(raw interface{}) error {
-	switch v := raw.(type) {
-	case []byte:
-		*u = UUID5(string(v))
-	case string:
-		*u = UUID5(v)
-	default:
-		return fmt.Errorf("cannot sql.Scan() strfmt.UUID5 from: %#v", v)
-	}
-
-	return nil
-}
-
 func (u UUID5) String() string {
 	return string(u)
 }
@@ -1040,20 +862,6 @@ func (u *ISBN) UnmarshalText(data []byte) error { // validation is performed lat
 	return nil
 }
 
-// Scan read a value from a database driver
-func (u *ISBN) Scan(raw interface{}) error {
-	switch v := raw.(type) {
-	case []byte:
-		*u = ISBN(string(v))
-	case string:
-		*u = ISBN(v)
-	default:
-		return fmt.Errorf("cannot sql.Scan() strfmt.ISBN from: %#v", v)
-	}
-
-	return nil
-}
-
 func (u ISBN) String() string {
 	return string(u)
 }
@@ -1107,20 +915,6 @@ func (u *ISBN10) UnmarshalText(data []byte) error { // validation is performed l
 	return nil
 }
 
-// Scan read a value from a database driver
-func (u *ISBN10) Scan(raw interface{}) error {
-	switch v := raw.(type) {
-	case []byte:
-		*u = ISBN10(string(v))
-	case string:
-		*u = ISBN10(v)
-	default:
-		return fmt.Errorf("cannot sql.Scan() strfmt.ISBN10 from: %#v", v)
-	}
-
-	return nil
-}
-
 func (u ISBN10) String() string {
 	return string(u)
 }
@@ -1174,20 +968,6 @@ func (u *ISBN13) UnmarshalText(data []byte) error { // validation is performed l
 	return nil
 }
 
-// Scan read a value from a database driver
-func (u *ISBN13) Scan(raw interface{}) error {
-	switch v := raw.(type) {
-	case []byte:
-		*u = ISBN13(string(v))
-	case string:
-		*u = ISBN13(v)
-	default:
-		return fmt.Errorf("cannot sql.Scan() strfmt.ISBN13 from: %#v", v)
-	}
-
-	return nil
-}
-
 func (u ISBN13) String() string {
 	return string(u)
 }
@@ -1241,20 +1021,6 @@ func (u *CreditCard) UnmarshalText(data []byte) error { // validation is perform
 	return nil
 }
 
-// Scan read a value from a database driver
-func (u *CreditCard) Scan(raw interface{}) error {
-	switch v := raw.(type) {
-	case []byte:
-		*u = CreditCard(string(v))
-	case string:
-		*u = CreditCard(v)
-	default:
-		return fmt.Errorf("cannot sql.Scan() strfmt.CreditCard from: %#v", v)
-	}
-
-	return nil
-}
-
 func (u CreditCard) String() string {
 	return string(u)
 }
@@ -1308,20 +1074,6 @@ func (u *SSN) UnmarshalText(data []byte) error { // validation is performed late
 	return nil
 }
 
-// Scan read a value from a database driver
-func (u *SSN) Scan(raw interface{}) error {
-	switch v := raw.(type) {
-	case []byte:
-		*u = SSN(string(v))
-	case string:
-		*u = SSN(v)
-	default:
-		return fmt.Errorf("cannot sql.Scan() strfmt.SSN from: %#v", v)
-	}
-
-	return nil
-}
-
 func (u SSN) String() string {
 	return string(u)
 }
@@ -1375,20 +1127,6 @@ func (h *HexColor) UnmarshalText(data []byte) error { // validation is performed
 	return nil
 }
 
-// Scan read a value from a database driver
-func (h *HexColor) Scan(raw interface{}) error {
-	switch v := raw.(type) {
-	case []byte:
-		*h = HexColor(string(v))
-	case string:
-		*h = HexColor(v)
-	default:
-		return fmt.Errorf("cannot sql.Scan() strfmt.HexColor from: %#v", v)
-	}
-
-	return nil
-}
-
 func (h HexColor) String() string {
 	return string(h)
 }
@@ -1442,20 +1180,6 @@ func (r *RGBColor) UnmarshalText(data []byte) error { // validation is performed
 	return nil
 }
 
-// Scan read a value from a database driver
-func (r *RGBColor) Scan(raw interface{}) error {
-	switch v := raw.(type) {
-	case []byte:
-		*r = RGBColor(string(v))
-	case string:
-		*r = RGBColor(v)
-	default:
-		return fmt.Errorf("cannot sql.Scan() strfmt.RGBColor from: %#v", v)
-	}
-
-	return nil
-}
-
 func (r RGBColor) String() string {
 	return string(r)
 }
@@ -1510,20 +1234,6 @@ func (r *Password) UnmarshalText(data []byte) error { // validation is performed
 	return nil
 }
 
-// Scan read a value from a database driver
-func (r *Password) Scan(raw interface{}) error {
-	switch v := raw.(type) {
-	case []byte:
-		*r = Password(string(v))
-	case string:
-		*r = Password(v)
-	default:
-		return fmt.Errorf("cannot sql.Scan() strfmt.Password from: %#v", v)
-	}
-
-	return nil
-}
-
 func (r Password) String() string {
 	return string(r)
 }
diff --git a/pkg/validation/strfmt/duration.go b/pkg/validation/strfmt/duration.go
index 8fbeb63..0454529 100644
--- a/pkg/validation/strfmt/duration.go
+++ b/pkg/validation/strfmt/duration.go
@@ -119,23 +119,6 @@ func ParseDuration(cand string) (time.Duration, error) {
 	return 0, fmt.Errorf("unable to parse %s as duration", cand)
 }
 
-// Scan reads a Duration value from database driver type.
-func (d *Duration) Scan(raw interface{}) error {
-	switch v := raw.(type) {
-	// TODO: case []byte: // ?
-	case int64:
-		*d = Duration(v)
-	case float64:
-		*d = Duration(int64(v))
-	case nil:
-		*d = Duration(0)
-	default:
-		return fmt.Errorf("cannot sql.Scan() strfmt.Duration from: %#v", v)
-	}
-
-	return nil
-}
-
 // String converts this duration to a string
 func (d Duration) String() string {
 	return time.Duration(d).String()
diff --git a/pkg/validation/strfmt/time.go b/pkg/validation/strfmt/time.go
index b2324db..d0fd31a 100644
--- a/pkg/validation/strfmt/time.go
+++ b/pkg/validation/strfmt/time.go
@@ -16,7 +16,6 @@ package strfmt
 
 import (
 	"encoding/json"
-	"fmt"
 	"regexp"
 	"strings"
 	"time"
@@ -114,25 +113,6 @@ func (t *DateTime) UnmarshalText(text []byte) error {
 	return nil
 }
 
-// Scan scans a DateTime value from database driver type.
-func (t *DateTime) Scan(raw interface{}) error {
-	// TODO: case int64: and case float64: ?
-	switch v := raw.(type) {
-	case []byte:
-		return t.UnmarshalText(v)
-	case string:
-		return t.UnmarshalText([]byte(v))
-	case time.Time:
-		*t = DateTime(v)
-	case nil:
-		*t = DateTime{}
-	default:
-		return fmt.Errorf("cannot sql.Scan() strfmt.DateTime from: %#v", v)
-	}
-
-	return nil
-}
-
 // MarshalJSON returns the DateTime as JSON
 func (t DateTime) MarshalJSON() ([]byte, error) {
 	return json.Marshal(time.Time(t).Format(MarshalFormat))



Test patch:
diff --git a/pkg/validation/strfmt/time_test.go b/pkg/validation/strfmt/time_test.go
index 38fc11e..6f85aaf 100644
--- a/pkg/validation/strfmt/time_test.go
+++ b/pkg/validation/strfmt/time_test.go
@@ -75,10 +75,6 @@ func TestParseDateTime_fullCycle(t *testing.T) {
 		assert.NoError(t, err)
 		assert.EqualValues(t, example.time, pp)
 
-		pp = NewDateTime()
-		err = pp.Scan(mt)
-		assert.NoError(t, err)
-		assert.Equal(t, DateTime(example.time), pp)
 	}
 }
 
@@ -172,48 +168,6 @@ func TestDateTime_MarshalJSON(t *testing.T) {
 	}
 }
 
-func TestDateTime_Scan(t *testing.T) {
-	for caseNum, example := range testCases {
-		t.Logf("Case #%d", caseNum)
-
-		pp := NewDateTime()
-		err := pp.Scan(example.in)
-		assert.NoError(t, err)
-		assert.Equal(t, DateTime(example.time), pp)
-
-		pp = NewDateTime()
-		err = pp.Scan(string(example.in))
-		assert.NoError(t, err)
-		assert.Equal(t, DateTime(example.time), pp)
-
-		pp = NewDateTime()
-		err = pp.Scan(example.time)
-		assert.NoError(t, err)
-		assert.Equal(t, DateTime(example.time), pp)
-	}
-}
-
-func TestDateTime_Scan_Failed(t *testing.T) {
-	pp := NewDateTime()
-	zero := NewDateTime()
-
-	err := pp.Scan(nil)
-	assert.NoError(t, err)
-	// Zero values differ...
-	//assert.Equal(t, zero, pp)
-	assert.Equal(t, DateTime{}, pp)
-
-	err = pp.Scan("")
-	assert.NoError(t, err)
-	assert.Equal(t, zero, pp)
-
-	err = pp.Scan(int64(0))
-	assert.Error(t, err)
-
-	err = pp.Scan(float64(0))
-	assert.Error(t, err)
-}
-
 func TestDeepCopyDateTime(t *testing.T) {
 	p, err := ParseDateTime("2011-08-18T19:03:37.000000000+01:00")
 	assert.NoError(t, err)