Refactor secret resolver implementation, add vault type and modify autoscaling listener controller to search for app config instead of secret
This commit is contained in:
parent
74ed8e6838
commit
379f466d8f
|
|
@ -20,10 +20,13 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
ConfigureUrl string `json:"configure_url"`
|
ConfigureUrl string `json:"configure_url"`
|
||||||
VaultType string `json:"vault_type"`
|
VaultType vault.VaultType `json:"vault_type"`
|
||||||
VaultLookupKey string `json:"vault_lookup_key"`
|
VaultLookupKey string `json:"vault_lookup_key"`
|
||||||
appconfig.AppConfig
|
// AppConfig contains the GitHub App configuration.
|
||||||
|
// It is initially set to nil if VaultType is set.
|
||||||
|
// Otherwise, it is populated with the GitHub App credentials from the GitHub secret.
|
||||||
|
*appconfig.AppConfig
|
||||||
EphemeralRunnerSetNamespace string `json:"ephemeral_runner_set_namespace"`
|
EphemeralRunnerSetNamespace string `json:"ephemeral_runner_set_namespace"`
|
||||||
EphemeralRunnerSetName string `json:"ephemeral_runner_set_name"`
|
EphemeralRunnerSetName string `json:"ephemeral_runner_set_name"`
|
||||||
MaxRunners int `json:"max_runners"`
|
MaxRunners int `json:"max_runners"`
|
||||||
|
|
@ -82,7 +85,7 @@ func Read(ctx context.Context, configPath string) (*Config, error) {
|
||||||
return nil, fmt.Errorf("failed to read app config from string: %v", err)
|
return nil, fmt.Errorf("failed to read app config from string: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
config.AppConfig = *appConfig
|
config.AppConfig = appConfig
|
||||||
|
|
||||||
if err := config.Validate(); err != nil {
|
if err := config.Validate(); err != nil {
|
||||||
return nil, fmt.Errorf("config validation failed: %w", err)
|
return nil, fmt.Errorf("config validation failed: %w", err)
|
||||||
|
|
@ -109,8 +112,14 @@ func (c *Config) Validate() error {
|
||||||
return fmt.Errorf(`MinRunners "%d" cannot be greater than MaxRunners "%d"`, c.MinRunners, c.MaxRunners)
|
return fmt.Errorf(`MinRunners "%d" cannot be greater than MaxRunners "%d"`, c.MinRunners, c.MaxRunners)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := c.AppConfig.Validate(); err != nil {
|
if c.VaultType != "" && c.VaultLookupKey == "" {
|
||||||
return fmt.Errorf("AppConfig validation failed: %w", err)
|
return fmt.Errorf("VaultLookupKey is required when VaultType is set to %q", c.VaultType)
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.VaultType != "" && c.VaultLookupKey == "" {
|
||||||
|
if err := c.AppConfig.Validate(); err != nil {
|
||||||
|
return fmt.Errorf("AppConfig validation failed: %w", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ func TestCustomerServerRootCA(t *testing.T) {
|
||||||
config := config.Config{
|
config := config.Config{
|
||||||
ConfigureUrl: server.ConfigURLForOrg("myorg"),
|
ConfigureUrl: server.ConfigURLForOrg("myorg"),
|
||||||
ServerRootCA: certsString,
|
ServerRootCA: certsString,
|
||||||
AppConfig: appconfig.AppConfig{
|
AppConfig: &appconfig.AppConfig{
|
||||||
Token: "token",
|
Token: "token",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -83,7 +83,7 @@ func TestProxySettings(t *testing.T) {
|
||||||
|
|
||||||
config := config.Config{
|
config := config.Config{
|
||||||
ConfigureUrl: "https://github.com/org/repo",
|
ConfigureUrl: "https://github.com/org/repo",
|
||||||
AppConfig: appconfig.AppConfig{
|
AppConfig: &appconfig.AppConfig{
|
||||||
Token: "token",
|
Token: "token",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -115,7 +115,7 @@ func TestProxySettings(t *testing.T) {
|
||||||
|
|
||||||
config := config.Config{
|
config := config.Config{
|
||||||
ConfigureUrl: "https://github.com/org/repo",
|
ConfigureUrl: "https://github.com/org/repo",
|
||||||
AppConfig: appconfig.AppConfig{
|
AppConfig: &appconfig.AppConfig{
|
||||||
Token: "token",
|
Token: "token",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -152,7 +152,7 @@ func TestProxySettings(t *testing.T) {
|
||||||
|
|
||||||
config := config.Config{
|
config := config.Config{
|
||||||
ConfigureUrl: "https://github.com/org/repo",
|
ConfigureUrl: "https://github.com/org/repo",
|
||||||
AppConfig: appconfig.AppConfig{
|
AppConfig: &appconfig.AppConfig{
|
||||||
Token: "token",
|
Token: "token",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/actions/actions-runner-controller/apis/actions.github.com/v1alpha1/appconfig"
|
"github.com/actions/actions-runner-controller/apis/actions.github.com/v1alpha1/appconfig"
|
||||||
|
"github.com/actions/actions-runner-controller/vault"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -16,7 +17,7 @@ func TestConfigValidationMinMax(t *testing.T) {
|
||||||
RunnerScaleSetId: 1,
|
RunnerScaleSetId: 1,
|
||||||
MinRunners: 5,
|
MinRunners: 5,
|
||||||
MaxRunners: 2,
|
MaxRunners: 2,
|
||||||
AppConfig: appconfig.AppConfig{
|
AppConfig: &appconfig.AppConfig{
|
||||||
Token: "token",
|
Token: "token",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -42,7 +43,7 @@ func TestConfigValidationAppKey(t *testing.T) {
|
||||||
t.Run("app id integer", func(t *testing.T) {
|
t.Run("app id integer", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
config := &Config{
|
config := &Config{
|
||||||
AppConfig: appconfig.AppConfig{
|
AppConfig: &appconfig.AppConfig{
|
||||||
AppID: "1",
|
AppID: "1",
|
||||||
AppInstallationID: 10,
|
AppInstallationID: 10,
|
||||||
},
|
},
|
||||||
|
|
@ -59,7 +60,7 @@ func TestConfigValidationAppKey(t *testing.T) {
|
||||||
t.Run("app id as client id", func(t *testing.T) {
|
t.Run("app id as client id", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
config := &Config{
|
config := &Config{
|
||||||
AppConfig: appconfig.AppConfig{
|
AppConfig: &appconfig.AppConfig{
|
||||||
AppID: "Iv23f8doAlphaNumer1c",
|
AppID: "Iv23f8doAlphaNumer1c",
|
||||||
AppInstallationID: 10,
|
AppInstallationID: 10,
|
||||||
},
|
},
|
||||||
|
|
@ -76,7 +77,7 @@ func TestConfigValidationAppKey(t *testing.T) {
|
||||||
|
|
||||||
func TestConfigValidationOnlyOneTypeOfCredentials(t *testing.T) {
|
func TestConfigValidationOnlyOneTypeOfCredentials(t *testing.T) {
|
||||||
config := &Config{
|
config := &Config{
|
||||||
AppConfig: appconfig.AppConfig{
|
AppConfig: &appconfig.AppConfig{
|
||||||
AppID: "1",
|
AppID: "1",
|
||||||
AppInstallationID: 10,
|
AppInstallationID: 10,
|
||||||
AppPrivateKey: "asdf",
|
AppPrivateKey: "asdf",
|
||||||
|
|
@ -100,7 +101,7 @@ func TestConfigValidation(t *testing.T) {
|
||||||
RunnerScaleSetId: 1,
|
RunnerScaleSetId: 1,
|
||||||
MinRunners: 1,
|
MinRunners: 1,
|
||||||
MaxRunners: 5,
|
MaxRunners: 5,
|
||||||
AppConfig: appconfig.AppConfig{
|
AppConfig: &appconfig.AppConfig{
|
||||||
Token: "asdf",
|
Token: "asdf",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -121,3 +122,50 @@ func TestConfigValidationConfigUrl(t *testing.T) {
|
||||||
|
|
||||||
assert.ErrorContains(t, err, "GitHubConfigUrl is not provided", "Expected error about missing ConfigureUrl")
|
assert.ErrorContains(t, err, "GitHubConfigUrl is not provided", "Expected error about missing ConfigureUrl")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestConfigValidationWithVaultConfig(t *testing.T) {
|
||||||
|
t.Run("valid", func(t *testing.T) {
|
||||||
|
config := &Config{
|
||||||
|
ConfigureUrl: "https://github.com/actions",
|
||||||
|
EphemeralRunnerSetNamespace: "namespace",
|
||||||
|
EphemeralRunnerSetName: "deployment",
|
||||||
|
RunnerScaleSetId: 1,
|
||||||
|
MinRunners: 1,
|
||||||
|
MaxRunners: 5,
|
||||||
|
VaultType: vault.VaultTypeAzureKeyVault,
|
||||||
|
VaultLookupKey: "testkey",
|
||||||
|
}
|
||||||
|
err := config.Validate()
|
||||||
|
assert.NoError(t, err, "Expected no error for valid vault type")
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("invalid vault type", func(t *testing.T) {
|
||||||
|
config := &Config{
|
||||||
|
ConfigureUrl: "https://github.com/actions",
|
||||||
|
EphemeralRunnerSetNamespace: "namespace",
|
||||||
|
EphemeralRunnerSetName: "deployment",
|
||||||
|
RunnerScaleSetId: 1,
|
||||||
|
MinRunners: 1,
|
||||||
|
MaxRunners: 5,
|
||||||
|
VaultType: vault.VaultType("invalid_vault_type"),
|
||||||
|
VaultLookupKey: "testkey",
|
||||||
|
}
|
||||||
|
err := config.Validate()
|
||||||
|
assert.ErrorContains(t, err, `unknown vault type: "invalid_vault_type"`, "Expected error for invalid vault type")
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("vault type set without lookup key", func(t *testing.T) {
|
||||||
|
config := &Config{
|
||||||
|
ConfigureUrl: "https://github.com/actions",
|
||||||
|
EphemeralRunnerSetNamespace: "namespace",
|
||||||
|
EphemeralRunnerSetName: "deployment",
|
||||||
|
RunnerScaleSetId: 1,
|
||||||
|
MinRunners: 1,
|
||||||
|
MaxRunners: 5,
|
||||||
|
VaultType: vault.VaultTypeAzureKeyVault,
|
||||||
|
VaultLookupKey: "",
|
||||||
|
}
|
||||||
|
err := config.Validate()
|
||||||
|
assert.ErrorContains(t, err, `vault type set to "invalid_vault_type", but lookup key is empty`, "Expected error for vault type without lookup key")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -32,6 +32,7 @@ import (
|
||||||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||||
|
|
||||||
v1alpha1 "github.com/actions/actions-runner-controller/apis/actions.github.com/v1alpha1"
|
v1alpha1 "github.com/actions/actions-runner-controller/apis/actions.github.com/v1alpha1"
|
||||||
|
"github.com/actions/actions-runner-controller/apis/actions.github.com/v1alpha1/appconfig"
|
||||||
"github.com/actions/actions-runner-controller/controllers/actions.github.com/metrics"
|
"github.com/actions/actions-runner-controller/controllers/actions.github.com/metrics"
|
||||||
"github.com/actions/actions-runner-controller/github/actions"
|
"github.com/actions/actions-runner-controller/github/actions"
|
||||||
hash "github.com/actions/actions-runner-controller/hash"
|
hash "github.com/actions/actions-runner-controller/hash"
|
||||||
|
|
@ -128,12 +129,16 @@ func (r *AutoscalingListenerReconciler) Reconcile(ctx context.Context, req ctrl.
|
||||||
return ctrl.Result{}, err
|
return ctrl.Result{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the GitHub config secret exists
|
appConfig, err := r.GetAppConfig(ctx, &autoscalingRunnerSet)
|
||||||
secret := new(corev1.Secret)
|
if err != nil {
|
||||||
if err := r.Get(ctx, types.NamespacedName{Namespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace, Name: autoscalingListener.Spec.GitHubConfigSecret}, secret); err != nil {
|
log.Error(
|
||||||
log.Error(err, "Failed to find GitHub config secret.",
|
err,
|
||||||
"namespace", autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
|
"Failed to get app config for AutoscalingRunnerSet.",
|
||||||
"name", autoscalingListener.Spec.GitHubConfigSecret)
|
"namespace",
|
||||||
|
autoscalingRunnerSet.Namespace,
|
||||||
|
"name",
|
||||||
|
autoscalingRunnerSet.GitHubConfigSecret,
|
||||||
|
)
|
||||||
return ctrl.Result{}, err
|
return ctrl.Result{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -218,7 +223,7 @@ func (r *AutoscalingListenerReconciler) Reconcile(ctx context.Context, req ctrl.
|
||||||
|
|
||||||
// Create a listener pod in the controller namespace
|
// Create a listener pod in the controller namespace
|
||||||
log.Info("Creating a listener pod")
|
log.Info("Creating a listener pod")
|
||||||
return r.createListenerPod(ctx, &autoscalingRunnerSet, autoscalingListener, serviceAccount, secret, log)
|
return r.createListenerPod(ctx, &autoscalingRunnerSet, autoscalingListener, serviceAccount, appConfig, log)
|
||||||
}
|
}
|
||||||
|
|
||||||
cs := listenerContainerStatus(listenerPod)
|
cs := listenerContainerStatus(listenerPod)
|
||||||
|
|
@ -377,7 +382,7 @@ func (r *AutoscalingListenerReconciler) createServiceAccountForListener(ctx cont
|
||||||
return ctrl.Result{}, nil
|
return ctrl.Result{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *AutoscalingListenerReconciler) createListenerPod(ctx context.Context, autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, autoscalingListener *v1alpha1.AutoscalingListener, serviceAccount *corev1.ServiceAccount, secret *corev1.Secret, logger logr.Logger) (ctrl.Result, error) {
|
func (r *AutoscalingListenerReconciler) createListenerPod(ctx context.Context, autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, autoscalingListener *v1alpha1.AutoscalingListener, serviceAccount *corev1.ServiceAccount, appConfig *appconfig.AppConfig, logger logr.Logger) (ctrl.Result, error) {
|
||||||
var envs []corev1.EnvVar
|
var envs []corev1.EnvVar
|
||||||
if autoscalingListener.Spec.Proxy != nil {
|
if autoscalingListener.Spec.Proxy != nil {
|
||||||
httpURL := corev1.EnvVar{
|
httpURL := corev1.EnvVar{
|
||||||
|
|
@ -446,7 +451,7 @@ func (r *AutoscalingListenerReconciler) createListenerPod(ctx context.Context, a
|
||||||
|
|
||||||
logger.Info("Creating listener config secret")
|
logger.Info("Creating listener config secret")
|
||||||
|
|
||||||
podConfig, err := r.newScaleSetListenerConfig(autoscalingListener, secret, metricsConfig, cert)
|
podConfig, err := r.newScaleSetListenerConfig(autoscalingListener, appConfig, metricsConfig, cert)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err, "Failed to build listener config secret")
|
logger.Error(err, "Failed to build listener config secret")
|
||||||
return ctrl.Result{}, err
|
return ctrl.Result{}, err
|
||||||
|
|
|
||||||
|
|
@ -394,7 +394,7 @@ func (r *AutoscalingRunnerSetReconciler) removeFinalizersFromDependentResources(
|
||||||
|
|
||||||
func (r *AutoscalingRunnerSetReconciler) createRunnerScaleSet(ctx context.Context, autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, logger logr.Logger) (ctrl.Result, error) {
|
func (r *AutoscalingRunnerSetReconciler) createRunnerScaleSet(ctx context.Context, autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, logger logr.Logger) (ctrl.Result, error) {
|
||||||
logger.Info("Creating a new runner scale set")
|
logger.Info("Creating a new runner scale set")
|
||||||
actionsClient, err := r.ActionsClientPool.Get(ctx, autoscalingRunnerSet)
|
actionsClient, err := r.SecretResolver.GetActionsService(ctx, autoscalingRunnerSet)
|
||||||
if len(autoscalingRunnerSet.Spec.RunnerScaleSetName) == 0 {
|
if len(autoscalingRunnerSet.Spec.RunnerScaleSetName) == 0 {
|
||||||
autoscalingRunnerSet.Spec.RunnerScaleSetName = autoscalingRunnerSet.Name
|
autoscalingRunnerSet.Spec.RunnerScaleSetName = autoscalingRunnerSet.Name
|
||||||
}
|
}
|
||||||
|
|
@ -490,7 +490,7 @@ func (r *AutoscalingRunnerSetReconciler) updateRunnerScaleSetRunnerGroup(ctx con
|
||||||
return ctrl.Result{}, err
|
return ctrl.Result{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
actionsClient, err := r.ActionsClientPool.Get(ctx, autoscalingRunnerSet)
|
actionsClient, err := r.SecretResolver.GetActionsService(ctx, autoscalingRunnerSet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err, "Failed to initialize Actions service client for updating a existing runner scale set")
|
logger.Error(err, "Failed to initialize Actions service client for updating a existing runner scale set")
|
||||||
return ctrl.Result{}, err
|
return ctrl.Result{}, err
|
||||||
|
|
@ -538,7 +538,7 @@ func (r *AutoscalingRunnerSetReconciler) updateRunnerScaleSetName(ctx context.Co
|
||||||
return ctrl.Result{}, nil
|
return ctrl.Result{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
actionsClient, err := r.ActionsClientPool.Get(ctx, autoscalingRunnerSet)
|
actionsClient, err := r.SecretResolver.GetActionsService(ctx, autoscalingRunnerSet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err, "Failed to initialize Actions service client for updating a existing runner scale set")
|
logger.Error(err, "Failed to initialize Actions service client for updating a existing runner scale set")
|
||||||
return ctrl.Result{}, err
|
return ctrl.Result{}, err
|
||||||
|
|
@ -589,7 +589,7 @@ func (r *AutoscalingRunnerSetReconciler) deleteRunnerScaleSet(ctx context.Contex
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
actionsClient, err := r.ActionsClientPool.Get(ctx, autoscalingRunnerSet)
|
actionsClient, err := r.SecretResolver.GetActionsService(ctx, autoscalingRunnerSet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err, "Failed to initialize Actions service client for updating a existing runner scale set")
|
logger.Error(err, "Failed to initialize Actions service client for updating a existing runner scale set")
|
||||||
return err
|
return err
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ var _ = Describe("Test AutoScalingRunnerSet controller", Ordered, func() {
|
||||||
ControllerNamespace: autoscalingNS.Name,
|
ControllerNamespace: autoscalingNS.Name,
|
||||||
DefaultRunnerScaleSetListenerImage: "ghcr.io/actions/arc",
|
DefaultRunnerScaleSetListenerImage: "ghcr.io/actions/arc",
|
||||||
ResourceBuilder: ResourceBuilder{
|
ResourceBuilder: ResourceBuilder{
|
||||||
ActionsClientPool: &ActionsClientPool{
|
SecretResolver: &SecretResolver{
|
||||||
k8sClient: k8sClient,
|
k8sClient: k8sClient,
|
||||||
multiClient: fake.NewMultiClient(),
|
multiClient: fake.NewMultiClient(),
|
||||||
},
|
},
|
||||||
|
|
@ -711,7 +711,7 @@ var _ = Describe("Test AutoScalingController updates", Ordered, func() {
|
||||||
ControllerNamespace: autoscalingNS.Name,
|
ControllerNamespace: autoscalingNS.Name,
|
||||||
DefaultRunnerScaleSetListenerImage: "ghcr.io/actions/arc",
|
DefaultRunnerScaleSetListenerImage: "ghcr.io/actions/arc",
|
||||||
ResourceBuilder: ResourceBuilder{
|
ResourceBuilder: ResourceBuilder{
|
||||||
ActionsClientPool: &ActionsClientPool{
|
SecretResolver: &SecretResolver{
|
||||||
k8sClient: k8sClient,
|
k8sClient: k8sClient,
|
||||||
multiClient: multiClient,
|
multiClient: multiClient,
|
||||||
},
|
},
|
||||||
|
|
@ -831,7 +831,7 @@ var _ = Describe("Test AutoscalingController creation failures", Ordered, func()
|
||||||
ControllerNamespace: autoscalingNS.Name,
|
ControllerNamespace: autoscalingNS.Name,
|
||||||
DefaultRunnerScaleSetListenerImage: "ghcr.io/actions/arc",
|
DefaultRunnerScaleSetListenerImage: "ghcr.io/actions/arc",
|
||||||
ResourceBuilder: ResourceBuilder{
|
ResourceBuilder: ResourceBuilder{
|
||||||
ActionsClientPool: &ActionsClientPool{
|
SecretResolver: &SecretResolver{
|
||||||
k8sClient: k8sClient,
|
k8sClient: k8sClient,
|
||||||
multiClient: fake.NewMultiClient(),
|
multiClient: fake.NewMultiClient(),
|
||||||
},
|
},
|
||||||
|
|
@ -962,7 +962,7 @@ var _ = Describe("Test client optional configuration", Ordered, func() {
|
||||||
ControllerNamespace: autoscalingNS.Name,
|
ControllerNamespace: autoscalingNS.Name,
|
||||||
DefaultRunnerScaleSetListenerImage: "ghcr.io/actions/arc",
|
DefaultRunnerScaleSetListenerImage: "ghcr.io/actions/arc",
|
||||||
ResourceBuilder: ResourceBuilder{
|
ResourceBuilder: ResourceBuilder{
|
||||||
ActionsClientPool: &ActionsClientPool{
|
SecretResolver: &SecretResolver{
|
||||||
k8sClient: k8sClient,
|
k8sClient: k8sClient,
|
||||||
multiClient: multiClient,
|
multiClient: multiClient,
|
||||||
},
|
},
|
||||||
|
|
@ -1150,7 +1150,7 @@ var _ = Describe("Test client optional configuration", Ordered, func() {
|
||||||
ControllerNamespace: autoscalingNS.Name,
|
ControllerNamespace: autoscalingNS.Name,
|
||||||
DefaultRunnerScaleSetListenerImage: "ghcr.io/actions/arc",
|
DefaultRunnerScaleSetListenerImage: "ghcr.io/actions/arc",
|
||||||
ResourceBuilder: ResourceBuilder{
|
ResourceBuilder: ResourceBuilder{
|
||||||
ActionsClientPool: &ActionsClientPool{
|
SecretResolver: &SecretResolver{
|
||||||
k8sClient: k8sClient,
|
k8sClient: k8sClient,
|
||||||
multiClient: fake.NewMultiClient(),
|
multiClient: fake.NewMultiClient(),
|
||||||
},
|
},
|
||||||
|
|
@ -1163,7 +1163,7 @@ var _ = Describe("Test client optional configuration", Ordered, func() {
|
||||||
})
|
})
|
||||||
|
|
||||||
It("should be able to make requests to a server using root CAs", func() {
|
It("should be able to make requests to a server using root CAs", func() {
|
||||||
controller.ActionsClientPool = &ActionsClientPool{
|
controller.SecretResolver = &SecretResolver{
|
||||||
k8sClient: k8sClient,
|
k8sClient: k8sClient,
|
||||||
multiClient: actions.NewMultiClient(logr.Discard()),
|
multiClient: actions.NewMultiClient(logr.Discard()),
|
||||||
}
|
}
|
||||||
|
|
@ -1392,7 +1392,7 @@ var _ = Describe("Test external permissions cleanup", Ordered, func() {
|
||||||
ControllerNamespace: autoscalingNS.Name,
|
ControllerNamespace: autoscalingNS.Name,
|
||||||
DefaultRunnerScaleSetListenerImage: "ghcr.io/actions/arc",
|
DefaultRunnerScaleSetListenerImage: "ghcr.io/actions/arc",
|
||||||
ResourceBuilder: ResourceBuilder{
|
ResourceBuilder: ResourceBuilder{
|
||||||
ActionsClientPool: &ActionsClientPool{
|
SecretResolver: &SecretResolver{
|
||||||
k8sClient: k8sClient,
|
k8sClient: k8sClient,
|
||||||
multiClient: fake.NewMultiClient(),
|
multiClient: fake.NewMultiClient(),
|
||||||
},
|
},
|
||||||
|
|
@ -1555,7 +1555,7 @@ var _ = Describe("Test external permissions cleanup", Ordered, func() {
|
||||||
ControllerNamespace: autoscalingNS.Name,
|
ControllerNamespace: autoscalingNS.Name,
|
||||||
DefaultRunnerScaleSetListenerImage: "ghcr.io/actions/arc",
|
DefaultRunnerScaleSetListenerImage: "ghcr.io/actions/arc",
|
||||||
ResourceBuilder: ResourceBuilder{
|
ResourceBuilder: ResourceBuilder{
|
||||||
ActionsClientPool: &ActionsClientPool{
|
SecretResolver: &SecretResolver{
|
||||||
k8sClient: k8sClient,
|
k8sClient: k8sClient,
|
||||||
multiClient: fake.NewMultiClient(),
|
multiClient: fake.NewMultiClient(),
|
||||||
},
|
},
|
||||||
|
|
@ -1768,7 +1768,7 @@ var _ = Describe("Test resource version and build version mismatch", func() {
|
||||||
ControllerNamespace: autoscalingNS.Name,
|
ControllerNamespace: autoscalingNS.Name,
|
||||||
DefaultRunnerScaleSetListenerImage: "ghcr.io/actions/arc",
|
DefaultRunnerScaleSetListenerImage: "ghcr.io/actions/arc",
|
||||||
ResourceBuilder: ResourceBuilder{
|
ResourceBuilder: ResourceBuilder{
|
||||||
ActionsClientPool: &ActionsClientPool{
|
SecretResolver: &SecretResolver{
|
||||||
k8sClient: k8sClient,
|
k8sClient: k8sClient,
|
||||||
multiClient: fake.NewMultiClient(),
|
multiClient: fake.NewMultiClient(),
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -528,7 +528,7 @@ func (r *EphemeralRunnerReconciler) deletePodAsFailed(ctx context.Context, ephem
|
||||||
func (r *EphemeralRunnerReconciler) updateStatusWithRunnerConfig(ctx context.Context, ephemeralRunner *v1alpha1.EphemeralRunner, log logr.Logger) (*ctrl.Result, error) {
|
func (r *EphemeralRunnerReconciler) updateStatusWithRunnerConfig(ctx context.Context, ephemeralRunner *v1alpha1.EphemeralRunner, log logr.Logger) (*ctrl.Result, error) {
|
||||||
// Runner is not registered with the service. We need to register it first
|
// Runner is not registered with the service. We need to register it first
|
||||||
log.Info("Creating ephemeral runner JIT config")
|
log.Info("Creating ephemeral runner JIT config")
|
||||||
actionsClient, err := r.ActionsClientPool.Get(ctx, ephemeralRunner)
|
actionsClient, err := r.SecretResolver.GetActionsService(ctx, ephemeralRunner)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &ctrl.Result{}, fmt.Errorf("failed to get actions client for generating JIT config: %w", err)
|
return &ctrl.Result{}, fmt.Errorf("failed to get actions client for generating JIT config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -755,7 +755,7 @@ func (r *EphemeralRunnerReconciler) updateRunStatusFromPod(ctx context.Context,
|
||||||
// runnerRegisteredWithService checks if the runner is still registered with the service
|
// runnerRegisteredWithService checks if the runner is still registered with the service
|
||||||
// Returns found=false and err=nil if ephemeral runner does not exist in GitHub service and should be deleted
|
// Returns found=false and err=nil if ephemeral runner does not exist in GitHub service and should be deleted
|
||||||
func (r EphemeralRunnerReconciler) runnerRegisteredWithService(ctx context.Context, runner *v1alpha1.EphemeralRunner, log logr.Logger) (found bool, err error) {
|
func (r EphemeralRunnerReconciler) runnerRegisteredWithService(ctx context.Context, runner *v1alpha1.EphemeralRunner, log logr.Logger) (found bool, err error) {
|
||||||
actionsClient, err := r.ActionsClientPool.Get(ctx, runner)
|
actionsClient, err := r.SecretResolver.GetActionsService(ctx, runner)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf("failed to get Actions client for ScaleSet: %w", err)
|
return false, fmt.Errorf("failed to get Actions client for ScaleSet: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -782,7 +782,7 @@ func (r EphemeralRunnerReconciler) runnerRegisteredWithService(ctx context.Conte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *EphemeralRunnerReconciler) deleteRunnerFromService(ctx context.Context, ephemeralRunner *v1alpha1.EphemeralRunner, log logr.Logger) error {
|
func (r *EphemeralRunnerReconciler) deleteRunnerFromService(ctx context.Context, ephemeralRunner *v1alpha1.EphemeralRunner, log logr.Logger) error {
|
||||||
client, err := r.ActionsClientPool.Get(ctx, ephemeralRunner)
|
client, err := r.SecretResolver.GetActionsService(ctx, ephemeralRunner)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to get actions client for runner: %w", err)
|
return fmt.Errorf("failed to get actions client for runner: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@ var _ = Describe("EphemeralRunner", func() {
|
||||||
Scheme: mgr.GetScheme(),
|
Scheme: mgr.GetScheme(),
|
||||||
Log: logf.Log,
|
Log: logf.Log,
|
||||||
ResourceBuilder: ResourceBuilder{
|
ResourceBuilder: ResourceBuilder{
|
||||||
ActionsClientPool: &ActionsClientPool{
|
SecretResolver: &SecretResolver{
|
||||||
k8sClient: mgr.GetClient(),
|
k8sClient: mgr.GetClient(),
|
||||||
multiClient: fake.NewMultiClient(),
|
multiClient: fake.NewMultiClient(),
|
||||||
},
|
},
|
||||||
|
|
@ -795,7 +795,7 @@ var _ = Describe("EphemeralRunner", func() {
|
||||||
Scheme: mgr.GetScheme(),
|
Scheme: mgr.GetScheme(),
|
||||||
Log: logf.Log,
|
Log: logf.Log,
|
||||||
ResourceBuilder: ResourceBuilder{
|
ResourceBuilder: ResourceBuilder{
|
||||||
ActionsClientPool: &ActionsClientPool{
|
SecretResolver: &SecretResolver{
|
||||||
k8sClient: mgr.GetClient(),
|
k8sClient: mgr.GetClient(),
|
||||||
multiClient: fake.NewMultiClient(
|
multiClient: fake.NewMultiClient(
|
||||||
fake.WithDefaultClient(
|
fake.WithDefaultClient(
|
||||||
|
|
@ -875,7 +875,7 @@ var _ = Describe("EphemeralRunner", func() {
|
||||||
Scheme: mgr.GetScheme(),
|
Scheme: mgr.GetScheme(),
|
||||||
Log: logf.Log,
|
Log: logf.Log,
|
||||||
ResourceBuilder: ResourceBuilder{
|
ResourceBuilder: ResourceBuilder{
|
||||||
ActionsClientPool: &ActionsClientPool{
|
SecretResolver: &SecretResolver{
|
||||||
k8sClient: mgr.GetClient(),
|
k8sClient: mgr.GetClient(),
|
||||||
multiClient: fake.NewMultiClient(),
|
multiClient: fake.NewMultiClient(),
|
||||||
},
|
},
|
||||||
|
|
@ -890,7 +890,7 @@ var _ = Describe("EphemeralRunner", func() {
|
||||||
It("uses an actions client with proxy transport", func() {
|
It("uses an actions client with proxy transport", func() {
|
||||||
// Use an actual client
|
// Use an actual client
|
||||||
controller.ResourceBuilder = ResourceBuilder{
|
controller.ResourceBuilder = ResourceBuilder{
|
||||||
ActionsClientPool: &ActionsClientPool{
|
SecretResolver: &SecretResolver{
|
||||||
k8sClient: mgr.GetClient(),
|
k8sClient: mgr.GetClient(),
|
||||||
multiClient: actions.NewMultiClient(logr.Discard()),
|
multiClient: actions.NewMultiClient(logr.Discard()),
|
||||||
},
|
},
|
||||||
|
|
@ -1049,7 +1049,7 @@ var _ = Describe("EphemeralRunner", func() {
|
||||||
Scheme: mgr.GetScheme(),
|
Scheme: mgr.GetScheme(),
|
||||||
Log: logf.Log,
|
Log: logf.Log,
|
||||||
ResourceBuilder: ResourceBuilder{
|
ResourceBuilder: ResourceBuilder{
|
||||||
ActionsClientPool: &ActionsClientPool{
|
SecretResolver: &SecretResolver{
|
||||||
k8sClient: mgr.GetClient(),
|
k8sClient: mgr.GetClient(),
|
||||||
multiClient: fake.NewMultiClient(),
|
multiClient: fake.NewMultiClient(),
|
||||||
},
|
},
|
||||||
|
|
@ -1085,7 +1085,7 @@ var _ = Describe("EphemeralRunner", func() {
|
||||||
|
|
||||||
// Use an actual client
|
// Use an actual client
|
||||||
controller.ResourceBuilder = ResourceBuilder{
|
controller.ResourceBuilder = ResourceBuilder{
|
||||||
ActionsClientPool: &ActionsClientPool{
|
SecretResolver: &SecretResolver{
|
||||||
k8sClient: mgr.GetClient(),
|
k8sClient: mgr.GetClient(),
|
||||||
multiClient: actions.NewMultiClient(logr.Discard()),
|
multiClient: actions.NewMultiClient(logr.Discard()),
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -331,7 +331,7 @@ func (r *EphemeralRunnerSetReconciler) cleanUpEphemeralRunners(ctx context.Conte
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
actionsClient, err := r.ActionsClientPool.Get(ctx, ephemeralRunnerSet)
|
actionsClient, err := r.SecretResolver.GetActionsService(ctx, ephemeralRunnerSet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
@ -439,7 +439,7 @@ func (r *EphemeralRunnerSetReconciler) deleteIdleEphemeralRunners(ctx context.Co
|
||||||
log.Info("No pending or running ephemeral runners running at this time for scale down")
|
log.Info("No pending or running ephemeral runners running at this time for scale down")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
actionsClient, err := r.ActionsClientPool.Get(ctx, ephemeralRunnerSet)
|
actionsClient, err := r.SecretResolver.GetActionsService(ctx, ephemeralRunnerSet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create actions client for ephemeral runner replica set: %w", err)
|
return fmt.Errorf("failed to create actions client for ephemeral runner replica set: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ var _ = Describe("Test EphemeralRunnerSet controller", func() {
|
||||||
Scheme: mgr.GetScheme(),
|
Scheme: mgr.GetScheme(),
|
||||||
Log: logf.Log,
|
Log: logf.Log,
|
||||||
ResourceBuilder: ResourceBuilder{
|
ResourceBuilder: ResourceBuilder{
|
||||||
ActionsClientPool: &ActionsClientPool{
|
SecretResolver: &SecretResolver{
|
||||||
k8sClient: mgr.GetClient(),
|
k8sClient: mgr.GetClient(),
|
||||||
multiClient: fake.NewMultiClient(),
|
multiClient: fake.NewMultiClient(),
|
||||||
},
|
},
|
||||||
|
|
@ -1113,7 +1113,7 @@ var _ = Describe("Test EphemeralRunnerSet controller with proxy settings", func(
|
||||||
Scheme: mgr.GetScheme(),
|
Scheme: mgr.GetScheme(),
|
||||||
Log: logf.Log,
|
Log: logf.Log,
|
||||||
ResourceBuilder: ResourceBuilder{
|
ResourceBuilder: ResourceBuilder{
|
||||||
ActionsClientPool: &ActionsClientPool{
|
SecretResolver: &SecretResolver{
|
||||||
k8sClient: mgr.GetClient(),
|
k8sClient: mgr.GetClient(),
|
||||||
multiClient: actions.NewMultiClient(logr.Discard()),
|
multiClient: actions.NewMultiClient(logr.Discard()),
|
||||||
},
|
},
|
||||||
|
|
@ -1417,7 +1417,7 @@ var _ = Describe("Test EphemeralRunnerSet controller with custom root CA", func(
|
||||||
Scheme: mgr.GetScheme(),
|
Scheme: mgr.GetScheme(),
|
||||||
Log: logf.Log,
|
Log: logf.Log,
|
||||||
ResourceBuilder: ResourceBuilder{
|
ResourceBuilder: ResourceBuilder{
|
||||||
ActionsClientPool: &ActionsClientPool{
|
SecretResolver: &SecretResolver{
|
||||||
k8sClient: mgr.GetClient(),
|
k8sClient: mgr.GetClient(),
|
||||||
multiClient: actions.NewMultiClient(logr.Discard()),
|
multiClient: actions.NewMultiClient(logr.Discard()),
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ import (
|
||||||
"github.com/actions/actions-runner-controller/github/actions"
|
"github.com/actions/actions-runner-controller/github/actions"
|
||||||
"github.com/actions/actions-runner-controller/hash"
|
"github.com/actions/actions-runner-controller/hash"
|
||||||
"github.com/actions/actions-runner-controller/logging"
|
"github.com/actions/actions-runner-controller/logging"
|
||||||
|
"github.com/actions/actions-runner-controller/vault"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
rbacv1 "k8s.io/api/rbac/v1"
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
@ -73,7 +74,7 @@ func SetListenerEntrypoint(entrypoint string) {
|
||||||
|
|
||||||
type ResourceBuilder struct {
|
type ResourceBuilder struct {
|
||||||
ExcludeLabelPropagationPrefixes []string
|
ExcludeLabelPropagationPrefixes []string
|
||||||
*ActionsClientPool
|
*SecretResolver
|
||||||
}
|
}
|
||||||
|
|
||||||
// boolPtr returns a pointer to a bool value
|
// boolPtr returns a pointer to a bool value
|
||||||
|
|
@ -166,7 +167,7 @@ func (lm *listenerMetricsServerConfig) containerPort() (corev1.ContainerPort, er
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *ResourceBuilder) newScaleSetListenerConfig(autoscalingListener *v1alpha1.AutoscalingListener, secret *corev1.Secret, metricsConfig *listenerMetricsServerConfig, cert string) (*corev1.Secret, error) {
|
func (b *ResourceBuilder) newScaleSetListenerConfig(autoscalingListener *v1alpha1.AutoscalingListener, appConfig *appconfig.AppConfig, metricsConfig *listenerMetricsServerConfig, cert string) (*corev1.Secret, error) {
|
||||||
var (
|
var (
|
||||||
metricsAddr = ""
|
metricsAddr = ""
|
||||||
metricsEndpoint = ""
|
metricsEndpoint = ""
|
||||||
|
|
@ -193,13 +194,13 @@ func (b *ResourceBuilder) newScaleSetListenerConfig(autoscalingListener *v1alpha
|
||||||
}
|
}
|
||||||
|
|
||||||
if ty, ok := autoscalingListener.Annotations[AnnotationKeyGitHubVaultType]; !ok {
|
if ty, ok := autoscalingListener.Annotations[AnnotationKeyGitHubVaultType]; !ok {
|
||||||
appConfig, err := appconfig.FromSecret(secret)
|
config.AppConfig = appConfig
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to parse appconfig from secret: %v", err)
|
|
||||||
}
|
|
||||||
config.AppConfig = *appConfig
|
|
||||||
} else {
|
} else {
|
||||||
config.VaultType = ty
|
vaultType := vault.VaultType(ty)
|
||||||
|
if err := vaultType.Validate(); err != nil {
|
||||||
|
return nil, fmt.Errorf("vault type validation error: %w", err)
|
||||||
|
}
|
||||||
|
config.VaultType = vaultType
|
||||||
config.VaultLookupKey = autoscalingListener.Spec.GitHubConfigSecret
|
config.VaultLookupKey = autoscalingListener.Spec.GitHubConfigSecret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,29 +18,29 @@ import (
|
||||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ActionsClientPool struct {
|
type SecretResolver struct {
|
||||||
k8sClient client.Client
|
k8sClient client.Client
|
||||||
vaultResolvers map[string]resolver
|
vaultResolvers map[vault.VaultType]resolver
|
||||||
multiClient actions.MultiClient
|
multiClient actions.MultiClient
|
||||||
}
|
}
|
||||||
|
|
||||||
type ActionsClientPoolOption func(*ActionsClientPool)
|
type SecretResolverOption func(*SecretResolver)
|
||||||
|
|
||||||
func WithVault(ty string, vault vault.Vault) ActionsClientPoolOption {
|
func WithVault(ty vault.VaultType, vault vault.Vault) SecretResolverOption {
|
||||||
return func(pool *ActionsClientPool) {
|
return func(pool *SecretResolver) {
|
||||||
pool.vaultResolvers[ty] = &vaultResolver{vault}
|
pool.vaultResolvers[ty] = &vaultResolver{vault}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewActionsClientPool(k8sClient client.Client, multiClient actions.MultiClient, opts ...ActionsClientPoolOption) *ActionsClientPool {
|
func NewSecretResolver(k8sClient client.Client, multiClient actions.MultiClient, opts ...SecretResolverOption) *SecretResolver {
|
||||||
if k8sClient == nil {
|
if k8sClient == nil {
|
||||||
panic("k8sClient must not be nil")
|
panic("k8sClient must not be nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
pool := &ActionsClientPool{
|
pool := &SecretResolver{
|
||||||
k8sClient: k8sClient,
|
k8sClient: k8sClient,
|
||||||
multiClient: multiClient,
|
multiClient: multiClient,
|
||||||
vaultResolvers: make(map[string]resolver),
|
vaultResolvers: make(map[vault.VaultType]resolver),
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
|
|
@ -58,8 +58,22 @@ type ActionsGitHubObject interface {
|
||||||
GitHubServerTLS() *v1alpha1.GitHubServerTLSConfig
|
GitHubServerTLS() *v1alpha1.GitHubServerTLSConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ActionsClientPool) Get(ctx context.Context, obj ActionsGitHubObject) (actions.ActionsService, error) {
|
func (sr *SecretResolver) GetAppConfig(ctx context.Context, obj ActionsGitHubObject) (*appconfig.AppConfig, error) {
|
||||||
resolver, err := p.resolverForObject(obj)
|
resolver, err := sr.resolverForObject(obj)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get resolver for object: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
appConfig, err := resolver.appConfig(ctx, obj.GitHubConfigSecret())
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to resolve app config: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return appConfig, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sr *SecretResolver) GetActionsService(ctx context.Context, obj ActionsGitHubObject) (actions.ActionsService, error) {
|
||||||
|
resolver, err := sr.resolverForObject(obj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to get resolver for object: %v", err)
|
return nil, fmt.Errorf("failed to get resolver for object: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -118,7 +132,7 @@ func (p *ActionsClientPool) Get(ctx context.Context, obj ActionsGitHubObject) (a
|
||||||
if tlsConfig != nil {
|
if tlsConfig != nil {
|
||||||
pool, err := tlsConfig.ToCertPool(func(name, key string) ([]byte, error) {
|
pool, err := tlsConfig.ToCertPool(func(name, key string) ([]byte, error) {
|
||||||
var configmap corev1.ConfigMap
|
var configmap corev1.ConfigMap
|
||||||
err := p.k8sClient.Get(
|
err := sr.k8sClient.Get(
|
||||||
ctx,
|
ctx,
|
||||||
types.NamespacedName{
|
types.NamespacedName{
|
||||||
Namespace: obj.GetNamespace(),
|
Namespace: obj.GetNamespace(),
|
||||||
|
|
@ -139,7 +153,7 @@ func (p *ActionsClientPool) Get(ctx context.Context, obj ActionsGitHubObject) (a
|
||||||
clientOptions = append(clientOptions, actions.WithRootCAs(pool))
|
clientOptions = append(clientOptions, actions.WithRootCAs(pool))
|
||||||
}
|
}
|
||||||
|
|
||||||
return p.multiClient.GetClientFor(
|
return sr.multiClient.GetClientFor(
|
||||||
ctx,
|
ctx,
|
||||||
obj.GitHubConfigUrl(),
|
obj.GitHubConfigUrl(),
|
||||||
appConfig,
|
appConfig,
|
||||||
|
|
@ -148,7 +162,7 @@ func (p *ActionsClientPool) Get(ctx context.Context, obj ActionsGitHubObject) (a
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ActionsClientPool) resolverForObject(obj ActionsGitHubObject) (resolver, error) {
|
func (p *SecretResolver) resolverForObject(obj ActionsGitHubObject) (resolver, error) {
|
||||||
ty, ok := obj.GetAnnotations()[AnnotationKeyGitHubVaultType]
|
ty, ok := obj.GetAnnotations()[AnnotationKeyGitHubVaultType]
|
||||||
if !ok {
|
if !ok {
|
||||||
return &k8sResolver{
|
return &k8sResolver{
|
||||||
|
|
@ -157,7 +171,12 @@ func (p *ActionsClientPool) resolverForObject(obj ActionsGitHubObject) (resolver
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
vault, ok := p.vaultResolvers[ty]
|
vaultType := vault.VaultType(ty)
|
||||||
|
if err := vaultType.Validate(); err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid vault type %q: %v", ty, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
vault, ok := p.vaultResolvers[vaultType]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("unknown vault resolver %q", ty)
|
return nil, fmt.Errorf("unknown vault resolver %q", ty)
|
||||||
}
|
}
|
||||||
10
main.go
10
main.go
|
|
@ -281,20 +281,20 @@ func main() {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
var poolOptions []actionsgithubcom.ActionsClientPoolOption
|
var secretResolverOptions []actionsgithubcom.SecretResolverOption
|
||||||
for name, vault := range vaults {
|
for name, vault := range vaults {
|
||||||
poolOptions = append(poolOptions, actionsgithubcom.WithVault(name, vault))
|
secretResolverOptions = append(secretResolverOptions, actionsgithubcom.WithVault(name, vault))
|
||||||
}
|
}
|
||||||
|
|
||||||
clientPool := actionsgithubcom.NewActionsClientPool(
|
secretResolver := actionsgithubcom.NewSecretResolver(
|
||||||
mgr.GetClient(),
|
mgr.GetClient(),
|
||||||
actionsMultiClient,
|
actionsMultiClient,
|
||||||
poolOptions...,
|
secretResolverOptions...,
|
||||||
)
|
)
|
||||||
|
|
||||||
rb := actionsgithubcom.ResourceBuilder{
|
rb := actionsgithubcom.ResourceBuilder{
|
||||||
ExcludeLabelPropagationPrefixes: excludeLabelPropagationPrefixes,
|
ExcludeLabelPropagationPrefixes: excludeLabelPropagationPrefixes,
|
||||||
ActionsClientPool: clientPool,
|
SecretResolver: secretResolver,
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info("Resource builder initializing")
|
log.Info("Resource builder initializing")
|
||||||
|
|
|
||||||
|
|
@ -14,11 +14,28 @@ type Vault interface {
|
||||||
GetSecret(ctx context.Context, name string) (string, error)
|
GetSecret(ctx context.Context, name string) (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VaultType represents the type of vault that can be used in the application.
|
||||||
|
// It is used to identify which vault integration should be used to resolve secrets.
|
||||||
|
type VaultType string
|
||||||
|
|
||||||
// VaultType is the type of vault supported
|
// VaultType is the type of vault supported
|
||||||
const (
|
const (
|
||||||
VaultTypeAzureKeyVault = "azure_key_vault"
|
VaultTypeAzureKeyVault VaultType = "azure_key_vault"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (t VaultType) String() string {
|
||||||
|
return string(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t VaultType) Validate() error {
|
||||||
|
switch t {
|
||||||
|
case VaultTypeAzureKeyVault:
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unknown vault type: %q", t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Compile-time checks
|
// Compile-time checks
|
||||||
var _ Vault = (*azurekeyvault.AzureKeyVault)(nil)
|
var _ Vault = (*azurekeyvault.AzureKeyVault)(nil)
|
||||||
|
|
||||||
|
|
@ -31,10 +48,10 @@ var _ Vault = (*azurekeyvault.AzureKeyVault)(nil)
|
||||||
//
|
//
|
||||||
// For example, listener has prefix "LISTENER_", has "AZURE_KEY_VAULT_" configured,
|
// For example, listener has prefix "LISTENER_", has "AZURE_KEY_VAULT_" configured,
|
||||||
// and should read the vault URL. The environment variable will be "LISTENER_AZURE_KEY_VAULT_URL".
|
// and should read the vault URL. The environment variable will be "LISTENER_AZURE_KEY_VAULT_URL".
|
||||||
func InitAll(prefix string) (map[string]Vault, error) {
|
func InitAll(prefix string) (map[VaultType]Vault, error) {
|
||||||
envs := os.Environ()
|
envs := os.Environ()
|
||||||
|
|
||||||
result := make(map[string]Vault)
|
result := make(map[VaultType]Vault)
|
||||||
for _, env := range envs {
|
for _, env := range envs {
|
||||||
if strings.HasPrefix(env, prefix+"AZURE_KEY_VAULT_") {
|
if strings.HasPrefix(env, prefix+"AZURE_KEY_VAULT_") {
|
||||||
akv, err := azurekeyvault.FromEnv(prefix + "AZURE_KEY_VAULT_")
|
akv, err := azurekeyvault.FromEnv(prefix + "AZURE_KEY_VAULT_")
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue