• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mendersoftware / mender-server / 1495380963

14 Oct 2024 03:35PM UTC coverage: 70.373% (-2.5%) from 72.904%
1495380963

Pull #101

gitlab-ci

mineralsfree
feat: tenant list added

Ticket: MEN-7568
Changelog: None

Signed-off-by: Mikita Pilinka <mikita.pilinka@northern.tech>
Pull Request #101: feat: tenant list added

4406 of 6391 branches covered (68.94%)

Branch coverage included in aggregate %.

88 of 183 new or added lines in 10 files covered. (48.09%)

2623 existing lines in 65 files now uncovered.

36673 of 51982 relevant lines covered (70.55%)

31.07 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.72
/backend/services/iot-manager/api/http/router.go
1
// Copyright 2024 Northern.tech AS
2
//
3
//    Licensed under the Apache License, Version 2.0 (the "License");
4
//    you may not use this file except in compliance with the License.
5
//    You may obtain a copy of the License at
6
//
7
//        http://www.apache.org/licenses/LICENSE-2.0
8
//
9
//    Unless required by applicable law or agreed to in writing, software
10
//    distributed under the License is distributed on an "AS IS" BASIS,
11
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
//    See the License for the specific language governing permissions and
13
//    limitations under the License.
14

15
package http
16

17
import (
18
        "context"
19
        "net/http"
20
        "time"
21

22
        "github.com/gin-gonic/gin"
23
        "github.com/gin-gonic/gin/binding"
24
        "github.com/pkg/errors"
25

26
        "github.com/mendersoftware/mender-server/pkg/accesslog"
27
        "github.com/mendersoftware/mender-server/pkg/identity"
28
        "github.com/mendersoftware/mender-server/pkg/log"
29
        "github.com/mendersoftware/mender-server/pkg/requestid"
30
        "github.com/mendersoftware/mender-server/pkg/rest.utils"
31

32
        "github.com/mendersoftware/mender-server/services/iot-manager/app"
33
)
34

35
// API URL used by the HTTP router
36
const (
37
        APIURLInternal = "/api/internal/v1/iot-manager"
38

39
        APIURLAlive             = "/alive"
40
        APIURLHealth            = "/health"
41
        APIURLTenants           = "/tenants"
42
        APIURLTenant            = APIURLTenants + "/:tenant_id"
43
        APIURLTenantAuth        = APIURLTenant + "/auth"
44
        APIURLTenantDevices     = APIURLTenant + "/devices"
45
        APIURLTenantDevice      = APIURLTenantDevices + "/:device_id"
46
        APIURLTenantBulkDevices = APIURLTenant + "/bulk/devices"
47
        APIURLTenantBulkStatus  = APIURLTenantBulkDevices + "/status/:status"
48

49
        APIURLManagement = "/api/management/v1/iot-manager"
50

51
        APIURLIntegrations           = "/integrations"
52
        APIURLIntegration            = "/integrations/:id"
53
        APIURLIntegrationCredentials = APIURLIntegration + "/credentials"
54

55
        APIURLDevice                 = "/devices/:id"
56
        APIURLDeviceState            = APIURLDevice + "/state"
57
        APIURLDeviceStateIntegration = APIURLDevice + "/state/:integrationId"
58

59
        APIURLEvents = "/events"
60
)
61

62
const (
63
        defaultTimeout = time.Second * 10
64
)
65

66
type Config struct {
67
        Client *http.Client
68
}
69

70
// NewConfig initializes a new empty config and optionally merges the
71
// configurations provided as argument.
72
func NewConfig(configs ...*Config) *Config {
1✔
73
        var config = new(Config)
1✔
74
        for _, conf := range configs {
2✔
75
                if conf == nil {
2✔
76
                        continue
1✔
77
                }
78
                if conf.Client != nil {
1✔
UNCOV
79
                        config.Client = conf.Client
×
UNCOV
80
                }
×
81
        }
82
        return config
1✔
83
}
84

UNCOV
85
func (conf *Config) SetClient(client *http.Client) *Config {
×
UNCOV
86
        conf.Client = client
×
UNCOV
87
        return conf
×
UNCOV
88
}
×
89

