From bb494dce6a1d11e69e71a8ebd361f7754fb670c8 Mon Sep 17 00:00:00 2001 From: Garrett Date: Mon, 24 Oct 2022 15:40:03 +0000 Subject: [PATCH 01/16] feat: support nested structs and arrays in config --- cli/deployment/config.go | 626 ++++++++++++++++---------------- coderd/deploymentconfig_test.go | 8 +- codersdk/deploymentconfig.go | 147 +++++--- 3 files changed, 403 insertions(+), 378 deletions(-) diff --git a/cli/deployment/config.go b/cli/deployment/config.go index de2a9c1c7049e..5b37570cbaa36 100644 --- a/cli/deployment/config.go +++ b/cli/deployment/config.go @@ -22,353 +22,273 @@ import ( func newConfig() codersdk.DeploymentConfig { return codersdk.DeploymentConfig{ AccessURL: codersdk.DeploymentConfigField[string]{ - Name: "Access URL", - Key: "access_url", Usage: "External URL to access your deployment. This must be accessible by all provisioned workspaces.", Flag: "access-url", }, WildcardAccessURL: codersdk.DeploymentConfigField[string]{ - Name: "Wildcard Access URL", - Key: "wildcard_access_url", Usage: "Specifies the wildcard hostname to use for workspace applications in the form \"*.example.com\".", Flag: "wildcard-access-url", }, Address: codersdk.DeploymentConfigField[string]{ - Name: "Address", - Key: "address", Usage: "Bind address of the server.", Flag: "address", Shorthand: "a", Value: "127.0.0.1:3000", }, AutobuildPollInterval: codersdk.DeploymentConfigField[time.Duration]{ - Name: "Autobuild Poll Interval", - Key: "autobuild_poll_interval", Usage: "Interval to poll for scheduled workspace builds.", Flag: "autobuild-poll-interval", Hidden: true, Value: time.Minute, }, - DERPServerEnable: codersdk.DeploymentConfigField[bool]{ - Name: "DERP Server Enable", - Key: "derp.server.enable", - Usage: "Whether to enable or disable the embedded DERP relay server.", - Flag: "derp-server-enable", - Value: true, - }, - DERPServerRegionID: codersdk.DeploymentConfigField[int]{ - Name: "DERP Server Region ID", - Key: "derp.server.region_id", - Usage: "Region ID to use for the embedded DERP server.", - Flag: "derp-server-region-id", - Value: 999, - }, - DERPServerRegionCode: codersdk.DeploymentConfigField[string]{ - Name: "DERP Server Region Code", - Key: "derp.server.region_code", - Usage: "Region code to use for the embedded DERP server.", - Flag: "derp-server-region-code", - Value: "coder", - }, - DERPServerRegionName: codersdk.DeploymentConfigField[string]{ - Name: "DERP Server Region Name", - Key: "derp.server.region_name", - Usage: "Region name that for the embedded DERP server.", - Flag: "derp-server-region-name", - Value: "Coder Embedded Relay", - }, - DERPServerSTUNAddresses: codersdk.DeploymentConfigField[[]string]{ - Name: "DERP Server STUN Addresses", - Key: "derp.server.stun_addresses", - Usage: "Addresses for STUN servers to establish P2P connections. Set empty to disable P2P connections.", - Flag: "derp-server-stun-addresses", - Value: []string{"stun.l.google.com:19302"}, - }, - DERPServerRelayURL: codersdk.DeploymentConfigField[string]{ - Name: "DERP Server Relay URL", - Key: "derp.server.relay_url", - Usage: "An HTTP URL that is accessible by other replicas to relay DERP traffic. Required for high availability.", - Flag: "derp-server-relay-url", - Enterprise: true, - }, - DERPConfigURL: codersdk.DeploymentConfigField[string]{ - Name: "DERP Config URL", - Key: "derp.config.url", - Usage: "URL to fetch a DERP mapping on startup. See: https://tailscale.com/kb/1118/custom-derp-servers/", - Flag: "derp-config-url", - }, - DERPConfigPath: codersdk.DeploymentConfigField[string]{ - Name: "DERP Config Path", - Key: "derp.config.path", - Usage: "Path to read a DERP mapping from. See: https://tailscale.com/kb/1118/custom-derp-servers/", - Flag: "derp-config-path", - }, - PrometheusEnable: codersdk.DeploymentConfigField[bool]{ - Name: "Prometheus Enable", - Key: "prometheus.enable", - Usage: "Serve prometheus metrics on the address defined by prometheus address.", - Flag: "prometheus-enable", - }, - PrometheusAddress: codersdk.DeploymentConfigField[string]{ - Name: "Prometheus Address", - Key: "prometheus.address", - Usage: "The bind address to serve prometheus metrics.", - Flag: "prometheus-address", - Value: "127.0.0.1:2112", - }, - PprofEnable: codersdk.DeploymentConfigField[bool]{ - Name: "Pprof Enable", - Key: "pprof.enable", - Usage: "Serve pprof metrics on the address defined by pprof address.", - Flag: "pprof-enable", - }, - PprofAddress: codersdk.DeploymentConfigField[string]{ - Name: "Pprof Address", - Key: "pprof.address", - Usage: "The bind address to serve pprof.", - Flag: "pprof-address", - Value: "127.0.0.1:6060", - }, - ProxyTrustedHeaders: codersdk.DeploymentConfigField[[]string]{ - Name: "Proxy Trusted Headers", - Key: "proxy.trusted_headers", - Flag: "proxy-trusted-headers", - Usage: "Headers to trust for forwarding IP addresses. e.g. Cf-Connecting-IP True-Client-Ip, X-Forwarded-for", - }, - ProxyTrustedOrigins: codersdk.DeploymentConfigField[[]string]{ - Name: "Proxy Trusted Origins", - Key: "proxy.trusted_origins", - Flag: "proxy-trusted-origins", - Usage: "Origin addresses to respect \"proxy-trusted-headers\". e.g. example.com", + DERP: codersdk.DERP{ + Server: codersdk.DERPServerConfig{ + Enable: codersdk.DeploymentConfigField[bool]{ + Usage: "Whether to enable or disable the embedded DERP relay server.", + Flag: "derp-server-enable", + Value: true, + }, + RegionID: codersdk.DeploymentConfigField[int]{ + Usage: "Region ID to use for the embedded DERP server.", + Flag: "derp-server-region-id", + Value: 999, + }, + RegionCode: codersdk.DeploymentConfigField[string]{ + Usage: "Region code to use for the embedded DERP server.", + Flag: "derp-server-region-code", + Value: "coder", + }, + RegionName: codersdk.DeploymentConfigField[string]{ + Usage: "Region name that for the embedded DERP server.", + Flag: "derp-server-region-name", + Value: "Coder Embedded Relay", + }, + STUNAddresses: codersdk.DeploymentConfigField[[]string]{ + Usage: "Addresses for STUN servers to establish P2P connections. Set empty to disable P2P connections.", + Flag: "derp-server-stun-addresses", + Value: []string{"stun.l.google.com:19302"}, + }, + RelayAddress: codersdk.DeploymentConfigField[string]{ + Usage: "An HTTP address that is accessible by other replicas to relay DERP traffic. Required for high availability.", + Flag: "derp-server-relay-address", + Enterprise: true, + }, + }, + Config: codersdk.DERPConfig{ + URL: codersdk.DeploymentConfigField[string]{ + Usage: "URL to fetch a DERP mapping on startup. See: https://tailscale.com/kb/1118/custom-derp-servers/", + Flag: "derp-config-url", + }, + Path: codersdk.DeploymentConfigField[string]{ + Usage: "Path to read a DERP mapping from. See: https://tailscale.com/kb/1118/custom-derp-servers/", + Flag: "derp-config-path", + }, + }, + }, + Prometheus: codersdk.PrometheusConfig{ + Enable: codersdk.DeploymentConfigField[bool]{ + Usage: "Serve prometheus metrics on the address defined by prometheus address.", + Flag: "prometheus-enable", + }, + Address: codersdk.DeploymentConfigField[string]{ + Usage: "The bind address to serve prometheus metrics.", + Flag: "prometheus-address", + Value: "127.0.0.1:2112", + }, + }, + Pprof: codersdk.PprofConfig{ + Enable: codersdk.DeploymentConfigField[bool]{ + Usage: "Serve pprof metrics on the address defined by pprof address.", + Flag: "pprof-enable", + }, + Address: codersdk.DeploymentConfigField[string]{ + Usage: "The bind address to serve pprof.", + Flag: "pprof-address", + Value: "127.0.0.1:6060", + }, }, CacheDirectory: codersdk.DeploymentConfigField[string]{ - Name: "Cache Directory", - Key: "cache_directory", + Usage: "The directory to cache temporary files. If unspecified and $CACHE_DIRECTORY is set, it will be used for compatibility with systemd.", Flag: "cache-dir", Value: defaultCacheDir(), }, InMemoryDatabase: codersdk.DeploymentConfigField[bool]{ - Name: "In Memory Database", - Key: "in_memory_database", + Usage: "Controls whether data will be stored in an in-memory database.", Flag: "in-memory", Hidden: true, }, ProvisionerDaemons: codersdk.DeploymentConfigField[int]{ - Name: "Provisioner Daemons", - Key: "provisioner.daemons", + Usage: "Number of provisioner daemons to create on start. If builds are stuck in queued state for a long time, consider increasing this.", Flag: "provisioner-daemons", Value: 3, }, PostgresURL: codersdk.DeploymentConfigField[string]{ - Name: "Postgres Connection URL", - Key: "pg_connection_url", + Usage: "URL of a PostgreSQL database. If empty, PostgreSQL binaries will be downloaded from Maven (https://repo1.maven.org/maven2) and store all data in the config root. Access the built-in database with \"coder server postgres-builtin-url\".", Flag: "postgres-url", }, - OAuth2GithubClientID: codersdk.DeploymentConfigField[string]{ - Name: "OAuth2 GitHub Client ID", - Key: "oauth2.github.client_id", - Usage: "Client ID for Login with GitHub.", - Flag: "oauth2-github-client-id", - }, - OAuth2GithubClientSecret: codersdk.DeploymentConfigField[string]{ - Name: "OAuth2 GitHub Client Secret", - Key: "oauth2.github.client_secret", - Usage: "Client secret for Login with GitHub.", - Flag: "oauth2-github-client-secret", - }, - OAuth2GithubAllowedOrgs: codersdk.DeploymentConfigField[[]string]{ - Name: "OAuth2 GitHub Allowed Orgs", - Key: "oauth2.github.allowed_orgs", - Usage: "Organizations the user must be a member of to Login with GitHub.", - Flag: "oauth2-github-allowed-orgs", - }, - OAuth2GithubAllowedTeams: codersdk.DeploymentConfigField[[]string]{ - Name: "OAuth2 GitHub Allowed Teams", - Key: "oauth2.github.allowed_teams", - Usage: "Teams inside organizations the user must be a member of to Login with GitHub. Structured as: /.", - Flag: "oauth2-github-allowed-teams", + OAuth2: codersdk.OAuth2Config{ + Github: codersdk.OAuth2GithubConfig{ + ClientID: codersdk.DeploymentConfigField[string]{ + Usage: "Client ID for Login with GitHub.", + Flag: "oauth2-github-client-id", + }, + ClientSecret: codersdk.DeploymentConfigField[string]{ + Usage: "Client secret for Login with GitHub.", + Flag: "oauth2-github-client-secret", + }, + AllowedOrganizations: codersdk.DeploymentConfigField[[]string]{ + Usage: "Organizations the user must be a member of to Login with GitHub.", + Flag: "oauth2-github-allowed-orgs", + }, + AllowedTeams: codersdk.DeploymentConfigField[[]string]{ + Usage: "Teams inside organizations the user must be a member of to Login with GitHub. Structured as: /.", + Flag: "oauth2-github-allowed-teams", + }, + AllowSignups: codersdk.DeploymentConfigField[bool]{ + Usage: "Whether new users can sign up with GitHub.", + Flag: "oauth2-github-allow-signups", + }, + EnterpriseBaseURL: codersdk.DeploymentConfigField[string]{ + Usage: "Base URL of a GitHub Enterprise deployment to use for Login with GitHub.", + Flag: "oauth2-github-enterprise-base-url", + }, + }, + }, + OIDC: codersdk.OIDCConfig{ + AllowSignups: codersdk.DeploymentConfigField[bool]{ + Usage: "Whether new users can sign up with OIDC.", + Flag: "oidc-allow-signups", + Value: true, + }, + ClientID: codersdk.DeploymentConfigField[string]{ + Usage: "Client ID to use for Login with OIDC.", + Flag: "oidc-client-id", + }, + ClientSecret: codersdk.DeploymentConfigField[string]{ + Usage: "Client secret to use for Login with OIDC.", + Flag: "oidc-client-secret", + }, + EmailDomain: codersdk.DeploymentConfigField[string]{ + Usage: "Email domain that clients logging in with OIDC must match.", + Flag: "oidc-email-domain", + }, + IssuerURL: codersdk.DeploymentConfigField[string]{ + Usage: "Issuer URL to use for Login with OIDC.", + Flag: "oidc-issuer-url", + }, + Scopes: codersdk.DeploymentConfigField[[]string]{ + Usage: "Scopes to grant when authenticating with OIDC.", + Flag: "oidc-scopes", + Value: []string{oidc.ScopeOpenID, "profile", "email"}, + }, }, - OAuth2GithubAllowSignups: codersdk.DeploymentConfigField[bool]{ - Name: "OAuth2 GitHub Allow Signups", - Key: "oauth2.github.allow_signups", - Usage: "Whether new users can sign up with GitHub.", - Flag: "oauth2-github-allow-signups", - }, - OAuth2GithubEnterpriseBaseURL: codersdk.DeploymentConfigField[string]{ - Name: "OAuth2 GitHub Enterprise Base URL", - Key: "oauth2.github.enterprise_base_url", - Usage: "Base URL of a GitHub Enterprise deployment to use for Login with GitHub.", - Flag: "oauth2-github-enterprise-base-url", - }, - OIDCAllowSignups: codersdk.DeploymentConfigField[bool]{ - Name: "OIDC Allow Signups", - Key: "oidc.allow_signups", - Usage: "Whether new users can sign up with OIDC.", - Flag: "oidc-allow-signups", - Value: true, - }, - OIDCClientID: codersdk.DeploymentConfigField[string]{ - Name: "OIDC Client ID", - Key: "oidc.client_id", - Usage: "Client ID to use for Login with OIDC.", - Flag: "oidc-client-id", - }, - OIDCClientSecret: codersdk.DeploymentConfigField[string]{ - Name: "OIDC Client Secret", - Key: "oidc.client_secret", - Usage: "Client secret to use for Login with OIDC.", - Flag: "oidc-client-secret", - }, - OIDCEmailDomain: codersdk.DeploymentConfigField[string]{ - Name: "OIDC Email Domain", - Key: "oidc.email_domain", - Usage: "Email domain that clients logging in with OIDC must match.", - Flag: "oidc-email-domain", - }, - OIDCIssuerURL: codersdk.DeploymentConfigField[string]{ - Name: "OIDC Issuer URL", - Key: "oidc.issuer_url", - Usage: "Issuer URL to use for Login with OIDC.", - Flag: "oidc-issuer-url", - }, - OIDCScopes: codersdk.DeploymentConfigField[[]string]{ - Name: "OIDC Scopes", - Key: "oidc.scopes", - Usage: "Scopes to grant when authenticating with OIDC.", - Flag: "oidc-scopes", - Value: []string{oidc.ScopeOpenID, "profile", "email"}, - }, - TelemetryEnable: codersdk.DeploymentConfigField[bool]{ - Name: "Telemetry Enable", - Key: "telemetry.enable", - Usage: "Whether telemetry is enabled or not. Coder collects anonymized usage data to help improve our product.", - Flag: "telemetry", - Value: flag.Lookup("test.v") == nil, - }, - TelemetryTrace: codersdk.DeploymentConfigField[bool]{ - Name: "Telemetry Trace", - Key: "telemetry.trace", - Usage: "Whether Opentelemetry traces are sent to Coder. Coder collects anonymized application tracing to help improve our product. Disabling telemetry also disables this option.", - Flag: "telemetry-trace", - Value: flag.Lookup("test.v") == nil, - }, - TelemetryURL: codersdk.DeploymentConfigField[string]{ - Name: "Telemetry URL", - Key: "telemetry.url", - Usage: "URL to send telemetry.", - Flag: "telemetry-url", - Hidden: true, - Value: "https://telemetry.coder.com", - }, - TLSEnable: codersdk.DeploymentConfigField[bool]{ - Name: "TLS Enable", - Key: "tls.enable", - Usage: "Whether TLS will be enabled.", - Flag: "tls-enable", - }, - TLSCertFiles: codersdk.DeploymentConfigField[[]string]{ - Name: "TLS Certificate Files", - Key: "tls.cert_file", - Usage: "Path to each certificate for TLS. It requires a PEM-encoded file. To configure the listener to use a CA certificate, concatenate the primary certificate and the CA certificate together. The primary certificate should appear first in the combined file.", - Flag: "tls-cert-file", - }, - TLSClientCAFile: codersdk.DeploymentConfigField[string]{ - Name: "TLS Client CA Files", - Key: "tls.client_ca_file", - Usage: "PEM-encoded Certificate Authority file used for checking the authenticity of client", - Flag: "tls-client-ca-file", - }, - TLSClientAuth: codersdk.DeploymentConfigField[string]{ - Name: "TLS Client Auth", - Key: "tls.client_auth", - Usage: "Policy the server will follow for TLS Client Authentication. Accepted values are \"none\", \"request\", \"require-any\", \"verify-if-given\", or \"require-and-verify\".", - Flag: "tls-client-auth", - Value: "request", - }, - TLSKeyFiles: codersdk.DeploymentConfigField[[]string]{ - Name: "TLS Key Files", - Key: "tls.key_file", - Usage: "Paths to the private keys for each of the certificates. It requires a PEM-encoded file.", - Flag: "tls-key-file", - }, - TLSMinVersion: codersdk.DeploymentConfigField[string]{ - Name: "TLS Minimum Version", - Key: "tls.min_version", - Usage: "Minimum supported version of TLS. Accepted values are \"tls10\", \"tls11\", \"tls12\" or \"tls13\"", - Flag: "tls-min-version", - Value: "tls12", + + Telemetry: codersdk.TelemetryConfig{ + Enable: codersdk.DeploymentConfigField[bool]{ + Usage: "Whether telemetry is enabled or not. Coder collects anonymized usage data to help improve our product.", + Flag: "telemetry", + Value: flag.Lookup("test.v") == nil, + }, + Trace: codersdk.DeploymentConfigField[bool]{ + Usage: "Whether Opentelemetry traces are sent to Coder. Coder collects anonymized application tracing to help improve our product. Disabling telemetry also disables this option.", + Flag: "telemetry-trace", + Value: flag.Lookup("test.v") == nil, + }, + URL: codersdk.DeploymentConfigField[string]{ + Usage: "URL to send telemetry.", + Flag: "telemetry-url", + Hidden: true, + Value: "https://telemetry.coder.com", + }, + }, + TLS: codersdk.TLSConfig{ + Enable: codersdk.DeploymentConfigField[bool]{ + Usage: "Whether TLS will be enabled.", + Flag: "tls-enable", + }, + CertFiles: codersdk.DeploymentConfigField[[]string]{ + Usage: "Path to each certificate for TLS. It requires a PEM-encoded file. To configure the listener to use a CA certificate, concatenate the primary certificate and the CA certificate together. The primary certificate should appear first in the combined file.", + Flag: "tls-cert-file", + }, + ClientCAFile: codersdk.DeploymentConfigField[string]{ + Usage: "PEM-encoded Certificate Authority file used for checking the authenticity of client", + Flag: "tls-client-ca-file", + }, + ClientAuth: codersdk.DeploymentConfigField[string]{ + Usage: "Policy the server will follow for TLS Client Authentication. Accepted values are \"none\", \"request\", \"require-any\", \"verify-if-given\", or \"require-and-verify\".", + Flag: "tls-client-auth", + Value: "request", + }, + KeyFiles: codersdk.DeploymentConfigField[[]string]{ + Usage: "Paths to the private keys for each of the certificates. It requires a PEM-encoded file.", + Flag: "tls-key-file", + }, + MinVersion: codersdk.DeploymentConfigField[string]{ + Usage: "Minimum supported version of TLS. Accepted values are \"tls10\", \"tls11\", \"tls12\" or \"tls13\"", + Flag: "tls-min-version", + Value: "tls12", + }, }, TraceEnable: codersdk.DeploymentConfigField[bool]{ - Name: "Trace Enable", - Key: "trace", + Usage: "Whether application tracing data is collected.", Flag: "trace", }, SecureAuthCookie: codersdk.DeploymentConfigField[bool]{ - Name: "Secure Auth Cookie", - Key: "secure_auth_cookie", + Usage: "Controls if the 'Secure' property is set on browser session cookies.", Flag: "secure-auth-cookie", }, SSHKeygenAlgorithm: codersdk.DeploymentConfigField[string]{ - Name: "SSH Keygen Algorithm", - Key: "ssh_keygen_algorithm", + Usage: "The algorithm to use for generating ssh keys. Accepted values are \"ed25519\", \"ecdsa\", or \"rsa4096\".", Flag: "ssh-keygen-algorithm", Value: "ed25519", }, AutoImportTemplates: codersdk.DeploymentConfigField[[]string]{ - Name: "Auto Import Templates", - Key: "auto_import_templates", + Usage: "Templates to auto-import. Available auto-importable templates are: kubernetes", Flag: "auto-import-template", Hidden: true, }, MetricsCacheRefreshInterval: codersdk.DeploymentConfigField[time.Duration]{ - Name: "Metrics Cache Refresh Interval", - Key: "metrics_cache_refresh_interval", + Usage: "How frequently metrics are refreshed", Flag: "metrics-cache-refresh-interval", Hidden: true, Value: time.Hour, }, AgentStatRefreshInterval: codersdk.DeploymentConfigField[time.Duration]{ - Name: "Agent Stat Refresh Interval", - Key: "agent_stat_refresh_interval", + Usage: "How frequently agent stats are recorded", Flag: "agent-stats-refresh-interval", Hidden: true, Value: 10 * time.Minute, }, AuditLogging: codersdk.DeploymentConfigField[bool]{ - Name: "Audit Logging", - Key: "audit_logging", + Usage: "Specifies whether audit logging is enabled.", Flag: "audit-logging", Value: true, Enterprise: true, }, BrowserOnly: codersdk.DeploymentConfigField[bool]{ - Name: "Browser Only", - Key: "browser_only", + Usage: "Whether Coder only allows connections to workspaces via the browser.", Flag: "browser-only", Enterprise: true, }, SCIMAPIKey: codersdk.DeploymentConfigField[string]{ - Name: "SCIM API Key", - Key: "scim_api_key", Usage: "Enables SCIM and sets the authentication header for the built-in SCIM server. New users are automatically created with OIDC authentication.", Flag: "scim-auth-header", Enterprise: true, }, UserWorkspaceQuota: codersdk.DeploymentConfigField[int]{ - Name: "User Workspace Quota", - Key: "user_workspace_quota", + Usage: "Enables and sets a limit on how many workspaces each user can create.", Flag: "user-workspace-quota", Enterprise: true, @@ -394,104 +314,172 @@ func Config(flagset *pflag.FlagSet, vip *viper.Viper) (codersdk.DeploymentConfig } } - dcv := reflect.ValueOf(&dc).Elem() - t := dcv.Type() - for i := 0; i < t.NumField(); i++ { - fve := dcv.Field(i) - key := fve.FieldByName("Key").String() - value := fve.FieldByName("Value").Interface() + setConfig("", vip, &dc) + + return dc, nil +} +func setConfig(prefix string, vip *viper.Viper, target interface{}) { + val := reflect.ValueOf(target).Elem() + typ := val.Type() + if strings.HasPrefix(typ.Name(), "DeploymentConfigField") { + value := val.FieldByName("Value").Interface() switch value.(type) { case string: - fve.FieldByName("Value").SetString(vip.GetString(key)) + val.FieldByName("Value").SetString(vip.GetString(prefix)) case bool: - fve.FieldByName("Value").SetBool(vip.GetBool(key)) + val.FieldByName("Value").SetBool(vip.GetBool(prefix)) case int: - fve.FieldByName("Value").SetInt(int64(vip.GetInt(key))) + val.FieldByName("Value").SetInt(int64(vip.GetInt(prefix))) case time.Duration: - fve.FieldByName("Value").SetInt(int64(vip.GetDuration(key))) + val.FieldByName("Value").SetInt(int64(vip.GetDuration(prefix))) case []string: - // As of October 21st, 2022 we supported delimiting a string - // with a comma, but Viper only supports with a space. This - // is a small hack around it! - rawSlice := reflect.ValueOf(vip.GetStringSlice(key)).Interface() - slice, ok := rawSlice.([]string) - if !ok { - return dc, xerrors.Errorf("string slice is of type %T", rawSlice) - } - value := make([]string, 0, len(slice)) - for _, entry := range slice { - value = append(value, strings.Split(entry, ",")...) - } - fve.FieldByName("Value").Set(reflect.ValueOf(value)) + val.FieldByName("Value").Set(reflect.ValueOf(vip.GetStringSlice(prefix))) default: - return dc, xerrors.Errorf("unsupported type %T", value) + panic(fmt.Sprintf("unsupported type %T", value)) } + return } - return dc, nil + for i := 0; i < typ.NumField(); i++ { + fv := val.Field(i) + ft := fv.Type() + tag := typ.Field(i).Tag.Get("json") + var key string + if prefix == "" { + key = tag + } else { + key = fmt.Sprintf("%s.%s", prefix, tag) + } + switch ft.Kind() { + case reflect.Struct: + v := fv.Interface() + setConfig(key, vip, &v) + case reflect.Slice: + for j := 0; j < fv.Len(); j++ { + key := fmt.Sprintf("%s.%d", key, j) + v := fv.Index(j) + setConfig(key, vip, &v) + } + default: + panic(fmt.Sprintf("unsupported type %T", ft)) + } + } } func NewViper() *viper.Viper { dc := newConfig() - v := viper.New() - v.SetEnvPrefix("coder") - v.AutomaticEnv() - v.SetEnvKeyReplacer(strings.NewReplacer("-", "_", ".", "_")) - - dcv := reflect.ValueOf(dc) - t := dcv.Type() - for i := 0; i < t.NumField(); i++ { - fv := dcv.Field(i) - key := fv.FieldByName("Key").String() - value := fv.FieldByName("Value").Interface() - v.SetDefault(key, value) + vip := viper.New() + vip.SetEnvPrefix("coder") + vip.AutomaticEnv() + + setViperDefaults("", vip, dc) + + return vip +} + +func setViperDefaults(prefix string, vip *viper.Viper, target interface{}) { + val := reflect.ValueOf(target) + typ := val.Type() + if strings.HasPrefix(typ.Name(), "DeploymentConfigField") { + value := val.FieldByName("Value").Interface() + vip.SetDefault(prefix, value) + return } - return v + for i := 0; i < typ.NumField(); i++ { + fv := val.Field(i) + ft := fv.Type() + tag := typ.Field(i).Tag.Get("json") + var key string + if prefix == "" { + key = tag + } else { + key = fmt.Sprintf("%s.%s", prefix, tag) + } + switch ft.Kind() { + case reflect.Struct: + setViperDefaults(key, vip, fv.Interface()) + case reflect.Slice: + for j := 0; j < fv.Len(); j++ { + key := fmt.Sprintf("%s.%d", key, j) + setViperDefaults(key, vip, fv.Index(j)) + } + default: + panic(fmt.Sprintf("unsupported type %T", ft)) + } + } } //nolint:revive func AttachFlags(flagset *pflag.FlagSet, vip *viper.Viper, enterprise bool) { - dc := newConfig() - dcv := reflect.ValueOf(dc) - t := dcv.Type() - for i := 0; i < t.NumField(); i++ { - fv := dcv.Field(i) - isEnt := fv.FieldByName("Enterprise").Bool() + setFlags("", flagset, vip, newConfig(), enterprise) +} + +//nolint:revive +func setFlags(prefix string, flagset *pflag.FlagSet, vip *viper.Viper, target interface{}, enterprise bool) { + val := reflect.ValueOf(target) + typ := val.Type() + fmt.Println(typ.Name()) + if strings.HasPrefix(typ.Name(), "DeploymentConfigField") { + isEnt := val.FieldByName("Enterprise").Bool() if enterprise != isEnt { - continue + return } - key := fv.FieldByName("Key").String() - flg := fv.FieldByName("Flag").String() + flg := val.FieldByName("Flag").String() if flg == "" { - continue + return } - usage := fv.FieldByName("Usage").String() - usage = fmt.Sprintf("%s\n%s", usage, cliui.Styles.Placeholder.Render("Consumes $"+formatEnv(key))) - shorthand := fv.FieldByName("Shorthand").String() - hidden := fv.FieldByName("Hidden").Bool() - value := fv.FieldByName("Value").Interface() + usage := val.FieldByName("Usage").String() + usage = fmt.Sprintf("%s\n%s", usage, cliui.Styles.Placeholder.Render("Consumes $"+formatEnv(prefix))) + shorthand := val.FieldByName("Shorthand").String() + hidden := val.FieldByName("Hidden").Bool() + value := val.FieldByName("Value").Interface() switch value.(type) { case string: - _ = flagset.StringP(flg, shorthand, vip.GetString(key), usage) + _ = flagset.StringP(flg, shorthand, vip.GetString(prefix), usage) case bool: - _ = flagset.BoolP(flg, shorthand, vip.GetBool(key), usage) + _ = flagset.BoolP(flg, shorthand, vip.GetBool(prefix), usage) case int: - _ = flagset.IntP(flg, shorthand, vip.GetInt(key), usage) + _ = flagset.IntP(flg, shorthand, vip.GetInt(prefix), usage) case time.Duration: - _ = flagset.DurationP(flg, shorthand, vip.GetDuration(key), usage) + _ = flagset.DurationP(flg, shorthand, vip.GetDuration(prefix), usage) case []string: - _ = flagset.StringSliceP(flg, shorthand, vip.GetStringSlice(key), usage) + _ = flagset.StringSliceP(flg, shorthand, vip.GetStringSlice(prefix), usage) default: - continue + panic(fmt.Sprintf("unsupported type %T", typ)) } - _ = vip.BindPFlag(key, flagset.Lookup(flg)) + _ = vip.BindPFlag(prefix, flagset.Lookup(flg)) if hidden { _ = flagset.MarkHidden(flg) } + + return + } + + for i := 0; i < typ.NumField(); i++ { + fv := val.Field(i) + ft := fv.Type() + tag := typ.Field(i).Tag.Get("json") + var key string + if prefix == "" { + key = tag + } else { + key = fmt.Sprintf("%s.%s", prefix, tag) + } + switch ft.Kind() { + case reflect.Struct: + setFlags(key, flagset, vip, fv.Interface(), enterprise) + case reflect.Slice: + for j := 0; j < fv.Len(); j++ { + key := fmt.Sprintf("%s.%d", key, j) + setFlags(key, flagset, vip, fv.Index(j), enterprise) + } + default: + panic(fmt.Sprintf("unsupported type %T", ft)) + } } } diff --git a/coderd/deploymentconfig_test.go b/coderd/deploymentconfig_test.go index 2f03e655c671d..a4c9c9f4b6529 100644 --- a/coderd/deploymentconfig_test.go +++ b/coderd/deploymentconfig_test.go @@ -26,8 +26,8 @@ func TestDeploymentConfig(t *testing.T) { // values should be returned cfg.AccessURL.Value = hi // values should not be returned - cfg.OAuth2GithubClientSecret.Value = hi - cfg.OIDCClientSecret.Value = hi + cfg.OAuth2.Github.ClientSecret.Value = hi + cfg.OIDC.ClientSecret.Value = hi cfg.PostgresURL.Value = hi cfg.SCIMAPIKey.Value = hi @@ -40,8 +40,8 @@ func TestDeploymentConfig(t *testing.T) { // ensure normal values pass through require.EqualValues(t, hi, scrubbed.AccessURL.Value) // ensure secrets are removed - require.Empty(t, scrubbed.OAuth2GithubClientSecret.Value) - require.Empty(t, scrubbed.OIDCClientSecret.Value) + require.Empty(t, scrubbed.OAuth2.Github.ClientSecret.Value) + require.Empty(t, scrubbed.OIDC.ClientSecret.Value) require.Empty(t, scrubbed.PostgresURL.Value) require.Empty(t, scrubbed.SCIMAPIKey.Value) } diff --git a/codersdk/deploymentconfig.go b/codersdk/deploymentconfig.go index 5933ec7c36d03..c85b76e88e8b5 100644 --- a/codersdk/deploymentconfig.go +++ b/codersdk/deploymentconfig.go @@ -12,59 +12,97 @@ import ( // DeploymentConfig is the central configuration for the coder server. // Secret values should specify `json:"-"` to prevent them from being returned by the API. type DeploymentConfig struct { - AccessURL DeploymentConfigField[string] `json:"access_url"` - WildcardAccessURL DeploymentConfigField[string] `json:"wildcard_access_url"` - Address DeploymentConfigField[string] `json:"address"` - AutobuildPollInterval DeploymentConfigField[time.Duration] `json:"autobuild_poll_interval"` - DERPServerEnable DeploymentConfigField[bool] `json:"derp_server_enabled"` - DERPServerRegionID DeploymentConfigField[int] `json:"derp_server_region_id"` - DERPServerRegionCode DeploymentConfigField[string] `json:"derp_server_region_code"` - DERPServerRegionName DeploymentConfigField[string] `json:"derp_server_region_name"` - DERPServerSTUNAddresses DeploymentConfigField[[]string] `json:"derp_server_stun_address"` - DERPServerRelayURL DeploymentConfigField[string] `json:"derp_server_relay_address"` - DERPConfigURL DeploymentConfigField[string] `json:"derp_config_url"` - DERPConfigPath DeploymentConfigField[string] `json:"derp_config_path"` - PrometheusEnable DeploymentConfigField[bool] `json:"prometheus_enabled"` - PrometheusAddress DeploymentConfigField[string] `json:"prometheus_address"` - PprofEnable DeploymentConfigField[bool] `json:"pprof_enabled"` - PprofAddress DeploymentConfigField[string] `json:"pprof_address"` - ProxyTrustedHeaders DeploymentConfigField[[]string] `json:"proxy_trusted_headers"` - ProxyTrustedOrigins DeploymentConfigField[[]string] `json:"proxy_trusted_origins"` - CacheDirectory DeploymentConfigField[string] `json:"cache_directory"` - InMemoryDatabase DeploymentConfigField[bool] `json:"in_memory_database"` - ProvisionerDaemons DeploymentConfigField[int] `json:"provisioner_daemon_count"` - PostgresURL DeploymentConfigField[string] `json:"-"` - OAuth2GithubClientID DeploymentConfigField[string] `json:"oauth2_github_client_id"` - OAuth2GithubClientSecret DeploymentConfigField[string] `json:"-"` - OAuth2GithubAllowedOrgs DeploymentConfigField[[]string] `json:"oauth2_github_allowed_orgs"` - OAuth2GithubAllowedTeams DeploymentConfigField[[]string] `json:"oauth2_github_allowed_teams"` - OAuth2GithubAllowSignups DeploymentConfigField[bool] `json:"oauth2_github_allow_signups"` - OAuth2GithubEnterpriseBaseURL DeploymentConfigField[string] `json:"oauth2_github_enterprise_base_url"` - OIDCAllowSignups DeploymentConfigField[bool] `json:"oidc_allow_signups"` - OIDCClientID DeploymentConfigField[string] `json:"oidc_client_id"` - OIDCClientSecret DeploymentConfigField[string] `json:"-"` - OIDCEmailDomain DeploymentConfigField[string] `json:"oidc_email_domain"` - OIDCIssuerURL DeploymentConfigField[string] `json:"oidc_issuer_url"` - OIDCScopes DeploymentConfigField[[]string] `json:"oidc_scopes"` - TelemetryEnable DeploymentConfigField[bool] `json:"telemetry_enable"` - TelemetryTrace DeploymentConfigField[bool] `json:"telemetry_trace_enable"` - TelemetryURL DeploymentConfigField[string] `json:"telemetry_url"` - TLSEnable DeploymentConfigField[bool] `json:"tls_enable"` - TLSCertFiles DeploymentConfigField[[]string] `json:"tls_cert_files"` - TLSClientCAFile DeploymentConfigField[string] `json:"tls_client_ca_file"` - TLSClientAuth DeploymentConfigField[string] `json:"tls_client_auth"` - TLSKeyFiles DeploymentConfigField[[]string] `json:"tls_key_files"` - TLSMinVersion DeploymentConfigField[string] `json:"tls_min_version"` - TraceEnable DeploymentConfigField[bool] `json:"trace_enable"` - SecureAuthCookie DeploymentConfigField[bool] `json:"secure_auth_cookie"` - SSHKeygenAlgorithm DeploymentConfigField[string] `json:"ssh_keygen_algorithm"` - AutoImportTemplates DeploymentConfigField[[]string] `json:"auto_import_templates"` - MetricsCacheRefreshInterval DeploymentConfigField[time.Duration] `json:"metrics_cache_refresh_interval"` - AgentStatRefreshInterval DeploymentConfigField[time.Duration] `json:"agent_stat_refresh_interval"` - AuditLogging DeploymentConfigField[bool] `json:"audit_logging"` - BrowserOnly DeploymentConfigField[bool] `json:"browser_only"` - SCIMAPIKey DeploymentConfigField[string] `json:"-"` - UserWorkspaceQuota DeploymentConfigField[int] `json:"user_workspace_quota"` + AccessURL DeploymentConfigField[string] `json:"access_url"` + WildcardAccessURL DeploymentConfigField[string] `json:"wildcard_access_url"` + Address DeploymentConfigField[string] `json:"address"` + AutobuildPollInterval DeploymentConfigField[time.Duration] `json:"autobuild_poll_interval"` + DERP DERP `json:"derp"` + Prometheus PrometheusConfig `json:"prometheus"` + Pprof PprofConfig `json:"pprof"` + CacheDirectory DeploymentConfigField[string] `json:"cache_directory"` + InMemoryDatabase DeploymentConfigField[bool] `json:"in_memory_database"` + ProvisionerDaemons DeploymentConfigField[int] `json:"provisioner_daemon_count"` + PostgresURL DeploymentConfigField[string] `json:"pg_connection_url"` + OAuth2 OAuth2Config `json:"oauth2"` + OIDC OIDCConfig `json:"oidc"` + Telemetry TelemetryConfig `json:"telemetry"` + TLS TLSConfig `json:"tls"` + TraceEnable DeploymentConfigField[bool] `json:"trace_enable"` + SecureAuthCookie DeploymentConfigField[bool] `json:"secure_auth_cookie"` + SSHKeygenAlgorithm DeploymentConfigField[string] `json:"ssh_keygen_algorithm"` + AutoImportTemplates DeploymentConfigField[[]string] `json:"auto_import_templates"` + MetricsCacheRefreshInterval DeploymentConfigField[time.Duration] `json:"metrics_cache_refresh_interval"` + AgentStatRefreshInterval DeploymentConfigField[time.Duration] `json:"agent_stat_refresh_interval"` + AuditLogging DeploymentConfigField[bool] `json:"audit_logging"` + BrowserOnly DeploymentConfigField[bool] `json:"browser_only"` + SCIMAPIKey DeploymentConfigField[string] `json:"scim_api_key"` + UserWorkspaceQuota DeploymentConfigField[int] `json:"user_workspace_quota"` +} + +type DERP struct { + Server DERPServerConfig `json:"server"` + Config DERPConfig `json:"config"` +} + +type DERPServerConfig struct { + Enable DeploymentConfigField[bool] `json:"enabled"` + RegionID DeploymentConfigField[int] `json:"region_id"` + RegionCode DeploymentConfigField[string] `json:"region_code"` + RegionName DeploymentConfigField[string] `json:"region_name"` + STUNAddresses DeploymentConfigField[[]string] `json:"stun_address"` + RelayAddress DeploymentConfigField[string] `json:"relay_address"` +} + +type DERPConfig struct { + URL DeploymentConfigField[string] `json:"url"` + Path DeploymentConfigField[string] `json:"path"` +} + +type PrometheusConfig struct { + Enable DeploymentConfigField[bool] `json:"enabled"` + Address DeploymentConfigField[string] `json:"address"` +} + +type PprofConfig struct { + Enable DeploymentConfigField[bool] `json:"enabled"` + Address DeploymentConfigField[string] `json:"address"` +} + +type OAuth2Config struct { + Github OAuth2GithubConfig `json:"github"` +} + +type OAuth2GithubConfig struct { + ClientID DeploymentConfigField[string] `json:"client_id"` + ClientSecret DeploymentConfigField[string] `json:"client_secret"` + AllowedOrganizations DeploymentConfigField[[]string] `json:"allowed_organizations"` + AllowedTeams DeploymentConfigField[[]string] `json:"allowed_teams"` + AllowSignups DeploymentConfigField[bool] `json:"allow_signups"` + EnterpriseBaseURL DeploymentConfigField[string] `json:"enterprise_base_url"` +} + +type OIDCConfig struct { + AllowSignups DeploymentConfigField[bool] `json:"allow_signups"` + ClientID DeploymentConfigField[string] `json:"client_id"` + ClientSecret DeploymentConfigField[string] `json:"client_secret"` + EmailDomain DeploymentConfigField[string] `json:"email_domain"` + IssuerURL DeploymentConfigField[string] `json:"issuer_url"` + Scopes DeploymentConfigField[[]string] `json:"scopes"` +} + +type TelemetryConfig struct { + Enable DeploymentConfigField[bool] `json:"enabled"` + Trace DeploymentConfigField[bool] `json:"trace"` + URL DeploymentConfigField[string] `json:"url"` +} + +type TLSConfig struct { + Enable DeploymentConfigField[bool] `json:"enable"` + CertFiles DeploymentConfigField[[]string] `json:"cert_files"` + ClientAuth DeploymentConfigField[string] `json:"client_auth"` + ClientCAFile DeploymentConfigField[string] `json:"client_ca_file"` + KeyFiles DeploymentConfigField[[]string] `json:"key_files"` + MinVersion DeploymentConfigField[string] `json:"min_version"` } type Flaggable interface { @@ -72,8 +110,7 @@ type Flaggable interface { } type DeploymentConfigField[T Flaggable] struct { - Key string `json:"key"` - // Name appears in the deployment UI. + // Key string `json:"key"` Name string `json:"name"` Usage string `json:"usage"` Flag string `json:"flag"` From d84d377f98a45e938b1c418be837d93ef12786b4 Mon Sep 17 00:00:00 2001 From: Garrett Date: Mon, 24 Oct 2022 15:50:20 +0000 Subject: [PATCH 02/16] update to main --- cli/deployment/config.go | 95 +++++++++++++++++++++++++++++------- codersdk/deploymentconfig.go | 5 +- 2 files changed, 81 insertions(+), 19 deletions(-) diff --git a/cli/deployment/config.go b/cli/deployment/config.go index 5b37570cbaa36..7040c4e8f155a 100644 --- a/cli/deployment/config.go +++ b/cli/deployment/config.go @@ -22,20 +22,24 @@ import ( func newConfig() codersdk.DeploymentConfig { return codersdk.DeploymentConfig{ AccessURL: codersdk.DeploymentConfigField[string]{ + Name: "Access URL", Usage: "External URL to access your deployment. This must be accessible by all provisioned workspaces.", Flag: "access-url", }, WildcardAccessURL: codersdk.DeploymentConfigField[string]{ + Name: "Wildcard Access URL", Usage: "Specifies the wildcard hostname to use for workspace applications in the form \"*.example.com\".", Flag: "wildcard-access-url", }, Address: codersdk.DeploymentConfigField[string]{ + Name: "Address", Usage: "Bind address of the server.", Flag: "address", Shorthand: "a", Value: "127.0.0.1:3000", }, AutobuildPollInterval: codersdk.DeploymentConfigField[time.Duration]{ + Name: "Autobuild Poll Interval", Usage: "Interval to poll for scheduled workspace builds.", Flag: "autobuild-poll-interval", Hidden: true, @@ -44,42 +48,50 @@ func newConfig() codersdk.DeploymentConfig { DERP: codersdk.DERP{ Server: codersdk.DERPServerConfig{ Enable: codersdk.DeploymentConfigField[bool]{ + Name: "DERP Server Enable", Usage: "Whether to enable or disable the embedded DERP relay server.", Flag: "derp-server-enable", Value: true, }, RegionID: codersdk.DeploymentConfigField[int]{ + Name: "DERP Server Region ID", Usage: "Region ID to use for the embedded DERP server.", Flag: "derp-server-region-id", Value: 999, }, RegionCode: codersdk.DeploymentConfigField[string]{ + Name: "DERP Server Region Code", Usage: "Region code to use for the embedded DERP server.", Flag: "derp-server-region-code", Value: "coder", }, RegionName: codersdk.DeploymentConfigField[string]{ + Name: "DERP Server Region Name", Usage: "Region name that for the embedded DERP server.", Flag: "derp-server-region-name", Value: "Coder Embedded Relay", }, STUNAddresses: codersdk.DeploymentConfigField[[]string]{ + Name: "DERP Server STUN Addresses", Usage: "Addresses for STUN servers to establish P2P connections. Set empty to disable P2P connections.", Flag: "derp-server-stun-addresses", Value: []string{"stun.l.google.com:19302"}, }, - RelayAddress: codersdk.DeploymentConfigField[string]{ - Usage: "An HTTP address that is accessible by other replicas to relay DERP traffic. Required for high availability.", - Flag: "derp-server-relay-address", + RelayURL: codersdk.DeploymentConfigField[string]{ + Name: "DERP Server Relay URL", + Usage: "An HTTP URL that is accessible by other replicas to relay DERP traffic. Required for high availability.", + Flag: "derp-server-relay-url", Enterprise: true, }, }, Config: codersdk.DERPConfig{ URL: codersdk.DeploymentConfigField[string]{ + Name: "DERP Config URL", Usage: "URL to fetch a DERP mapping on startup. See: https://tailscale.com/kb/1118/custom-derp-servers/", Flag: "derp-config-url", }, Path: codersdk.DeploymentConfigField[string]{ + Name: "DERP Config Path", Usage: "Path to read a DERP mapping from. See: https://tailscale.com/kb/1118/custom-derp-servers/", Flag: "derp-config-path", }, @@ -87,10 +99,12 @@ func newConfig() codersdk.DeploymentConfig { }, Prometheus: codersdk.PrometheusConfig{ Enable: codersdk.DeploymentConfigField[bool]{ + Name: "Prometheus Enable", Usage: "Serve prometheus metrics on the address defined by prometheus address.", Flag: "prometheus-enable", }, Address: codersdk.DeploymentConfigField[string]{ + Name: "Prometheus Address", Usage: "The bind address to serve prometheus metrics.", Flag: "prometheus-address", Value: "127.0.0.1:2112", @@ -98,61 +112,79 @@ func newConfig() codersdk.DeploymentConfig { }, Pprof: codersdk.PprofConfig{ Enable: codersdk.DeploymentConfigField[bool]{ + Name: "Pprof Enable", Usage: "Serve pprof metrics on the address defined by pprof address.", Flag: "pprof-enable", }, Address: codersdk.DeploymentConfigField[string]{ + Name: "Pprof Address", Usage: "The bind address to serve pprof.", Flag: "pprof-address", Value: "127.0.0.1:6060", }, }, + ProxyTrustedHeaders: codersdk.DeploymentConfigField[[]string]{ + Name: "Proxy Trusted Headers", + Flag: "proxy-trusted-headers", + Usage: "Headers to trust for forwarding IP addresses. e.g. Cf-Connecting-IP True-Client-Ip, X-Forwarded-for", + }, + ProxyTrustedOrigins: codersdk.DeploymentConfigField[[]string]{ + Name: "Proxy Trusted Origins", + Flag: "proxy-trusted-origins", + Usage: "Origin addresses to respect \"proxy-trusted-headers\". e.g. example.com", + }, CacheDirectory: codersdk.DeploymentConfigField[string]{ - + Name: "Cache Directory", Usage: "The directory to cache temporary files. If unspecified and $CACHE_DIRECTORY is set, it will be used for compatibility with systemd.", Flag: "cache-dir", Value: defaultCacheDir(), }, InMemoryDatabase: codersdk.DeploymentConfigField[bool]{ - + Name: "In Memory Database", Usage: "Controls whether data will be stored in an in-memory database.", Flag: "in-memory", Hidden: true, }, ProvisionerDaemons: codersdk.DeploymentConfigField[int]{ - + Name: "Provisioner Daemons", Usage: "Number of provisioner daemons to create on start. If builds are stuck in queued state for a long time, consider increasing this.", Flag: "provisioner-daemons", Value: 3, }, PostgresURL: codersdk.DeploymentConfigField[string]{ - + Name: "Postgres Connection URL", Usage: "URL of a PostgreSQL database. If empty, PostgreSQL binaries will be downloaded from Maven (https://repo1.maven.org/maven2) and store all data in the config root. Access the built-in database with \"coder server postgres-builtin-url\".", Flag: "postgres-url", }, OAuth2: codersdk.OAuth2Config{ Github: codersdk.OAuth2GithubConfig{ ClientID: codersdk.DeploymentConfigField[string]{ + Name: "OAuth2 GitHub Client ID", Usage: "Client ID for Login with GitHub.", Flag: "oauth2-github-client-id", }, ClientSecret: codersdk.DeploymentConfigField[string]{ + Name: "OAuth2 GitHub Client Secret", Usage: "Client secret for Login with GitHub.", Flag: "oauth2-github-client-secret", }, AllowedOrganizations: codersdk.DeploymentConfigField[[]string]{ + Name: "OAuth2 GitHub Allowed Orgs", Usage: "Organizations the user must be a member of to Login with GitHub.", Flag: "oauth2-github-allowed-orgs", }, AllowedTeams: codersdk.DeploymentConfigField[[]string]{ + Name: "OAuth2 GitHub Allowed Teams", Usage: "Teams inside organizations the user must be a member of to Login with GitHub. Structured as: /.", Flag: "oauth2-github-allowed-teams", }, AllowSignups: codersdk.DeploymentConfigField[bool]{ + Name: "OAuth2 GitHub Allow Signups", Usage: "Whether new users can sign up with GitHub.", Flag: "oauth2-github-allow-signups", }, EnterpriseBaseURL: codersdk.DeploymentConfigField[string]{ + Name: "OAuth2 GitHub Enterprise Base URL", Usage: "Base URL of a GitHub Enterprise deployment to use for Login with GitHub.", Flag: "oauth2-github-enterprise-base-url", }, @@ -160,27 +192,33 @@ func newConfig() codersdk.DeploymentConfig { }, OIDC: codersdk.OIDCConfig{ AllowSignups: codersdk.DeploymentConfigField[bool]{ + Name: "OIDC Allow Signups", Usage: "Whether new users can sign up with OIDC.", Flag: "oidc-allow-signups", Value: true, }, ClientID: codersdk.DeploymentConfigField[string]{ + Name: "OIDC Client ID", Usage: "Client ID to use for Login with OIDC.", Flag: "oidc-client-id", }, ClientSecret: codersdk.DeploymentConfigField[string]{ + Name: "OIDC Client Secret", Usage: "Client secret to use for Login with OIDC.", Flag: "oidc-client-secret", }, EmailDomain: codersdk.DeploymentConfigField[string]{ + Name: "OIDC Email Domain", Usage: "Email domain that clients logging in with OIDC must match.", Flag: "oidc-email-domain", }, IssuerURL: codersdk.DeploymentConfigField[string]{ + Name: "OIDC Issuer URL", Usage: "Issuer URL to use for Login with OIDC.", Flag: "oidc-issuer-url", }, Scopes: codersdk.DeploymentConfigField[[]string]{ + Name: "OIDC Scopes", Usage: "Scopes to grant when authenticating with OIDC.", Flag: "oidc-scopes", Value: []string{oidc.ScopeOpenID, "profile", "email"}, @@ -189,16 +227,19 @@ func newConfig() codersdk.DeploymentConfig { Telemetry: codersdk.TelemetryConfig{ Enable: codersdk.DeploymentConfigField[bool]{ + Name: "Telemetry Enable", Usage: "Whether telemetry is enabled or not. Coder collects anonymized usage data to help improve our product.", Flag: "telemetry", Value: flag.Lookup("test.v") == nil, }, Trace: codersdk.DeploymentConfigField[bool]{ + Name: "Telemetry Trace", Usage: "Whether Opentelemetry traces are sent to Coder. Coder collects anonymized application tracing to help improve our product. Disabling telemetry also disables this option.", Flag: "telemetry-trace", Value: flag.Lookup("test.v") == nil, }, URL: codersdk.DeploymentConfigField[string]{ + Name: "Telemetry URL", Usage: "URL to send telemetry.", Flag: "telemetry-url", Hidden: true, @@ -207,88 +248,95 @@ func newConfig() codersdk.DeploymentConfig { }, TLS: codersdk.TLSConfig{ Enable: codersdk.DeploymentConfigField[bool]{ + Name: "TLS Enable", Usage: "Whether TLS will be enabled.", Flag: "tls-enable", }, CertFiles: codersdk.DeploymentConfigField[[]string]{ + Name: "TLS Certificate Files", Usage: "Path to each certificate for TLS. It requires a PEM-encoded file. To configure the listener to use a CA certificate, concatenate the primary certificate and the CA certificate together. The primary certificate should appear first in the combined file.", Flag: "tls-cert-file", }, ClientCAFile: codersdk.DeploymentConfigField[string]{ + Name: "TLS Client CA Files", Usage: "PEM-encoded Certificate Authority file used for checking the authenticity of client", Flag: "tls-client-ca-file", }, ClientAuth: codersdk.DeploymentConfigField[string]{ + Name: "TLS Client Auth", Usage: "Policy the server will follow for TLS Client Authentication. Accepted values are \"none\", \"request\", \"require-any\", \"verify-if-given\", or \"require-and-verify\".", Flag: "tls-client-auth", Value: "request", }, KeyFiles: codersdk.DeploymentConfigField[[]string]{ + Name: "TLS Key Files", Usage: "Paths to the private keys for each of the certificates. It requires a PEM-encoded file.", Flag: "tls-key-file", }, MinVersion: codersdk.DeploymentConfigField[string]{ + Name: "TLS Minimum Version", Usage: "Minimum supported version of TLS. Accepted values are \"tls10\", \"tls11\", \"tls12\" or \"tls13\"", Flag: "tls-min-version", Value: "tls12", }, }, TraceEnable: codersdk.DeploymentConfigField[bool]{ - + Name: "Trace Enable", Usage: "Whether application tracing data is collected.", Flag: "trace", }, SecureAuthCookie: codersdk.DeploymentConfigField[bool]{ - + Name: "Secure Auth Cookie", Usage: "Controls if the 'Secure' property is set on browser session cookies.", Flag: "secure-auth-cookie", }, SSHKeygenAlgorithm: codersdk.DeploymentConfigField[string]{ - + Name: "SSH Keygen Algorithm", Usage: "The algorithm to use for generating ssh keys. Accepted values are \"ed25519\", \"ecdsa\", or \"rsa4096\".", Flag: "ssh-keygen-algorithm", Value: "ed25519", }, AutoImportTemplates: codersdk.DeploymentConfigField[[]string]{ - + Name: "Auto Import Templates", Usage: "Templates to auto-import. Available auto-importable templates are: kubernetes", Flag: "auto-import-template", Hidden: true, }, MetricsCacheRefreshInterval: codersdk.DeploymentConfigField[time.Duration]{ - + Name: "Metrics Cache Refresh Interval", Usage: "How frequently metrics are refreshed", Flag: "metrics-cache-refresh-interval", Hidden: true, Value: time.Hour, }, AgentStatRefreshInterval: codersdk.DeploymentConfigField[time.Duration]{ - + Name: "Agent Stat Refresh Interval", Usage: "How frequently agent stats are recorded", Flag: "agent-stats-refresh-interval", Hidden: true, Value: 10 * time.Minute, }, AuditLogging: codersdk.DeploymentConfigField[bool]{ - + Name: "Audit Logging", Usage: "Specifies whether audit logging is enabled.", Flag: "audit-logging", Value: true, Enterprise: true, }, BrowserOnly: codersdk.DeploymentConfigField[bool]{ - + Name: "Browser Only", Usage: "Whether Coder only allows connections to workspaces via the browser.", Flag: "browser-only", Enterprise: true, }, SCIMAPIKey: codersdk.DeploymentConfigField[string]{ + Name: "SCIM API Key", Usage: "Enables SCIM and sets the authentication header for the built-in SCIM server. New users are automatically created with OIDC authentication.", Flag: "scim-auth-header", Enterprise: true, }, UserWorkspaceQuota: codersdk.DeploymentConfigField[int]{ - + Name: "User Workspace Quota", Usage: "Enables and sets a limit on how many workspaces each user can create.", Flag: "user-workspace-quota", Enterprise: true, @@ -334,7 +382,19 @@ func setConfig(prefix string, vip *viper.Viper, target interface{}) { case time.Duration: val.FieldByName("Value").SetInt(int64(vip.GetDuration(prefix))) case []string: - val.FieldByName("Value").Set(reflect.ValueOf(vip.GetStringSlice(prefix))) + // As of October 21st, 2022 we supported delimiting a string + // with a comma, but Viper only supports with a space. This + // is a small hack around it! + rawSlice := reflect.ValueOf(vip.GetStringSlice(prefix)).Interface() + slice, ok := rawSlice.([]string) + if !ok { + panic(fmt.Sprintf("string slice is of type %T", rawSlice)) + } + value := make([]string, 0, len(slice)) + for _, entry := range slice { + value = append(value, strings.Split(entry, ",")...) + } + val.FieldByName("Value").Set(reflect.ValueOf(value)) default: panic(fmt.Sprintf("unsupported type %T", value)) } @@ -372,6 +432,7 @@ func NewViper() *viper.Viper { vip := viper.New() vip.SetEnvPrefix("coder") vip.AutomaticEnv() + vip.SetEnvKeyReplacer(strings.NewReplacer("-", "_", ".", "_")) setViperDefaults("", vip, dc) diff --git a/codersdk/deploymentconfig.go b/codersdk/deploymentconfig.go index c85b76e88e8b5..c97082ae9c456 100644 --- a/codersdk/deploymentconfig.go +++ b/codersdk/deploymentconfig.go @@ -19,6 +19,8 @@ type DeploymentConfig struct { DERP DERP `json:"derp"` Prometheus PrometheusConfig `json:"prometheus"` Pprof PprofConfig `json:"pprof"` + ProxyTrustedHeaders DeploymentConfigField[[]string] `json:"proxy_trusted_headers"` + ProxyTrustedOrigins DeploymentConfigField[[]string] `json:"proxy_trusted_origin"` CacheDirectory DeploymentConfigField[string] `json:"cache_directory"` InMemoryDatabase DeploymentConfigField[bool] `json:"in_memory_database"` ProvisionerDaemons DeploymentConfigField[int] `json:"provisioner_daemon_count"` @@ -50,7 +52,7 @@ type DERPServerConfig struct { RegionCode DeploymentConfigField[string] `json:"region_code"` RegionName DeploymentConfigField[string] `json:"region_name"` STUNAddresses DeploymentConfigField[[]string] `json:"stun_address"` - RelayAddress DeploymentConfigField[string] `json:"relay_address"` + RelayURL DeploymentConfigField[string] `json:"relay_address"` } type DERPConfig struct { @@ -110,7 +112,6 @@ type Flaggable interface { } type DeploymentConfigField[T Flaggable] struct { - // Key string `json:"key"` Name string `json:"name"` Usage string `json:"usage"` Flag string `json:"flag"` From b1876bbf364f4975ab6e85872d117fcbdb363727 Mon Sep 17 00:00:00 2001 From: Garrett Date: Mon, 24 Oct 2022 15:52:32 +0000 Subject: [PATCH 03/16] fix tests --- cli/deployment/config.go | 2 +- cli/deployment/config_test.go | 70 +++++++++++++++++------------------ codersdk/deploymentconfig.go | 12 +++--- 3 files changed, 42 insertions(+), 42 deletions(-) diff --git a/cli/deployment/config.go b/cli/deployment/config.go index 7040c4e8f155a..6e849e811bc16 100644 --- a/cli/deployment/config.go +++ b/cli/deployment/config.go @@ -168,7 +168,7 @@ func newConfig() codersdk.DeploymentConfig { Usage: "Client secret for Login with GitHub.", Flag: "oauth2-github-client-secret", }, - AllowedOrganizations: codersdk.DeploymentConfigField[[]string]{ + AllowedOrgs: codersdk.DeploymentConfigField[[]string]{ Name: "OAuth2 GitHub Allowed Orgs", Usage: "Organizations the user must be a member of to Login with GitHub.", Flag: "oauth2-github-allowed-orgs", diff --git a/cli/deployment/config_test.go b/cli/deployment/config_test.go index da67f486c8153..d0812284c1c63 100644 --- a/cli/deployment/config_test.go +++ b/cli/deployment/config_test.go @@ -43,15 +43,15 @@ func TestConfig(t *testing.T) { require.Equal(t, config.Address.Value, "0.0.0.0:8443") require.Equal(t, config.AccessURL.Value, "https://dev.coder.com") require.Equal(t, config.PostgresURL.Value, "some-url") - require.Equal(t, config.PprofAddress.Value, "something") - require.Equal(t, config.PprofEnable.Value, true) - require.Equal(t, config.PrometheusAddress.Value, "hello-world") - require.Equal(t, config.PrometheusEnable.Value, true) + require.Equal(t, config.Pprof.Address.Value, "something") + require.Equal(t, config.Pprof.Enable.Value, true) + require.Equal(t, config.Prometheus.Address.Value, "hello-world") + require.Equal(t, config.Prometheus.Enable.Value, true) require.Equal(t, config.ProvisionerDaemons.Value, 5) require.Equal(t, config.SecureAuthCookie.Value, true) require.Equal(t, config.SSHKeygenAlgorithm.Value, "potato") - require.Equal(t, config.TelemetryEnable.Value, false) - require.Equal(t, config.TelemetryTrace.Value, false) + require.Equal(t, config.Telemetry.Enable.Value, false) + require.Equal(t, config.Telemetry.Trace.Value, false) require.Equal(t, config.WildcardAccessURL.Value, "something-wildcard.com") }, }, { @@ -67,14 +67,14 @@ func TestConfig(t *testing.T) { "CODER_DERP_SERVER_STUN_ADDRESSES": "google.org", }, Valid: func(config codersdk.DeploymentConfig) { - require.Equal(t, config.DERPConfigPath.Value, "/example/path") - require.Equal(t, config.DERPConfigURL.Value, "https://google.com") - require.Equal(t, config.DERPServerEnable.Value, false) - require.Equal(t, config.DERPServerRegionCode.Value, "something") - require.Equal(t, config.DERPServerRegionID.Value, 123) - require.Equal(t, config.DERPServerRegionName.Value, "Code-Land") - require.Equal(t, config.DERPServerRelayURL.Value, "1.1.1.1") - require.Equal(t, config.DERPServerSTUNAddresses.Value, []string{"google.org"}) + require.Equal(t, config.DERP.Config.Path.Value, "/example/path") + require.Equal(t, config.DERP.Config.URL.Value, "https://google.com") + require.Equal(t, config.DERP.Server.Enable.Value, false) + require.Equal(t, config.DERP.Server.RegionCode.Value, "something") + require.Equal(t, config.DERP.Server.RegionID.Value, 123) + require.Equal(t, config.DERP.Server.RegionName.Value, "Code-Land") + require.Equal(t, config.DERP.Server.RelayURL.Value, "1.1.1.1") + require.Equal(t, config.DERP.Server.STUNAddresses.Value, []string{"google.org"}) }, }, { Name: "Enterprise", @@ -101,18 +101,18 @@ func TestConfig(t *testing.T) { "CODER_TLS_MIN_VERSION": "tls10", }, Valid: func(config codersdk.DeploymentConfig) { - require.Len(t, config.TLSCertFiles.Value, 2) - require.Equal(t, config.TLSCertFiles.Value[0], "/etc/acme-sh/dev.coder.com") - require.Equal(t, config.TLSCertFiles.Value[1], "/etc/acme-sh/*.dev.coder.com") + require.Len(t, config.TLS.CertFiles.Value, 2) + require.Equal(t, config.TLS.CertFiles.Value[0], "/etc/acme-sh/dev.coder.com") + require.Equal(t, config.TLS.CertFiles.Value[1], "/etc/acme-sh/*.dev.coder.com") - require.Len(t, config.TLSKeyFiles.Value, 2) - require.Equal(t, config.TLSKeyFiles.Value[0], "/etc/acme-sh/dev.coder.com") - require.Equal(t, config.TLSKeyFiles.Value[1], "/etc/acme-sh/*.dev.coder.com") + require.Len(t, config.TLS.KeyFiles.Value, 2) + require.Equal(t, config.TLS.KeyFiles.Value[0], "/etc/acme-sh/dev.coder.com") + require.Equal(t, config.TLS.KeyFiles.Value[1], "/etc/acme-sh/*.dev.coder.com") - require.Equal(t, config.TLSClientAuth.Value, "/some/path") - require.Equal(t, config.TLSClientCAFile.Value, "/some/path") - require.Equal(t, config.TLSEnable.Value, true) - require.Equal(t, config.TLSMinVersion.Value, "tls10") + require.Equal(t, config.TLS.ClientAuth.Value, "/some/path") + require.Equal(t, config.TLS.ClientCAFile.Value, "/some/path") + require.Equal(t, config.TLS.Enable.Value, true) + require.Equal(t, config.TLS.MinVersion.Value, "tls10") }, }, { Name: "OIDC", @@ -125,12 +125,12 @@ func TestConfig(t *testing.T) { "CODER_OIDC_SCOPES": "something,here", }, Valid: func(config codersdk.DeploymentConfig) { - require.Equal(t, config.OIDCIssuerURL.Value, "https://accounts.google.com") - require.Equal(t, config.OIDCEmailDomain.Value, "coder.com") - require.Equal(t, config.OIDCClientID.Value, "client") - require.Equal(t, config.OIDCClientSecret.Value, "secret") - require.Equal(t, config.OIDCAllowSignups.Value, false) - require.Equal(t, config.OIDCScopes.Value, []string{"something", "here"}) + require.Equal(t, config.OIDC.IssuerURL.Value, "https://accounts.google.com") + require.Equal(t, config.OIDC.EmailDomain.Value, "coder.com") + require.Equal(t, config.OIDC.ClientID.Value, "client") + require.Equal(t, config.OIDC.ClientSecret.Value, "secret") + require.Equal(t, config.OIDC.AllowSignups.Value, false) + require.Equal(t, config.OIDC.Scopes.Value, []string{"something", "here"}) }, }, { Name: "GitHub", @@ -142,11 +142,11 @@ func TestConfig(t *testing.T) { "CODER_OAUTH2_GITHUB_ALLOW_SIGNUPS": "true", }, Valid: func(config codersdk.DeploymentConfig) { - require.Equal(t, config.OAuth2GithubClientID.Value, "client") - require.Equal(t, config.OAuth2GithubClientSecret.Value, "secret") - require.Equal(t, []string{"coder"}, config.OAuth2GithubAllowedOrgs.Value) - require.Equal(t, []string{"coder"}, config.OAuth2GithubAllowedTeams.Value) - require.Equal(t, config.OAuth2GithubAllowSignups.Value, true) + require.Equal(t, config.OAuth2.Github.ClientID.Value, "client") + require.Equal(t, config.OAuth2.Github.ClientSecret.Value, "secret") + require.Equal(t, []string{"coder"}, config.OAuth2.Github.AllowedOrgs.Value) + require.Equal(t, []string{"coder"}, config.OAuth2.Github.AllowedTeams.Value) + require.Equal(t, config.OAuth2.Github.AllowSignups.Value, true) }, }} { tc := tc diff --git a/codersdk/deploymentconfig.go b/codersdk/deploymentconfig.go index c97082ae9c456..b3eb9a8c3d805 100644 --- a/codersdk/deploymentconfig.go +++ b/codersdk/deploymentconfig.go @@ -75,12 +75,12 @@ type OAuth2Config struct { } type OAuth2GithubConfig struct { - ClientID DeploymentConfigField[string] `json:"client_id"` - ClientSecret DeploymentConfigField[string] `json:"client_secret"` - AllowedOrganizations DeploymentConfigField[[]string] `json:"allowed_organizations"` - AllowedTeams DeploymentConfigField[[]string] `json:"allowed_teams"` - AllowSignups DeploymentConfigField[bool] `json:"allow_signups"` - EnterpriseBaseURL DeploymentConfigField[string] `json:"enterprise_base_url"` + ClientID DeploymentConfigField[string] `json:"client_id"` + ClientSecret DeploymentConfigField[string] `json:"client_secret"` + AllowedOrgs DeploymentConfigField[[]string] `json:"allowed_orgs"` + AllowedTeams DeploymentConfigField[[]string] `json:"allowed_teams"` + AllowSignups DeploymentConfigField[bool] `json:"allow_signups"` + EnterpriseBaseURL DeploymentConfigField[string] `json:"enterprise_base_url"` } type OIDCConfig struct { From 426e6383d03746770022a464221d44631519fab5 Mon Sep 17 00:00:00 2001 From: Garrett Date: Mon, 24 Oct 2022 15:56:16 +0000 Subject: [PATCH 04/16] fix server --- cli/server.go | 94 +++++++++++++++++++++++++-------------------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/cli/server.go b/cli/server.go index e937c2ac80aeb..dd67555ecac8a 100644 --- a/cli/server.go +++ b/cli/server.go @@ -117,11 +117,11 @@ func Server(vip *viper.Viper, newAPI func(context.Context, *coderd.Options) (*co // Coder tracing should be disabled if telemetry is disabled unless // --telemetry-trace was explicitly provided. - shouldCoderTrace := cfg.TelemetryEnable.Value && !isTest() + shouldCoderTrace := cfg.Telemetry.Enable.Value && !isTest() // Only override if telemetryTraceEnable was specifically set. // By default we want it to be controlled by telemetryEnable. if cmd.Flags().Changed("telemetry-trace") { - shouldCoderTrace = cfg.TelemetryTrace.Value + shouldCoderTrace = cfg.Telemetry.Trace.Value } if cfg.TraceEnable.Value || shouldCoderTrace { @@ -174,13 +174,13 @@ func Server(vip *viper.Viper, newAPI func(context.Context, *coderd.Options) (*co defer listener.Close() var tlsConfig *tls.Config - if cfg.TLSEnable.Value { + if cfg.TLS.Enable.Value { tlsConfig, err = configureTLS( - cfg.TLSMinVersion.Value, - cfg.TLSClientAuth.Value, - cfg.TLSCertFiles.Value, - cfg.TLSKeyFiles.Value, - cfg.TLSClientCAFile.Value, + cfg.TLS.MinVersion.Value, + cfg.TLS.ClientAuth.Value, + cfg.TLS.CertFiles.Value, + cfg.TLS.KeyFiles.Value, + cfg.TLS.ClientCAFile.Value, ) if err != nil { return xerrors.Errorf("configure tls: %w", err) @@ -202,7 +202,7 @@ func Server(vip *viper.Viper, newAPI func(context.Context, *coderd.Options) (*co Scheme: "http", Host: tcpAddr.String(), } - if cfg.TLSEnable.Value { + if cfg.TLS.Enable.Value { localURL.Scheme = "https" } @@ -297,22 +297,22 @@ func Server(vip *viper.Viper, newAPI func(context.Context, *coderd.Options) (*co defaultRegion := &tailcfg.DERPRegion{ EmbeddedRelay: true, - RegionID: cfg.DERPServerRegionID.Value, - RegionCode: cfg.DERPServerRegionCode.Value, - RegionName: cfg.DERPServerRegionName.Value, + RegionID: cfg.DERP.Server.RegionID.Value, + RegionCode: cfg.DERP.Server.RegionCode.Value, + RegionName: cfg.DERP.Server.RegionName.Value, Nodes: []*tailcfg.DERPNode{{ - Name: fmt.Sprintf("%db", cfg.DERPServerRegionID.Value), - RegionID: cfg.DERPServerRegionID.Value, + Name: fmt.Sprintf("%db", cfg.DERP.Server.RegionID.Value), + RegionID: cfg.DERP.Server.RegionID.Value, HostName: accessURLParsed.Hostname(), DERPPort: accessURLPort, STUNPort: -1, ForceHTTP: accessURLParsed.Scheme == "http", }}, } - if !cfg.DERPServerEnable.Value { + if !cfg.DERP.Server.Enable.Value { defaultRegion = nil } - derpMap, err := tailnet.NewDERPMap(ctx, defaultRegion, cfg.DERPServerSTUNAddresses.Value, cfg.DERPConfigURL.Value, cfg.DERPConfigPath.Value) + derpMap, err := tailnet.NewDERPMap(ctx, defaultRegion, cfg.DERP.Server.STUNAddresses.Value, cfg.DERP.Config.URL.Value, cfg.DERP.Config.Path.Value) if err != nil { return xerrors.Errorf("create derp map: %w", err) } @@ -356,29 +356,29 @@ func Server(vip *viper.Viper, newAPI func(context.Context, *coderd.Options) (*co options.TLSCertificates = tlsConfig.Certificates } - if cfg.OAuth2GithubClientSecret.Value != "" { + if cfg.OAuth2.Github.ClientSecret.Value != "" { options.GithubOAuth2Config, err = configureGithubOAuth2(accessURLParsed, - cfg.OAuth2GithubClientID.Value, - cfg.OAuth2GithubClientSecret.Value, - cfg.OAuth2GithubAllowSignups.Value, - cfg.OAuth2GithubAllowedOrgs.Value, - cfg.OAuth2GithubAllowedTeams.Value, - cfg.OAuth2GithubEnterpriseBaseURL.Value, + cfg.OAuth2.Github.ClientID.Value, + cfg.OAuth2.Github.ClientSecret.Value, + cfg.OAuth2.Github.AllowSignups.Value, + cfg.OAuth2.Github.AllowedOrgs.Value, + cfg.OAuth2.Github.AllowedTeams.Value, + cfg.OAuth2.Github.EnterpriseBaseURL.Value, ) if err != nil { return xerrors.Errorf("configure github oauth2: %w", err) } } - if cfg.OIDCClientSecret.Value != "" { - if cfg.OIDCClientID.Value == "" { + if cfg.OIDC.ClientSecret.Value != "" { + if cfg.OIDC.ClientID.Value == "" { return xerrors.Errorf("OIDC client ID be set!") } - if cfg.OIDCIssuerURL.Value == "" { + if cfg.OIDC.IssuerURL.Value == "" { return xerrors.Errorf("OIDC issuer URL must be set!") } - oidcProvider, err := oidc.NewProvider(ctx, cfg.OIDCIssuerURL.Value) + oidcProvider, err := oidc.NewProvider(ctx, cfg.OIDC.IssuerURL.Value) if err != nil { return xerrors.Errorf("configure oidc provider: %w", err) } @@ -388,17 +388,17 @@ func Server(vip *viper.Viper, newAPI func(context.Context, *coderd.Options) (*co } options.OIDCConfig = &coderd.OIDCConfig{ OAuth2Config: &oauth2.Config{ - ClientID: cfg.OIDCClientID.Value, - ClientSecret: cfg.OIDCClientSecret.Value, + ClientID: cfg.OIDC.ClientID.Value, + ClientSecret: cfg.OIDC.ClientSecret.Value, RedirectURL: redirectURL.String(), Endpoint: oidcProvider.Endpoint(), - Scopes: cfg.OIDCScopes.Value, + Scopes: cfg.OIDC.Scopes.Value, }, Verifier: oidcProvider.Verifier(&oidc.Config{ - ClientID: cfg.OIDCClientID.Value, + ClientID: cfg.OIDC.ClientID.Value, }), - EmailDomain: cfg.OIDCEmailDomain.Value, - AllowSignups: cfg.OIDCAllowSignups.Value, + EmailDomain: cfg.OIDC.EmailDomain.Value, + AllowSignups: cfg.OIDC.AllowSignups.Value, } } @@ -461,26 +461,26 @@ func Server(vip *viper.Viper, newAPI func(context.Context, *coderd.Options) (*co } // Parse the raw telemetry URL! - telemetryURL, err := parseURL(ctx, cfg.TelemetryURL.Value) + telemetryURL, err := parseURL(ctx, cfg.Telemetry.URL.Value) if err != nil { return xerrors.Errorf("parse telemetry url: %w", err) } // Disable telemetry if the in-memory database is used unless explicitly defined! - if cfg.InMemoryDatabase.Value && !cmd.Flags().Changed(cfg.TelemetryEnable.Flag) { - cfg.TelemetryEnable.Value = false + if cfg.InMemoryDatabase.Value && !cmd.Flags().Changed(cfg.Telemetry.Enable.Flag) { + cfg.Telemetry.Enable.Value = false } - if cfg.TelemetryEnable.Value { + if cfg.Telemetry.Enable.Value { options.Telemetry, err = telemetry.New(telemetry.Options{ BuiltinPostgres: builtinPostgres, DeploymentID: deploymentID, Database: options.Database, Logger: logger.Named("telemetry"), URL: telemetryURL, - GitHubOAuth: cfg.OAuth2GithubClientID.Value != "", - OIDCAuth: cfg.OIDCClientID.Value != "", - OIDCIssuerURL: cfg.OIDCIssuerURL.Value, - Prometheus: cfg.PrometheusEnable.Value, - STUN: len(cfg.DERPServerSTUNAddresses.Value) != 0, + GitHubOAuth: cfg.OAuth2.Github.ClientID.Value != "", + OIDCAuth: cfg.OIDC.ClientID.Value != "", + OIDCIssuerURL: cfg.OIDC.IssuerURL.Value, + Prometheus: cfg.Prometheus.Enable.Value, + STUN: len(cfg.DERP.Server.STUNAddresses.Value) != 0, Tunnel: tunnel != nil, }) if err != nil { @@ -491,11 +491,11 @@ func Server(vip *viper.Viper, newAPI func(context.Context, *coderd.Options) (*co // This prevents the pprof import from being accidentally deleted. _ = pprof.Handler - if cfg.PprofEnable.Value { + if cfg.Pprof.Enable.Value { //nolint:revive - defer serveHandler(ctx, logger, nil, cfg.PprofAddress.Value, "pprof")() + defer serveHandler(ctx, logger, nil, cfg.Pprof.Address.Value, "pprof")() } - if cfg.PrometheusEnable.Value { + if cfg.Prometheus.Enable.Value { options.PrometheusRegistry = prometheus.NewRegistry() closeUsersFunc, err := prometheusmetrics.ActiveUsers(ctx, options.PrometheusRegistry, options.Database, 0) if err != nil { @@ -512,7 +512,7 @@ func Server(vip *viper.Viper, newAPI func(context.Context, *coderd.Options) (*co //nolint:revive defer serveHandler(ctx, logger, promhttp.InstrumentMetricHandler( options.PrometheusRegistry, promhttp.HandlerFor(options.PrometheusRegistry, promhttp.HandlerOpts{}), - ), cfg.PrometheusAddress.Value, "prometheus")() + ), cfg.Prometheus.Address.Value, "prometheus")() } // We use a separate coderAPICloser so the Enterprise API @@ -524,7 +524,7 @@ func Server(vip *viper.Viper, newAPI func(context.Context, *coderd.Options) (*co } client := codersdk.New(localURL) - if cfg.TLSEnable.Value { + if cfg.TLS.Enable.Value { // Secure transport isn't needed for locally communicating! client.HTTPClient.Transport = &http.Transport{ TLSClientConfig: &tls.Config{ From faadaa0b2bf005bcd3ada041b988012c562aa134 Mon Sep 17 00:00:00 2001 From: Garrett Date: Mon, 24 Oct 2022 15:56:44 +0000 Subject: [PATCH 05/16] fix ent --- enterprise/cli/server.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/enterprise/cli/server.go b/enterprise/cli/server.go index 7700cd3b7e6ca..46595ca3fdd00 100644 --- a/enterprise/cli/server.go +++ b/enterprise/cli/server.go @@ -26,8 +26,8 @@ import ( func server() *cobra.Command { vip := deployment.NewViper() cmd := agpl.Server(vip, func(ctx context.Context, options *agplcoderd.Options) (*agplcoderd.API, io.Closer, error) { - if options.DeploymentConfig.DERPServerRelayURL.Value != "" { - _, err := url.Parse(options.DeploymentConfig.DERPServerRelayURL.Value) + if options.DeploymentConfig.DERP.Server.RelayURL.Value != "" { + _, err := url.Parse(options.DeploymentConfig.DERP.Server.RelayURL.Value) if err != nil { return nil, nil, xerrors.Errorf("derp-server-relay-address must be a valid HTTP URL: %w", err) } @@ -63,8 +63,8 @@ func server() *cobra.Command { SCIMAPIKey: []byte(options.DeploymentConfig.SCIMAPIKey.Value), UserWorkspaceQuota: options.DeploymentConfig.UserWorkspaceQuota.Value, RBAC: true, - DERPServerRelayAddress: options.DeploymentConfig.DERPServerRelayURL.Value, - DERPServerRegionID: options.DeploymentConfig.DERPServerRegionID.Value, + DERPServerRelayAddress: options.DeploymentConfig.DERP.Server.RelayURL.Value, + DERPServerRegionID: options.DeploymentConfig.DERP.Server.RegionID.Value, Options: options, } From 4bcdd0aff03bdb20700429036f5f66cdf3ab11fb Mon Sep 17 00:00:00 2001 From: Garrett Date: Mon, 24 Oct 2022 17:43:51 +0000 Subject: [PATCH 06/16] get reflect working with ptr --- cli/deployment/config.go | 161 ++++++++++++++++---------------- cli/deployment/config_test.go | 14 +-- cli/server.go | 2 +- coderd/deploymentconfig_test.go | 2 +- codersdk/deploymentconfig.go | 126 ++++++++++++------------- 5 files changed, 154 insertions(+), 151 deletions(-) diff --git a/cli/deployment/config.go b/cli/deployment/config.go index 6e849e811bc16..f45b905033382 100644 --- a/cli/deployment/config.go +++ b/cli/deployment/config.go @@ -19,205 +19,205 @@ import ( "github.com/coder/coder/codersdk" ) -func newConfig() codersdk.DeploymentConfig { - return codersdk.DeploymentConfig{ - AccessURL: codersdk.DeploymentConfigField[string]{ +func newConfig() *codersdk.DeploymentConfig { + return &codersdk.DeploymentConfig{ + AccessURL: &codersdk.DeploymentConfigField[string]{ Name: "Access URL", Usage: "External URL to access your deployment. This must be accessible by all provisioned workspaces.", Flag: "access-url", }, - WildcardAccessURL: codersdk.DeploymentConfigField[string]{ + WildcardAccessURL: &codersdk.DeploymentConfigField[string]{ Name: "Wildcard Access URL", Usage: "Specifies the wildcard hostname to use for workspace applications in the form \"*.example.com\".", Flag: "wildcard-access-url", }, - Address: codersdk.DeploymentConfigField[string]{ + Address: &codersdk.DeploymentConfigField[string]{ Name: "Address", Usage: "Bind address of the server.", Flag: "address", Shorthand: "a", Value: "127.0.0.1:3000", }, - AutobuildPollInterval: codersdk.DeploymentConfigField[time.Duration]{ + AutobuildPollInterval: &codersdk.DeploymentConfigField[time.Duration]{ Name: "Autobuild Poll Interval", Usage: "Interval to poll for scheduled workspace builds.", Flag: "autobuild-poll-interval", Hidden: true, Value: time.Minute, }, - DERP: codersdk.DERP{ - Server: codersdk.DERPServerConfig{ - Enable: codersdk.DeploymentConfigField[bool]{ + DERP: &codersdk.DERP{ + Server: &codersdk.DERPServerConfig{ + Enable: &codersdk.DeploymentConfigField[bool]{ Name: "DERP Server Enable", Usage: "Whether to enable or disable the embedded DERP relay server.", Flag: "derp-server-enable", Value: true, }, - RegionID: codersdk.DeploymentConfigField[int]{ + RegionID: &codersdk.DeploymentConfigField[int]{ Name: "DERP Server Region ID", Usage: "Region ID to use for the embedded DERP server.", Flag: "derp-server-region-id", Value: 999, }, - RegionCode: codersdk.DeploymentConfigField[string]{ + RegionCode: &codersdk.DeploymentConfigField[string]{ Name: "DERP Server Region Code", Usage: "Region code to use for the embedded DERP server.", Flag: "derp-server-region-code", Value: "coder", }, - RegionName: codersdk.DeploymentConfigField[string]{ + RegionName: &codersdk.DeploymentConfigField[string]{ Name: "DERP Server Region Name", Usage: "Region name that for the embedded DERP server.", Flag: "derp-server-region-name", Value: "Coder Embedded Relay", }, - STUNAddresses: codersdk.DeploymentConfigField[[]string]{ + STUNAddresses: &codersdk.DeploymentConfigField[[]string]{ Name: "DERP Server STUN Addresses", Usage: "Addresses for STUN servers to establish P2P connections. Set empty to disable P2P connections.", Flag: "derp-server-stun-addresses", Value: []string{"stun.l.google.com:19302"}, }, - RelayURL: codersdk.DeploymentConfigField[string]{ + RelayURL: &codersdk.DeploymentConfigField[string]{ Name: "DERP Server Relay URL", Usage: "An HTTP URL that is accessible by other replicas to relay DERP traffic. Required for high availability.", Flag: "derp-server-relay-url", Enterprise: true, }, }, - Config: codersdk.DERPConfig{ - URL: codersdk.DeploymentConfigField[string]{ + Config: &codersdk.DERPConfig{ + URL: &codersdk.DeploymentConfigField[string]{ Name: "DERP Config URL", Usage: "URL to fetch a DERP mapping on startup. See: https://tailscale.com/kb/1118/custom-derp-servers/", Flag: "derp-config-url", }, - Path: codersdk.DeploymentConfigField[string]{ + Path: &codersdk.DeploymentConfigField[string]{ Name: "DERP Config Path", Usage: "Path to read a DERP mapping from. See: https://tailscale.com/kb/1118/custom-derp-servers/", Flag: "derp-config-path", }, }, }, - Prometheus: codersdk.PrometheusConfig{ - Enable: codersdk.DeploymentConfigField[bool]{ + Prometheus: &codersdk.PrometheusConfig{ + Enable: &codersdk.DeploymentConfigField[bool]{ Name: "Prometheus Enable", Usage: "Serve prometheus metrics on the address defined by prometheus address.", Flag: "prometheus-enable", }, - Address: codersdk.DeploymentConfigField[string]{ + Address: &codersdk.DeploymentConfigField[string]{ Name: "Prometheus Address", Usage: "The bind address to serve prometheus metrics.", Flag: "prometheus-address", Value: "127.0.0.1:2112", }, }, - Pprof: codersdk.PprofConfig{ - Enable: codersdk.DeploymentConfigField[bool]{ + Pprof: &codersdk.PprofConfig{ + Enable: &codersdk.DeploymentConfigField[bool]{ Name: "Pprof Enable", Usage: "Serve pprof metrics on the address defined by pprof address.", Flag: "pprof-enable", }, - Address: codersdk.DeploymentConfigField[string]{ + Address: &codersdk.DeploymentConfigField[string]{ Name: "Pprof Address", Usage: "The bind address to serve pprof.", Flag: "pprof-address", Value: "127.0.0.1:6060", }, }, - ProxyTrustedHeaders: codersdk.DeploymentConfigField[[]string]{ + ProxyTrustedHeaders: &codersdk.DeploymentConfigField[[]string]{ Name: "Proxy Trusted Headers", Flag: "proxy-trusted-headers", Usage: "Headers to trust for forwarding IP addresses. e.g. Cf-Connecting-IP True-Client-Ip, X-Forwarded-for", }, - ProxyTrustedOrigins: codersdk.DeploymentConfigField[[]string]{ + ProxyTrustedOrigins: &codersdk.DeploymentConfigField[[]string]{ Name: "Proxy Trusted Origins", Flag: "proxy-trusted-origins", Usage: "Origin addresses to respect \"proxy-trusted-headers\". e.g. example.com", }, - CacheDirectory: codersdk.DeploymentConfigField[string]{ + CacheDirectory: &codersdk.DeploymentConfigField[string]{ Name: "Cache Directory", Usage: "The directory to cache temporary files. If unspecified and $CACHE_DIRECTORY is set, it will be used for compatibility with systemd.", Flag: "cache-dir", Value: defaultCacheDir(), }, - InMemoryDatabase: codersdk.DeploymentConfigField[bool]{ + InMemoryDatabase: &codersdk.DeploymentConfigField[bool]{ Name: "In Memory Database", Usage: "Controls whether data will be stored in an in-memory database.", Flag: "in-memory", Hidden: true, }, - ProvisionerDaemons: codersdk.DeploymentConfigField[int]{ + ProvisionerDaemons: &codersdk.DeploymentConfigField[int]{ Name: "Provisioner Daemons", Usage: "Number of provisioner daemons to create on start. If builds are stuck in queued state for a long time, consider increasing this.", Flag: "provisioner-daemons", Value: 3, }, - PostgresURL: codersdk.DeploymentConfigField[string]{ + PostgresURL: &codersdk.DeploymentConfigField[string]{ Name: "Postgres Connection URL", Usage: "URL of a PostgreSQL database. If empty, PostgreSQL binaries will be downloaded from Maven (https://repo1.maven.org/maven2) and store all data in the config root. Access the built-in database with \"coder server postgres-builtin-url\".", Flag: "postgres-url", }, - OAuth2: codersdk.OAuth2Config{ - Github: codersdk.OAuth2GithubConfig{ - ClientID: codersdk.DeploymentConfigField[string]{ + OAuth2: &codersdk.OAuth2Config{ + Github: &codersdk.OAuth2GithubConfig{ + ClientID: &codersdk.DeploymentConfigField[string]{ Name: "OAuth2 GitHub Client ID", Usage: "Client ID for Login with GitHub.", Flag: "oauth2-github-client-id", }, - ClientSecret: codersdk.DeploymentConfigField[string]{ + ClientSecret: &codersdk.DeploymentConfigField[string]{ Name: "OAuth2 GitHub Client Secret", Usage: "Client secret for Login with GitHub.", Flag: "oauth2-github-client-secret", }, - AllowedOrgs: codersdk.DeploymentConfigField[[]string]{ + AllowedOrgs: &codersdk.DeploymentConfigField[[]string]{ Name: "OAuth2 GitHub Allowed Orgs", Usage: "Organizations the user must be a member of to Login with GitHub.", Flag: "oauth2-github-allowed-orgs", }, - AllowedTeams: codersdk.DeploymentConfigField[[]string]{ + AllowedTeams: &codersdk.DeploymentConfigField[[]string]{ Name: "OAuth2 GitHub Allowed Teams", Usage: "Teams inside organizations the user must be a member of to Login with GitHub. Structured as: /.", Flag: "oauth2-github-allowed-teams", }, - AllowSignups: codersdk.DeploymentConfigField[bool]{ + AllowSignups: &codersdk.DeploymentConfigField[bool]{ Name: "OAuth2 GitHub Allow Signups", Usage: "Whether new users can sign up with GitHub.", Flag: "oauth2-github-allow-signups", }, - EnterpriseBaseURL: codersdk.DeploymentConfigField[string]{ + EnterpriseBaseURL: &codersdk.DeploymentConfigField[string]{ Name: "OAuth2 GitHub Enterprise Base URL", Usage: "Base URL of a GitHub Enterprise deployment to use for Login with GitHub.", Flag: "oauth2-github-enterprise-base-url", }, }, }, - OIDC: codersdk.OIDCConfig{ - AllowSignups: codersdk.DeploymentConfigField[bool]{ + OIDC: &codersdk.OIDCConfig{ + AllowSignups: &codersdk.DeploymentConfigField[bool]{ Name: "OIDC Allow Signups", Usage: "Whether new users can sign up with OIDC.", Flag: "oidc-allow-signups", Value: true, }, - ClientID: codersdk.DeploymentConfigField[string]{ + ClientID: &codersdk.DeploymentConfigField[string]{ Name: "OIDC Client ID", Usage: "Client ID to use for Login with OIDC.", Flag: "oidc-client-id", }, - ClientSecret: codersdk.DeploymentConfigField[string]{ + ClientSecret: &codersdk.DeploymentConfigField[string]{ Name: "OIDC Client Secret", Usage: "Client secret to use for Login with OIDC.", Flag: "oidc-client-secret", }, - EmailDomain: codersdk.DeploymentConfigField[string]{ + EmailDomain: &codersdk.DeploymentConfigField[string]{ Name: "OIDC Email Domain", Usage: "Email domain that clients logging in with OIDC must match.", Flag: "oidc-email-domain", }, - IssuerURL: codersdk.DeploymentConfigField[string]{ + IssuerURL: &codersdk.DeploymentConfigField[string]{ Name: "OIDC Issuer URL", Usage: "Issuer URL to use for Login with OIDC.", Flag: "oidc-issuer-url", }, - Scopes: codersdk.DeploymentConfigField[[]string]{ + Scopes: &codersdk.DeploymentConfigField[[]string]{ Name: "OIDC Scopes", Usage: "Scopes to grant when authenticating with OIDC.", Flag: "oidc-scopes", @@ -225,20 +225,20 @@ func newConfig() codersdk.DeploymentConfig { }, }, - Telemetry: codersdk.TelemetryConfig{ - Enable: codersdk.DeploymentConfigField[bool]{ + Telemetry: &codersdk.TelemetryConfig{ + Enable: &codersdk.DeploymentConfigField[bool]{ Name: "Telemetry Enable", Usage: "Whether telemetry is enabled or not. Coder collects anonymized usage data to help improve our product.", Flag: "telemetry", Value: flag.Lookup("test.v") == nil, }, - Trace: codersdk.DeploymentConfigField[bool]{ + Trace: &codersdk.DeploymentConfigField[bool]{ Name: "Telemetry Trace", Usage: "Whether Opentelemetry traces are sent to Coder. Coder collects anonymized application tracing to help improve our product. Disabling telemetry also disables this option.", Flag: "telemetry-trace", Value: flag.Lookup("test.v") == nil, }, - URL: codersdk.DeploymentConfigField[string]{ + URL: &codersdk.DeploymentConfigField[string]{ Name: "Telemetry URL", Usage: "URL to send telemetry.", Flag: "telemetry-url", @@ -246,96 +246,96 @@ func newConfig() codersdk.DeploymentConfig { Value: "https://telemetry.coder.com", }, }, - TLS: codersdk.TLSConfig{ - Enable: codersdk.DeploymentConfigField[bool]{ + TLS: &codersdk.TLSConfig{ + Enable: &codersdk.DeploymentConfigField[bool]{ Name: "TLS Enable", Usage: "Whether TLS will be enabled.", Flag: "tls-enable", }, - CertFiles: codersdk.DeploymentConfigField[[]string]{ + CertFiles: &codersdk.DeploymentConfigField[[]string]{ Name: "TLS Certificate Files", Usage: "Path to each certificate for TLS. It requires a PEM-encoded file. To configure the listener to use a CA certificate, concatenate the primary certificate and the CA certificate together. The primary certificate should appear first in the combined file.", Flag: "tls-cert-file", }, - ClientCAFile: codersdk.DeploymentConfigField[string]{ + ClientCAFile: &codersdk.DeploymentConfigField[string]{ Name: "TLS Client CA Files", Usage: "PEM-encoded Certificate Authority file used for checking the authenticity of client", Flag: "tls-client-ca-file", }, - ClientAuth: codersdk.DeploymentConfigField[string]{ + ClientAuth: &codersdk.DeploymentConfigField[string]{ Name: "TLS Client Auth", Usage: "Policy the server will follow for TLS Client Authentication. Accepted values are \"none\", \"request\", \"require-any\", \"verify-if-given\", or \"require-and-verify\".", Flag: "tls-client-auth", Value: "request", }, - KeyFiles: codersdk.DeploymentConfigField[[]string]{ + KeyFiles: &codersdk.DeploymentConfigField[[]string]{ Name: "TLS Key Files", Usage: "Paths to the private keys for each of the certificates. It requires a PEM-encoded file.", Flag: "tls-key-file", }, - MinVersion: codersdk.DeploymentConfigField[string]{ + MinVersion: &codersdk.DeploymentConfigField[string]{ Name: "TLS Minimum Version", Usage: "Minimum supported version of TLS. Accepted values are \"tls10\", \"tls11\", \"tls12\" or \"tls13\"", Flag: "tls-min-version", Value: "tls12", }, }, - TraceEnable: codersdk.DeploymentConfigField[bool]{ + TraceEnable: &codersdk.DeploymentConfigField[bool]{ Name: "Trace Enable", Usage: "Whether application tracing data is collected.", Flag: "trace", }, - SecureAuthCookie: codersdk.DeploymentConfigField[bool]{ + SecureAuthCookie: &codersdk.DeploymentConfigField[bool]{ Name: "Secure Auth Cookie", Usage: "Controls if the 'Secure' property is set on browser session cookies.", Flag: "secure-auth-cookie", }, - SSHKeygenAlgorithm: codersdk.DeploymentConfigField[string]{ + SSHKeygenAlgorithm: &codersdk.DeploymentConfigField[string]{ Name: "SSH Keygen Algorithm", Usage: "The algorithm to use for generating ssh keys. Accepted values are \"ed25519\", \"ecdsa\", or \"rsa4096\".", Flag: "ssh-keygen-algorithm", Value: "ed25519", }, - AutoImportTemplates: codersdk.DeploymentConfigField[[]string]{ + AutoImportTemplates: &codersdk.DeploymentConfigField[[]string]{ Name: "Auto Import Templates", Usage: "Templates to auto-import. Available auto-importable templates are: kubernetes", Flag: "auto-import-template", Hidden: true, }, - MetricsCacheRefreshInterval: codersdk.DeploymentConfigField[time.Duration]{ + MetricsCacheRefreshInterval: &codersdk.DeploymentConfigField[time.Duration]{ Name: "Metrics Cache Refresh Interval", Usage: "How frequently metrics are refreshed", Flag: "metrics-cache-refresh-interval", Hidden: true, Value: time.Hour, }, - AgentStatRefreshInterval: codersdk.DeploymentConfigField[time.Duration]{ + AgentStatRefreshInterval: &codersdk.DeploymentConfigField[time.Duration]{ Name: "Agent Stat Refresh Interval", Usage: "How frequently agent stats are recorded", Flag: "agent-stats-refresh-interval", Hidden: true, Value: 10 * time.Minute, }, - AuditLogging: codersdk.DeploymentConfigField[bool]{ + AuditLogging: &codersdk.DeploymentConfigField[bool]{ Name: "Audit Logging", Usage: "Specifies whether audit logging is enabled.", Flag: "audit-logging", Value: true, Enterprise: true, }, - BrowserOnly: codersdk.DeploymentConfigField[bool]{ + BrowserOnly: &codersdk.DeploymentConfigField[bool]{ Name: "Browser Only", Usage: "Whether Coder only allows connections to workspaces via the browser.", Flag: "browser-only", Enterprise: true, }, - SCIMAPIKey: codersdk.DeploymentConfigField[string]{ + SCIMAPIKey: &codersdk.DeploymentConfigField[string]{ Name: "SCIM API Key", Usage: "Enables SCIM and sets the authentication header for the built-in SCIM server. New users are automatically created with OIDC authentication.", Flag: "scim-auth-header", Enterprise: true, }, - UserWorkspaceQuota: codersdk.DeploymentConfigField[int]{ + UserWorkspaceQuota: &codersdk.DeploymentConfigField[int]{ Name: "User Workspace Quota", Usage: "Enables and sets a limit on how many workspaces each user can create.", Flag: "user-workspace-quota", @@ -345,11 +345,11 @@ func newConfig() codersdk.DeploymentConfig { } //nolint:revive -func Config(flagset *pflag.FlagSet, vip *viper.Viper) (codersdk.DeploymentConfig, error) { +func Config(flagset *pflag.FlagSet, vip *viper.Viper) (*codersdk.DeploymentConfig, error) { dc := newConfig() flg, err := flagset.GetString(config.FlagName) if err != nil { - return dc, xerrors.Errorf("get global config from flag: %w", err) + return nil, xerrors.Errorf("get global config from flag: %w", err) } vip.SetEnvPrefix("coder") vip.AutomaticEnv() @@ -368,9 +368,13 @@ func Config(flagset *pflag.FlagSet, vip *viper.Viper) (codersdk.DeploymentConfig } func setConfig(prefix string, vip *viper.Viper, target interface{}) { - val := reflect.ValueOf(target).Elem() + val := reflect.Indirect(reflect.ValueOf(target)) typ := val.Type() - if strings.HasPrefix(typ.Name(), "DeploymentConfigField") { + if typ.Kind() != reflect.Struct { + val = val.Elem() + typ = val.Type() + } + if strings.HasPrefix(typ.Name(), "DeploymentConfigField[") { value := val.FieldByName("Value").Interface() switch value.(type) { case string: @@ -412,14 +416,13 @@ func setConfig(prefix string, vip *viper.Viper, target interface{}) { key = fmt.Sprintf("%s.%s", prefix, tag) } switch ft.Kind() { - case reflect.Struct: - v := fv.Interface() - setConfig(key, vip, &v) + case reflect.Ptr: + setConfig(key, vip, fv.Interface()) case reflect.Slice: for j := 0; j < fv.Len(); j++ { key := fmt.Sprintf("%s.%d", key, j) v := fv.Index(j) - setConfig(key, vip, &v) + setConfig(key, vip, v) } default: panic(fmt.Sprintf("unsupported type %T", ft)) @@ -434,13 +437,14 @@ func NewViper() *viper.Viper { vip.AutomaticEnv() vip.SetEnvKeyReplacer(strings.NewReplacer("-", "_", ".", "_")) - setViperDefaults("", vip, dc) + setViperDefaults("", vip, &dc) return vip } func setViperDefaults(prefix string, vip *viper.Viper, target interface{}) { - val := reflect.ValueOf(target) + val := reflect.ValueOf(target).Elem() + val = reflect.Indirect(val) typ := val.Type() if strings.HasPrefix(typ.Name(), "DeploymentConfigField") { value := val.FieldByName("Value").Interface() @@ -459,7 +463,7 @@ func setViperDefaults(prefix string, vip *viper.Viper, target interface{}) { key = fmt.Sprintf("%s.%s", prefix, tag) } switch ft.Kind() { - case reflect.Struct: + case reflect.Ptr: setViperDefaults(key, vip, fv.Interface()) case reflect.Slice: for j := 0; j < fv.Len(); j++ { @@ -479,9 +483,8 @@ func AttachFlags(flagset *pflag.FlagSet, vip *viper.Viper, enterprise bool) { //nolint:revive func setFlags(prefix string, flagset *pflag.FlagSet, vip *viper.Viper, target interface{}, enterprise bool) { - val := reflect.ValueOf(target) + val := reflect.Indirect(reflect.ValueOf(target)) typ := val.Type() - fmt.Println(typ.Name()) if strings.HasPrefix(typ.Name(), "DeploymentConfigField") { isEnt := val.FieldByName("Enterprise").Bool() if enterprise != isEnt { @@ -531,7 +534,7 @@ func setFlags(prefix string, flagset *pflag.FlagSet, vip *viper.Viper, target in key = fmt.Sprintf("%s.%s", prefix, tag) } switch ft.Kind() { - case reflect.Struct: + case reflect.Ptr: setFlags(key, flagset, vip, fv.Interface(), enterprise) case reflect.Slice: for j := 0; j < fv.Len(); j++ { diff --git a/cli/deployment/config_test.go b/cli/deployment/config_test.go index d0812284c1c63..aeb50d4914b5a 100644 --- a/cli/deployment/config_test.go +++ b/cli/deployment/config_test.go @@ -21,7 +21,7 @@ func TestConfig(t *testing.T) { for _, tc := range []struct { Name string Env map[string]string - Valid func(config codersdk.DeploymentConfig) + Valid func(config *codersdk.DeploymentConfig) }{{ Name: "Deployment", Env: map[string]string{ @@ -39,7 +39,7 @@ func TestConfig(t *testing.T) { "CODER_TELEMETRY_TRACE": "false", "CODER_WILDCARD_ACCESS_URL": "something-wildcard.com", }, - Valid: func(config codersdk.DeploymentConfig) { + Valid: func(config *codersdk.DeploymentConfig) { require.Equal(t, config.Address.Value, "0.0.0.0:8443") require.Equal(t, config.AccessURL.Value, "https://dev.coder.com") require.Equal(t, config.PostgresURL.Value, "some-url") @@ -66,7 +66,7 @@ func TestConfig(t *testing.T) { "CODER_DERP_SERVER_RELAY_URL": "1.1.1.1", "CODER_DERP_SERVER_STUN_ADDRESSES": "google.org", }, - Valid: func(config codersdk.DeploymentConfig) { + Valid: func(config *codersdk.DeploymentConfig) { require.Equal(t, config.DERP.Config.Path.Value, "/example/path") require.Equal(t, config.DERP.Config.URL.Value, "https://google.com") require.Equal(t, config.DERP.Server.Enable.Value, false) @@ -84,7 +84,7 @@ func TestConfig(t *testing.T) { "CODER_SCIM_API_KEY": "some-key", "CODER_USER_WORKSPACE_QUOTA": "10", }, - Valid: func(config codersdk.DeploymentConfig) { + Valid: func(config *codersdk.DeploymentConfig) { require.Equal(t, config.AuditLogging.Value, false) require.Equal(t, config.BrowserOnly.Value, true) require.Equal(t, config.SCIMAPIKey.Value, "some-key") @@ -100,7 +100,7 @@ func TestConfig(t *testing.T) { "CODER_TLS_ENABLE": "true", "CODER_TLS_MIN_VERSION": "tls10", }, - Valid: func(config codersdk.DeploymentConfig) { + Valid: func(config *codersdk.DeploymentConfig) { require.Len(t, config.TLS.CertFiles.Value, 2) require.Equal(t, config.TLS.CertFiles.Value[0], "/etc/acme-sh/dev.coder.com") require.Equal(t, config.TLS.CertFiles.Value[1], "/etc/acme-sh/*.dev.coder.com") @@ -124,7 +124,7 @@ func TestConfig(t *testing.T) { "CODER_OIDC_ALLOW_SIGNUPS": "false", "CODER_OIDC_SCOPES": "something,here", }, - Valid: func(config codersdk.DeploymentConfig) { + Valid: func(config *codersdk.DeploymentConfig) { require.Equal(t, config.OIDC.IssuerURL.Value, "https://accounts.google.com") require.Equal(t, config.OIDC.EmailDomain.Value, "coder.com") require.Equal(t, config.OIDC.ClientID.Value, "client") @@ -141,7 +141,7 @@ func TestConfig(t *testing.T) { "CODER_OAUTH2_GITHUB_ALLOWED_TEAMS": "coder", "CODER_OAUTH2_GITHUB_ALLOW_SIGNUPS": "true", }, - Valid: func(config codersdk.DeploymentConfig) { + Valid: func(config *codersdk.DeploymentConfig) { require.Equal(t, config.OAuth2.Github.ClientID.Value, "client") require.Equal(t, config.OAuth2.Github.ClientSecret.Value, "secret") require.Equal(t, []string{"coder"}, config.OAuth2.Github.AllowedOrgs.Value) diff --git a/cli/server.go b/cli/server.go index dd67555ecac8a..c46f1114fbbe3 100644 --- a/cli/server.go +++ b/cli/server.go @@ -350,7 +350,7 @@ func Server(vip *viper.Viper, newAPI func(context.Context, *coderd.Options) (*co MetricsCacheRefreshInterval: cfg.MetricsCacheRefreshInterval.Value, AgentStatsRefreshInterval: cfg.AgentStatRefreshInterval.Value, Experimental: ExperimentalEnabled(cmd), - DeploymentConfig: &cfg, + DeploymentConfig: cfg, } if tlsConfig != nil { options.TLSCertificates = tlsConfig.Certificates diff --git a/coderd/deploymentconfig_test.go b/coderd/deploymentconfig_test.go index a4c9c9f4b6529..a0031ac6c391f 100644 --- a/coderd/deploymentconfig_test.go +++ b/coderd/deploymentconfig_test.go @@ -32,7 +32,7 @@ func TestDeploymentConfig(t *testing.T) { cfg.SCIMAPIKey.Value = hi client := coderdtest.New(t, &coderdtest.Options{ - DeploymentConfig: &cfg, + DeploymentConfig: cfg, }) _ = coderdtest.CreateFirstUser(t, client) scrubbed, err := client.DeploymentConfig(ctx) diff --git a/codersdk/deploymentconfig.go b/codersdk/deploymentconfig.go index b3eb9a8c3d805..297e08aaf8052 100644 --- a/codersdk/deploymentconfig.go +++ b/codersdk/deploymentconfig.go @@ -12,99 +12,99 @@ import ( // DeploymentConfig is the central configuration for the coder server. // Secret values should specify `json:"-"` to prevent them from being returned by the API. type DeploymentConfig struct { - AccessURL DeploymentConfigField[string] `json:"access_url"` - WildcardAccessURL DeploymentConfigField[string] `json:"wildcard_access_url"` - Address DeploymentConfigField[string] `json:"address"` - AutobuildPollInterval DeploymentConfigField[time.Duration] `json:"autobuild_poll_interval"` - DERP DERP `json:"derp"` - Prometheus PrometheusConfig `json:"prometheus"` - Pprof PprofConfig `json:"pprof"` - ProxyTrustedHeaders DeploymentConfigField[[]string] `json:"proxy_trusted_headers"` - ProxyTrustedOrigins DeploymentConfigField[[]string] `json:"proxy_trusted_origin"` - CacheDirectory DeploymentConfigField[string] `json:"cache_directory"` - InMemoryDatabase DeploymentConfigField[bool] `json:"in_memory_database"` - ProvisionerDaemons DeploymentConfigField[int] `json:"provisioner_daemon_count"` - PostgresURL DeploymentConfigField[string] `json:"pg_connection_url"` - OAuth2 OAuth2Config `json:"oauth2"` - OIDC OIDCConfig `json:"oidc"` - Telemetry TelemetryConfig `json:"telemetry"` - TLS TLSConfig `json:"tls"` - TraceEnable DeploymentConfigField[bool] `json:"trace_enable"` - SecureAuthCookie DeploymentConfigField[bool] `json:"secure_auth_cookie"` - SSHKeygenAlgorithm DeploymentConfigField[string] `json:"ssh_keygen_algorithm"` - AutoImportTemplates DeploymentConfigField[[]string] `json:"auto_import_templates"` - MetricsCacheRefreshInterval DeploymentConfigField[time.Duration] `json:"metrics_cache_refresh_interval"` - AgentStatRefreshInterval DeploymentConfigField[time.Duration] `json:"agent_stat_refresh_interval"` - AuditLogging DeploymentConfigField[bool] `json:"audit_logging"` - BrowserOnly DeploymentConfigField[bool] `json:"browser_only"` - SCIMAPIKey DeploymentConfigField[string] `json:"scim_api_key"` - UserWorkspaceQuota DeploymentConfigField[int] `json:"user_workspace_quota"` + AccessURL *DeploymentConfigField[string] `json:"access_url"` + WildcardAccessURL *DeploymentConfigField[string] `json:"wildcard_access_url"` + Address *DeploymentConfigField[string] `json:"address"` + AutobuildPollInterval *DeploymentConfigField[time.Duration] `json:"autobuild_poll_interval"` + DERP *DERP `json:"derp"` + Prometheus *PrometheusConfig `json:"prometheus"` + Pprof *PprofConfig `json:"pprof"` + ProxyTrustedHeaders *DeploymentConfigField[[]string] `json:"proxy_trusted_headers"` + ProxyTrustedOrigins *DeploymentConfigField[[]string] `json:"proxy_trusted_origin"` + CacheDirectory *DeploymentConfigField[string] `json:"cache_directory"` + InMemoryDatabase *DeploymentConfigField[bool] `json:"in_memory_database"` + ProvisionerDaemons *DeploymentConfigField[int] `json:"provisioner_daemon_count"` + PostgresURL *DeploymentConfigField[string] `json:"pg_connection_url"` + OAuth2 *OAuth2Config `json:"oauth2"` + OIDC *OIDCConfig `json:"oidc"` + Telemetry *TelemetryConfig `json:"telemetry"` + TLS *TLSConfig `json:"tls"` + TraceEnable *DeploymentConfigField[bool] `json:"trace_enable"` + SecureAuthCookie *DeploymentConfigField[bool] `json:"secure_auth_cookie"` + SSHKeygenAlgorithm *DeploymentConfigField[string] `json:"ssh_keygen_algorithm"` + AutoImportTemplates *DeploymentConfigField[[]string] `json:"auto_import_templates"` + MetricsCacheRefreshInterval *DeploymentConfigField[time.Duration] `json:"metrics_cache_refresh_interval"` + AgentStatRefreshInterval *DeploymentConfigField[time.Duration] `json:"agent_stat_refresh_interval"` + AuditLogging *DeploymentConfigField[bool] `json:"audit_logging"` + BrowserOnly *DeploymentConfigField[bool] `json:"browser_only"` + SCIMAPIKey *DeploymentConfigField[string] `json:"scim_api_key"` + UserWorkspaceQuota *DeploymentConfigField[int] `json:"user_workspace_quota"` } type DERP struct { - Server DERPServerConfig `json:"server"` - Config DERPConfig `json:"config"` + Server *DERPServerConfig `json:"server"` + Config *DERPConfig `json:"config"` } type DERPServerConfig struct { - Enable DeploymentConfigField[bool] `json:"enabled"` - RegionID DeploymentConfigField[int] `json:"region_id"` - RegionCode DeploymentConfigField[string] `json:"region_code"` - RegionName DeploymentConfigField[string] `json:"region_name"` - STUNAddresses DeploymentConfigField[[]string] `json:"stun_address"` - RelayURL DeploymentConfigField[string] `json:"relay_address"` + Enable *DeploymentConfigField[bool] `json:"enabled"` + RegionID *DeploymentConfigField[int] `json:"region_id"` + RegionCode *DeploymentConfigField[string] `json:"region_code"` + RegionName *DeploymentConfigField[string] `json:"region_name"` + STUNAddresses *DeploymentConfigField[[]string] `json:"stun_address"` + RelayURL *DeploymentConfigField[string] `json:"relay_address"` } type DERPConfig struct { - URL DeploymentConfigField[string] `json:"url"` - Path DeploymentConfigField[string] `json:"path"` + URL *DeploymentConfigField[string] `json:"url"` + Path *DeploymentConfigField[string] `json:"path"` } type PrometheusConfig struct { - Enable DeploymentConfigField[bool] `json:"enabled"` - Address DeploymentConfigField[string] `json:"address"` + Enable *DeploymentConfigField[bool] `json:"enabled"` + Address *DeploymentConfigField[string] `json:"address"` } type PprofConfig struct { - Enable DeploymentConfigField[bool] `json:"enabled"` - Address DeploymentConfigField[string] `json:"address"` + Enable *DeploymentConfigField[bool] `json:"enabled"` + Address *DeploymentConfigField[string] `json:"address"` } type OAuth2Config struct { - Github OAuth2GithubConfig `json:"github"` + Github *OAuth2GithubConfig `json:"github"` } type OAuth2GithubConfig struct { - ClientID DeploymentConfigField[string] `json:"client_id"` - ClientSecret DeploymentConfigField[string] `json:"client_secret"` - AllowedOrgs DeploymentConfigField[[]string] `json:"allowed_orgs"` - AllowedTeams DeploymentConfigField[[]string] `json:"allowed_teams"` - AllowSignups DeploymentConfigField[bool] `json:"allow_signups"` - EnterpriseBaseURL DeploymentConfigField[string] `json:"enterprise_base_url"` + ClientID *DeploymentConfigField[string] `json:"client_id"` + ClientSecret *DeploymentConfigField[string] `json:"client_secret"` + AllowedOrgs *DeploymentConfigField[[]string] `json:"allowed_orgs"` + AllowedTeams *DeploymentConfigField[[]string] `json:"allowed_teams"` + AllowSignups *DeploymentConfigField[bool] `json:"allow_signups"` + EnterpriseBaseURL *DeploymentConfigField[string] `json:"enterprise_base_url"` } type OIDCConfig struct { - AllowSignups DeploymentConfigField[bool] `json:"allow_signups"` - ClientID DeploymentConfigField[string] `json:"client_id"` - ClientSecret DeploymentConfigField[string] `json:"client_secret"` - EmailDomain DeploymentConfigField[string] `json:"email_domain"` - IssuerURL DeploymentConfigField[string] `json:"issuer_url"` - Scopes DeploymentConfigField[[]string] `json:"scopes"` + AllowSignups *DeploymentConfigField[bool] `json:"allow_signups"` + ClientID *DeploymentConfigField[string] `json:"client_id"` + ClientSecret *DeploymentConfigField[string] `json:"client_secret"` + EmailDomain *DeploymentConfigField[string] `json:"email_domain"` + IssuerURL *DeploymentConfigField[string] `json:"issuer_url"` + Scopes *DeploymentConfigField[[]string] `json:"scopes"` } type TelemetryConfig struct { - Enable DeploymentConfigField[bool] `json:"enabled"` - Trace DeploymentConfigField[bool] `json:"trace"` - URL DeploymentConfigField[string] `json:"url"` + Enable *DeploymentConfigField[bool] `json:"enabled"` + Trace *DeploymentConfigField[bool] `json:"trace"` + URL *DeploymentConfigField[string] `json:"url"` } type TLSConfig struct { - Enable DeploymentConfigField[bool] `json:"enable"` - CertFiles DeploymentConfigField[[]string] `json:"cert_files"` - ClientAuth DeploymentConfigField[string] `json:"client_auth"` - ClientCAFile DeploymentConfigField[string] `json:"client_ca_file"` - KeyFiles DeploymentConfigField[[]string] `json:"key_files"` - MinVersion DeploymentConfigField[string] `json:"min_version"` + Enable *DeploymentConfigField[bool] `json:"enable"` + CertFiles *DeploymentConfigField[[]string] `json:"cert_files"` + ClientAuth *DeploymentConfigField[string] `json:"client_auth"` + ClientCAFile *DeploymentConfigField[string] `json:"client_ca_file"` + KeyFiles *DeploymentConfigField[[]string] `json:"key_files"` + MinVersion *DeploymentConfigField[string] `json:"min_version"` } type Flaggable interface { From e6522cb12e37fed478fb27b3a85bcee98210bb9a Mon Sep 17 00:00:00 2001 From: Garrett Date: Mon, 24 Oct 2022 18:08:05 +0000 Subject: [PATCH 07/16] support slices --- cli/deployment/config.go | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/cli/deployment/config.go b/cli/deployment/config.go index f45b905033382..2dca373aa9249 100644 --- a/cli/deployment/config.go +++ b/cli/deployment/config.go @@ -374,6 +374,10 @@ func setConfig(prefix string, vip *viper.Viper, target interface{}) { val = val.Elem() typ = val.Type() } + + // Manually bind to env to support CODER_$INDEX_$FIELD format for structured slices. + _ = vip.BindEnv(prefix, formatEnv(prefix)) + if strings.HasPrefix(typ.Name(), "DeploymentConfigField[") { value := val.FieldByName("Value").Interface() switch value.(type) { @@ -421,8 +425,7 @@ func setConfig(prefix string, vip *viper.Viper, target interface{}) { case reflect.Slice: for j := 0; j < fv.Len(); j++ { key := fmt.Sprintf("%s.%d", key, j) - v := fv.Index(j) - setConfig(key, vip, v) + setConfig(key, vip, fv.Index(j).Interface()) } default: panic(fmt.Sprintf("unsupported type %T", ft)) @@ -466,10 +469,8 @@ func setViperDefaults(prefix string, vip *viper.Viper, target interface{}) { case reflect.Ptr: setViperDefaults(key, vip, fv.Interface()) case reflect.Slice: - for j := 0; j < fv.Len(); j++ { - key := fmt.Sprintf("%s.%d", key, j) - setViperDefaults(key, vip, fv.Index(j)) - } + // we currently don't support default values on structured slices + continue default: panic(fmt.Sprintf("unsupported type %T", ft)) } @@ -539,7 +540,7 @@ func setFlags(prefix string, flagset *pflag.FlagSet, vip *viper.Viper, target in case reflect.Slice: for j := 0; j < fv.Len(); j++ { key := fmt.Sprintf("%s.%d", key, j) - setFlags(key, flagset, vip, fv.Index(j), enterprise) + setFlags(key, flagset, vip, fv.Index(j).Interface(), enterprise) } default: panic(fmt.Sprintf("unsupported type %T", ft)) From 429f91be806ef4fe3e1e0b01abd662ccbd1b1a87 Mon Sep 17 00:00:00 2001 From: Garrett Date: Mon, 24 Oct 2022 18:13:34 +0000 Subject: [PATCH 08/16] make tests pass --- codersdk/deploymentconfig.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/codersdk/deploymentconfig.go b/codersdk/deploymentconfig.go index 297e08aaf8052..b47963e835ec2 100644 --- a/codersdk/deploymentconfig.go +++ b/codersdk/deploymentconfig.go @@ -23,7 +23,7 @@ type DeploymentConfig struct { ProxyTrustedOrigins *DeploymentConfigField[[]string] `json:"proxy_trusted_origin"` CacheDirectory *DeploymentConfigField[string] `json:"cache_directory"` InMemoryDatabase *DeploymentConfigField[bool] `json:"in_memory_database"` - ProvisionerDaemons *DeploymentConfigField[int] `json:"provisioner_daemon_count"` + ProvisionerDaemons *DeploymentConfigField[int] `json:"provisioner_daemons"` PostgresURL *DeploymentConfigField[string] `json:"pg_connection_url"` OAuth2 *OAuth2Config `json:"oauth2"` OIDC *OIDCConfig `json:"oidc"` @@ -47,12 +47,12 @@ type DERP struct { } type DERPServerConfig struct { - Enable *DeploymentConfigField[bool] `json:"enabled"` + Enable *DeploymentConfigField[bool] `json:"enable"` RegionID *DeploymentConfigField[int] `json:"region_id"` RegionCode *DeploymentConfigField[string] `json:"region_code"` RegionName *DeploymentConfigField[string] `json:"region_name"` - STUNAddresses *DeploymentConfigField[[]string] `json:"stun_address"` - RelayURL *DeploymentConfigField[string] `json:"relay_address"` + STUNAddresses *DeploymentConfigField[[]string] `json:"stun_addresses"` + RelayURL *DeploymentConfigField[string] `json:"relay_url"` } type DERPConfig struct { @@ -61,12 +61,12 @@ type DERPConfig struct { } type PrometheusConfig struct { - Enable *DeploymentConfigField[bool] `json:"enabled"` + Enable *DeploymentConfigField[bool] `json:"enable"` Address *DeploymentConfigField[string] `json:"address"` } type PprofConfig struct { - Enable *DeploymentConfigField[bool] `json:"enabled"` + Enable *DeploymentConfigField[bool] `json:"enable"` Address *DeploymentConfigField[string] `json:"address"` } @@ -93,17 +93,17 @@ type OIDCConfig struct { } type TelemetryConfig struct { - Enable *DeploymentConfigField[bool] `json:"enabled"` + Enable *DeploymentConfigField[bool] `json:"enable"` Trace *DeploymentConfigField[bool] `json:"trace"` URL *DeploymentConfigField[string] `json:"url"` } type TLSConfig struct { Enable *DeploymentConfigField[bool] `json:"enable"` - CertFiles *DeploymentConfigField[[]string] `json:"cert_files"` + CertFiles *DeploymentConfigField[[]string] `json:"cert_file"` ClientAuth *DeploymentConfigField[string] `json:"client_auth"` ClientCAFile *DeploymentConfigField[string] `json:"client_ca_file"` - KeyFiles *DeploymentConfigField[[]string] `json:"key_files"` + KeyFiles *DeploymentConfigField[[]string] `json:"key_file"` MinVersion *DeploymentConfigField[string] `json:"min_version"` } From 552e43855da79fa6754593be2c8f26324749ab26 Mon Sep 17 00:00:00 2001 From: Garrett Date: Mon, 24 Oct 2022 18:15:46 +0000 Subject: [PATCH 09/16] move to default --- cli/deployment/config.go | 176 +++++++++++++++++------------------ codersdk/deploymentconfig.go | 1 + 2 files changed, 89 insertions(+), 88 deletions(-) diff --git a/cli/deployment/config.go b/cli/deployment/config.go index 2dca373aa9249..6b21891359109 100644 --- a/cli/deployment/config.go +++ b/cli/deployment/config.go @@ -36,46 +36,46 @@ func newConfig() *codersdk.DeploymentConfig { Usage: "Bind address of the server.", Flag: "address", Shorthand: "a", - Value: "127.0.0.1:3000", + Default: "127.0.0.1:3000", }, AutobuildPollInterval: &codersdk.DeploymentConfigField[time.Duration]{ - Name: "Autobuild Poll Interval", - Usage: "Interval to poll for scheduled workspace builds.", - Flag: "autobuild-poll-interval", - Hidden: true, - Value: time.Minute, + Name: "Autobuild Poll Interval", + Usage: "Interval to poll for scheduled workspace builds.", + Flag: "autobuild-poll-interval", + Hidden: true, + Default: time.Minute, }, DERP: &codersdk.DERP{ Server: &codersdk.DERPServerConfig{ Enable: &codersdk.DeploymentConfigField[bool]{ - Name: "DERP Server Enable", - Usage: "Whether to enable or disable the embedded DERP relay server.", - Flag: "derp-server-enable", - Value: true, + Name: "DERP Server Enable", + Usage: "Whether to enable or disable the embedded DERP relay server.", + Flag: "derp-server-enable", + Default: true, }, RegionID: &codersdk.DeploymentConfigField[int]{ - Name: "DERP Server Region ID", - Usage: "Region ID to use for the embedded DERP server.", - Flag: "derp-server-region-id", - Value: 999, + Name: "DERP Server Region ID", + Usage: "Region ID to use for the embedded DERP server.", + Flag: "derp-server-region-id", + Default: 999, }, RegionCode: &codersdk.DeploymentConfigField[string]{ - Name: "DERP Server Region Code", - Usage: "Region code to use for the embedded DERP server.", - Flag: "derp-server-region-code", - Value: "coder", + Name: "DERP Server Region Code", + Usage: "Region code to use for the embedded DERP server.", + Flag: "derp-server-region-code", + Default: "coder", }, RegionName: &codersdk.DeploymentConfigField[string]{ - Name: "DERP Server Region Name", - Usage: "Region name that for the embedded DERP server.", - Flag: "derp-server-region-name", - Value: "Coder Embedded Relay", + Name: "DERP Server Region Name", + Usage: "Region name that for the embedded DERP server.", + Flag: "derp-server-region-name", + Default: "Coder Embedded Relay", }, STUNAddresses: &codersdk.DeploymentConfigField[[]string]{ - Name: "DERP Server STUN Addresses", - Usage: "Addresses for STUN servers to establish P2P connections. Set empty to disable P2P connections.", - Flag: "derp-server-stun-addresses", - Value: []string{"stun.l.google.com:19302"}, + Name: "DERP Server STUN Addresses", + Usage: "Addresses for STUN servers to establish P2P connections. Set empty to disable P2P connections.", + Flag: "derp-server-stun-addresses", + Default: []string{"stun.l.google.com:19302"}, }, RelayURL: &codersdk.DeploymentConfigField[string]{ Name: "DERP Server Relay URL", @@ -104,10 +104,10 @@ func newConfig() *codersdk.DeploymentConfig { Flag: "prometheus-enable", }, Address: &codersdk.DeploymentConfigField[string]{ - Name: "Prometheus Address", - Usage: "The bind address to serve prometheus metrics.", - Flag: "prometheus-address", - Value: "127.0.0.1:2112", + Name: "Prometheus Address", + Usage: "The bind address to serve prometheus metrics.", + Flag: "prometheus-address", + Default: "127.0.0.1:2112", }, }, Pprof: &codersdk.PprofConfig{ @@ -117,10 +117,10 @@ func newConfig() *codersdk.DeploymentConfig { Flag: "pprof-enable", }, Address: &codersdk.DeploymentConfigField[string]{ - Name: "Pprof Address", - Usage: "The bind address to serve pprof.", - Flag: "pprof-address", - Value: "127.0.0.1:6060", + Name: "Pprof Address", + Usage: "The bind address to serve pprof.", + Flag: "pprof-address", + Default: "127.0.0.1:6060", }, }, ProxyTrustedHeaders: &codersdk.DeploymentConfigField[[]string]{ @@ -134,10 +134,10 @@ func newConfig() *codersdk.DeploymentConfig { Usage: "Origin addresses to respect \"proxy-trusted-headers\". e.g. example.com", }, CacheDirectory: &codersdk.DeploymentConfigField[string]{ - Name: "Cache Directory", - Usage: "The directory to cache temporary files. If unspecified and $CACHE_DIRECTORY is set, it will be used for compatibility with systemd.", - Flag: "cache-dir", - Value: defaultCacheDir(), + Name: "Cache Directory", + Usage: "The directory to cache temporary files. If unspecified and $CACHE_DIRECTORY is set, it will be used for compatibility with systemd.", + Flag: "cache-dir", + Default: defaultCacheDir(), }, InMemoryDatabase: &codersdk.DeploymentConfigField[bool]{ Name: "In Memory Database", @@ -146,10 +146,10 @@ func newConfig() *codersdk.DeploymentConfig { Hidden: true, }, ProvisionerDaemons: &codersdk.DeploymentConfigField[int]{ - Name: "Provisioner Daemons", - Usage: "Number of provisioner daemons to create on start. If builds are stuck in queued state for a long time, consider increasing this.", - Flag: "provisioner-daemons", - Value: 3, + Name: "Provisioner Daemons", + Usage: "Number of provisioner daemons to create on start. If builds are stuck in queued state for a long time, consider increasing this.", + Flag: "provisioner-daemons", + Default: 3, }, PostgresURL: &codersdk.DeploymentConfigField[string]{ Name: "Postgres Connection URL", @@ -192,10 +192,10 @@ func newConfig() *codersdk.DeploymentConfig { }, OIDC: &codersdk.OIDCConfig{ AllowSignups: &codersdk.DeploymentConfigField[bool]{ - Name: "OIDC Allow Signups", - Usage: "Whether new users can sign up with OIDC.", - Flag: "oidc-allow-signups", - Value: true, + Name: "OIDC Allow Signups", + Usage: "Whether new users can sign up with OIDC.", + Flag: "oidc-allow-signups", + Default: true, }, ClientID: &codersdk.DeploymentConfigField[string]{ Name: "OIDC Client ID", @@ -218,32 +218,32 @@ func newConfig() *codersdk.DeploymentConfig { Flag: "oidc-issuer-url", }, Scopes: &codersdk.DeploymentConfigField[[]string]{ - Name: "OIDC Scopes", - Usage: "Scopes to grant when authenticating with OIDC.", - Flag: "oidc-scopes", - Value: []string{oidc.ScopeOpenID, "profile", "email"}, + Name: "OIDC Scopes", + Usage: "Scopes to grant when authenticating with OIDC.", + Flag: "oidc-scopes", + Default: []string{oidc.ScopeOpenID, "profile", "email"}, }, }, Telemetry: &codersdk.TelemetryConfig{ Enable: &codersdk.DeploymentConfigField[bool]{ - Name: "Telemetry Enable", - Usage: "Whether telemetry is enabled or not. Coder collects anonymized usage data to help improve our product.", - Flag: "telemetry", - Value: flag.Lookup("test.v") == nil, + Name: "Telemetry Enable", + Usage: "Whether telemetry is enabled or not. Coder collects anonymized usage data to help improve our product.", + Flag: "telemetry", + Default: flag.Lookup("test.v") == nil, }, Trace: &codersdk.DeploymentConfigField[bool]{ - Name: "Telemetry Trace", - Usage: "Whether Opentelemetry traces are sent to Coder. Coder collects anonymized application tracing to help improve our product. Disabling telemetry also disables this option.", - Flag: "telemetry-trace", - Value: flag.Lookup("test.v") == nil, + Name: "Telemetry Trace", + Usage: "Whether Opentelemetry traces are sent to Coder. Coder collects anonymized application tracing to help improve our product. Disabling telemetry also disables this option.", + Flag: "telemetry-trace", + Default: flag.Lookup("test.v") == nil, }, URL: &codersdk.DeploymentConfigField[string]{ - Name: "Telemetry URL", - Usage: "URL to send telemetry.", - Flag: "telemetry-url", - Hidden: true, - Value: "https://telemetry.coder.com", + Name: "Telemetry URL", + Usage: "URL to send telemetry.", + Flag: "telemetry-url", + Hidden: true, + Default: "https://telemetry.coder.com", }, }, TLS: &codersdk.TLSConfig{ @@ -263,10 +263,10 @@ func newConfig() *codersdk.DeploymentConfig { Flag: "tls-client-ca-file", }, ClientAuth: &codersdk.DeploymentConfigField[string]{ - Name: "TLS Client Auth", - Usage: "Policy the server will follow for TLS Client Authentication. Accepted values are \"none\", \"request\", \"require-any\", \"verify-if-given\", or \"require-and-verify\".", - Flag: "tls-client-auth", - Value: "request", + Name: "TLS Client Auth", + Usage: "Policy the server will follow for TLS Client Authentication. Accepted values are \"none\", \"request\", \"require-any\", \"verify-if-given\", or \"require-and-verify\".", + Flag: "tls-client-auth", + Default: "request", }, KeyFiles: &codersdk.DeploymentConfigField[[]string]{ Name: "TLS Key Files", @@ -274,10 +274,10 @@ func newConfig() *codersdk.DeploymentConfig { Flag: "tls-key-file", }, MinVersion: &codersdk.DeploymentConfigField[string]{ - Name: "TLS Minimum Version", - Usage: "Minimum supported version of TLS. Accepted values are \"tls10\", \"tls11\", \"tls12\" or \"tls13\"", - Flag: "tls-min-version", - Value: "tls12", + Name: "TLS Minimum Version", + Usage: "Minimum supported version of TLS. Accepted values are \"tls10\", \"tls11\", \"tls12\" or \"tls13\"", + Flag: "tls-min-version", + Default: "tls12", }, }, TraceEnable: &codersdk.DeploymentConfigField[bool]{ @@ -291,10 +291,10 @@ func newConfig() *codersdk.DeploymentConfig { Flag: "secure-auth-cookie", }, SSHKeygenAlgorithm: &codersdk.DeploymentConfigField[string]{ - Name: "SSH Keygen Algorithm", - Usage: "The algorithm to use for generating ssh keys. Accepted values are \"ed25519\", \"ecdsa\", or \"rsa4096\".", - Flag: "ssh-keygen-algorithm", - Value: "ed25519", + Name: "SSH Keygen Algorithm", + Usage: "The algorithm to use for generating ssh keys. Accepted values are \"ed25519\", \"ecdsa\", or \"rsa4096\".", + Flag: "ssh-keygen-algorithm", + Default: "ed25519", }, AutoImportTemplates: &codersdk.DeploymentConfigField[[]string]{ Name: "Auto Import Templates", @@ -303,24 +303,24 @@ func newConfig() *codersdk.DeploymentConfig { Hidden: true, }, MetricsCacheRefreshInterval: &codersdk.DeploymentConfigField[time.Duration]{ - Name: "Metrics Cache Refresh Interval", - Usage: "How frequently metrics are refreshed", - Flag: "metrics-cache-refresh-interval", - Hidden: true, - Value: time.Hour, + Name: "Metrics Cache Refresh Interval", + Usage: "How frequently metrics are refreshed", + Flag: "metrics-cache-refresh-interval", + Hidden: true, + Default: time.Hour, }, AgentStatRefreshInterval: &codersdk.DeploymentConfigField[time.Duration]{ - Name: "Agent Stat Refresh Interval", - Usage: "How frequently agent stats are recorded", - Flag: "agent-stats-refresh-interval", - Hidden: true, - Value: 10 * time.Minute, + Name: "Agent Stat Refresh Interval", + Usage: "How frequently agent stats are recorded", + Flag: "agent-stats-refresh-interval", + Hidden: true, + Default: 10 * time.Minute, }, AuditLogging: &codersdk.DeploymentConfigField[bool]{ Name: "Audit Logging", Usage: "Specifies whether audit logging is enabled.", Flag: "audit-logging", - Value: true, + Default: true, Enterprise: true, }, BrowserOnly: &codersdk.DeploymentConfigField[bool]{ @@ -450,7 +450,7 @@ func setViperDefaults(prefix string, vip *viper.Viper, target interface{}) { val = reflect.Indirect(val) typ := val.Type() if strings.HasPrefix(typ.Name(), "DeploymentConfigField") { - value := val.FieldByName("Value").Interface() + value := val.FieldByName("Default").Interface() vip.SetDefault(prefix, value) return } @@ -499,7 +499,7 @@ func setFlags(prefix string, flagset *pflag.FlagSet, vip *viper.Viper, target in usage = fmt.Sprintf("%s\n%s", usage, cliui.Styles.Placeholder.Render("Consumes $"+formatEnv(prefix))) shorthand := val.FieldByName("Shorthand").String() hidden := val.FieldByName("Hidden").Bool() - value := val.FieldByName("Value").Interface() + value := val.FieldByName("Default").Interface() switch value.(type) { case string: diff --git a/codersdk/deploymentconfig.go b/codersdk/deploymentconfig.go index b47963e835ec2..b873d3313a999 100644 --- a/codersdk/deploymentconfig.go +++ b/codersdk/deploymentconfig.go @@ -118,6 +118,7 @@ type DeploymentConfigField[T Flaggable] struct { Shorthand string `json:"shorthand"` Enterprise bool `json:"enterprise"` Hidden bool `json:"hidden"` + Default T `json:"default"` Value T `json:"value"` } From 24bdf1b21006a726181cd2e133506292267ec684 Mon Sep 17 00:00:00 2001 From: Garrett Date: Mon, 24 Oct 2022 18:52:24 +0000 Subject: [PATCH 10/16] safely return secrets --- cli/deployment/config.go | 24 ++++++++++++++---------- codersdk/deploymentconfig.go | 20 ++++++++++++++++++++ 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/cli/deployment/config.go b/cli/deployment/config.go index 6b21891359109..6f606f6d3d023 100644 --- a/cli/deployment/config.go +++ b/cli/deployment/config.go @@ -152,9 +152,10 @@ func newConfig() *codersdk.DeploymentConfig { Default: 3, }, PostgresURL: &codersdk.DeploymentConfigField[string]{ - Name: "Postgres Connection URL", - Usage: "URL of a PostgreSQL database. If empty, PostgreSQL binaries will be downloaded from Maven (https://repo1.maven.org/maven2) and store all data in the config root. Access the built-in database with \"coder server postgres-builtin-url\".", - Flag: "postgres-url", + Name: "Postgres Connection URL", + Usage: "URL of a PostgreSQL database. If empty, PostgreSQL binaries will be downloaded from Maven (https://repo1.maven.org/maven2) and store all data in the config root. Access the built-in database with \"coder server postgres-builtin-url\".", + Flag: "postgres-url", + Secret: true, }, OAuth2: &codersdk.OAuth2Config{ Github: &codersdk.OAuth2GithubConfig{ @@ -164,9 +165,10 @@ func newConfig() *codersdk.DeploymentConfig { Flag: "oauth2-github-client-id", }, ClientSecret: &codersdk.DeploymentConfigField[string]{ - Name: "OAuth2 GitHub Client Secret", - Usage: "Client secret for Login with GitHub.", - Flag: "oauth2-github-client-secret", + Name: "OAuth2 GitHub Client Secret", + Usage: "Client secret for Login with GitHub.", + Flag: "oauth2-github-client-secret", + Secret: true, }, AllowedOrgs: &codersdk.DeploymentConfigField[[]string]{ Name: "OAuth2 GitHub Allowed Orgs", @@ -203,9 +205,10 @@ func newConfig() *codersdk.DeploymentConfig { Flag: "oidc-client-id", }, ClientSecret: &codersdk.DeploymentConfigField[string]{ - Name: "OIDC Client Secret", - Usage: "Client secret to use for Login with OIDC.", - Flag: "oidc-client-secret", + Name: "OIDC Client Secret", + Usage: "Client secret to use for Login with OIDC.", + Flag: "oidc-client-secret", + Secret: true, }, EmailDomain: &codersdk.DeploymentConfigField[string]{ Name: "OIDC Email Domain", @@ -334,6 +337,7 @@ func newConfig() *codersdk.DeploymentConfig { Usage: "Enables SCIM and sets the authentication header for the built-in SCIM server. New users are automatically created with OIDC authentication.", Flag: "scim-auth-header", Enterprise: true, + Secret: true, }, UserWorkspaceQuota: &codersdk.DeploymentConfigField[int]{ Name: "User Workspace Quota", @@ -440,7 +444,7 @@ func NewViper() *viper.Viper { vip.AutomaticEnv() vip.SetEnvKeyReplacer(strings.NewReplacer("-", "_", ".", "_")) - setViperDefaults("", vip, &dc) + setViperDefaults("", vip, dc) return vip } diff --git a/codersdk/deploymentconfig.go b/codersdk/deploymentconfig.go index b873d3313a999..42779dadded73 100644 --- a/codersdk/deploymentconfig.go +++ b/codersdk/deploymentconfig.go @@ -118,10 +118,30 @@ type DeploymentConfigField[T Flaggable] struct { Shorthand string `json:"shorthand"` Enterprise bool `json:"enterprise"` Hidden bool `json:"hidden"` + Secret bool `json:"secret"` Default T `json:"default"` Value T `json:"value"` } +// MarshalJSON removes the Value field from the JSON output of any fields marked Secret. +// nolint: revive +func (f *DeploymentConfigField[T]) MarshalJSON() ([]byte, error) { + if !f.Secret { + return json.Marshal(f) + } + + return json.Marshal(DeploymentConfigField[T]{ + Name: f.Name, + Usage: f.Usage, + Flag: f.Flag, + Shorthand: f.Shorthand, + Enterprise: f.Enterprise, + Hidden: f.Hidden, + Secret: f.Secret, + Default: f.Default, + }) +} + // DeploymentConfig returns the deployment config for the coder server. func (c *Client) DeploymentConfig(ctx context.Context) (DeploymentConfig, error) { res, err := c.Request(ctx, http.MethodGet, "/api/v2/config/deployment", nil) From d71ef7bbbcac92876816a5863fa39883b3d5b6f8 Mon Sep 17 00:00:00 2001 From: Garrett Date: Mon, 24 Oct 2022 19:00:55 +0000 Subject: [PATCH 11/16] lol --- codersdk/deploymentconfig.go | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/codersdk/deploymentconfig.go b/codersdk/deploymentconfig.go index 42779dadded73..b11ce8775592d 100644 --- a/codersdk/deploymentconfig.go +++ b/codersdk/deploymentconfig.go @@ -130,7 +130,17 @@ func (f *DeploymentConfigField[T]) MarshalJSON() ([]byte, error) { return json.Marshal(f) } - return json.Marshal(DeploymentConfigField[T]{ + type SafeField[T Flaggable] struct { + Name string `json:"name"` + Usage string `json:"usage"` + Flag string `json:"flag"` + Shorthand string `json:"shorthand"` + Enterprise bool `json:"enterprise"` + Hidden bool `json:"hidden"` + Secret bool `json:"secret"` + } + + return json.Marshal(SafeField[T]{ Name: f.Name, Usage: f.Usage, Flag: f.Flag, @@ -138,7 +148,6 @@ func (f *DeploymentConfigField[T]) MarshalJSON() ([]byte, error) { Enterprise: f.Enterprise, Hidden: f.Hidden, Secret: f.Secret, - Default: f.Default, }) } From cead44fabfbfaa6c70a83f98e768becc3eb2a2fd Mon Sep 17 00:00:00 2001 From: Garrett Date: Mon, 24 Oct 2022 19:11:53 +0000 Subject: [PATCH 12/16] fix tests --- codersdk/deploymentconfig.go | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/codersdk/deploymentconfig.go b/codersdk/deploymentconfig.go index b11ce8775592d..3875afcf7db67 100644 --- a/codersdk/deploymentconfig.go +++ b/codersdk/deploymentconfig.go @@ -127,10 +127,30 @@ type DeploymentConfigField[T Flaggable] struct { // nolint: revive func (f *DeploymentConfigField[T]) MarshalJSON() ([]byte, error) { if !f.Secret { - return json.Marshal(f) + return json.Marshal(struct { + Name string `json:"name"` + Usage string `json:"usage"` + Flag string `json:"flag"` + Shorthand string `json:"shorthand"` + Enterprise bool `json:"enterprise"` + Hidden bool `json:"hidden"` + Secret bool `json:"secret"` + Default T `json:"default"` + Value T `json:"value"` + }{ + Name: f.Name, + Usage: f.Usage, + Flag: f.Flag, + Shorthand: f.Shorthand, + Enterprise: f.Enterprise, + Hidden: f.Hidden, + Secret: f.Secret, + Default: f.Default, + Value: f.Value, + }) } - type SafeField[T Flaggable] struct { + return json.Marshal(struct { Name string `json:"name"` Usage string `json:"usage"` Flag string `json:"flag"` @@ -138,9 +158,7 @@ func (f *DeploymentConfigField[T]) MarshalJSON() ([]byte, error) { Enterprise bool `json:"enterprise"` Hidden bool `json:"hidden"` Secret bool `json:"secret"` - } - - return json.Marshal(SafeField[T]{ + }{ Name: f.Name, Usage: f.Usage, Flag: f.Flag, From c28069241fe9fd5aa930b8e704efe0ab17466efa Mon Sep 17 00:00:00 2001 From: Garrett Date: Mon, 24 Oct 2022 19:14:04 +0000 Subject: [PATCH 13/16] lint --- codersdk/deploymentconfig.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codersdk/deploymentconfig.go b/codersdk/deploymentconfig.go index 3875afcf7db67..0849aba1b1ff1 100644 --- a/codersdk/deploymentconfig.go +++ b/codersdk/deploymentconfig.go @@ -124,7 +124,7 @@ type DeploymentConfigField[T Flaggable] struct { } // MarshalJSON removes the Value field from the JSON output of any fields marked Secret. -// nolint: revive +// nolint:revive func (f *DeploymentConfigField[T]) MarshalJSON() ([]byte, error) { if !f.Secret { return json.Marshal(struct { From a43640d25036f3cba4bc5b7e9943141e99bb90a2 Mon Sep 17 00:00:00 2001 From: Garrett Date: Mon, 24 Oct 2022 19:20:55 +0000 Subject: [PATCH 14/16] make gen --- codersdk/deploymentconfig.go | 126 ++++++++++++++++----------------- site/src/api/typesGenerated.ts | 123 +++++++++++++++++++++++--------- 2 files changed, 152 insertions(+), 97 deletions(-) diff --git a/codersdk/deploymentconfig.go b/codersdk/deploymentconfig.go index 0849aba1b1ff1..29c7ab0f1e41f 100644 --- a/codersdk/deploymentconfig.go +++ b/codersdk/deploymentconfig.go @@ -12,99 +12,99 @@ import ( // DeploymentConfig is the central configuration for the coder server. // Secret values should specify `json:"-"` to prevent them from being returned by the API. type DeploymentConfig struct { - AccessURL *DeploymentConfigField[string] `json:"access_url"` - WildcardAccessURL *DeploymentConfigField[string] `json:"wildcard_access_url"` - Address *DeploymentConfigField[string] `json:"address"` - AutobuildPollInterval *DeploymentConfigField[time.Duration] `json:"autobuild_poll_interval"` - DERP *DERP `json:"derp"` - Prometheus *PrometheusConfig `json:"prometheus"` - Pprof *PprofConfig `json:"pprof"` - ProxyTrustedHeaders *DeploymentConfigField[[]string] `json:"proxy_trusted_headers"` - ProxyTrustedOrigins *DeploymentConfigField[[]string] `json:"proxy_trusted_origin"` - CacheDirectory *DeploymentConfigField[string] `json:"cache_directory"` - InMemoryDatabase *DeploymentConfigField[bool] `json:"in_memory_database"` - ProvisionerDaemons *DeploymentConfigField[int] `json:"provisioner_daemons"` - PostgresURL *DeploymentConfigField[string] `json:"pg_connection_url"` - OAuth2 *OAuth2Config `json:"oauth2"` - OIDC *OIDCConfig `json:"oidc"` - Telemetry *TelemetryConfig `json:"telemetry"` - TLS *TLSConfig `json:"tls"` - TraceEnable *DeploymentConfigField[bool] `json:"trace_enable"` - SecureAuthCookie *DeploymentConfigField[bool] `json:"secure_auth_cookie"` - SSHKeygenAlgorithm *DeploymentConfigField[string] `json:"ssh_keygen_algorithm"` - AutoImportTemplates *DeploymentConfigField[[]string] `json:"auto_import_templates"` - MetricsCacheRefreshInterval *DeploymentConfigField[time.Duration] `json:"metrics_cache_refresh_interval"` - AgentStatRefreshInterval *DeploymentConfigField[time.Duration] `json:"agent_stat_refresh_interval"` - AuditLogging *DeploymentConfigField[bool] `json:"audit_logging"` - BrowserOnly *DeploymentConfigField[bool] `json:"browser_only"` - SCIMAPIKey *DeploymentConfigField[string] `json:"scim_api_key"` - UserWorkspaceQuota *DeploymentConfigField[int] `json:"user_workspace_quota"` + AccessURL *DeploymentConfigField[string] `json:"access_url" typescript:",notnull"` + WildcardAccessURL *DeploymentConfigField[string] `json:"wildcard_access_url" typescript:",notnull"` + Address *DeploymentConfigField[string] `json:"address" typescript:",notnull"` + AutobuildPollInterval *DeploymentConfigField[time.Duration] `json:"autobuild_poll_interval" typescript:",notnull"` + DERP *DERP `json:"derp" typescript:",notnull"` + Prometheus *PrometheusConfig `json:"prometheus" typescript:",notnull"` + Pprof *PprofConfig `json:"pprof" typescript:",notnull"` + ProxyTrustedHeaders *DeploymentConfigField[[]string] `json:"proxy_trusted_headers" typescript:",notnull"` + ProxyTrustedOrigins *DeploymentConfigField[[]string] `json:"proxy_trusted_origin" typescript:",notnull"` + CacheDirectory *DeploymentConfigField[string] `json:"cache_directory" typescript:",notnull"` + InMemoryDatabase *DeploymentConfigField[bool] `json:"in_memory_database" typescript:",notnull"` + ProvisionerDaemons *DeploymentConfigField[int] `json:"provisioner_daemons" typescript:",notnull"` + PostgresURL *DeploymentConfigField[string] `json:"pg_connection_url" typescript:",notnull"` + OAuth2 *OAuth2Config `json:"oauth2" typescript:",notnull"` + OIDC *OIDCConfig `json:"oidc" typescript:",notnull"` + Telemetry *TelemetryConfig `json:"telemetry" typescript:",notnull"` + TLS *TLSConfig `json:"tls" typescript:",notnull"` + TraceEnable *DeploymentConfigField[bool] `json:"trace_enable" typescript:",notnull"` + SecureAuthCookie *DeploymentConfigField[bool] `json:"secure_auth_cookie" typescript:",notnull"` + SSHKeygenAlgorithm *DeploymentConfigField[string] `json:"ssh_keygen_algorithm" typescript:",notnull"` + AutoImportTemplates *DeploymentConfigField[[]string] `json:"auto_import_templates" typescript:",notnull"` + MetricsCacheRefreshInterval *DeploymentConfigField[time.Duration] `json:"metrics_cache_refresh_interval" typescript:",notnull"` + AgentStatRefreshInterval *DeploymentConfigField[time.Duration] `json:"agent_stat_refresh_interval" typescript:",notnull"` + AuditLogging *DeploymentConfigField[bool] `json:"audit_logging" typescript:",notnull"` + BrowserOnly *DeploymentConfigField[bool] `json:"browser_only" typescript:",notnull"` + SCIMAPIKey *DeploymentConfigField[string] `json:"scim_api_key" typescript:",notnull"` + UserWorkspaceQuota *DeploymentConfigField[int] `json:"user_workspace_quota" typescript:",notnull"` } type DERP struct { - Server *DERPServerConfig `json:"server"` - Config *DERPConfig `json:"config"` + Server *DERPServerConfig `json:"server" typescript:",notnull"` + Config *DERPConfig `json:"config" typescript:",notnull"` } type DERPServerConfig struct { - Enable *DeploymentConfigField[bool] `json:"enable"` - RegionID *DeploymentConfigField[int] `json:"region_id"` - RegionCode *DeploymentConfigField[string] `json:"region_code"` - RegionName *DeploymentConfigField[string] `json:"region_name"` - STUNAddresses *DeploymentConfigField[[]string] `json:"stun_addresses"` - RelayURL *DeploymentConfigField[string] `json:"relay_url"` + Enable *DeploymentConfigField[bool] `json:"enable" typescript:",notnull"` + RegionID *DeploymentConfigField[int] `json:"region_id" typescript:",notnull"` + RegionCode *DeploymentConfigField[string] `json:"region_code" typescript:",notnull"` + RegionName *DeploymentConfigField[string] `json:"region_name" typescript:",notnull"` + STUNAddresses *DeploymentConfigField[[]string] `json:"stun_addresses" typescript:",notnull"` + RelayURL *DeploymentConfigField[string] `json:"relay_url" typescript:",notnull"` } type DERPConfig struct { - URL *DeploymentConfigField[string] `json:"url"` - Path *DeploymentConfigField[string] `json:"path"` + URL *DeploymentConfigField[string] `json:"url" typescript:",notnull"` + Path *DeploymentConfigField[string] `json:"path" typescript:",notnull"` } type PrometheusConfig struct { - Enable *DeploymentConfigField[bool] `json:"enable"` - Address *DeploymentConfigField[string] `json:"address"` + Enable *DeploymentConfigField[bool] `json:"enable" typescript:",notnull"` + Address *DeploymentConfigField[string] `json:"address" typescript:",notnull"` } type PprofConfig struct { - Enable *DeploymentConfigField[bool] `json:"enable"` - Address *DeploymentConfigField[string] `json:"address"` + Enable *DeploymentConfigField[bool] `json:"enable" typescript:",notnull"` + Address *DeploymentConfigField[string] `json:"address" typescript:",notnull"` } type OAuth2Config struct { - Github *OAuth2GithubConfig `json:"github"` + Github *OAuth2GithubConfig `json:"github" typescript:",notnull"` } type OAuth2GithubConfig struct { - ClientID *DeploymentConfigField[string] `json:"client_id"` - ClientSecret *DeploymentConfigField[string] `json:"client_secret"` - AllowedOrgs *DeploymentConfigField[[]string] `json:"allowed_orgs"` - AllowedTeams *DeploymentConfigField[[]string] `json:"allowed_teams"` - AllowSignups *DeploymentConfigField[bool] `json:"allow_signups"` - EnterpriseBaseURL *DeploymentConfigField[string] `json:"enterprise_base_url"` + ClientID *DeploymentConfigField[string] `json:"client_id" typescript:",notnull"` + ClientSecret *DeploymentConfigField[string] `json:"client_secret" typescript:",notnull"` + AllowedOrgs *DeploymentConfigField[[]string] `json:"allowed_orgs" typescript:",notnull"` + AllowedTeams *DeploymentConfigField[[]string] `json:"allowed_teams" typescript:",notnull"` + AllowSignups *DeploymentConfigField[bool] `json:"allow_signups" typescript:",notnull"` + EnterpriseBaseURL *DeploymentConfigField[string] `json:"enterprise_base_url" typescript:",notnull"` } type OIDCConfig struct { - AllowSignups *DeploymentConfigField[bool] `json:"allow_signups"` - ClientID *DeploymentConfigField[string] `json:"client_id"` - ClientSecret *DeploymentConfigField[string] `json:"client_secret"` - EmailDomain *DeploymentConfigField[string] `json:"email_domain"` - IssuerURL *DeploymentConfigField[string] `json:"issuer_url"` - Scopes *DeploymentConfigField[[]string] `json:"scopes"` + AllowSignups *DeploymentConfigField[bool] `json:"allow_signups" typescript:",notnull"` + ClientID *DeploymentConfigField[string] `json:"client_id" typescript:",notnull"` + ClientSecret *DeploymentConfigField[string] `json:"client_secret" typescript:",notnull"` + EmailDomain *DeploymentConfigField[string] `json:"email_domain" typescript:",notnull"` + IssuerURL *DeploymentConfigField[string] `json:"issuer_url" typescript:",notnull"` + Scopes *DeploymentConfigField[[]string] `json:"scopes" typescript:",notnull"` } type TelemetryConfig struct { - Enable *DeploymentConfigField[bool] `json:"enable"` - Trace *DeploymentConfigField[bool] `json:"trace"` - URL *DeploymentConfigField[string] `json:"url"` + Enable *DeploymentConfigField[bool] `json:"enable" typescript:",notnull"` + Trace *DeploymentConfigField[bool] `json:"trace" typescript:",notnull"` + URL *DeploymentConfigField[string] `json:"url" typescript:",notnull"` } type TLSConfig struct { - Enable *DeploymentConfigField[bool] `json:"enable"` - CertFiles *DeploymentConfigField[[]string] `json:"cert_file"` - ClientAuth *DeploymentConfigField[string] `json:"client_auth"` - ClientCAFile *DeploymentConfigField[string] `json:"client_ca_file"` - KeyFiles *DeploymentConfigField[[]string] `json:"key_file"` - MinVersion *DeploymentConfigField[string] `json:"min_version"` + Enable *DeploymentConfigField[bool] `json:"enable" typescript:",notnull"` + CertFiles *DeploymentConfigField[[]string] `json:"cert_file" typescript:",notnull"` + ClientAuth *DeploymentConfigField[string] `json:"client_auth" typescript:",notnull"` + ClientCAFile *DeploymentConfigField[string] `json:"client_ca_file" typescript:",notnull"` + KeyFiles *DeploymentConfigField[[]string] `json:"key_file" typescript:",notnull"` + MinVersion *DeploymentConfigField[string] `json:"min_version" typescript:",notnull"` } type Flaggable interface { diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index 8cf296785becc..f6d5d5a99c7aa 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -245,54 +245,53 @@ export interface DAUEntry { readonly amount: number } +// From codersdk/deploymentconfig.go +export interface DERP { + readonly server: DERPServerConfig + readonly config: DERPConfig +} + +// From codersdk/deploymentconfig.go +export interface DERPConfig { + readonly url: DeploymentConfigField + readonly path: DeploymentConfigField +} + // From codersdk/workspaceagents.go export interface DERPRegion { readonly preferred: boolean readonly latency_ms: number } +// From codersdk/deploymentconfig.go +export interface DERPServerConfig { + readonly enable: DeploymentConfigField + readonly region_id: DeploymentConfigField + readonly region_code: DeploymentConfigField + readonly region_name: DeploymentConfigField + readonly stun_addresses: DeploymentConfigField + readonly relay_url: DeploymentConfigField +} + // From codersdk/deploymentconfig.go export interface DeploymentConfig { readonly access_url: DeploymentConfigField readonly wildcard_access_url: DeploymentConfigField readonly address: DeploymentConfigField readonly autobuild_poll_interval: DeploymentConfigField - readonly derp_server_enabled: DeploymentConfigField - readonly derp_server_region_id: DeploymentConfigField - readonly derp_server_region_code: DeploymentConfigField - readonly derp_server_region_name: DeploymentConfigField - readonly derp_server_stun_address: DeploymentConfigField - readonly derp_server_relay_address: DeploymentConfigField - readonly derp_config_url: DeploymentConfigField - readonly derp_config_path: DeploymentConfigField - readonly prometheus_enabled: DeploymentConfigField - readonly prometheus_address: DeploymentConfigField - readonly pprof_enabled: DeploymentConfigField - readonly pprof_address: DeploymentConfigField + readonly derp: DERP + readonly prometheus: PrometheusConfig + readonly pprof: PprofConfig readonly proxy_trusted_headers: DeploymentConfigField - readonly proxy_trusted_origins: DeploymentConfigField + readonly proxy_trusted_origin: DeploymentConfigField readonly cache_directory: DeploymentConfigField readonly in_memory_database: DeploymentConfigField - readonly provisioner_daemon_count: DeploymentConfigField - readonly oauth2_github_client_id: DeploymentConfigField - readonly oauth2_github_allowed_orgs: DeploymentConfigField - readonly oauth2_github_allowed_teams: DeploymentConfigField - readonly oauth2_github_allow_signups: DeploymentConfigField - readonly oauth2_github_enterprise_base_url: DeploymentConfigField - readonly oidc_allow_signups: DeploymentConfigField - readonly oidc_client_id: DeploymentConfigField - readonly oidc_email_domain: DeploymentConfigField - readonly oidc_issuer_url: DeploymentConfigField - readonly oidc_scopes: DeploymentConfigField - readonly telemetry_enable: DeploymentConfigField - readonly telemetry_trace_enable: DeploymentConfigField - readonly telemetry_url: DeploymentConfigField - readonly tls_enable: DeploymentConfigField - readonly tls_cert_files: DeploymentConfigField - readonly tls_client_ca_file: DeploymentConfigField - readonly tls_client_auth: DeploymentConfigField - readonly tls_key_files: DeploymentConfigField - readonly tls_min_version: DeploymentConfigField + readonly provisioner_daemons: DeploymentConfigField + readonly pg_connection_url: DeploymentConfigField + readonly oauth2: OAuth2Config + readonly oidc: OIDCConfig + readonly telemetry: TelemetryConfig + readonly tls: TLSConfig readonly trace_enable: DeploymentConfigField readonly secure_auth_cookie: DeploymentConfigField readonly ssh_keygen_algorithm: DeploymentConfigField @@ -301,18 +300,20 @@ export interface DeploymentConfig { readonly agent_stat_refresh_interval: DeploymentConfigField readonly audit_logging: DeploymentConfigField readonly browser_only: DeploymentConfigField + readonly scim_api_key: DeploymentConfigField readonly user_workspace_quota: DeploymentConfigField } // From codersdk/deploymentconfig.go export interface DeploymentConfigField { - readonly key: string readonly name: string readonly usage: string readonly flag: string readonly shorthand: string readonly enterprise: boolean readonly hidden: boolean + readonly secret: boolean + readonly default: T readonly value: T } @@ -399,6 +400,31 @@ export interface LoginWithPasswordResponse { readonly session_token: string } +// From codersdk/deploymentconfig.go +export interface OAuth2Config { + readonly github: OAuth2GithubConfig +} + +// From codersdk/deploymentconfig.go +export interface OAuth2GithubConfig { + readonly client_id: DeploymentConfigField + readonly client_secret: DeploymentConfigField + readonly allowed_orgs: DeploymentConfigField + readonly allowed_teams: DeploymentConfigField + readonly allow_signups: DeploymentConfigField + readonly enterprise_base_url: DeploymentConfigField +} + +// From codersdk/deploymentconfig.go +export interface OIDCConfig { + readonly allow_signups: DeploymentConfigField + readonly client_id: DeploymentConfigField + readonly client_secret: DeploymentConfigField + readonly email_domain: DeploymentConfigField + readonly issuer_url: DeploymentConfigField + readonly scopes: DeploymentConfigField +} + // From codersdk/organizations.go export interface Organization { readonly id: string @@ -464,6 +490,18 @@ export interface PatchGroupRequest { readonly avatar_url?: string } +// From codersdk/deploymentconfig.go +export interface PprofConfig { + readonly enable: DeploymentConfigField + readonly address: DeploymentConfigField +} + +// From codersdk/deploymentconfig.go +export interface PrometheusConfig { + readonly enable: DeploymentConfigField + readonly address: DeploymentConfigField +} + // From codersdk/provisionerdaemons.go export interface ProvisionerDaemon { readonly id: string @@ -532,6 +570,23 @@ export interface ServerSentEvent { readonly data: any } +// From codersdk/deploymentconfig.go +export interface TLSConfig { + readonly enable: DeploymentConfigField + readonly cert_file: DeploymentConfigField + readonly client_auth: DeploymentConfigField + readonly client_ca_file: DeploymentConfigField + readonly key_file: DeploymentConfigField + readonly min_version: DeploymentConfigField +} + +// From codersdk/deploymentconfig.go +export interface TelemetryConfig { + readonly enable: DeploymentConfigField + readonly trace: DeploymentConfigField + readonly url: DeploymentConfigField +} + // From codersdk/templates.go export interface Template { readonly id: string From 1a37ac48925c581ee135c5a4e4ab7e432218b7af Mon Sep 17 00:00:00 2001 From: Garrett Date: Mon, 24 Oct 2022 20:19:34 +0000 Subject: [PATCH 15/16] fis js --- codersdk/deploymentconfig.go | 40 ++++++------------- site/src/api/typesGenerated.ts | 2 +- .../DeploySettingsLayout/OptionsTable.tsx | 4 +- .../DeploySettingsPage/AuthSettingsPage.tsx | 34 ++++++++-------- .../NetworkSettingsPage.tsx | 8 ++-- .../SecuritySettingsPage.tsx | 8 ++-- 6 files changed, 40 insertions(+), 56 deletions(-) diff --git a/codersdk/deploymentconfig.go b/codersdk/deploymentconfig.go index 29c7ab0f1e41f..a33f79718ffec 100644 --- a/codersdk/deploymentconfig.go +++ b/codersdk/deploymentconfig.go @@ -10,7 +10,6 @@ import ( ) // DeploymentConfig is the central configuration for the coder server. -// Secret values should specify `json:"-"` to prevent them from being returned by the API. type DeploymentConfig struct { AccessURL *DeploymentConfigField[string] `json:"access_url" typescript:",notnull"` WildcardAccessURL *DeploymentConfigField[string] `json:"wildcard_access_url" typescript:",notnull"` @@ -20,7 +19,7 @@ type DeploymentConfig struct { Prometheus *PrometheusConfig `json:"prometheus" typescript:",notnull"` Pprof *PprofConfig `json:"pprof" typescript:",notnull"` ProxyTrustedHeaders *DeploymentConfigField[[]string] `json:"proxy_trusted_headers" typescript:",notnull"` - ProxyTrustedOrigins *DeploymentConfigField[[]string] `json:"proxy_trusted_origin" typescript:",notnull"` + ProxyTrustedOrigins *DeploymentConfigField[[]string] `json:"proxy_trusted_origins" typescript:",notnull"` CacheDirectory *DeploymentConfigField[string] `json:"cache_directory" typescript:",notnull"` InMemoryDatabase *DeploymentConfigField[bool] `json:"in_memory_database" typescript:",notnull"` ProvisionerDaemons *DeploymentConfigField[int] `json:"provisioner_daemons" typescript:",notnull"` @@ -126,31 +125,7 @@ type DeploymentConfigField[T Flaggable] struct { // MarshalJSON removes the Value field from the JSON output of any fields marked Secret. // nolint:revive func (f *DeploymentConfigField[T]) MarshalJSON() ([]byte, error) { - if !f.Secret { - return json.Marshal(struct { - Name string `json:"name"` - Usage string `json:"usage"` - Flag string `json:"flag"` - Shorthand string `json:"shorthand"` - Enterprise bool `json:"enterprise"` - Hidden bool `json:"hidden"` - Secret bool `json:"secret"` - Default T `json:"default"` - Value T `json:"value"` - }{ - Name: f.Name, - Usage: f.Usage, - Flag: f.Flag, - Shorthand: f.Shorthand, - Enterprise: f.Enterprise, - Hidden: f.Hidden, - Secret: f.Secret, - Default: f.Default, - Value: f.Value, - }) - } - - return json.Marshal(struct { + copy := struct { Name string `json:"name"` Usage string `json:"usage"` Flag string `json:"flag"` @@ -158,6 +133,8 @@ func (f *DeploymentConfigField[T]) MarshalJSON() ([]byte, error) { Enterprise bool `json:"enterprise"` Hidden bool `json:"hidden"` Secret bool `json:"secret"` + Default T `json:"default"` + Value T `json:"value"` }{ Name: f.Name, Usage: f.Usage, @@ -166,7 +143,14 @@ func (f *DeploymentConfigField[T]) MarshalJSON() ([]byte, error) { Enterprise: f.Enterprise, Hidden: f.Hidden, Secret: f.Secret, - }) + } + + if !f.Secret { + copy.Default = f.Default + copy.Value = f.Value + } + + return json.Marshal(copy) } // DeploymentConfig returns the deployment config for the coder server. diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index f6d5d5a99c7aa..e9345e9ffafe2 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -283,7 +283,7 @@ export interface DeploymentConfig { readonly prometheus: PrometheusConfig readonly pprof: PprofConfig readonly proxy_trusted_headers: DeploymentConfigField - readonly proxy_trusted_origin: DeploymentConfigField + readonly proxy_trusted_origins: DeploymentConfigField readonly cache_directory: DeploymentConfigField readonly in_memory_database: DeploymentConfigField readonly provisioner_daemons: DeploymentConfigField diff --git a/site/src/components/DeploySettingsLayout/OptionsTable.tsx b/site/src/components/DeploySettingsLayout/OptionsTable.tsx index 8c47eb9b58aa0..d46dfc23fd283 100644 --- a/site/src/components/DeploySettingsLayout/OptionsTable.tsx +++ b/site/src/components/DeploySettingsLayout/OptionsTable.tsx @@ -5,7 +5,7 @@ import TableCell from "@material-ui/core/TableCell" import TableContainer from "@material-ui/core/TableContainer" import TableHead from "@material-ui/core/TableHead" import TableRow from "@material-ui/core/TableRow" -import { DeploymentConfig } from "api/typesGenerated" +import { DeploymentConfigField, Flaggable } from "api/typesGenerated" import { OptionDescription, OptionName, @@ -13,7 +13,7 @@ import { } from "components/DeploySettingsLayout/Option" import React from "react" -const OptionsTable: React.FC<{ options: Partial }> = ({ +const OptionsTable: React.FC<{ options: Record> }> = ({ options, }) => { const styles = useStyles() diff --git a/site/src/pages/DeploySettingsPage/AuthSettingsPage.tsx b/site/src/pages/DeploySettingsPage/AuthSettingsPage.tsx index 4a76c04e2797a..7878a7c7d9823 100644 --- a/site/src/pages/DeploySettingsPage/AuthSettingsPage.tsx +++ b/site/src/pages/DeploySettingsPage/AuthSettingsPage.tsx @@ -32,7 +32,7 @@ const AuthSettingsPage: React.FC = () => { /> - {deploymentConfig.oidc_client_id.value ? ( + {deploymentConfig.oidc.client_id.value ? ( ) : ( @@ -41,11 +41,11 @@ const AuthSettingsPage: React.FC = () => { @@ -59,7 +59,7 @@ const AuthSettingsPage: React.FC = () => { /> - {deploymentConfig.oauth2_github_client_id.value ? ( + {deploymentConfig.oauth2.github.client_id.value ? ( ) : ( @@ -68,16 +68,16 @@ const AuthSettingsPage: React.FC = () => { diff --git a/site/src/pages/DeploySettingsPage/NetworkSettingsPage.tsx b/site/src/pages/DeploySettingsPage/NetworkSettingsPage.tsx index 23e87a284e4b2..f9d6843d3789e 100644 --- a/site/src/pages/DeploySettingsPage/NetworkSettingsPage.tsx +++ b/site/src/pages/DeploySettingsPage/NetworkSettingsPage.tsx @@ -22,10 +22,10 @@ const NetworkSettingsPage: React.FC = () => { diff --git a/site/src/pages/DeploySettingsPage/SecuritySettingsPage.tsx b/site/src/pages/DeploySettingsPage/SecuritySettingsPage.tsx index 0a7e3afdccae9..3a14de7711c66 100644 --- a/site/src/pages/DeploySettingsPage/SecuritySettingsPage.tsx +++ b/site/src/pages/DeploySettingsPage/SecuritySettingsPage.tsx @@ -89,10 +89,10 @@ const SecuritySettingsPage: React.FC = () => { From b5bbd5f873ad033ed586cd55420ba16104374cc2 Mon Sep 17 00:00:00 2001 From: Garrett Date: Mon, 24 Oct 2022 20:21:24 +0000 Subject: [PATCH 16/16] make fmt --- .../components/DeploySettingsLayout/OptionsTable.tsx | 6 +++--- .../src/pages/DeploySettingsPage/AuthSettingsPage.tsx | 11 ++++------- .../pages/DeploySettingsPage/NetworkSettingsPage.tsx | 3 ++- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/site/src/components/DeploySettingsLayout/OptionsTable.tsx b/site/src/components/DeploySettingsLayout/OptionsTable.tsx index d46dfc23fd283..e613b0348a634 100644 --- a/site/src/components/DeploySettingsLayout/OptionsTable.tsx +++ b/site/src/components/DeploySettingsLayout/OptionsTable.tsx @@ -13,9 +13,9 @@ import { } from "components/DeploySettingsLayout/Option" import React from "react" -const OptionsTable: React.FC<{ options: Record> }> = ({ - options, -}) => { +const OptionsTable: React.FC<{ + options: Record> +}> = ({ options }) => { const styles = useStyles() return ( diff --git a/site/src/pages/DeploySettingsPage/AuthSettingsPage.tsx b/site/src/pages/DeploySettingsPage/AuthSettingsPage.tsx index 7878a7c7d9823..22bf85b0505a2 100644 --- a/site/src/pages/DeploySettingsPage/AuthSettingsPage.tsx +++ b/site/src/pages/DeploySettingsPage/AuthSettingsPage.tsx @@ -69,15 +69,12 @@ const AuthSettingsPage: React.FC = () => { diff --git a/site/src/pages/DeploySettingsPage/NetworkSettingsPage.tsx b/site/src/pages/DeploySettingsPage/NetworkSettingsPage.tsx index f9d6843d3789e..931dba1b7f2a8 100644 --- a/site/src/pages/DeploySettingsPage/NetworkSettingsPage.tsx +++ b/site/src/pages/DeploySettingsPage/NetworkSettingsPage.tsx @@ -24,7 +24,8 @@ const NetworkSettingsPage: React.FC = () => { options={{ derp_server_enable: deploymentConfig.derp.server.enable, derp_server_region_name: deploymentConfig.derp.server.region_name, - derp_server_stun_addresses: deploymentConfig.derp.server.stun_addresses, + derp_server_stun_addresses: + deploymentConfig.derp.server.stun_addresses, derp_config_url: deploymentConfig.derp.config.url, }} />