refactor: remove usages of experimental maps package (#7849)

All 4 usages of the `maps.Keys` function from the
`golang.org/x/exp/maps` package can be refactored to a simpler
alternative. If we need it in the future, it is available in the
standard library since Go 1.23.
This commit is contained in:
Eng Zer Jun 2024-12-07 03:50:32 +08:00 committed by GitHub
parent 87104b0a3e
commit 13db2a252f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 92 additions and 176 deletions

View File

@ -2,6 +2,7 @@ package main
import (
"context"
"errors"
"fmt"
"github.com/jmhodges/clock"
@ -94,3 +95,22 @@ func newAdmin(configFile string, dryRun bool) (*admin, error) {
log: logger,
}, nil
}
// findActiveInputMethodFlag returns a single key from setInputs with a value of `true`,
// if exactly one exists. Otherwise it returns an error.
func findActiveInputMethodFlag(setInputs map[string]bool) (string, error) {
var activeFlags []string
for flag, isSet := range setInputs {
if isSet {
activeFlags = append(activeFlags, flag)
}
}
if len(activeFlags) == 0 {
return "", errors.New("at least one input method flag must be specified")
} else if len(activeFlags) > 1 {
return "", fmt.Errorf("more than one input method flag specified: %v", activeFlags)
}
return activeFlags[0], nil
}

59
cmd/admin/admin_test.go Normal file
View File

@ -0,0 +1,59 @@
package main
import (
"testing"
"github.com/letsencrypt/boulder/test"
)
func Test_findActiveInputMethodFlag(t *testing.T) {
tests := []struct {
name string
setInputs map[string]bool
expected string
wantErr bool
}{
{
name: "No active flags",
setInputs: map[string]bool{
"-private-key": false,
"-spki-file": false,
"-cert-file": false,
},
expected: "",
wantErr: true,
},
{
name: "Multiple active flags",
setInputs: map[string]bool{
"-private-key": true,
"-spki-file": true,
"-cert-file": false,
},
expected: "",
wantErr: true,
},
{
name: "Single active flag",
setInputs: map[string]bool{
"-private-key": true,
"-spki-file": false,
"-cert-file": false,
},
expected: "-private-key",
wantErr: false,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
result, err := findActiveInputMethodFlag(tc.setInputs)
if tc.wantErr {
test.AssertError(t, err, "findActiveInputMethodFlag() should have errored")
} else {
test.AssertNotError(t, err, "findActiveInputMethodFlag() should not have errored")
test.AssertEquals(t, result, tc.expected)
}
})
}
}

View File

@ -15,7 +15,6 @@ import (
"unicode"
"golang.org/x/crypto/ocsp"
"golang.org/x/exp/maps"
core "github.com/letsencrypt/boulder/core"
berrors "github.com/letsencrypt/boulder/errors"
@ -109,16 +108,13 @@ func (s *subcommandRevokeCert) Run(ctx context.Context, a *admin) error {
"-reg-id": s.regID != 0,
"-cert-file": s.certFile != "",
}
maps.DeleteFunc(setInputs, func(_ string, v bool) bool { return !v })
if len(setInputs) == 0 {
return errors.New("at least one input method flag must be specified")
} else if len(setInputs) > 1 {
return fmt.Errorf("more than one input method flag specified: %v", maps.Keys(setInputs))
activeFlag, err := findActiveInputMethodFlag(setInputs)
if err != nil {
return err
}
var serials []string
var err error
switch maps.Keys(setInputs)[0] {
switch activeFlag {
case "-serial":
serials, err = []string{s.serial}, nil
case "-incident-table":

View File

@ -15,7 +15,6 @@ import (
"sync"
"sync/atomic"
"golang.org/x/exp/maps"
"google.golang.org/protobuf/types/known/timestamppb"
"github.com/letsencrypt/boulder/core"
@ -69,16 +68,13 @@ func (s *subcommandBlockKey) Run(ctx context.Context, a *admin) error {
"-cert-file": s.certFile != "",
"-csr-file": s.csrFile != "",
}
maps.DeleteFunc(setInputs, func(_ string, v bool) bool { return !v })
if len(setInputs) == 0 {
return errors.New("at least one input method flag must be specified")
} else if len(setInputs) > 1 {
return fmt.Errorf("more than one input method flag specified: %v", maps.Keys(setInputs))
activeFlag, err := findActiveInputMethodFlag(setInputs)
if err != nil {
return err
}
var spkiHashes [][]byte
var err error
switch maps.Keys(setInputs)[0] {
switch activeFlag {
case "-private-key":
var spkiHash []byte
spkiHash, err = a.spkiHashFromPrivateKey(s.privKey)

View File

@ -14,7 +14,6 @@ import (
sapb "github.com/letsencrypt/boulder/sa/proto"
"github.com/letsencrypt/boulder/unpause"
"golang.org/x/exp/maps"
)
// subcommandUnpauseAccount encapsulates the "admin unpause-account" command.
@ -44,16 +43,13 @@ func (u *subcommandUnpauseAccount) Run(ctx context.Context, a *admin) error {
"-account": u.accountID != 0,
"-batch-file": u.batchFile != "",
}
maps.DeleteFunc(setInputs, func(_ string, v bool) bool { return !v })
if len(setInputs) == 0 {
return errors.New("at least one input method flag must be specified")
} else if len(setInputs) > 1 {
return fmt.Errorf("more than one input method flag specified: %v", maps.Keys(setInputs))
activeFlag, err := findActiveInputMethodFlag(setInputs)
if err != nil {
return err
}
var regIDs []int64
var err error
switch maps.Keys(setInputs)[0] {
switch activeFlag {
case "-account":
regIDs = []int64{u.accountID}
case "-batch-file":

1
go.mod
View File

@ -37,7 +37,6 @@ require (
go.opentelemetry.io/otel/sdk v1.30.0
go.opentelemetry.io/otel/trace v1.30.0
golang.org/x/crypto v0.27.0
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3
golang.org/x/net v0.29.0
golang.org/x/sync v0.8.0
golang.org/x/term v0.24.0

2
go.sum
View File

@ -309,8 +309,6 @@ golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 h1:hNQpMuAJe5CtcUqCXaWga3FHu+kQvCqcsoVaQgSV60o=
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=

27
vendor/golang.org/x/exp/LICENSE generated vendored
View File

@ -1,27 +0,0 @@
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

22
vendor/golang.org/x/exp/PATENTS generated vendored
View File

@ -1,22 +0,0 @@
Additional IP Rights Grant (Patents)
"This implementation" means the copyrightable works distributed by
Google as part of the Go project.
Google hereby grants to You a perpetual, worldwide, non-exclusive,
no-charge, royalty-free, irrevocable (except as stated in this section)
patent license to make, have made, use, offer to sell, sell, import,
transfer and otherwise run, modify and propagate the contents of this
implementation of Go, where such license applies only to those patent
claims, both currently owned or controlled by Google and acquired in
the future, licensable by Google that are necessarily infringed by this
implementation of Go. This grant does not include claims that would be
infringed only as a consequence of further modification of this
implementation. If you or your agent or exclusive licensee institute or
order or agree to the institution of patent litigation against any
entity (including a cross-claim or counterclaim in a lawsuit) alleging
that this implementation of Go or any code incorporated within this
implementation of Go constitutes direct or contributory patent
infringement, or inducement of patent infringement, then any patent
rights granted to you under this License for this implementation of Go
shall terminate as of the date such litigation is filed.

94
vendor/golang.org/x/exp/maps/maps.go generated vendored
View File

@ -1,94 +0,0 @@
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package maps defines various functions useful with maps of any type.
package maps
// Keys returns the keys of the map m.
// The keys will be in an indeterminate order.
func Keys[M ~map[K]V, K comparable, V any](m M) []K {
r := make([]K, 0, len(m))
for k := range m {
r = append(r, k)
}
return r
}
// Values returns the values of the map m.
// The values will be in an indeterminate order.
func Values[M ~map[K]V, K comparable, V any](m M) []V {
r := make([]V, 0, len(m))
for _, v := range m {
r = append(r, v)
}
return r
}
// Equal reports whether two maps contain the same key/value pairs.
// Values are compared using ==.
func Equal[M1, M2 ~map[K]V, K, V comparable](m1 M1, m2 M2) bool {
if len(m1) != len(m2) {
return false
}
for k, v1 := range m1 {
if v2, ok := m2[k]; !ok || v1 != v2 {
return false
}
}
return true
}
// EqualFunc is like Equal, but compares values using eq.
// Keys are still compared with ==.
func EqualFunc[M1 ~map[K]V1, M2 ~map[K]V2, K comparable, V1, V2 any](m1 M1, m2 M2, eq func(V1, V2) bool) bool {
if len(m1) != len(m2) {
return false
}
for k, v1 := range m1 {
if v2, ok := m2[k]; !ok || !eq(v1, v2) {
return false
}
}
return true
}
// Clear removes all entries from m, leaving it empty.
func Clear[M ~map[K]V, K comparable, V any](m M) {
for k := range m {
delete(m, k)
}
}
// Clone returns a copy of m. This is a shallow clone:
// the new keys and values are set using ordinary assignment.
func Clone[M ~map[K]V, K comparable, V any](m M) M {
// Preserve nil in case it matters.
if m == nil {
return nil
}
r := make(M, len(m))
for k, v := range m {
r[k] = v
}
return r
}
// Copy copies all key/value pairs in src adding them to dst.
// When a key in src is already present in dst,
// the value in dst will be overwritten by the value associated
// with the key in src.
func Copy[M1 ~map[K]V, M2 ~map[K]V, K comparable, V any](dst M1, src M2) {
for k, v := range src {
dst[k] = v
}
}
// DeleteFunc deletes any key/value pairs from m for which del returns true.
func DeleteFunc[M ~map[K]V, K comparable, V any](m M, del func(K, V) bool) {
for k, v := range m {
if del(k, v) {
delete(m, k)
}
}
}

3
vendor/modules.txt vendored
View File

@ -369,9 +369,6 @@ golang.org/x/crypto/cryptobyte/asn1
golang.org/x/crypto/ed25519
golang.org/x/crypto/ocsp
golang.org/x/crypto/pbkdf2
# golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3
## explicit; go 1.20
golang.org/x/exp/maps
# golang.org/x/mod v0.18.0
## explicit; go 1.18
golang.org/x/mod/semver

View File

@ -13,7 +13,6 @@ import (
"math/rand/v2"
"net"
"net/http"
"slices"
"strconv"
"strings"
"time"
@ -22,7 +21,6 @@ import (
"github.com/prometheus/client_golang/prometheus"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
"go.opentelemetry.io/otel/trace"
"golang.org/x/exp/maps"
"google.golang.org/protobuf/types/known/emptypb"
"github.com/letsencrypt/boulder/core"
@ -2273,7 +2271,7 @@ func (wfe *WebFrontEndImpl) validateCertificateProfileName(profile string) error
// No profile name is specified.
return nil
}
if !slices.Contains(maps.Keys(wfe.certProfiles), profile) {
if _, ok := wfe.certProfiles[profile]; !ok {
// The profile name is not in the list of configured profiles.
return errors.New("not a recognized profile name")
}