90
// NewRouter returns the gin router
91
func NewRouter(
92
        app app.App,
93
        config ...*Config,
94
) *gin.Engine {
1✔
95
        conf := NewConfig(config...)
1✔
96
        gin.SetMode(gin.ReleaseMode)
1✔
97
        gin.DisableConsoleColor()
1✔
98
        handler := NewAPIHandler(app, conf)
1✔
99
        internal := (*InternalHandler)(handler)
1✔
100
        management := (*ManagementHandler)(handler)
1✔
101

1✔
102
        router := gin.New()
1✔
103
        router.Use(accesslog.Middleware())
1✔
104
        router.Use(requestid.Middleware())
1✔
105

1✔
106
        router.NoRoute(handler.NoRoute)
1✔
107

1✔
108
        internalAPI := router.Group(APIURLInternal)
1✔
109
        internalAPI.GET(APIURLAlive, handler.Alive)
1✔
110
        internalAPI.GET(APIURLHealth, handler.Health)
1✔
111

1✔
112
        internalAPI.DELETE(APIURLTenant, internal.DeleteTenant)
1✔
113
        internalAPI.POST(APIURLTenantDevices, internal.ProvisionDevice)
1✔
114
        internalAPI.DELETE(APIURLTenantDevice, internal.DecommissionDevice)
1✔
115
        internalAPI.PUT(APIURLTenantBulkStatus, internal.BulkSetDeviceStatus)
1✔
116

1✔
117
        internalAPI.POST(APIURLTenantAuth, internal.PreauthorizeHandler)
1✔
118

1✔
119
        managementAPI := router.Group(APIURLManagement, identity.Middleware())
1✔
120
        managementAPI.GET(APIURLIntegrations, management.GetIntegrations)
1✔
121
        managementAPI.GET(APIURLIntegration, management.GetIntegrationById)
1✔
122
        managementAPI.POST(APIURLIntegrations, management.CreateIntegration)
1✔
123
        managementAPI.PUT(APIURLIntegrationCredentials, management.SetIntegrationCredentials)
1✔
124
        managementAPI.DELETE(APIURLIntegration, management.RemoveIntegration)
1✔
125

1✔
126
        managementAPI.GET(APIURLDeviceState, management.GetDeviceState)
1✔
127
        managementAPI.GET(APIURLDeviceStateIntegration, management.GetDeviceStateIntegration)
1✔
128
        managementAPI.PUT(APIURLDeviceStateIntegration, management.SetDeviceStateIntegration)
1✔
129

1✔
130
        managementAPI.GET(APIURLEvents, management.GetEvents)
1✔
131

1✔
132
        return router
1✔
133
}
1✔
134

135
type APIHandler struct {
136
        *http.Client
137
        app app.App
138
}
139

140
func NewAPIHandler(app app.App, config ...*Config) *APIHandler {
1✔
141
        conf := NewConfig(config...)
1✔
142
        if conf.Client == nil {
2✔
143
                conf.Client = new(http.Client)
1✔
144
        }
1✔
145
        return &APIHandler{
1✔
146
                Client: conf.Client,
1✔
147
                app:    app,
1✔
148
        }
1✔
149
}
150

151
// Alive responds to GET /alive
152
func (h *APIHandler) Alive(c *gin.Context) {
1✔
153
        c.Writer.WriteHeader(http.StatusNoContent)
1✔
154
}
1✔
155

156
// Health responds to GET /health
157
func (h *APIHandler) Health(c *gin.Context) {
1✔
158
        ctx := c.Request.Context()
1✔
159
        l := log.FromContext(ctx)
1✔
160
        ctx, cancel := context.WithTimeout(ctx, defaultTimeout)
1✔
161
        defer cancel()
1✔
162

1✔
163
        err := h.app.HealthCheck(ctx)
1✔
164
        if err != nil {
2✔
165
                l.Error(errors.Wrap(err, "health check failed"))
1✔
166
                c.JSON(http.StatusServiceUnavailable, gin.H{
1✔
167
                        "error": err.Error(),
1✔
168
                })
1✔
169
                return
1✔
170
        }
1✔
171

172
        c.Writer.WriteHeader(http.StatusNoContent)
1✔
173
}
174

175
func (h *APIHandler) NoRoute(c *gin.Context) {
1✔
176
        c.JSON(http.StatusNotFound, rest.Error{
1✔
177
                Err:       "not found",
1✔
178
                RequestID: requestid.FromContext(c.Request.Context()),
1✔
179
        })
1✔
180
}
1✔
181

182
// Make gin-gonic use validatable structs instead of relying on go-playground
183
// validator interface.
184
type validateValidatableValidator struct{}
185

186
func (validateValidatableValidator) ValidateStruct(obj interface{}) error {
1✔
187
        if v, ok := obj.(interface{ Validate() error }); ok {
2✔
188
                return v.Validate()
1✔
189
        }
1✔
190
        return nil
1✔
191
}
192

193
func (validateValidatableValidator) Engine() interface{} {
×
194
        return nil
×
195
}
×
196

197
func init() {
1✔
198
        binding.Validator = validateValidatableValidator{}
1✔
199
}
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc