2017-08-25 14:10:03 +00:00
package configuration
2015-09-07 08:38:58 +00:00
2015-09-25 09:44:19 +00:00
import (
2016-01-23 16:41:56 +00:00
"fmt"
2016-05-03 14:52:14 +00:00
"strings"
"time"
2016-08-05 14:02:46 +00:00
2018-07-31 17:28:03 +00:00
"github.com/containous/flaeg/parse"
2016-08-05 14:02:46 +00:00
"github.com/containous/traefik/acme"
2018-11-14 09:18:03 +00:00
"github.com/containous/traefik/old/api"
"github.com/containous/traefik/old/log"
"github.com/containous/traefik/old/middlewares/tracing"
"github.com/containous/traefik/old/middlewares/tracing/datadog"
"github.com/containous/traefik/old/middlewares/tracing/jaeger"
"github.com/containous/traefik/old/middlewares/tracing/zipkin"
"github.com/containous/traefik/old/ping"
"github.com/containous/traefik/old/provider/boltdb"
"github.com/containous/traefik/old/provider/consul"
"github.com/containous/traefik/old/provider/consulcatalog"
"github.com/containous/traefik/old/provider/docker"
"github.com/containous/traefik/old/provider/dynamodb"
"github.com/containous/traefik/old/provider/ecs"
"github.com/containous/traefik/old/provider/etcd"
"github.com/containous/traefik/old/provider/eureka"
"github.com/containous/traefik/old/provider/file"
"github.com/containous/traefik/old/provider/kubernetes"
"github.com/containous/traefik/old/provider/marathon"
"github.com/containous/traefik/old/provider/mesos"
"github.com/containous/traefik/old/provider/rancher"
"github.com/containous/traefik/old/provider/rest"
"github.com/containous/traefik/old/provider/zk"
2018-11-27 16:42:04 +00:00
"github.com/containous/traefik/old/tls"
2018-11-14 09:18:03 +00:00
"github.com/containous/traefik/old/types"
2018-03-05 19:54:04 +00:00
acmeprovider "github.com/containous/traefik/provider/acme"
2018-11-14 09:18:03 +00:00
newtypes "github.com/containous/traefik/types"
2018-10-08 17:24:03 +00:00
"github.com/pkg/errors"
2018-10-11 08:50:03 +00:00
lego "github.com/xenolf/lego/acme"
2015-09-25 09:44:19 +00:00
)
2017-08-18 13:34:04 +00:00
const (
2017-11-09 15:12:04 +00:00
// DefaultInternalEntryPointName the name of the default internal entry point
DefaultInternalEntryPointName = "traefik"
2017-08-18 13:34:04 +00:00
// DefaultHealthCheckInterval is the default health check interval.
DefaultHealthCheckInterval = 30 * time . Second
2018-09-27 18:16:03 +00:00
// DefaultHealthCheckTimeout is the default health check request timeout.
DefaultHealthCheckTimeout = 5 * time . Second
2017-08-18 13:34:04 +00:00
// DefaultDialTimeout when connecting to a backend server.
DefaultDialTimeout = 30 * time . Second
2017-08-25 14:10:03 +00:00
2017-08-18 13:34:04 +00:00
// DefaultIdleTimeout before closing an idle connection.
DefaultIdleTimeout = 180 * time . Second
2017-09-26 08:22:03 +00:00
// DefaultGraceTimeout controls how long Traefik serves pending requests
// prior to shutting down.
DefaultGraceTimeout = 10 * time . Second
2018-05-22 14:08:03 +00:00
// DefaultAcmeCAServer is the default ACME API endpoint
DefaultAcmeCAServer = "https://acme-v02.api.letsencrypt.org/directory"
2017-08-18 13:34:04 +00:00
)
2017-03-24 08:36:33 +00:00
2015-11-06 17:11:57 +00:00
// GlobalConfiguration holds global configuration (with providers, etc.).
// It's populated from the traefik configuration file passed as an argument to the binary.
2015-09-10 13:13:35 +00:00
type GlobalConfiguration struct {
2018-07-13 15:32:03 +00:00
LifeCycle * LifeCycle ` description:"Timeouts influencing the server life cycle" export:"true" `
Debug bool ` short:"d" description:"Enable debug mode" export:"true" `
CheckNewVersion bool ` description:"Periodically check if a new version has been released" export:"true" `
SendAnonymousUsage bool ` description:"send periodically anonymous usage statistics" export:"true" `
AccessLog * types . AccessLog ` description:"Access log settings" export:"true" `
TraefikLog * types . TraefikLog ` description:"Traefik log settings" export:"true" `
Tracing * tracing . Tracing ` description:"OpenTracing configuration" export:"true" `
LogLevel string ` short:"l" description:"Log level" export:"true" `
EntryPoints EntryPoints ` description:"Entrypoints definition using format: --entryPoints='Name:http Address::8000 Redirect.EntryPoint:https' --entryPoints='Name:https Address::4442 TLS:tests/traefik.crt,tests/traefik.key;prod/traefik.crt,prod/traefik.key'" export:"true" `
Cluster * types . Cluster
2017-10-02 08:32:02 +00:00
Constraints types . Constraints ` description:"Filter services by constraint, matching with service tags" export:"true" `
ACME * acme . ACME ` description:"Enable ACME (Let's Encrypt): automatic SSL" export:"true" `
DefaultEntryPoints DefaultEntryPoints ` description:"Entrypoints to be used by frontends that do not specify any entrypoint" export:"true" `
2018-07-31 17:28:03 +00:00
ProvidersThrottleDuration parse . Duration ` description:"Backends throttle duration: minimum duration between 2 events from providers before applying a new configuration. It avoids unnecessary reloads if multiples events are sent in a short amount of time." export:"true" `
2017-10-02 08:32:02 +00:00
MaxIdleConnsPerHost int ` description:"If non-zero, controls the maximum idle (keep-alive) to keep per-host. If zero, DefaultMaxIdleConnsPerHost is used" export:"true" `
InsecureSkipVerify bool ` description:"Disable SSL certificate verification" export:"true" `
2018-08-29 09:36:03 +00:00
RootCAs tls . FilesOrContents ` description:"Add cert file for self-signed certificate" `
2017-10-02 08:32:02 +00:00
Retry * Retry ` description:"Enable retry sending request if network error" export:"true" `
HealthCheck * HealthCheckConfig ` description:"Health check parameters" export:"true" `
RespondingTimeouts * RespondingTimeouts ` description:"Timeouts for incoming requests to the Traefik instance" export:"true" `
ForwardingTimeouts * ForwardingTimeouts ` description:"Timeouts for requests forwarded to the backend servers" export:"true" `
2018-10-30 11:34:00 +00:00
KeepTrailingSlash bool ` description:"Do not remove trailing slash." export:"true" ` // Deprecated
2017-10-02 08:32:02 +00:00
Docker * docker . Provider ` description:"Enable Docker backend with default settings" export:"true" `
File * file . Provider ` description:"Enable File backend with default settings" export:"true" `
Marathon * marathon . Provider ` description:"Enable Marathon backend with default settings" export:"true" `
Consul * consul . Provider ` description:"Enable Consul backend with default settings" export:"true" `
2018-01-04 14:56:03 +00:00
ConsulCatalog * consulcatalog . Provider ` description:"Enable Consul catalog backend with default settings" export:"true" `
2017-10-02 08:32:02 +00:00
Etcd * etcd . Provider ` description:"Enable Etcd backend with default settings" export:"true" `
Zookeeper * zk . Provider ` description:"Enable Zookeeper backend with default settings" export:"true" `
Boltdb * boltdb . Provider ` description:"Enable Boltdb backend with default settings" export:"true" `
Kubernetes * kubernetes . Provider ` description:"Enable Kubernetes backend with default settings" export:"true" `
Mesos * mesos . Provider ` description:"Enable Mesos backend with default settings" export:"true" `
Eureka * eureka . Provider ` description:"Enable Eureka backend with default settings" export:"true" `
ECS * ecs . Provider ` description:"Enable ECS backend with default settings" export:"true" `
Rancher * rancher . Provider ` description:"Enable Rancher backend with default settings" export:"true" `
DynamoDB * dynamodb . Provider ` description:"Enable DynamoDB backend with default settings" export:"true" `
2017-11-09 15:12:04 +00:00
Rest * rest . Provider ` description:"Enable Rest backend with default settings" export:"true" `
API * api . Handler ` description:"Enable api/dashboard" export:"true" `
Metrics * types . Metrics ` description:"Enable a metrics exporter" export:"true" `
Ping * ping . Handler ` description:"Enable ping" export:"true" `
2018-07-03 14:44:05 +00:00
HostResolver * HostResolverConfig ` description:"Enable CNAME Flattening" export:"true" `
2017-11-09 15:12:04 +00:00
}
2017-10-16 21:10:44 +00:00
// SetEffectiveConfiguration adds missing configuration parameters derived from existing ones.
// It also takes care of maintaining backwards compatibility.
2017-10-11 08:38:03 +00:00
func ( gc * GlobalConfiguration ) SetEffectiveConfiguration ( configFile string ) {
2017-09-26 08:22:03 +00:00
if len ( gc . EntryPoints ) == 0 {
2017-10-16 21:10:44 +00:00
gc . EntryPoints = map [ string ] * EntryPoint { "http" : {
Address : ":80" ,
2018-08-24 14:20:03 +00:00
ForwardedHeaders : & ForwardedHeaders { } ,
2017-10-16 21:10:44 +00:00
} }
2017-09-26 08:22:03 +00:00
gc . DefaultEntryPoints = [ ] string { "http" }
}
2017-11-09 15:12:04 +00:00
if ( gc . API != nil && gc . API . EntryPoint == DefaultInternalEntryPointName ) ||
( gc . Ping != nil && gc . Ping . EntryPoint == DefaultInternalEntryPointName ) ||
( gc . Metrics != nil && gc . Metrics . Prometheus != nil && gc . Metrics . Prometheus . EntryPoint == DefaultInternalEntryPointName ) ||
( gc . Rest != nil && gc . Rest . EntryPoint == DefaultInternalEntryPointName ) {
if _ , ok := gc . EntryPoints [ DefaultInternalEntryPointName ] ; ! ok {
gc . EntryPoints [ DefaultInternalEntryPointName ] = & EntryPoint { Address : ":8080" }
}
}
2017-10-16 21:10:44 +00:00
for entryPointName := range gc . EntryPoints {
entryPoint := gc . EntryPoints [ entryPointName ]
2018-03-23 16:40:04 +00:00
// ForwardedHeaders must be remove in the next breaking version
2017-10-16 21:10:44 +00:00
if entryPoint . ForwardedHeaders == nil {
2018-08-24 14:20:03 +00:00
entryPoint . ForwardedHeaders = & ForwardedHeaders { }
2018-03-23 16:40:04 +00:00
}
2018-09-28 22:04:02 +00:00
if entryPoint . TLS != nil && entryPoint . TLS . DefaultCertificate == nil && len ( entryPoint . TLS . Certificates ) > 0 {
log . Infof ( "No tls.defaultCertificate given for %s: using the first item in tls.certificates as a fallback." , entryPointName )
entryPoint . TLS . DefaultCertificate = & entryPoint . TLS . Certificates [ 0 ]
}
2017-10-16 21:10:44 +00:00
}
2017-09-26 08:22:03 +00:00
// Make sure LifeCycle isn't nil to spare nil checks elsewhere.
if gc . LifeCycle == nil {
gc . LifeCycle = & LifeCycle { }
}
if gc . Rancher != nil {
// Ensure backwards compatibility for now
if len ( gc . Rancher . AccessKey ) > 0 ||
len ( gc . Rancher . Endpoint ) > 0 ||
len ( gc . Rancher . SecretKey ) > 0 {
if gc . Rancher . API == nil {
gc . Rancher . API = & rancher . APIConfiguration {
AccessKey : gc . Rancher . AccessKey ,
SecretKey : gc . Rancher . SecretKey ,
Endpoint : gc . Rancher . Endpoint ,
}
}
log . Warn ( "Deprecated configuration found: rancher.[accesskey|secretkey|endpoint]. " +
"Please use rancher.api.[accesskey|secretkey|endpoint] instead." )
}
if gc . Rancher . Metadata != nil && len ( gc . Rancher . Metadata . Prefix ) == 0 {
gc . Rancher . Metadata . Prefix = "latest"
}
}
2017-11-09 15:12:04 +00:00
if gc . API != nil {
gc . API . Debug = gc . Debug
}
2018-05-22 10:02:03 +00:00
if gc . File != nil {
gc . File . TraefikFile = configFile
2017-09-26 08:22:03 +00:00
}
2018-01-15 15:04:05 +00:00
2018-03-05 19:54:04 +00:00
gc . initACMEProvider ( )
2018-04-16 15:42:03 +00:00
gc . initTracing ( )
}
func ( gc * GlobalConfiguration ) initTracing ( ) {
if gc . Tracing != nil {
switch gc . Tracing . Backend {
case jaeger . Name :
if gc . Tracing . Jaeger == nil {
gc . Tracing . Jaeger = & jaeger . Config {
SamplingServerURL : "http://localhost:5778/sampling" ,
SamplingType : "const" ,
SamplingParam : 1.0 ,
2018-04-24 17:22:03 +00:00
LocalAgentHostPort : "127.0.0.1:6831" ,
2018-08-01 11:52:03 +00:00
Propagation : "jaeger" ,
Gen128Bit : false ,
2018-04-16 15:42:03 +00:00
}
}
if gc . Tracing . Zipkin != nil {
log . Warn ( "Zipkin configuration will be ignored" )
gc . Tracing . Zipkin = nil
}
2018-07-26 15:44:03 +00:00
if gc . Tracing . DataDog != nil {
log . Warn ( "DataDog configuration will be ignored" )
gc . Tracing . DataDog = nil
}
2018-04-16 15:42:03 +00:00
case zipkin . Name :
if gc . Tracing . Zipkin == nil {
gc . Tracing . Zipkin = & zipkin . Config {
HTTPEndpoint : "http://localhost:9411/api/v1/spans" ,
SameSpan : false ,
ID128Bit : true ,
Debug : false ,
2018-10-09 08:18:02 +00:00
SampleRate : 1.0 ,
2018-04-16 15:42:03 +00:00
}
}
if gc . Tracing . Jaeger != nil {
log . Warn ( "Jaeger configuration will be ignored" )
gc . Tracing . Jaeger = nil
}
2018-07-26 15:44:03 +00:00
if gc . Tracing . DataDog != nil {
log . Warn ( "DataDog configuration will be ignored" )
gc . Tracing . DataDog = nil
}
case datadog . Name :
if gc . Tracing . DataDog == nil {
gc . Tracing . DataDog = & datadog . Config {
LocalAgentHostPort : "localhost:8126" ,
GlobalTag : "" ,
Debug : false ,
}
}
if gc . Tracing . Zipkin != nil {
log . Warn ( "Zipkin configuration will be ignored" )
gc . Tracing . Zipkin = nil
}
if gc . Tracing . Jaeger != nil {
2018-04-16 15:42:03 +00:00
log . Warn ( "Jaeger configuration will be ignored" )
gc . Tracing . Jaeger = nil
}
default :
log . Warnf ( "Unknown tracer %q" , gc . Tracing . Backend )
return
}
}
2018-03-05 19:54:04 +00:00
}
func ( gc * GlobalConfiguration ) initACMEProvider ( ) {
2018-01-15 15:04:05 +00:00
if gc . ACME != nil {
2018-05-22 14:08:03 +00:00
gc . ACME . CAServer = getSafeACMECAServer ( gc . ACME . CAServer )
if gc . ACME . DNSChallenge != nil && gc . ACME . HTTPChallenge != nil {
log . Warn ( "Unable to use DNS challenge and HTTP challenge at the same time. Fallback to DNS challenge." )
gc . ACME . HTTPChallenge = nil
}
2018-07-03 10:44:04 +00:00
if gc . ACME . DNSChallenge != nil && gc . ACME . TLSChallenge != nil {
log . Warn ( "Unable to use DNS challenge and TLS challenge at the same time. Fallback to DNS challenge." )
gc . ACME . TLSChallenge = nil
}
if gc . ACME . HTTPChallenge != nil && gc . ACME . TLSChallenge != nil {
log . Warn ( "Unable to use HTTP challenge and TLS challenge at the same time. Fallback to TLS challenge." )
gc . ACME . HTTPChallenge = nil
}
2018-01-15 15:04:05 +00:00
if gc . ACME . OnDemand {
log . Warn ( "ACME.OnDemand is deprecated" )
}
2018-04-24 20:40:04 +00:00
}
}
2018-03-05 19:54:04 +00:00
2018-04-24 20:40:04 +00:00
// InitACMEProvider create an acme provider from the ACME part of globalConfiguration
2018-10-08 17:24:03 +00:00
func ( gc * GlobalConfiguration ) InitACMEProvider ( ) ( * acmeprovider . Provider , error ) {
2018-04-24 20:40:04 +00:00
if gc . ACME != nil {
2018-10-08 17:24:03 +00:00
if len ( gc . ACME . Storage ) == 0 {
// Delete the ACME configuration to avoid starting ACME in cluster mode
gc . ACME = nil
return nil , errors . New ( "unable to initialize ACME provider with no storage location for the certificates" )
}
2018-03-05 19:54:04 +00:00
// TODO: Remove when Provider ACME will replace totally ACME
// If provider file, use Provider ACME instead of ACME
if gc . Cluster == nil {
2018-04-24 20:40:04 +00:00
provider := & acmeprovider . Provider { }
2018-11-14 09:18:03 +00:00
provider . Configuration = convertACMEChallenge ( gc . ACME )
2018-04-24 20:40:04 +00:00
store := acmeprovider . NewLocalStore ( provider . Storage )
2018-07-03 10:44:04 +00:00
provider . Store = store
2018-04-24 20:40:04 +00:00
acme . ConvertToNewFormat ( provider . Storage )
2018-03-05 19:54:04 +00:00
gc . ACME = nil
2018-10-08 17:24:03 +00:00
return provider , nil
2018-03-05 19:54:04 +00:00
}
2018-01-15 15:04:05 +00:00
}
2018-10-08 17:24:03 +00:00
return nil , nil
2017-09-26 08:22:03 +00:00
}
2018-05-22 14:08:03 +00:00
func getSafeACMECAServer ( caServerSrc string ) string {
if len ( caServerSrc ) == 0 {
return DefaultAcmeCAServer
}
if strings . HasPrefix ( caServerSrc , "https://acme-v01.api.letsencrypt.org" ) {
caServer := strings . Replace ( caServerSrc , "v01" , "v02" , 1 )
log . Warnf ( "The CA server %[1]q refers to a v01 endpoint of the ACME API, please change to %[2]q. Fallback to %[2]q." , caServerSrc , caServer )
return caServer
}
if strings . HasPrefix ( caServerSrc , "https://acme-staging.api.letsencrypt.org" ) {
caServer := strings . Replace ( caServerSrc , "https://acme-staging.api.letsencrypt.org" , "https://acme-staging-v02.api.letsencrypt.org" , 1 )
log . Warnf ( "The CA server %[1]q refers to a v01 endpoint of the ACME API, please change to %[2]q. Fallback to %[2]q." , caServerSrc , caServer )
return caServer
}
return caServerSrc
}
2018-01-25 11:02:04 +00:00
// ValidateConfiguration validate that configuration is coherent
func ( gc * GlobalConfiguration ) ValidateConfiguration ( ) {
if gc . ACME != nil {
if _ , ok := gc . EntryPoints [ gc . ACME . EntryPoint ] ; ! ok {
log . Fatalf ( "Unknown entrypoint %q for ACME configuration" , gc . ACME . EntryPoint )
} else {
if gc . EntryPoints [ gc . ACME . EntryPoint ] . TLS == nil {
2018-03-27 10:22:03 +00:00
log . Fatalf ( "Entrypoint %q has no TLS configuration for ACME configuration" , gc . ACME . EntryPoint )
2018-01-25 11:02:04 +00:00
}
}
}
}
2016-01-29 19:34:17 +00:00
// DefaultEntryPoints holds default entry points
type DefaultEntryPoints [ ] string
// String is the method to format the flag's value, part of the flag.Value interface.
// The String method's output will be used in diagnostics.
func ( dep * DefaultEntryPoints ) String ( ) string {
2016-05-27 09:13:34 +00:00
return strings . Join ( * dep , "," )
2016-01-29 19:34:17 +00:00
}
// Set is the method to set the flag value, part of the flag.Value interface.
// Set's argument is a string to be parsed to set the flag.
// It's a comma-separated list, so we split it.
func ( dep * DefaultEntryPoints ) Set ( value string ) error {
entrypoints := strings . Split ( value , "," )
if len ( entrypoints ) == 0 {
2017-05-26 15:03:14 +00:00
return fmt . Errorf ( "bad DefaultEntryPoints format: %s" , value )
2016-01-29 19:34:17 +00:00
}
for _ , entrypoint := range entrypoints {
* dep = append ( * dep , entrypoint )
}
return nil
}
2016-05-03 14:52:14 +00:00
// Get return the EntryPoints map
2016-08-16 17:13:18 +00:00
func ( dep * DefaultEntryPoints ) Get ( ) interface { } {
2017-12-18 08:14:03 +00:00
return * dep
2016-08-16 17:13:18 +00:00
}
2016-05-03 14:52:14 +00:00
// SetValue sets the EntryPoints map with val
func ( dep * DefaultEntryPoints ) SetValue ( val interface { } ) {
2017-12-18 08:14:03 +00:00
* dep = val . ( DefaultEntryPoints )
2016-05-03 14:52:14 +00:00
}
2016-01-29 19:34:17 +00:00
// Type is type of the struct
func ( dep * DefaultEntryPoints ) Type ( ) string {
2017-06-23 13:15:07 +00:00
return "defaultentrypoints"
}
2016-03-29 20:25:32 +00:00
// Retry contains request retry config
type Retry struct {
2017-10-02 08:32:02 +00:00
Attempts int ` description:"Number of attempts" export:"true" `
2016-03-29 20:25:32 +00:00
}
2017-03-24 08:36:33 +00:00
// HealthCheckConfig contains health check configuration parameters.
type HealthCheckConfig struct {
2018-07-31 17:28:03 +00:00
Interval parse . Duration ` description:"Default periodicity of enabled health checks" export:"true" `
2018-09-27 18:16:03 +00:00
Timeout parse . Duration ` description:"Default request timeout of enabled health checks" export:"true" `
2017-03-24 08:36:33 +00:00
}
2017-08-18 13:34:04 +00:00
// RespondingTimeouts contains timeout configurations for incoming requests to the Traefik instance.
type RespondingTimeouts struct {
2018-07-31 17:28:03 +00:00
ReadTimeout parse . Duration ` description:"ReadTimeout is the maximum duration for reading the entire request, including the body. If zero, no timeout is set" export:"true" `
WriteTimeout parse . Duration ` description:"WriteTimeout is the maximum duration before timing out writes of the response. If zero, no timeout is set" export:"true" `
IdleTimeout parse . Duration ` description:"IdleTimeout is the maximum amount duration an idle (keep-alive) connection will remain idle before closing itself. Defaults to 180 seconds. If zero, no timeout is set" export:"true" `
2017-08-18 13:34:04 +00:00
}
// ForwardingTimeouts contains timeout configurations for forwarding requests to the backend servers.
type ForwardingTimeouts struct {
2018-07-31 17:28:03 +00:00
DialTimeout parse . Duration ` description:"The amount of time to wait until a connection to a backend server can be established. Defaults to 30 seconds. If zero, no timeout exists" export:"true" `
ResponseHeaderTimeout parse . Duration ` description:"The amount of time to wait for a server's response headers after fully writing the request (including its body, if any). If zero, no timeout exists" export:"true" `
2017-08-18 13:34:04 +00:00
}
2017-09-26 08:22:03 +00:00
// LifeCycle contains configurations relevant to the lifecycle (such as the
// shutdown phase) of Traefik.
type LifeCycle struct {
2018-07-31 17:28:03 +00:00
RequestAcceptGraceTimeout parse . Duration ` description:"Duration to keep accepting requests before Traefik initiates the graceful shutdown procedure" `
GraceTimeOut parse . Duration ` description:"Duration to give active requests a chance to finish before Traefik stops" `
2017-09-26 08:22:03 +00:00
}
2018-07-03 14:44:05 +00:00
// HostResolverConfig contain configuration for CNAME Flattening
type HostResolverConfig struct {
CnameFlattening bool ` description:"A flag to enable/disable CNAME flattening" export:"true" `
ResolvConfig string ` description:"resolv.conf used for DNS resolving" export:"true" `
ResolvDepth int ` description:"The maximal depth of DNS recursive resolving" export:"true" `
}
2018-11-14 09:18:03 +00:00
// Deprecated
func convertACMEChallenge ( oldACMEChallenge * acme . ACME ) * acmeprovider . Configuration {
conf := & acmeprovider . Configuration {
KeyType : oldACMEChallenge . KeyType ,
OnHostRule : oldACMEChallenge . OnHostRule ,
OnDemand : oldACMEChallenge . OnDemand ,
Email : oldACMEChallenge . Email ,
Storage : oldACMEChallenge . Storage ,
ACMELogging : oldACMEChallenge . ACMELogging ,
CAServer : oldACMEChallenge . CAServer ,
EntryPoint : oldACMEChallenge . EntryPoint ,
}
for _ , domain := range oldACMEChallenge . Domains {
if domain . Main != lego . UnFqdn ( domain . Main ) {
log . Warnf ( "FQDN detected, please remove the trailing dot: %s" , domain . Main )
}
for _ , san := range domain . SANs {
if san != lego . UnFqdn ( san ) {
log . Warnf ( "FQDN detected, please remove the trailing dot: %s" , san )
}
}
conf . Domains = append ( conf . Domains , newtypes . Domain ( domain ) )
}
if oldACMEChallenge . HTTPChallenge != nil {
conf . HTTPChallenge = & acmeprovider . HTTPChallenge {
EntryPoint : oldACMEChallenge . HTTPChallenge . EntryPoint ,
}
}
if oldACMEChallenge . DNSChallenge != nil {
conf . DNSChallenge = & acmeprovider . DNSChallenge {
Provider : oldACMEChallenge . DNSChallenge . Provider ,
DelayBeforeCheck : oldACMEChallenge . DNSChallenge . DelayBeforeCheck ,
}
}
if oldACMEChallenge . TLSChallenge != nil {
conf . TLSChallenge = & acmeprovider . TLSChallenge { }
}
return conf
}