c6c2c525a6
Also fix some tests that were broken by bumping golang and dependencies in the previous commits. Note that in addition to changes made to satisfy the linter which do not impact the behavior of the code, this commit also adds ReadHeaderTimeout to all usages of http.Server to satisfy the linter (and because it seemed like a good suggestion).
87 lines
3.2 KiB
Go
87 lines
3.2 KiB
Go
// Copyright 2021-2022 the Pinniped contributors. All Rights Reserved.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
// Package issuerconfig contains helpers for updating CredentialIssuer status entries.
|
|
package issuerconfig
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"sort"
|
|
|
|
apiequality "k8s.io/apimachinery/pkg/api/equality"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
|
|
"go.pinniped.dev/generated/latest/apis/concierge/config/v1alpha1"
|
|
"go.pinniped.dev/generated/latest/client/concierge/clientset/versioned"
|
|
)
|
|
|
|
// Update a strategy on an existing CredentialIssuer, merging into any existing strategy entries.
|
|
func Update(ctx context.Context, client versioned.Interface, issuer *v1alpha1.CredentialIssuer, strategy v1alpha1.CredentialIssuerStrategy) error {
|
|
// Update the existing object to merge in the new strategy.
|
|
updated := issuer.DeepCopy()
|
|
mergeStrategy(&updated.Status, strategy)
|
|
|
|
// If the status has not changed, we're done.
|
|
if apiequality.Semantic.DeepEqual(issuer.Status, updated.Status) {
|
|
return nil
|
|
}
|
|
|
|
if _, err := client.ConfigV1alpha1().CredentialIssuers().UpdateStatus(ctx, updated, metav1.UpdateOptions{}); err != nil {
|
|
return fmt.Errorf("failed to update CredentialIssuer status: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func mergeStrategy(configToUpdate *v1alpha1.CredentialIssuerStatus, strategy v1alpha1.CredentialIssuerStrategy) {
|
|
var existing *v1alpha1.CredentialIssuerStrategy
|
|
for i := range configToUpdate.Strategies {
|
|
if configToUpdate.Strategies[i].Type == strategy.Type {
|
|
existing = &configToUpdate.Strategies[i]
|
|
break
|
|
}
|
|
}
|
|
if existing != nil {
|
|
if !equalExceptLastUpdated(existing, &strategy) {
|
|
strategy.DeepCopyInto(existing)
|
|
}
|
|
} else {
|
|
configToUpdate.Strategies = append(configToUpdate.Strategies, strategy)
|
|
}
|
|
sort.Stable(sortableStrategies(configToUpdate.Strategies))
|
|
|
|
// Special case: the "TokenCredentialRequestAPI" data is mirrored into the deprecated status.kubeConfigInfo field.
|
|
if strategy.Frontend != nil && strategy.Frontend.Type == v1alpha1.TokenCredentialRequestAPIFrontendType {
|
|
configToUpdate.KubeConfigInfo = &v1alpha1.CredentialIssuerKubeConfigInfo{
|
|
Server: strategy.Frontend.TokenCredentialRequestAPIInfo.Server,
|
|
CertificateAuthorityData: strategy.Frontend.TokenCredentialRequestAPIInfo.CertificateAuthorityData,
|
|
}
|
|
}
|
|
}
|
|
|
|
// weights are a set of priorities for each strategy type.
|
|
var weights = map[v1alpha1.StrategyType]int{ //nolint:gochecknoglobals
|
|
v1alpha1.KubeClusterSigningCertificateStrategyType: 2, // most preferred strategy
|
|
v1alpha1.ImpersonationProxyStrategyType: 1,
|
|
// unknown strategy types will have weight 0 by default
|
|
}
|
|
|
|
type sortableStrategies []v1alpha1.CredentialIssuerStrategy
|
|
|
|
func (s sortableStrategies) Len() int { return len(s) }
|
|
func (s sortableStrategies) Less(i, j int) bool {
|
|
if wi, wj := weights[s[i].Type], weights[s[j].Type]; wi != wj {
|
|
return wi > wj
|
|
}
|
|
return s[i].Type < s[j].Type
|
|
}
|
|
func (s sortableStrategies) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
|
|
|
func equalExceptLastUpdated(s1, s2 *v1alpha1.CredentialIssuerStrategy) bool {
|
|
s1 = s1.DeepCopy()
|
|
s2 = s2.DeepCopy()
|
|
s1.LastUpdateTime = metav1.Time{}
|
|
s2.LastUpdateTime = metav1.Time{}
|
|
return apiequality.Semantic.DeepEqual(s1, s2)
|
|
}
|