Skip to content
This repository has been archived by the owner on Mar 16, 2024. It is now read-only.

Commit

Permalink
add: boolmap type flags (for feature flags)
Browse files Browse the repository at this point in the history
Signed-off-by: Thorsten Klein <tk@thklein.io>
  • Loading branch information
iwilltry42 committed May 29, 2023
1 parent c650b35 commit 7ea340e
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 51 deletions.
2 changes: 1 addition & 1 deletion docs/docs/100-reference/01-command-line/acorn_install.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ acorn install
--cluster-domain strings The externally addressable cluster domain (default .oss-acorn.io)
--controller-replicas int acorn-controller deployment replica count
--controller-service-account-annotation strings annotation to apply to the acorn-system service account
--features strings Enable or disable features. (example foo=true,bar=false)
-h, --help help for install
--http-endpoint-pattern string Go template for formatting application http endpoints. Valid variables to use are: App, Container, Namespace, Hash and ClusterDomain. (default pattern is {{hashConcat 8 .Container .App .Namespace | truncate}}.{{.ClusterDomain}})
--ignore-user-labels-and-annotations Don't propagate user-defined labels and annotations to dependent objects
--image string Override the default image used for the deployment
--image-allow-rules-enabled If true, ImageAllowRules will be enabled and the deny-by-default policy will be enforced for all projects. (default false)
--ingress-class-name string The ingress class name to assign to all created ingress resources (default '')
--ingress-controller-namespace string The namespace where the ingress controller runs - used to secure published HTTP ports with NetworkPolicies.
--internal-cluster-domain string The Kubernetes internal cluster domain (default svc.cluster.local)
Expand Down
62 changes: 31 additions & 31 deletions pkg/apis/api.acorn.io/v1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -397,37 +397,37 @@ type Config struct {
// For repeatable flags, ensure the struct and json fields are plural and the flag name is singular.
// See ClusterDomains as an example.

IngressClassName *string `json:"ingressClassName" usage:"The ingress class name to assign to all created ingress resources (default '')"`
ClusterDomains []string `json:"clusterDomains" name:"cluster-domain" usage:"The externally addressable cluster domain (default .oss-acorn.io)"`
LetsEncrypt *string `json:"letsEncrypt" name:"lets-encrypt" usage:"enabled|disabled|staging. If enabled, acorn generated endpoints will be secured using TLS certificate from Let's Encrypt. Staging uses Let's Encrypt's staging environment. (default disabled)"`
LetsEncryptEmail string `json:"letsEncryptEmail" name:"lets-encrypt-email" usage:"Required if --lets-encrypt=enabled. The email address to use for Let's Encrypt registration(default '')"`
LetsEncryptTOSAgree *bool `json:"letsEncryptTOSAgree" name:"lets-encrypt-tos-agree" usage:"Required if --lets-encrypt=enabled. If true, you agree to the Let's Encrypt terms of service (default false)"`
SetPodSecurityEnforceProfile *bool `json:"setPodSecurityEnforceProfile" usage:"Set the PodSecurity profile on created namespaces (default true)"`
PodSecurityEnforceProfile string `json:"podSecurityEnforceProfile" usage:"The name of the PodSecurity profile to set (default baseline)" wrangler:"nullable"`
HttpEndpointPattern *string `json:"httpEndpointPattern" name:"http-endpoint-pattern" usage:"Go template for formatting application http endpoints. Valid variables to use are: App, Container, Namespace, Hash and ClusterDomain. (default pattern is {{hashConcat 8 .Container .App .Namespace | truncate}}.{{.ClusterDomain}})" wrangler:"nullable"`
InternalClusterDomain string `json:"internalClusterDomain" usage:"The Kubernetes internal cluster domain (default svc.cluster.local)" wrangler:"nullable"`
AcornDNS *string `json:"acornDNS" name:"acorn-dns" usage:"enabled|disabled|auto. If enabled, containers created by Acorn will get public FQDNs. Auto functions as disabled if a custom clusterDomain has been supplied (default auto)"`
AcornDNSEndpoint *string `json:"acornDNSEndpoint" name:"acorn-dns-endpoint" usage:"The URL to access the Acorn DNS service"`
AutoUpgradeInterval *string `json:"autoUpgradeInterval" name:"auto-upgrade-interval" usage:"For apps configured with automatic upgrades enabled, the interval at which to check for new versions. Upgrade intervals configured at the application level cannot be smaller than this. (default '5m' - 5 minutes)"`
RecordBuilds *bool `json:"recordBuilds" name:"record-builds" usage:"Keep a record of each acorn build that happens"`
PublishBuilders *bool `json:"publishBuilders" name:"publish-builders" usage:"Publish the builders through ingress to so build traffic does not traverse the api-server"`
BuilderPerProject *bool `json:"builderPerProject" name:"builder-per-project" usage:"Create a dedicated builder per project"`
InternalRegistryPrefix *string `json:"internalRegistryPrefix" name:"internal-registry-prefix" usage:"The image prefix to use when pushing internal images (example ghcr.io/my-org/)"`
IgnoreUserLabelsAndAnnotations *bool `json:"ignoreUserLabelsAndAnnotations" name:"ignore-user-labels-and-annotations" usage:"Don't propagate user-defined labels and annotations to dependent objects"`
AllowUserLabels []string `json:"allowUserLabels" name:"allow-user-label" usage:"Allow these labels to propagate to dependent objects, no effect if --ignore-user-labels-and-annotations not true"`
AllowUserAnnotations []string `json:"allowUserAnnotations" name:"allow-user-annotation" usage:"Allow these annotations to propagate to dependent objects, no effect if --ignore-user-labels-and-annotations not true"`
WorkloadMemoryDefault *int64 `json:"workloadMemoryDefault" name:"workload-memory-default" quantity:"true" usage:"Set the default memory for acorn workloads. Accepts binary suffixes (Ki, Mi, Gi, etc) and \".\" and \"_\" seperators (default 0)" short:"m"`
WorkloadMemoryMaximum *int64 `json:"workloadMemoryMaximum" name:"workload-memory-maximum" quantity:"true" usage:"Set the maximum memory for acorn workloads. Accepts binary suffixes (Ki, Mi, Gi, etc) and \".\" and \"_\" seperators (default 0)"`
UseCustomCABundle *bool `json:"useCustomCABundle" name:"use-custom-ca-bundle" usage:"Use CA bundle for admin supplied secret for all acorn control plane components. Defaults to false."`
PropagateProjectAnnotations []string `json:"propagateProjectAnnotations" name:"propagate-project-annotation" usage:"The list of keys of annotations to propagate from acorn project to app namespaces"`
PropagateProjectLabels []string `json:"propagateProjectLabels" name:"propagate-project-label" usage:"The list of keys of labels to propagate from acorn project to app namespaces"`
ManageVolumeClasses *bool `json:"manageVolumeClasses" name:"manage-volume-classes" usage:"Manually manage volume classes rather than sync with storage classes, setting to 'true' will delete Acorn-created volume classes"`
NetworkPolicies *bool `json:"networkPolicies" name:"network-policies" usage:"Create Kubernetes NetworkPolicies which block cross-project network traffic (default true)"`
IngressControllerNamespace *string `json:"ingressControllerNamespace" name:"ingress-controller-namespace" usage:"The namespace where the ingress controller runs - used to secure published HTTP ports with NetworkPolicies."`
AllowTrafficFromNamespace []string `json:"allowTrafficFromNamespace" name:"allow-traffic-from-namespace" usage:"Namespaces that are allowed to send network traffic to all Acorn apps"`
ServiceLBAnnotations []string `json:"serviceLBAnnotations" name:"service-lb-annotation" usage:"Annotation to add to the service of type LoadBalancer. Defaults to empty. (example key=value)"`
AWSIdentityProviderARN *string `json:"awsIdentityProviderArn" name:"aws-identity-provider-arn" usage:"ARN of cluster's OpenID Connect provider registered in AWS"`
ImageAllowRulesEnabled *bool `json:"imageAllowRulesEnabled" name:"image-allow-rules-enabled" usage:"If true, ImageAllowRules will be enabled and the deny-by-default policy will be enforced for all projects. (default false)"`
IngressClassName *string `json:"ingressClassName" usage:"The ingress class name to assign to all created ingress resources (default '')"`
ClusterDomains []string `json:"clusterDomains" name:"cluster-domain" usage:"The externally addressable cluster domain (default .oss-acorn.io)"`
LetsEncrypt *string `json:"letsEncrypt" name:"lets-encrypt" usage:"enabled|disabled|staging. If enabled, acorn generated endpoints will be secured using TLS certificate from Let's Encrypt. Staging uses Let's Encrypt's staging environment. (default disabled)"`
LetsEncryptEmail string `json:"letsEncryptEmail" name:"lets-encrypt-email" usage:"Required if --lets-encrypt=enabled. The email address to use for Let's Encrypt registration(default '')"`
LetsEncryptTOSAgree *bool `json:"letsEncryptTOSAgree" name:"lets-encrypt-tos-agree" usage:"Required if --lets-encrypt=enabled. If true, you agree to the Let's Encrypt terms of service (default false)"`
SetPodSecurityEnforceProfile *bool `json:"setPodSecurityEnforceProfile" usage:"Set the PodSecurity profile on created namespaces (default true)"`
PodSecurityEnforceProfile string `json:"podSecurityEnforceProfile" usage:"The name of the PodSecurity profile to set (default baseline)" wrangler:"nullable"`
HttpEndpointPattern *string `json:"httpEndpointPattern" name:"http-endpoint-pattern" usage:"Go template for formatting application http endpoints. Valid variables to use are: App, Container, Namespace, Hash and ClusterDomain. (default pattern is {{hashConcat 8 .Container .App .Namespace | truncate}}.{{.ClusterDomain}})" wrangler:"nullable"`
InternalClusterDomain string `json:"internalClusterDomain" usage:"The Kubernetes internal cluster domain (default svc.cluster.local)" wrangler:"nullable"`
AcornDNS *string `json:"acornDNS" name:"acorn-dns" usage:"enabled|disabled|auto. If enabled, containers created by Acorn will get public FQDNs. Auto functions as disabled if a custom clusterDomain has been supplied (default auto)"`
AcornDNSEndpoint *string `json:"acornDNSEndpoint" name:"acorn-dns-endpoint" usage:"The URL to access the Acorn DNS service"`
AutoUpgradeInterval *string `json:"autoUpgradeInterval" name:"auto-upgrade-interval" usage:"For apps configured with automatic upgrades enabled, the interval at which to check for new versions. Upgrade intervals configured at the application level cannot be smaller than this. (default '5m' - 5 minutes)"`
RecordBuilds *bool `json:"recordBuilds" name:"record-builds" usage:"Keep a record of each acorn build that happens"`
PublishBuilders *bool `json:"publishBuilders" name:"publish-builders" usage:"Publish the builders through ingress to so build traffic does not traverse the api-server"`
BuilderPerProject *bool `json:"builderPerProject" name:"builder-per-project" usage:"Create a dedicated builder per project"`
InternalRegistryPrefix *string `json:"internalRegistryPrefix" name:"internal-registry-prefix" usage:"The image prefix to use when pushing internal images (example ghcr.io/my-org/)"`
IgnoreUserLabelsAndAnnotations *bool `json:"ignoreUserLabelsAndAnnotations" name:"ignore-user-labels-and-annotations" usage:"Don't propagate user-defined labels and annotations to dependent objects"`
AllowUserLabels []string `json:"allowUserLabels" name:"allow-user-label" usage:"Allow these labels to propagate to dependent objects, no effect if --ignore-user-labels-and-annotations not true"`
AllowUserAnnotations []string `json:"allowUserAnnotations" name:"allow-user-annotation" usage:"Allow these annotations to propagate to dependent objects, no effect if --ignore-user-labels-and-annotations not true"`
WorkloadMemoryDefault *int64 `json:"workloadMemoryDefault" name:"workload-memory-default" quantity:"true" usage:"Set the default memory for acorn workloads. Accepts binary suffixes (Ki, Mi, Gi, etc) and \".\" and \"_\" seperators (default 0)" short:"m"`
WorkloadMemoryMaximum *int64 `json:"workloadMemoryMaximum" name:"workload-memory-maximum" quantity:"true" usage:"Set the maximum memory for acorn workloads. Accepts binary suffixes (Ki, Mi, Gi, etc) and \".\" and \"_\" seperators (default 0)"`
UseCustomCABundle *bool `json:"useCustomCABundle" name:"use-custom-ca-bundle" usage:"Use CA bundle for admin supplied secret for all acorn control plane components. Defaults to false."`
PropagateProjectAnnotations []string `json:"propagateProjectAnnotations" name:"propagate-project-annotation" usage:"The list of keys of annotations to propagate from acorn project to app namespaces"`
PropagateProjectLabels []string `json:"propagateProjectLabels" name:"propagate-project-label" usage:"The list of keys of labels to propagate from acorn project to app namespaces"`
ManageVolumeClasses *bool `json:"manageVolumeClasses" name:"manage-volume-classes" usage:"Manually manage volume classes rather than sync with storage classes, setting to 'true' will delete Acorn-created volume classes"`
NetworkPolicies *bool `json:"networkPolicies" name:"network-policies" usage:"Create Kubernetes NetworkPolicies which block cross-project network traffic (default true)"`
IngressControllerNamespace *string `json:"ingressControllerNamespace" name:"ingress-controller-namespace" usage:"The namespace where the ingress controller runs - used to secure published HTTP ports with NetworkPolicies."`
AllowTrafficFromNamespace []string `json:"allowTrafficFromNamespace" name:"allow-traffic-from-namespace" usage:"Namespaces that are allowed to send network traffic to all Acorn apps"`
ServiceLBAnnotations []string `json:"serviceLBAnnotations" name:"service-lb-annotation" usage:"Annotation to add to the service of type LoadBalancer. Defaults to empty. (example key=value)"`
AWSIdentityProviderARN *string `json:"awsIdentityProviderArn" name:"aws-identity-provider-arn" usage:"ARN of cluster's OpenID Connect provider registered in AWS"`
Features map[string]bool `json:"features" name:"features" boolmap:"true" usage:"Enable or disable features. (example foo=true,bar=false)"`
}

type EncryptionKey struct {
Expand Down
10 changes: 6 additions & 4 deletions pkg/apis/api.acorn.io/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

44 changes: 40 additions & 4 deletions pkg/cli/builder/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ func Command(obj Runnable, cmd cobra.Command) *cobra.Command {
arrays = map[string]reflect.Value{}
slices = map[string]reflect.Value{}
maps = map[string]reflect.Value{}
boolmaps = map[string]reflect.Value{}
quantities = map[string]reflect.Value{}
optString = map[string]reflect.Value{}
optBool = map[string]reflect.Value{}
Expand Down Expand Up @@ -140,7 +141,12 @@ func Command(obj Runnable, cmd cobra.Command) *cobra.Command {
flags.StringSliceP(name, alias, nil, usage)
}
case reflect.Map:
maps[name] = v
switch fieldType.Tag.Get("boolmap") {
case "true":
boolmaps[name] = v
default:
maps[name] = v
}
flags.StringSliceP(name, alias, nil, usage)
case reflect.Bool:
flags.BoolVarP((*bool)(unsafe.Pointer(v.Addr().Pointer())), name, alias, false, usage)
Expand Down Expand Up @@ -191,9 +197,9 @@ func Command(obj Runnable, cmd cobra.Command) *cobra.Command {
}

c.RunE = obj.Run
c.PersistentPreRunE = bind(c.PersistentPreRunE, arrays, slices, maps, optInt, optBool, optString, quantities, envs)
c.PreRunE = bind(c.PreRunE, arrays, slices, maps, optInt, optBool, optString, quantities, envs)
c.RunE = bind(c.RunE, arrays, slices, maps, optInt, optBool, optString, quantities, envs)
c.PersistentPreRunE = bind(c.PersistentPreRunE, arrays, slices, maps, boolmaps, optInt, optBool, optString, quantities, envs)
c.PreRunE = bind(c.PreRunE, arrays, slices, maps, boolmaps, optInt, optBool, optString, quantities, envs)
c.RunE = bind(c.RunE, arrays, slices, maps, boolmaps, optInt, optBool, optString, quantities, envs)

cust, ok := obj.(customizer)
if ok {
Expand Down Expand Up @@ -294,6 +300,32 @@ func assignMaps(app *cobra.Command, maps map[string]reflect.Value) error {
return nil
}

func assignBoolMaps(app *cobra.Command, maps map[string]reflect.Value) error {
for k, v := range maps {
k = contextKey(k)
s, err := app.Flags().GetStringSlice(k)
if err != nil {
return err
}
if s != nil {
values := map[string]bool{}
for _, part := range s {
parts := strings.SplitN(part, "=", 2)
if len(parts) == 1 {
values[parts[0]] = true
} else {
values[parts[0]], err = strconv.ParseBool(parts[1])
if err != nil {
return err
}
}
}
v.Set(reflect.ValueOf(values))
}
}
return nil
}

func assignSlices(app *cobra.Command, slices map[string]reflect.Value) error {
for k, v := range slices {
k = contextKey(k)
Expand Down Expand Up @@ -357,6 +389,7 @@ func bind(next func(*cobra.Command, []string) error,
arrays map[string]reflect.Value,
slices map[string]reflect.Value,
maps map[string]reflect.Value,
boolMaps map[string]reflect.Value,
optInt map[string]reflect.Value,
optBool map[string]reflect.Value,
optString map[string]reflect.Value,
Expand All @@ -378,6 +411,9 @@ func bind(next func(*cobra.Command, []string) error,
if err := assignMaps(cmd, maps); err != nil {
return err
}
if err := assignBoolMaps(cmd, boolMaps); err != nil {
return err
}
if err := assignOptInt(cmd, optInt); err != nil {
return err
}
Expand Down
22 changes: 17 additions & 5 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ var (

// Default HttpEndpointPattern set to enable Let's Encrypt
DefaultHttpEndpointPattern = "{{hashConcat 8 .Container .App .Namespace | truncate}}.{{.ClusterDomain}}"

// Features
FeatureImageAllowRules = "image-allow-rules"
FeatureDefaults = map[string]bool{
FeatureImageAllowRules: false,
}
)

func complete(ctx context.Context, c *apiv1.Config, getter kclient.Reader) error {
Expand Down Expand Up @@ -100,10 +106,15 @@ func complete(ctx context.Context, c *apiv1.Config, getter kclient.Reader) error
if c.AWSIdentityProviderARN == nil {
c.AWSIdentityProviderARN = new(string)
}
if c.ImageAllowRulesEnabled == nil {
c.ImageAllowRulesEnabled = new(bool)
if c.Features == nil {
c.Features = FeatureDefaults
} else {
for k, v := range FeatureDefaults {
if _, ok := c.Features[k]; !ok {
c.Features[k] = v
}
}
}

return nil
}

Expand Down Expand Up @@ -316,8 +327,9 @@ func merge(oldConfig, newConfig *apiv1.Config) *apiv1.Config {
if newConfig.UseCustomCABundle != nil {
mergedConfig.UseCustomCABundle = newConfig.UseCustomCABundle
}
if newConfig.ImageAllowRulesEnabled != nil {
mergedConfig.ImageAllowRulesEnabled = newConfig.ImageAllowRulesEnabled

if newConfig.Features != nil {
mergedConfig.Features = newConfig.Features
}

if len(newConfig.PropagateProjectAnnotations) > 0 && newConfig.PropagateProjectAnnotations[0] == "" {
Expand Down
2 changes: 1 addition & 1 deletion pkg/imageallowrules/imageallowrules.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func CheckImageAgainstRules(ctx context.Context, c client.Reader, namespace stri
}

// IAR not enabled? Allow all images.
if cfg.ImageAllowRulesEnabled == nil || !*cfg.ImageAllowRulesEnabled {
if cfg.Features == nil || !cfg.Features[config.FeatureImageAllowRules] {
return nil
}

Expand Down
Loading

0 comments on commit 7ea340e

Please sign in to comment.