cli: declare mastersecret as immutable and print attestationCfg diff in warning (#2167)

This commit is contained in:
Adrian Stobbe 2023-08-08 13:03:23 +02:00 committed by GitHub
parent e97b2afc14
commit 70861ee8ad
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 219 additions and 105 deletions

View file

@ -4481,8 +4481,8 @@ def go_dependencies():
build_file_generation = "on", build_file_generation = "on",
build_file_proto_mode = "disable_global", build_file_proto_mode = "disable_global",
importpath = "github.com/rogpeppe/go-internal", importpath = "github.com/rogpeppe/go-internal",
sum = "h1:3RPlVWzZ/PDqmVuf/FKHARG5EMid/tl7cv54Sw/QRVY=", sum = "h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=",
version = "v1.10.1-0.20230524175051-ec119421bb97", version = "v1.11.0",
) )
go_repository( go_repository(
name = "com_github_rs_cors", name = "com_github_rs_cors",

View file

@ -89,6 +89,7 @@ go_library(
"@com_github_google_go_sev_guest//kds", "@com_github_google_go_sev_guest//kds",
"@com_github_google_uuid//:uuid", "@com_github_google_uuid//:uuid",
"@com_github_mattn_go_isatty//:go-isatty", "@com_github_mattn_go_isatty//:go-isatty",
"@com_github_rogpeppe_go_internal//diff",
"@com_github_siderolabs_talos_pkg_machinery//config/encoder", "@com_github_siderolabs_talos_pkg_machinery//config/encoder",
"@com_github_spf13_afero//:afero", "@com_github_spf13_afero//:afero",
"@com_github_spf13_cobra//:cobra", "@com_github_spf13_cobra//:cobra",

View file

@ -89,8 +89,6 @@ func runStatus(cmd *cobra.Command, _ []string) error {
return helmClient.Versions() return helmClient.Versions()
} }
stableClient := kubernetes.NewStableClient(kubeClient)
fetcher := attestationconfigapi.NewFetcher() fetcher := attestationconfigapi.NewFetcher()
conf, err := config.New(fileHandler, constants.ConfigFilename, fetcher, flags.force) conf, err := config.New(fileHandler, constants.ConfigFilename, fetcher, flags.force)
var configValidationErr *config.ValidationError var configValidationErr *config.ValidationError
@ -99,6 +97,10 @@ func runStatus(cmd *cobra.Command, _ []string) error {
} }
variant := conf.GetAttestationConfig().GetVariant() variant := conf.GetAttestationConfig().GetVariant()
stableClient, err := kubernetes.NewStableClient(constants.AdminConfFilename)
if err != nil {
return fmt.Errorf("setting up stable client: %w", err)
}
output, err := status(cmd.Context(), kubeClient, stableClient, helmVersionGetter, kubernetes.NewNodeVersionClient(unstructuredClient), variant) output, err := status(cmd.Context(), kubeClient, stableClient, helmVersionGetter, kubernetes.NewNodeVersionClient(unstructuredClient), variant)
if err != nil { if err != nil {
return fmt.Errorf("getting status: %w", err) return fmt.Errorf("getting status: %w", err)
@ -121,18 +123,9 @@ func status(
return "", fmt.Errorf("expected exactly one condition, got %d", len(nodeVersion.Status.Conditions)) return "", fmt.Errorf("expected exactly one condition, got %d", len(nodeVersion.Status.Conditions))
} }
// attestation version attestationConfig, err := getAttestationConfig(ctx, cmClient, attestVariant)
joinConfig, err := cmClient.GetCurrentConfigMap(ctx, constants.JoinConfigMap)
if err != nil { if err != nil {
return "", fmt.Errorf("getting current config map: %w", err) return "", fmt.Errorf("getting attestation config: %w", err)
}
rawAttestationConfig, ok := joinConfig.Data[constants.AttestationConfigFilename]
if !ok {
return "", fmt.Errorf("attestationConfig not found in %s", constants.JoinConfigMap)
}
attestationConfig, err := config.UnmarshalAttestationConfig([]byte(rawAttestationConfig), attestVariant)
if err != nil {
return "", fmt.Errorf("unmarshalling attestation config: %w", err)
} }
prettyYAML, err := yaml.Marshal(attestationConfig) prettyYAML, err := yaml.Marshal(attestationConfig)
if err != nil { if err != nil {
@ -157,6 +150,22 @@ func status(
return statusOutput(targetVersions, serviceVersions, status, nodeVersion, string(prettyYAML)), nil return statusOutput(targetVersions, serviceVersions, status, nodeVersion, string(prettyYAML)), nil
} }
func getAttestationConfig(ctx context.Context, cmClient configMapClient, attestVariant variant.Variant) (config.AttestationCfg, error) {
joinConfig, err := cmClient.GetCurrentConfigMap(ctx, constants.JoinConfigMap)
if err != nil {
return nil, fmt.Errorf("getting current config map: %w", err)
}
rawAttestationConfig, ok := joinConfig.Data[constants.AttestationConfigFilename]
if !ok {
return nil, fmt.Errorf("attestationConfig not found in %s", constants.JoinConfigMap)
}
attestationConfig, err := config.UnmarshalAttestationConfig([]byte(rawAttestationConfig), attestVariant)
if err != nil {
return nil, fmt.Errorf("unmarshalling attestation config: %w", err)
}
return attestationConfig, nil
}
// statusOutput creates the status cmd output string by formatting the received information. // statusOutput creates the status cmd output string by formatting the received information.
func statusOutput( func statusOutput(
targetVersions kubernetes.TargetVersions, serviceVersions fmt.Stringer, targetVersions kubernetes.TargetVersions, serviceVersions fmt.Stringer,

View file

@ -28,8 +28,10 @@ import (
"github.com/edgelesssys/constellation/v2/internal/file" "github.com/edgelesssys/constellation/v2/internal/file"
"github.com/edgelesssys/constellation/v2/internal/imagefetcher" "github.com/edgelesssys/constellation/v2/internal/imagefetcher"
"github.com/edgelesssys/constellation/v2/internal/versions" "github.com/edgelesssys/constellation/v2/internal/versions"
"github.com/rogpeppe/go-internal/diff"
"github.com/spf13/afero" "github.com/spf13/afero"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"gopkg.in/yaml.v3"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
) )
@ -73,9 +75,19 @@ func runUpgradeApply(cmd *cobra.Command, _ []string) error {
imagefetcher := imagefetcher.New() imagefetcher := imagefetcher.New()
configFetcher := attestationconfigapi.NewFetcher() configFetcher := attestationconfigapi.NewFetcher()
applyCmd := upgradeApplyCmd{upgrader: upgrader, log: log, imageFetcher: imagefetcher, configFetcher: configFetcher} applyCmd := upgradeApplyCmd{upgrader: upgrader, log: log, imageFetcher: imagefetcher, configFetcher: configFetcher}
return applyCmd.upgradeApply(cmd, fileHandler) return applyCmd.upgradeApply(cmd, fileHandler, stableClientFactoryImpl)
}
type stableClientFactory func(kubeconfigPath string) (getConfigMapper, error)
// needed because StableClient returns the bigger kubernetes.StableInterface.
func stableClientFactoryImpl(kubeconfigPath string) (getConfigMapper, error) {
return kubernetes.NewStableClient(kubeconfigPath)
}
type getConfigMapper interface {
GetCurrentConfigMap(ctx context.Context, name string) (*corev1.ConfigMap, error)
} }
type upgradeApplyCmd struct { type upgradeApplyCmd struct {
@ -85,7 +97,7 @@ type upgradeApplyCmd struct {
log debugLog log debugLog
} }
func (u *upgradeApplyCmd) upgradeApply(cmd *cobra.Command, fileHandler file.Handler) error { func (u *upgradeApplyCmd) upgradeApply(cmd *cobra.Command, fileHandler file.Handler, stableClientFactory stableClientFactory) error {
flags, err := parseUpgradeApplyFlags(cmd) flags, err := parseUpgradeApplyFlags(cmd)
if err != nil { if err != nil {
return fmt.Errorf("parsing flags: %w", err) return fmt.Errorf("parsing flags: %w", err)
@ -112,7 +124,6 @@ func (u *upgradeApplyCmd) upgradeApply(cmd *cobra.Command, fileHandler file.Hand
} }
} }
} }
if err := handleInvalidK8sPatchVersion(cmd, conf.KubernetesVersion, flags.yes); err != nil { if err := handleInvalidK8sPatchVersion(cmd, conf.KubernetesVersion, flags.yes); err != nil {
return err return err
} }
@ -124,7 +135,11 @@ func (u *upgradeApplyCmd) upgradeApply(cmd *cobra.Command, fileHandler file.Hand
conf.UpdateMAAURL(idFile.AttestationURL) conf.UpdateMAAURL(idFile.AttestationURL)
// If an image upgrade was just executed there won't be a diff. The function will return nil in that case. // If an image upgrade was just executed there won't be a diff. The function will return nil in that case.
if err := u.upgradeAttestConfigIfDiff(cmd, conf.GetAttestationConfig(), flags); err != nil { stableClient, err := stableClientFactory(constants.AdminConfFilename)
if err != nil {
return fmt.Errorf("creating stable client: %w", err)
}
if err := u.upgradeAttestConfigIfDiff(cmd, stableClient, conf.GetAttestationConfig(), flags); err != nil {
return fmt.Errorf("upgrading measurements: %w", err) return fmt.Errorf("upgrading measurements: %w", err)
} }
// not moving existing Terraform migrator because of planned apply refactor // not moving existing Terraform migrator because of planned apply refactor
@ -172,6 +187,20 @@ func (u *upgradeApplyCmd) upgradeApply(cmd *cobra.Command, fileHandler file.Hand
return nil return nil
} }
func diffAttestationCfg(currentAttestationCfg config.AttestationCfg, newAttestationCfg config.AttestationCfg) (string, error) {
// cannot compare structs directly with go-cmp because of unexported fields in the attestation config
currentYml, err := yaml.Marshal(currentAttestationCfg)
if err != nil {
return "", fmt.Errorf("marshalling remote attestation config: %w", err)
}
newYml, err := yaml.Marshal(newAttestationCfg)
if err != nil {
return "", fmt.Errorf("marshalling local attestation config: %w", err)
}
diff := string(diff.Diff("current", currentYml, "new", newYml))
return diff, nil
}
func getImage(ctx context.Context, conf *config.Config, fetcher imageFetcher) (string, error) { func getImage(ctx context.Context, conf *config.Config, fetcher imageFetcher) (string, error) {
// Fetch variables to execute Terraform script with // Fetch variables to execute Terraform script with
provider := conf.GetProvider() provider := conf.GetProvider()
@ -290,8 +319,8 @@ type imageFetcher interface {
// upgradeAttestConfigIfDiff checks if the locally configured measurements are different from the cluster's measurements. // upgradeAttestConfigIfDiff checks if the locally configured measurements are different from the cluster's measurements.
// If so the function will ask the user to confirm (if --yes is not set) and upgrade the measurements only. // If so the function will ask the user to confirm (if --yes is not set) and upgrade the measurements only.
func (u *upgradeApplyCmd) upgradeAttestConfigIfDiff(cmd *cobra.Command, newConfig config.AttestationCfg, flags upgradeApplyFlags) error { func (u *upgradeApplyCmd) upgradeAttestConfigIfDiff(cmd *cobra.Command, stableClient getConfigMapper, newConfig config.AttestationCfg, flags upgradeApplyFlags) error {
clusterAttestationConfig, _, err := u.upgrader.GetClusterAttestationConfig(cmd.Context(), newConfig.GetVariant()) clusterAttestationConfig, err := getAttestationConfig(cmd.Context(), stableClient, newConfig.GetVariant())
if err != nil { if err != nil {
return fmt.Errorf("getting cluster attestation config: %w", err) return fmt.Errorf("getting cluster attestation config: %w", err)
} }
@ -305,7 +334,14 @@ func (u *upgradeApplyCmd) upgradeAttestConfigIfDiff(cmd *cobra.Command, newConfi
} }
if !flags.yes { if !flags.yes {
ok, err := askToConfirm(cmd, "You are about to change your cluster's attestation config. Are you sure you want to continue?") cmd.Println("The configured attestation config is different from the attestation config in the cluster.")
diffStr, err := diffAttestationCfg(clusterAttestationConfig, newConfig)
if err != nil {
return fmt.Errorf("diffing attestation configs: %w", err)
}
cmd.Println("The following changes will be applied to the attestation config:")
cmd.Println(diffStr)
ok, err := askToConfirm(cmd, "Are you sure you want to change your cluster's attestation config?")
if err != nil { if err != nil {
return fmt.Errorf("asking for confirmation: %w", err) return fmt.Errorf("asking for confirmation: %w", err)
} }

View file

@ -9,6 +9,7 @@ package cmd
import ( import (
"bytes" "bytes"
"context" "context"
"encoding/json"
"errors" "errors"
"testing" "testing"
"time" "time"
@ -37,6 +38,7 @@ func TestUpgradeApply(t *testing.T) {
wantErr bool wantErr bool
yesFlag bool yesFlag bool
stdin string stdin string
remoteAttestationCfg config.AttestationCfg // attestation config returned by the stub Kubernetes client
}{ }{
"success": { "success": {
upgrader: stubUpgrader{currentConfig: config.DefaultForAzureSEVSNP()}, upgrader: stubUpgrader{currentConfig: config.DefaultForAzureSEVSNP()},
@ -140,12 +142,19 @@ func TestUpgradeApply(t *testing.T) {
handler := file.NewHandler(afero.NewMemMapFs()) handler := file.NewHandler(afero.NewMemMapFs())
cfg := defaultConfigWithExpectedMeasurements(t, config.Default(), cloudprovider.Azure) cfg := defaultConfigWithExpectedMeasurements(t, config.Default(), cloudprovider.Azure)
if tc.remoteAttestationCfg == nil {
tc.remoteAttestationCfg = fakeAttestationConfigFromCluster(cmd.Context(), t, cloudprovider.Azure)
}
require.NoError(handler.WriteYAML(constants.ConfigFilename, cfg)) require.NoError(handler.WriteYAML(constants.ConfigFilename, cfg))
require.NoError(handler.WriteJSON(constants.ClusterIDsFilename, clusterid.File{})) require.NoError(handler.WriteJSON(constants.ClusterIDsFilename, clusterid.File{}))
upgrader := upgradeApplyCmd{upgrader: tc.upgrader, log: logger.NewTest(t), imageFetcher: tc.fetcher, configFetcher: stubAttestationFetcher{}} upgrader := upgradeApplyCmd{upgrader: tc.upgrader, log: logger.NewTest(t), imageFetcher: tc.fetcher, configFetcher: stubAttestationFetcher{}}
err := upgrader.upgradeApply(cmd, handler) stubStableClientFactory := func(_ string) (getConfigMapper, error) {
return stubGetConfigMap{tc.remoteAttestationCfg}, nil
}
err := upgrader.upgradeApply(cmd, handler, stubStableClientFactory)
if tc.wantErr { if tc.wantErr {
assert.Error(err) assert.Error(err)
} else { } else {
@ -155,6 +164,21 @@ func TestUpgradeApply(t *testing.T) {
} }
} }
type stubGetConfigMap struct {
attestationCfg config.AttestationCfg
}
func (s stubGetConfigMap) GetCurrentConfigMap(_ context.Context, _ string) (*corev1.ConfigMap, error) {
data, err := json.Marshal(s.attestationCfg)
if err != nil {
return nil, err
}
dataMap := map[string]string{
constants.AttestationConfigFilename: string(data),
}
return &corev1.ConfigMap{Data: dataMap}, nil
}
type stubUpgrader struct { type stubUpgrader struct {
currentConfig config.AttestationCfg currentConfig config.AttestationCfg
nodeVersionErr error nodeVersionErr error
@ -222,3 +246,11 @@ func (f stubImageFetcher) FetchReference(_ context.Context,
) (string, error) { ) (string, error) {
return "", f.fetchReferenceErr return "", f.fetchReferenceErr
} }
func fakeAttestationConfigFromCluster(ctx context.Context, t *testing.T, provider cloudprovider.Provider) config.AttestationCfg {
cpCfg := defaultConfigWithExpectedMeasurements(t, config.Default(), provider)
// the cluster attestation config needs to have real version numbers that are translated from "latest" as defined in config.Default()
err := cpCfg.Attestation.AzureSEVSNP.FetchAndSetLatestVersionNumbers(ctx, stubAttestationFetcher{}, time.Date(2022, time.January, 1, 0, 0, 0, 0, time.UTC))
require.NoError(t, err)
return cpCfg.GetAttestationConfig()
}

View file

@ -1,6 +1,7 @@
apiVersion: v1 apiVersion: v1
kind: Secret kind: Secret
type: Opaque type: Opaque
immutable: true
metadata: metadata:
name: {{ .Values.masterSecretName | quote }} name: {{ .Values.masterSecretName | quote }}
namespace: {{ .Release.Namespace }} namespace: {{ .Release.Namespace }}

View file

@ -1,6 +1,7 @@
apiVersion: v1 apiVersion: v1
kind: Secret kind: Secret
type: Opaque type: Opaque
immutable: true
metadata: metadata:
name: constellation-mastersecret name: constellation-mastersecret
namespace: testNamespace namespace: testNamespace

View file

@ -1,6 +1,7 @@
apiVersion: v1 apiVersion: v1
kind: Secret kind: Secret
type: Opaque type: Opaque
immutable: true
metadata: metadata:
name: constellation-mastersecret name: constellation-mastersecret
namespace: testNamespace namespace: testNamespace

View file

@ -1,6 +1,7 @@
apiVersion: v1 apiVersion: v1
kind: Secret kind: Secret
type: Opaque type: Opaque
immutable: true
metadata: metadata:
name: constellation-mastersecret name: constellation-mastersecret
namespace: testNamespace namespace: testNamespace

View file

@ -1,6 +1,7 @@
apiVersion: v1 apiVersion: v1
kind: Secret kind: Secret
type: Opaque type: Opaque
immutable: true
metadata: metadata:
name: constellation-mastersecret name: constellation-mastersecret
namespace: testNamespace namespace: testNamespace

View file

@ -1,6 +1,7 @@
apiVersion: v1 apiVersion: v1
kind: Secret kind: Secret
type: Opaque type: Opaque
immutable: true
metadata: metadata:
name: constellation-mastersecret name: constellation-mastersecret
namespace: testNamespace namespace: testNamespace

View file

@ -10,3 +10,72 @@ Package kubernetes provides functions to interact with a live cluster to the CLI
Currently it is used to implement the status and upgrade commands. Currently it is used to implement the status and upgrade commands.
*/ */
package kubernetes package kubernetes
import (
"context"
"fmt"
"github.com/edgelesssys/constellation/v2/internal/constants"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
)
func newClient(kubeconfigPath string) (kubernetes.Interface, error) {
kubeConfig, err := clientcmd.BuildConfigFromFlags("", kubeconfigPath)
if err != nil {
return nil, fmt.Errorf("building kubernetes config: %w", err)
}
kubeClient, err := kubernetes.NewForConfig(kubeConfig)
if err != nil {
return nil, fmt.Errorf("setting up kubernetes client: %w", err)
}
return kubeClient, nil
}
// StableInterface is an interface to interact with stable resources.
type StableInterface interface {
GetCurrentConfigMap(ctx context.Context, name string) (*corev1.ConfigMap, error)
UpdateConfigMap(ctx context.Context, configMap *corev1.ConfigMap) (*corev1.ConfigMap, error)
CreateConfigMap(ctx context.Context, configMap *corev1.ConfigMap) (*corev1.ConfigMap, error)
KubernetesVersion() (string, error)
}
// NewStableClient returns a new StableClient.
func NewStableClient(kubeconfigPath string) (StableInterface, error) {
client, err := newClient(kubeconfigPath)
if err != nil {
return nil, err
}
return &stableClient{client}, nil
}
type stableClient struct {
client kubernetes.Interface
}
// GetCurrentConfigMap returns a ConfigMap given it's name.
func (u *stableClient) GetCurrentConfigMap(ctx context.Context, name string) (*corev1.ConfigMap, error) {
return u.client.CoreV1().ConfigMaps(constants.ConstellationNamespace).Get(ctx, name, metav1.GetOptions{})
}
// UpdateConfigMap updates the given ConfigMap.
func (u *stableClient) UpdateConfigMap(ctx context.Context, configMap *corev1.ConfigMap) (*corev1.ConfigMap, error) {
return u.client.CoreV1().ConfigMaps(constants.ConstellationNamespace).Update(ctx, configMap, metav1.UpdateOptions{})
}
// CreateConfigMap creates the given ConfigMap.
func (u *stableClient) CreateConfigMap(ctx context.Context, configMap *corev1.ConfigMap) (*corev1.ConfigMap, error) {
return u.client.CoreV1().ConfigMaps(constants.ConstellationNamespace).Create(ctx, configMap, metav1.CreateOptions{})
}
// KubernetesVersion returns the Kubernetes version of the cluster.
func (u *stableClient) KubernetesVersion() (string, error) {
serverVersion, err := u.client.Discovery().ServerVersion()
if err != nil {
return "", err
}
return serverVersion.GitVersion, nil
}

View file

@ -42,7 +42,6 @@ import (
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/dynamic" "k8s.io/client-go/dynamic"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/util/retry" "k8s.io/client-go/util/retry"
kubeadmv1beta3 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3" kubeadmv1beta3 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
@ -121,18 +120,17 @@ func NewUpgrader(
upgradeID: upgradeID, upgradeID: upgradeID,
} }
kubeConfig, err := clientcmd.BuildConfigFromFlags("", kubeConfigPath) kubeClient, err := newClient(kubeConfigPath)
if err != nil { if err != nil {
return nil, fmt.Errorf("building kubernetes config: %w", err) return nil, err
}
kubeClient, err := kubernetes.NewForConfig(kubeConfig)
if err != nil {
return nil, fmt.Errorf("setting up kubernetes client: %w", err)
} }
u.stableInterface = &stableClient{client: kubeClient} u.stableInterface = &stableClient{client: kubeClient}
// use unstructured client to avoid importing the operator packages // use unstructured client to avoid importing the operator packages
kubeConfig, err := clientcmd.BuildConfigFromFlags("", kubeConfigPath)
if err != nil {
return nil, fmt.Errorf("building kubernetes config: %w", err)
}
unstructuredClient, err := dynamic.NewForConfig(kubeConfig) unstructuredClient, err := dynamic.NewForConfig(kubeConfig)
if err != nil { if err != nil {
return nil, fmt.Errorf("setting up custom resource client: %w", err) return nil, fmt.Errorf("setting up custom resource client: %w", err)
@ -554,47 +552,6 @@ func upgradeInProgress(nodeVersion updatev1alpha1.NodeVersion) bool {
return false return false
} }
// StableInterface is an interface to interact with stable resources.
type StableInterface interface {
GetCurrentConfigMap(ctx context.Context, name string) (*corev1.ConfigMap, error)
UpdateConfigMap(ctx context.Context, configMap *corev1.ConfigMap) (*corev1.ConfigMap, error)
CreateConfigMap(ctx context.Context, configMap *corev1.ConfigMap) (*corev1.ConfigMap, error)
KubernetesVersion() (string, error)
}
// NewStableClient returns a new StableInterface.
func NewStableClient(client kubernetes.Interface) StableInterface {
return &stableClient{client: client}
}
type stableClient struct {
client kubernetes.Interface
}
// GetCurrentConfigMap returns a ConfigMap given it's name.
func (u *stableClient) GetCurrentConfigMap(ctx context.Context, name string) (*corev1.ConfigMap, error) {
return u.client.CoreV1().ConfigMaps(constants.ConstellationNamespace).Get(ctx, name, metav1.GetOptions{})
}
// UpdateConfigMap updates the given ConfigMap.
func (u *stableClient) UpdateConfigMap(ctx context.Context, configMap *corev1.ConfigMap) (*corev1.ConfigMap, error) {
return u.client.CoreV1().ConfigMaps(constants.ConstellationNamespace).Update(ctx, configMap, metav1.UpdateOptions{})
}
// CreateConfigMap creates the given ConfigMap.
func (u *stableClient) CreateConfigMap(ctx context.Context, configMap *corev1.ConfigMap) (*corev1.ConfigMap, error) {
return u.client.CoreV1().ConfigMaps(constants.ConstellationNamespace).Create(ctx, configMap, metav1.CreateOptions{})
}
// KubernetesVersion returns the Kubernetes version of the cluster.
func (u *stableClient) KubernetesVersion() (string, error) {
serverVersion, err := u.client.Discovery().ServerVersion()
if err != nil {
return "", err
}
return serverVersion.GitVersion, nil
}
type helmInterface interface { type helmInterface interface {
Upgrade(ctx context.Context, config *config.Config, idFile clusterid.File, timeout time.Duration, allowDestructive, force bool, upgradeID string) error Upgrade(ctx context.Context, config *config.Config, idFile clusterid.File, timeout time.Duration, allowDestructive, force bool, upgradeID string) error
} }

View file

@ -38,7 +38,7 @@ import (
func TestUpgradeNodeVersion(t *testing.T) { func TestUpgradeNodeVersion(t *testing.T) {
someErr := errors.New("some error") someErr := errors.New("some error")
testCases := map[string]struct { testCases := map[string]struct {
stable *stubStableClient stable *fakeStableClient
conditions []metav1.Condition conditions []metav1.Condition
currentImageVersion string currentImageVersion string
newImageReference string newImageReference string
@ -61,7 +61,7 @@ func TestUpgradeNodeVersion(t *testing.T) {
}(), }(),
currentImageVersion: "v1.2.2", currentImageVersion: "v1.2.2",
currentClusterVersion: versions.SupportedK8sVersions()[0], currentClusterVersion: versions.SupportedK8sVersions()[0],
stable: &stubStableClient{ stable: &fakeStableClient{
configMaps: map[string]*corev1.ConfigMap{ configMaps: map[string]*corev1.ConfigMap{
constants.JoinConfigMap: newJoinConfigMap(`{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":false}}`), constants.JoinConfigMap: newJoinConfigMap(`{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":false}}`),
}, },
@ -77,7 +77,7 @@ func TestUpgradeNodeVersion(t *testing.T) {
}(), }(),
currentImageVersion: "v1.2.2", currentImageVersion: "v1.2.2",
currentClusterVersion: versions.SupportedK8sVersions()[0], currentClusterVersion: versions.SupportedK8sVersions()[0],
stable: &stubStableClient{ stable: &fakeStableClient{
configMaps: map[string]*corev1.ConfigMap{ configMaps: map[string]*corev1.ConfigMap{
constants.JoinConfigMap: newJoinConfigMap(`{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":false}}`), constants.JoinConfigMap: newJoinConfigMap(`{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":false}}`),
}, },
@ -98,7 +98,7 @@ func TestUpgradeNodeVersion(t *testing.T) {
}(), }(),
currentImageVersion: "v1.2.2", currentImageVersion: "v1.2.2",
currentClusterVersion: versions.SupportedK8sVersions()[0], currentClusterVersion: versions.SupportedK8sVersions()[0],
stable: &stubStableClient{ stable: &fakeStableClient{
configMaps: map[string]*corev1.ConfigMap{ configMaps: map[string]*corev1.ConfigMap{
constants.JoinConfigMap: newJoinConfigMap(`{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":false}}`), constants.JoinConfigMap: newJoinConfigMap(`{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":false}}`),
}, },
@ -119,7 +119,7 @@ func TestUpgradeNodeVersion(t *testing.T) {
}(), }(),
currentImageVersion: "v1.2.2", currentImageVersion: "v1.2.2",
currentClusterVersion: versions.SupportedK8sVersions()[0], currentClusterVersion: versions.SupportedK8sVersions()[0],
stable: &stubStableClient{}, stable: &fakeStableClient{},
wantErr: true, wantErr: true,
assertCorrectError: func(t *testing.T, err error) bool { assertCorrectError: func(t *testing.T, err error) bool {
var upgradeErr *compatibility.InvalidUpgradeError var upgradeErr *compatibility.InvalidUpgradeError
@ -139,7 +139,7 @@ func TestUpgradeNodeVersion(t *testing.T) {
}}, }},
currentImageVersion: "v1.2.2", currentImageVersion: "v1.2.2",
currentClusterVersion: versions.SupportedK8sVersions()[0], currentClusterVersion: versions.SupportedK8sVersions()[0],
stable: &stubStableClient{}, stable: &fakeStableClient{},
wantErr: true, wantErr: true,
assertCorrectError: func(t *testing.T, err error) bool { assertCorrectError: func(t *testing.T, err error) bool {
return assert.ErrorIs(t, err, ErrInProgress) return assert.ErrorIs(t, err, ErrInProgress)
@ -158,7 +158,7 @@ func TestUpgradeNodeVersion(t *testing.T) {
}}, }},
currentImageVersion: "v1.2.2", currentImageVersion: "v1.2.2",
currentClusterVersion: versions.SupportedK8sVersions()[0], currentClusterVersion: versions.SupportedK8sVersions()[0],
stable: &stubStableClient{}, stable: &fakeStableClient{},
force: true, force: true,
wantUpdate: true, wantUpdate: true,
}, },
@ -184,7 +184,7 @@ func TestUpgradeNodeVersion(t *testing.T) {
newImageReference: "path/to/image:v1.4.2", newImageReference: "path/to/image:v1.4.2",
currentImageVersion: "v1.2.2", currentImageVersion: "v1.2.2",
currentClusterVersion: versions.SupportedK8sVersions()[0], currentClusterVersion: versions.SupportedK8sVersions()[0],
stable: &stubStableClient{ stable: &fakeStableClient{
configMaps: map[string]*corev1.ConfigMap{ configMaps: map[string]*corev1.ConfigMap{
constants.JoinConfigMap: newJoinConfigMap(`{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":false}}`), constants.JoinConfigMap: newJoinConfigMap(`{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":false}}`),
}, },
@ -206,7 +206,7 @@ func TestUpgradeNodeVersion(t *testing.T) {
newImageReference: "path/to/image:v1.4.2", newImageReference: "path/to/image:v1.4.2",
currentImageVersion: "v1.2.2", currentImageVersion: "v1.2.2",
currentClusterVersion: versions.SupportedK8sVersions()[0], currentClusterVersion: versions.SupportedK8sVersions()[0],
stable: &stubStableClient{ stable: &fakeStableClient{
configMaps: map[string]*corev1.ConfigMap{ configMaps: map[string]*corev1.ConfigMap{
constants.JoinConfigMap: newJoinConfigMap(`{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":false}}`), constants.JoinConfigMap: newJoinConfigMap(`{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":false}}`),
}, },
@ -224,7 +224,7 @@ func TestUpgradeNodeVersion(t *testing.T) {
currentImageVersion: "v1.2.2", currentImageVersion: "v1.2.2",
currentClusterVersion: versions.SupportedK8sVersions()[0], currentClusterVersion: versions.SupportedK8sVersions()[0],
badImageVersion: "v3.2.1", badImageVersion: "v3.2.1",
stable: &stubStableClient{ stable: &fakeStableClient{
configMaps: map[string]*corev1.ConfigMap{ configMaps: map[string]*corev1.ConfigMap{
constants.JoinConfigMap: newJoinConfigMap(`{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":false}}`), constants.JoinConfigMap: newJoinConfigMap(`{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":false}}`),
}, },
@ -245,7 +245,7 @@ func TestUpgradeNodeVersion(t *testing.T) {
}(), }(),
currentImageVersion: "v1.2.2", currentImageVersion: "v1.2.2",
currentClusterVersion: versions.SupportedK8sVersions()[0], currentClusterVersion: versions.SupportedK8sVersions()[0],
stable: &stubStableClient{ stable: &fakeStableClient{
configMaps: map[string]*corev1.ConfigMap{ configMaps: map[string]*corev1.ConfigMap{
constants.JoinConfigMap: newJoinConfigMap(`{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":false}}`), constants.JoinConfigMap: newJoinConfigMap(`{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":false}}`),
}, },
@ -266,7 +266,7 @@ func TestUpgradeNodeVersion(t *testing.T) {
}(), }(),
currentImageVersion: "v1.2.2", currentImageVersion: "v1.2.2",
currentClusterVersion: versions.SupportedK8sVersions()[0], currentClusterVersion: versions.SupportedK8sVersions()[0],
stable: &stubStableClient{ stable: &fakeStableClient{
configMaps: map[string]*corev1.ConfigMap{ configMaps: map[string]*corev1.ConfigMap{
constants.JoinConfigMap: newJoinConfigMap(`{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":false}}`), constants.JoinConfigMap: newJoinConfigMap(`{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":false}}`),
}, },
@ -340,13 +340,13 @@ func TestUpgradeNodeVersion(t *testing.T) {
func TestUpdateMeasurements(t *testing.T) { func TestUpdateMeasurements(t *testing.T) {
someErr := errors.New("error") someErr := errors.New("error")
testCases := map[string]struct { testCases := map[string]struct {
updater *stubStableClient updater *fakeStableClient
newConfig config.AttestationCfg newConfig config.AttestationCfg
wantUpdate bool wantUpdate bool
wantErr bool wantErr bool
}{ }{
"success": { "success": {
updater: &stubStableClient{ updater: &fakeStableClient{
configMaps: map[string]*corev1.ConfigMap{ configMaps: map[string]*corev1.ConfigMap{
constants.JoinConfigMap: newJoinConfigMap(`{"measurements":{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":false}}}`), constants.JoinConfigMap: newJoinConfigMap(`{"measurements":{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":false}}}`),
}, },
@ -359,7 +359,7 @@ func TestUpdateMeasurements(t *testing.T) {
wantUpdate: true, wantUpdate: true,
}, },
"measurements are the same": { "measurements are the same": {
updater: &stubStableClient{ updater: &fakeStableClient{
configMaps: map[string]*corev1.ConfigMap{ configMaps: map[string]*corev1.ConfigMap{
constants.JoinConfigMap: newJoinConfigMap(`{"measurements":{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":false}}}`), constants.JoinConfigMap: newJoinConfigMap(`{"measurements":{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":false}}}`),
}, },
@ -371,7 +371,7 @@ func TestUpdateMeasurements(t *testing.T) {
}, },
}, },
"setting warnOnly to true is allowed": { "setting warnOnly to true is allowed": {
updater: &stubStableClient{ updater: &fakeStableClient{
configMaps: map[string]*corev1.ConfigMap{ configMaps: map[string]*corev1.ConfigMap{
constants.JoinConfigMap: newJoinConfigMap(`{"measurements":{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":false}}}`), constants.JoinConfigMap: newJoinConfigMap(`{"measurements":{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":false}}}`),
}, },
@ -384,7 +384,7 @@ func TestUpdateMeasurements(t *testing.T) {
wantUpdate: true, wantUpdate: true,
}, },
"setting warnOnly to false is allowed": { "setting warnOnly to false is allowed": {
updater: &stubStableClient{ updater: &fakeStableClient{
configMaps: map[string]*corev1.ConfigMap{ configMaps: map[string]*corev1.ConfigMap{
constants.JoinConfigMap: newJoinConfigMap(`{"measurements":{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":true}}}`), constants.JoinConfigMap: newJoinConfigMap(`{"measurements":{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":true}}}`),
}, },
@ -397,7 +397,7 @@ func TestUpdateMeasurements(t *testing.T) {
wantUpdate: true, wantUpdate: true,
}, },
"getCurrent error": { "getCurrent error": {
updater: &stubStableClient{getErr: someErr}, updater: &fakeStableClient{getErr: someErr},
newConfig: &config.GCPSEVES{ newConfig: &config.GCPSEVES{
Measurements: measurements.M{ Measurements: measurements.M{
0: measurements.WithAllBytes(0xBB, measurements.Enforce, measurements.PCRMeasurementLength), 0: measurements.WithAllBytes(0xBB, measurements.Enforce, measurements.PCRMeasurementLength),
@ -406,7 +406,7 @@ func TestUpdateMeasurements(t *testing.T) {
wantErr: true, wantErr: true,
}, },
"update error": { "update error": {
updater: &stubStableClient{ updater: &fakeStableClient{
configMaps: map[string]*corev1.ConfigMap{ configMaps: map[string]*corev1.ConfigMap{
constants.JoinConfigMap: newJoinConfigMap(`{"measurements":{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":false}}}`), constants.JoinConfigMap: newJoinConfigMap(`{"measurements":{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":false}}}`),
}, },
@ -616,7 +616,7 @@ func (u *stubDynamicClient) Update(_ context.Context, updatedObject *unstructure
return u.updatedObject, u.updateErr return u.updatedObject, u.updateErr
} }
type stubStableClient struct { type fakeStableClient struct {
configMaps map[string]*corev1.ConfigMap configMaps map[string]*corev1.ConfigMap
updatedConfigMaps map[string]*corev1.ConfigMap updatedConfigMaps map[string]*corev1.ConfigMap
k8sVersion string k8sVersion string
@ -626,11 +626,11 @@ type stubStableClient struct {
k8sErr error k8sErr error
} }
func (s *stubStableClient) GetCurrentConfigMap(_ context.Context, name string) (*corev1.ConfigMap, error) { func (s *fakeStableClient) GetCurrentConfigMap(_ context.Context, name string) (*corev1.ConfigMap, error) {
return s.configMaps[name], s.getErr return s.configMaps[name], s.getErr
} }
func (s *stubStableClient) UpdateConfigMap(_ context.Context, configMap *corev1.ConfigMap) (*corev1.ConfigMap, error) { func (s *fakeStableClient) UpdateConfigMap(_ context.Context, configMap *corev1.ConfigMap) (*corev1.ConfigMap, error) {
if s.updatedConfigMaps == nil { if s.updatedConfigMaps == nil {
s.updatedConfigMaps = map[string]*corev1.ConfigMap{} s.updatedConfigMaps = map[string]*corev1.ConfigMap{}
} }
@ -638,7 +638,7 @@ func (s *stubStableClient) UpdateConfigMap(_ context.Context, configMap *corev1.
return s.updatedConfigMaps[configMap.ObjectMeta.Name], s.updateErr return s.updatedConfigMaps[configMap.ObjectMeta.Name], s.updateErr
} }
func (s *stubStableClient) CreateConfigMap(_ context.Context, configMap *corev1.ConfigMap) (*corev1.ConfigMap, error) { func (s *fakeStableClient) CreateConfigMap(_ context.Context, configMap *corev1.ConfigMap) (*corev1.ConfigMap, error) {
if s.configMaps == nil { if s.configMaps == nil {
s.configMaps = map[string]*corev1.ConfigMap{} s.configMaps = map[string]*corev1.ConfigMap{}
} }
@ -646,7 +646,7 @@ func (s *stubStableClient) CreateConfigMap(_ context.Context, configMap *corev1.
return s.configMaps[configMap.ObjectMeta.Name], s.createErr return s.configMaps[configMap.ObjectMeta.Name], s.createErr
} }
func (s *stubStableClient) KubernetesVersion() (string, error) { func (s *fakeStableClient) KubernetesVersion() (string, error) {
return s.k8sVersion, s.k8sErr return s.k8sVersion, s.k8sErr
} }

1
go.mod
View file

@ -92,6 +92,7 @@ require (
github.com/mattn/go-isatty v0.0.19 github.com/mattn/go-isatty v0.0.19
github.com/microsoft/ApplicationInsights-Go v0.4.4 github.com/microsoft/ApplicationInsights-Go v0.4.4
github.com/pkg/errors v0.9.1 github.com/pkg/errors v0.9.1
github.com/rogpeppe/go-internal v1.11.0
github.com/schollz/progressbar/v3 v3.13.1 github.com/schollz/progressbar/v3 v3.13.1
github.com/siderolabs/talos/pkg/machinery v1.4.6 github.com/siderolabs/talos/pkg/machinery v1.4.6
github.com/sigstore/rekor v1.2.2 github.com/sigstore/rekor v1.2.2

3
go.sum
View file

@ -916,7 +916,8 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/rubenv/sql-migrate v1.3.1 h1:Vx+n4Du8X8VTYuXbhNxdEUoh6wiJERA0GlWocR5FrbA= github.com/rubenv/sql-migrate v1.3.1 h1:Vx+n4Du8X8VTYuXbhNxdEUoh6wiJERA0GlWocR5FrbA=
github.com/rubenv/sql-migrate v1.3.1/go.mod h1:YzG/Vh82CwyhTFXy+Mf5ahAiiEOpAlHurg+23VEzcsk= github.com/rubenv/sql-migrate v1.3.1/go.mod h1:YzG/Vh82CwyhTFXy+Mf5ahAiiEOpAlHurg+23VEzcsk=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=

View file

@ -248,6 +248,7 @@ require (
github.com/prometheus/common v0.42.0 // indirect github.com/prometheus/common v0.42.0 // indirect
github.com/prometheus/procfs v0.10.1 // indirect github.com/prometheus/procfs v0.10.1 // indirect
github.com/rivo/uniseg v0.4.4 // indirect github.com/rivo/uniseg v0.4.4 // indirect
github.com/rogpeppe/go-internal v1.11.0 // indirect
github.com/rubenv/sql-migrate v1.3.1 // indirect github.com/rubenv/sql-migrate v1.3.1 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sassoftware/relic v7.2.1+incompatible // indirect github.com/sassoftware/relic v7.2.1+incompatible // indirect

View file

@ -869,7 +869,8 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/rubenv/sql-migrate v1.3.1 h1:Vx+n4Du8X8VTYuXbhNxdEUoh6wiJERA0GlWocR5FrbA= github.com/rubenv/sql-migrate v1.3.1 h1:Vx+n4Du8X8VTYuXbhNxdEUoh6wiJERA0GlWocR5FrbA=
github.com/rubenv/sql-migrate v1.3.1/go.mod h1:YzG/Vh82CwyhTFXy+Mf5ahAiiEOpAlHurg+23VEzcsk= github.com/rubenv/sql-migrate v1.3.1/go.mod h1:YzG/Vh82CwyhTFXy+Mf5ahAiiEOpAlHurg+23VEzcsk=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=

View file

@ -297,7 +297,7 @@ github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+Pymzi
github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM=
github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=