podman

Форк
0
149 строк · 3.4 Кб
1
package rest
2

3
import (
4
	"errors"
5
	"fmt"
6
	"net/url"
7
	"strings"
8

9
	"github.com/crc-org/vfkit/pkg/cmdline"
10
	"github.com/gin-gonic/gin"
11
	"github.com/sirupsen/logrus"
12
)
13

14
type Endpoint struct {
15
	Host   string
16
	Path   string
17
	Scheme ServiceScheme
18
}
19

20
func NewEndpoint(input string) (*Endpoint, error) {
21
	uri, err := parseRestfulURI(input)
22
	if err != nil {
23
		return nil, err
24
	}
25
	scheme, err := toRestScheme(uri.Scheme)
26
	if err != nil {
27
		return nil, err
28
	}
29
	return &Endpoint{
30
		Host:   uri.Host,
31
		Path:   uri.Path,
32
		Scheme: scheme,
33
	}, nil
34
}
35

36
func (ep *Endpoint) ToCmdLine() ([]string, error) {
37
	args := []string{"--restful-uri"}
38
	switch ep.Scheme {
39
	case Unix:
40
		args = append(args, fmt.Sprintf("unix://%s", ep.Path))
41
	case TCP:
42
		args = append(args, fmt.Sprintf("tcp://%s%s", ep.Host, ep.Path))
43
	case None:
44
		return []string{}, nil
45
	default:
46
		return []string{}, errors.New("invalid endpoint scheme")
47
	}
48
	return args, nil
49
}
50

51
// VFKitService is used for the restful service; it describes
52
// the variables of the service like host/path but also has
53
// the router object
54
type VFKitService struct {
55
	*Endpoint
56
	router *gin.Engine
57
}
58

59
// Start initiates the already configured gin service
60
func (v *VFKitService) Start() {
61
	go func() {
62
		var err error
63
		switch v.Scheme {
64
		case TCP:
65
			err = v.router.Run(v.Host)
66
		case Unix:
67
			err = v.router.RunUnix(v.Path)
68
		}
69
		logrus.Fatal(err)
70
	}()
71
}
72

73
// NewServer creates a new restful service
74
func NewServer(inspector VirtualMachineInspector, stateHandler VirtualMachineStateHandler, endpoint string) (*VFKitService, error) {
75
	r := gin.Default()
76
	ep, err := NewEndpoint(endpoint)
77
	if err != nil {
78
		return nil, err
79
	}
80
	s := VFKitService{
81
		router:   r,
82
		Endpoint: ep,
83
	}
84

85
	// Handlers for the restful service.  This is where endpoints are defined.
86
	r.GET("/vm/state", stateHandler.GetVMState)
87
	r.POST("/vm/state", stateHandler.SetVMState)
88
	r.GET("/vm/inspect", inspector.Inspect)
89
	return &s, nil
90
}
91

92
type VirtualMachineInspector interface {
93
	Inspect(c *gin.Context)
94
}
95

96
type VirtualMachineStateHandler interface {
97
	GetVMState(c *gin.Context)
98
	SetVMState(c *gin.Context)
99
}
100

101
// parseRestfulURI validates the input URI and returns an URL object
102
func parseRestfulURI(inputURI string) (*url.URL, error) {
103
	restURI, err := url.ParseRequestURI(inputURI)
104
	if err != nil {
105
		return nil, err
106
	}
107
	scheme, err := toRestScheme(restURI.Scheme)
108
	if err != nil {
109
		return nil, err
110
	}
111
	if scheme == TCP && len(restURI.Host) < 1 {
112
		return nil, errors.New("invalid TCP uri: missing host")
113
	}
114
	if scheme == TCP && len(restURI.Path) > 0 {
115
		return nil, errors.New("invalid TCP uri: path is forbidden")
116
	}
117
	if scheme == TCP && restURI.Port() == "" {
118
		return nil, errors.New("invalid TCP uri: missing port")
119
	}
120
	if scheme == Unix && len(restURI.Path) < 1 {
121
		return nil, errors.New("invalid unix uri: missing path")
122
	}
123
	if scheme == Unix && len(restURI.Host) > 0 {
124
		return nil, errors.New("invalid unix uri: host is forbidden")
125
	}
126
	return restURI, err
127
}
128

129
// toRestScheme converts a string to a ServiceScheme
130
func toRestScheme(s string) (ServiceScheme, error) {
131
	switch strings.ToUpper(s) {
132
	case "NONE":
133
		return None, nil
134
	case "UNIX":
135
		return Unix, nil
136
	case "TCP", "HTTP":
137
		return TCP, nil
138
	}
139
	return None, fmt.Errorf("invalid scheme %s", s)
140
}
141

142
func validateRestfulURI(inputURI string) error {
143
	if inputURI != cmdline.DefaultRestfulURI {
144
		if _, err := parseRestfulURI(inputURI); err != nil {
145
			return err
146
		}
147
	}
148
	return nil
149
}
150

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.