mirror of
				https://github.com/caddyserver/caddy.git
				synced 2025-10-31 10:37:24 -04:00 
			
		
		
		
	admin listener as opt-in for initial config (#2834)
* Always cleanup admin endpoint first * Error out if no config has been set (#2833) * Ignore explicitly missing admin config (#2833) * Separate config loading from admin initialization (#2833) * Add admin option to specify admin listener address (#2833) * Use zap for reporting admin endpoint status
This commit is contained in:
		
							parent
							
								
									4611537f06
								
							
						
					
					
						commit
						432b94239d
					
				
							
								
								
									
										40
									
								
								admin.go
									
									
									
									
									
								
							
							
						
						
									
										40
									
								
								admin.go
									
									
									
									
									
								
							| @ -18,6 +18,7 @@ import ( | ||||
| 	"bytes" | ||||
| 	"context" | ||||
| 	"encoding/json" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"io/ioutil" | ||||
| @ -42,6 +43,8 @@ var ( | ||||
| 	cfgEndptSrvMu sync.Mutex | ||||
| ) | ||||
| 
 | ||||
| var ErrAdminInterfaceNotConfigured = errors.New("no admin configuration has been set") | ||||
| 
 | ||||
| // AdminConfig configures the admin endpoint. | ||||
| type AdminConfig struct { | ||||
| 	Listen string `json:"listen,omitempty"` | ||||
| @ -60,10 +63,24 @@ var DefaultAdminConfig = &AdminConfig{ | ||||
| // in the format of JSON bytes. It opens a listener | ||||
| // resource. When no longer needed, StopAdmin should | ||||
| // be called. | ||||
| // If no configuration is given, a default listener is | ||||
| // started. If a configuration is given that does NOT | ||||
| // specifically configure the admin interface, | ||||
| // `ErrAdminInterfaceNotConfigured` is returned and no | ||||
| // listener is initialized. | ||||
| func StartAdmin(initialConfigJSON []byte) error { | ||||
| 	cfgEndptSrvMu.Lock() | ||||
| 	defer cfgEndptSrvMu.Unlock() | ||||
| 
 | ||||
| 	if cfgEndptSrv != nil { | ||||
| 		ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) | ||||
| 		defer cancel() | ||||
| 		err := cfgEndptSrv.Shutdown(ctx) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("shutting down old admin endpoint: %v", err) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	adminConfig := DefaultAdminConfig | ||||
| 	if len(initialConfigJSON) > 0 { | ||||
| 		var config *Config | ||||
| @ -71,16 +88,11 @@ func StartAdmin(initialConfigJSON []byte) error { | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("unmarshaling bootstrap config: %v", err) | ||||
| 		} | ||||
| 		if config != nil && config.Admin != nil { | ||||
| 			adminConfig = config.Admin | ||||
| 		} | ||||
| 		if cfgEndptSrv != nil { | ||||
| 			ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) | ||||
| 			defer cancel() | ||||
| 			err := cfgEndptSrv.Shutdown(ctx) | ||||
| 			if err != nil { | ||||
| 				return fmt.Errorf("shutting down old admin endpoint: %v", err) | ||||
| 		if config != nil { | ||||
| 			if config.Admin == nil { | ||||
| 				return ErrAdminInterfaceNotConfigured | ||||
| 			} | ||||
| 			adminConfig = config.Admin | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| @ -136,15 +148,7 @@ func StartAdmin(initialConfigJSON []byte) error { | ||||
| 
 | ||||
| 	go cfgEndptSrv.Serve(ln) | ||||
| 
 | ||||
| 	fmt.Println("Caddy 2 admin endpoint listening on", adminConfig.Listen) | ||||
| 
 | ||||
| 	if len(initialConfigJSON) > 0 { | ||||
| 		err := Load(bytes.NewReader(initialConfigJSON)) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("loading initial config: %v", err) | ||||
| 		} | ||||
| 		fmt.Println("Caddy 2 serving initial configuration") | ||||
| 	} | ||||
| 	Log().Named("admin").Info("Caddy 2 admin endpoint started.", zap.String("listenAddress", adminConfig.Listen)) | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| @ -74,6 +74,8 @@ func (st ServerType) Setup(originalServerBlocks []caddyfile.ServerBlock, | ||||
| 				val, err = parseOptACMECA(disp) | ||||
| 			case "email": | ||||
| 				val, err = parseOptEmail(disp) | ||||
| 			case "admin": | ||||
| 				val, err = parseOptAdmin(disp) | ||||
| 			default: | ||||
| 				return nil, warnings, fmt.Errorf("unrecognized parameter name: %s", dir) | ||||
| 			} | ||||
| @ -254,6 +256,9 @@ func (st ServerType) Setup(originalServerBlocks []caddyfile.ServerBlock, | ||||
| 			storageCvtr.(caddy.Module).CaddyModule().ID(), | ||||
| 			&warnings) | ||||
| 	} | ||||
| 	if adminConfig, ok := options["admin"].(string); ok && adminConfig != "" { | ||||
| 		cfg.Admin = &caddy.AdminConfig{Listen: adminConfig} | ||||
| 	} | ||||
| 
 | ||||
| 	return cfg, warnings, nil | ||||
| } | ||||
|  | ||||
| @ -132,3 +132,17 @@ func parseOptEmail(d *caddyfile.Dispenser) (string, error) { | ||||
| 	} | ||||
| 	return val, nil | ||||
| } | ||||
| 
 | ||||
| func parseOptAdmin(d *caddyfile.Dispenser) (string, error) { | ||||
| 	if d.Next() { | ||||
| 		var listenAddress string | ||||
| 		d.AllArgs(&listenAddress) | ||||
| 
 | ||||
| 		if listenAddress == "" { | ||||
| 			listenAddress = caddy.DefaultAdminListen | ||||
| 		} | ||||
| 
 | ||||
| 		return listenAddress, nil | ||||
| 	} | ||||
| 	return "", nil | ||||
| } | ||||
|  | ||||
| @ -161,12 +161,24 @@ func cmdRun(fl Flags) (int, error) { | ||||
| 	certmagic.UserAgent = "Caddy/" + cleanModVersion | ||||
| 
 | ||||
| 	// start the admin endpoint along with any initial config | ||||
| 	// a configuration without admin config is considered fine | ||||
| 	// but does not enable the admin endpoint at all | ||||
| 	err = caddy.StartAdmin(config) | ||||
| 	if err != nil { | ||||
| 	if err == nil { | ||||
| 		defer caddy.StopAdmin() | ||||
| 	} else if err != caddy.ErrAdminInterfaceNotConfigured { | ||||
| 		return caddy.ExitCodeFailedStartup, | ||||
| 			fmt.Errorf("starting caddy administration endpoint: %v", err) | ||||
| 	} | ||||
| 	defer caddy.StopAdmin() | ||||
| 
 | ||||
| 	// if a config has been supplied, load it as initial config | ||||
| 	if len(config) > 0 { | ||||
| 		err := caddy.Load(bytes.NewReader(config)) | ||||
| 		if err != nil { | ||||
| 			return caddy.ExitCodeFailedStartup, fmt.Errorf("loading initial config: %v", err) | ||||
| 		} | ||||
| 		caddy.Log().Named("admin").Info("Caddy 2 serving initial configuration") | ||||
| 	} | ||||
| 
 | ||||
| 	// if we are to report to another process the successful start | ||||
| 	// of the server, do so now by echoing back contents of stdin | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user