/
service.go
132 lines (110 loc) · 3.72 KB
/
service.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Copyright 2017 Microsoft. All rights reserved.
// MIT License
package cns
import (
"fmt"
"github.com/Azure/azure-container-networking/cns/logger"
"net/http"
"net/url"
"strings"
"github.com/Azure/azure-container-networking/cns/common"
acn "github.com/Azure/azure-container-networking/common"
"github.com/Azure/azure-container-networking/log"
"github.com/Azure/azure-container-networking/store"
)
const (
// Default CNS server URL.
defaultAPIServerURL = "tcp://localhost:10090"
genericData = "com.microsoft.azure.network.generic"
)
// Service defines Container Networking Service.
type Service struct {
*common.Service
EndpointType string
Listener *acn.Listener
}
// NewService creates a new Service object.
func NewService(name, version, channelMode string, store store.KeyValueStore) (*Service, error) {
service, err := common.NewService(name, version, channelMode, store)
if err != nil {
return nil, err
}
return &Service{
Service: service,
}, nil
}
// GetAPIServerURL returns the API server URL.
func (service *Service) getAPIServerURL() string {
urls, _ := service.GetOption(acn.OptCnsURL).(string)
if urls == "" {
urls = defaultAPIServerURL
}
return urls
}
// Initialize initializes the service and starts the listener.
func (service *Service) Initialize(config *common.ServiceConfig) error {
log.Debugf("[Azure CNS] Going to initialize a service with config: %+v", config)
// Initialize the base service.
service.Service.Initialize(config)
// Initialize the listener.
if config.Listener == nil {
// Fetch and parse the API server URL.
u, err := url.Parse(service.getAPIServerURL())
if err != nil {
return err
}
// Create the listener.
listener, err := acn.NewListener(u)
if err != nil {
return err
}
if config.TlsSettings.TLSPort != "" {
// listener.URL.Host will always be hostname:port, passed in to CNS via CNS command
// else it will default to localhost
// extract hostname and override tls port.
hostParts := strings.Split(listener.URL.Host, ":")
config.TlsSettings.TLSEndpoint = hostParts[0] + ":" + config.TlsSettings.TLSPort
// Start the listener and HTTP and HTTPS server.
if err = listener.StartTLS(config.ErrChan, config.TlsSettings); err != nil {
return err
}
}
logger.Printf("HTTP listener will be started later after CNS state has been reconciled")
config.Listener = listener
}
service.Listener = config.Listener
log.Debugf("[Azure CNS] Successfully initialized a service with config: %+v", config)
return nil
}
func (service *Service) StartListener(config *common.ServiceConfig) error {
log.Debugf("[Azure CNS] Going to start listener: %+v", config)
// Initialize the listener.
if service.Listener != nil {
log.Debugf("[Azure CNS] Starting listener: %+v", config)
// Start the listener.
// continue to listen on the normal endpoint for http traffic, this will be supported
// for sometime until partners migrate fully to https
if err := service.Listener.Start(config.ErrChan); err != nil {
return err
}
} else {
return fmt.Errorf("Failed to start a listener, it is not initialized, config %+v", config)
}
return nil
}
// Uninitialize cleans up the plugin.
func (service *Service) Uninitialize() {
service.Listener.Stop()
service.Service.Uninitialize()
}
// ParseOptions returns generic options from a libnetwork request.
func (service *Service) ParseOptions(options OptionMap) OptionMap {
opt, _ := options[genericData].(OptionMap)
return opt
}
// SendErrorResponse sends and logs an error response.
func (service *Service) SendErrorResponse(w http.ResponseWriter, errMsg error) {
resp := errorResponse{errMsg.Error()}
err := service.Listener.Encode(w, &resp)
log.Errorf("[%s] %+v %s.", service.Name, &resp, err.Error())
}