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

mendersoftware / deployments / 843450222

pending completion
843450222

Pull #854

gitlab-ci

Alf-Rune Siqveland
chore: Add `--throttle` flag to `propagate-reporting` command
Pull Request #854: chore: Add `--throttle` flag to `propagate-reporting` command

8 of 11 new or added lines in 1 file covered. (72.73%)

434 existing lines in 4 files now uncovered.

6943 of 8758 relevant lines covered (79.28%)

70.43 hits per line

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

93.24
/api/http/routing.go
1
// Copyright 2023 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/url"
20
        "strings"
21

22
        "github.com/ant0ine/go-json-rest/rest"
23
        "github.com/mendersoftware/go-lib-micro/log"
24

25
        "github.com/mendersoftware/deployments/app"
26
        "github.com/mendersoftware/deployments/store"
27
        "github.com/mendersoftware/deployments/utils/restutil"
28
        "github.com/mendersoftware/deployments/utils/restutil/view"
29
)
30

31
const (
32
        ApiUrlInternal   = "/api/internal/v1/deployments"
33
        ApiUrlManagement = "/api/management/v1/deployments"
34
        ApiUrlDevices    = "/api/devices/v1/deployments"
35

36
        ApiUrlManagementArtifacts               = ApiUrlManagement + "/artifacts"
37
        ApiUrlManagementArtifactsList           = ApiUrlManagement + "/artifacts/list"
38
        ApiUrlManagementArtifactsGenerate       = ApiUrlManagement + "/artifacts/generate"
39
        ApiUrlManagementArtifactsDirectUpload   = ApiUrlManagement + "/artifacts/directupload"
40
        ApiUrlManagementArtifactsCompleteUpload = ApiUrlManagementArtifactsDirectUpload +
41
                "/#id/complete"
42
        ApiUrlManagementArtifactsId         = ApiUrlManagement + "/artifacts/#id"
43
        ApiUrlManagementArtifactsIdDownload = ApiUrlManagement + "/artifacts/#id/download"
44

45
        ApiUrlManagementDeployments                   = ApiUrlManagement + "/deployments"
46
        ApiUrlManagementMultipleDeploymentsStatistics = ApiUrlManagement +
47
                "/deployments/statistics/list"
48
        ApiUrlManagementDeploymentsGroup       = ApiUrlManagement + "/deployments/group/#name"
49
        ApiUrlManagementDeploymentsId          = ApiUrlManagement + "/deployments/#id"
50
        ApiUrlManagementDeploymentsStatistics  = ApiUrlManagement + "/deployments/#id/statistics"
51
        ApiUrlManagementDeploymentsStatus      = ApiUrlManagement + "/deployments/#id/status"
52
        ApiUrlManagementDeploymentsDevices     = ApiUrlManagement + "/deployments/#id/devices"
53
        ApiUrlManagementDeploymentsDevicesList = ApiUrlManagement + "/deployments/#id/devices/list"
54
        ApiUrlManagementDeploymentsLog         = ApiUrlManagement +
55
                "/deployments/#id/devices/#devid/log"
56
        ApiUrlManagementDeploymentsDeviceId      = ApiUrlManagement + "/deployments/devices/#id"
57
        ApiUrlManagementDeploymentsDeviceHistory = ApiUrlManagement + "/deployments/devices/#id/history"
58
        ApiUrlManagementDeploymentsDeviceList    = ApiUrlManagement + "/deployments/#id/device_list"
59

60
        ApiUrlManagementReleases     = ApiUrlManagement + "/deployments/releases"
61
        ApiUrlManagementReleasesList = ApiUrlManagement + "/deployments/releases/list"
62

63
        ApiUrlManagementLimitsName = ApiUrlManagement + "/limits/#name"
64

65
        ApiUrlDevicesDeploymentsNext  = ApiUrlDevices + "/device/deployments/next"
66
        ApiUrlDevicesDeploymentStatus = ApiUrlDevices + "/device/deployments/#id/status"
67
        ApiUrlDevicesDeploymentsLog   = ApiUrlDevices + "/device/deployments/#id/log"
68
        ApiUrlDevicesDownloadConfig   = ApiUrlDevices +
69
                "/download/configuration/#deployment_id/#device_type/#device_id"
70

71
        ApiUrlInternalAlive                    = ApiUrlInternal + "/alive"
72
        ApiUrlInternalHealth                   = ApiUrlInternal + "/health"
73
        ApiUrlInternalTenants                  = ApiUrlInternal + "/tenants"
74
        ApiUrlInternalTenantDeployments        = ApiUrlInternal + "/tenants/#tenant/deployments"
75
        ApiUrlInternalTenantDeploymentsDevices = ApiUrlInternal + "/tenants/#tenant/deployments/devices"
76
        ApiUrlInternalTenantDeploymentsDevice  = ApiUrlInternal +
77
                "/tenants/#tenant/deployments/devices/#id"
78
        ApiUrlInternalTenantArtifacts       = ApiUrlInternal + "/tenants/#tenant/artifacts"
79
        ApiUrlInternalTenantStorageSettings = ApiUrlInternal +
80
                "/tenants/#tenant/storage/settings"
81
        ApiUrlInternalDeviceConfigurationDeployments = ApiUrlInternal +
82
                "/tenants/#tenant/configuration/deployments/#deployment_id/devices/#device_id"
83
)
84

85
// NewRouter defines all REST API routes.
86
func NewRouter(
87
        ctx context.Context,
88
        app app.App,
89
        ds store.DataStore,
90
        cfg *Config,
91
) (rest.App, error) {
13✔
92

13✔
93
        // Create and configure API handlers
13✔
94
        //
13✔
95
        // Encode base64 secret in either std or URL encoding ignoring padding.
13✔
96
        deploymentsHandlers := NewDeploymentsApiHandlers(
13✔
97
                ds, new(view.RESTView), app, cfg,
13✔
98
        )
13✔
99

13✔
100
        // Routing
13✔
101
        imageRoutes := NewImagesResourceRoutes(deploymentsHandlers, cfg)
13✔
102
        deploymentsRoutes := NewDeploymentsResourceRoutes(deploymentsHandlers)
13✔
103
        limitsRoutes := NewLimitsResourceRoutes(deploymentsHandlers)
13✔
104
        tenantsRoutes := TenantRoutes(deploymentsHandlers)
13✔
105
        releasesRoutes := ReleasesRoutes(deploymentsHandlers)
13✔
106

13✔
107
        routes := append(releasesRoutes, deploymentsRoutes...)
13✔
108
        routes = append(routes, limitsRoutes...)
13✔
109
        routes = append(routes, tenantsRoutes...)
13✔
110
        routes = append(routes, imageRoutes...)
13✔
111

13✔
112
        return rest.MakeRouter(restutil.AutogenOptionsRoutes(restutil.NewOptionsHandler, routes...)...)
13✔
113
}
13✔
114

115
func NewImagesResourceRoutes(controller *DeploymentsApiHandlers, cfg *Config) []*rest.Route {
13✔
116

13✔
117
        if controller == nil {
13✔
UNCOV
118
                return []*rest.Route{}
×
UNCOV
119
        }
×
120

121
        routes := []*rest.Route{
13✔
122
                rest.Post(ApiUrlManagementArtifacts, controller.NewImage),
13✔
123
                rest.Post(ApiUrlManagementArtifactsGenerate, controller.GenerateImage),
13✔
124
                rest.Get(ApiUrlManagementArtifacts, controller.GetImages),
13✔
125
                rest.Get(ApiUrlManagementArtifactsList, controller.ListImages),
13✔
126

13✔
127
                rest.Get(ApiUrlManagementArtifactsId, controller.GetImage),
13✔
128
                rest.Delete(ApiUrlManagementArtifactsId, controller.DeleteImage),
13✔
129
                rest.Put(ApiUrlManagementArtifactsId, controller.EditImage),
13✔
130

13✔
131
                rest.Get(ApiUrlManagementArtifactsIdDownload, controller.DownloadLink),
13✔
132
        }
13✔
133
        if cfg.EnableDirectUpload {
26✔
134
                log.NewEmpty().Infof(
13✔
135
                        "direct upload enabled: POST %s",
13✔
136
                        ApiUrlManagementArtifactsDirectUpload,
13✔
137
                )
13✔
138
                routes = append(routes, rest.Post(
13✔
139
                        ApiUrlManagementArtifactsDirectUpload,
13✔
140
                        controller.UploadLink,
13✔
141
                ))
13✔
142
                routes = append(routes, rest.Post(
13✔
143
                        ApiUrlManagementArtifactsCompleteUpload,
13✔
144
                        controller.CompleteUpload,
13✔
145
                ))
13✔
146
        }
13✔
147
        return routes
13✔
148
}
149

150
func NewDeploymentsResourceRoutes(controller *DeploymentsApiHandlers) []*rest.Route {
53✔
151

53✔
152
        if controller == nil {
53✔
UNCOV
153
                return []*rest.Route{}
×
UNCOV
154
        }
×
155

156
        return []*rest.Route{
53✔
157

53✔
158
                // Deployments
53✔
159
                rest.Post(ApiUrlManagementDeployments, controller.PostDeployment),
53✔
160
                rest.Post(ApiUrlManagementDeploymentsGroup, controller.DeployToGroup),
53✔
161
                rest.Get(ApiUrlManagementDeployments, controller.LookupDeployment),
53✔
162
                rest.Get(ApiUrlManagementDeploymentsId, controller.GetDeployment),
53✔
163
                rest.Post(ApiUrlManagementMultipleDeploymentsStatistics,
53✔
164
                        controller.GetDeploymentsStats),
53✔
165
                rest.Get(ApiUrlManagementDeploymentsStatistics, controller.GetDeploymentStats),
53✔
166
                rest.Put(ApiUrlManagementDeploymentsStatus, controller.AbortDeployment),
53✔
167
                rest.Get(ApiUrlManagementDeploymentsDevices,
53✔
168
                        controller.GetDeviceStatusesForDeployment),
53✔
169
                rest.Get(ApiUrlManagementDeploymentsDevicesList,
53✔
170
                        controller.GetDevicesListForDeployment),
53✔
171
                rest.Get(ApiUrlManagementDeploymentsLog,
53✔
172
                        controller.GetDeploymentLogForDevice),
53✔
173
                rest.Delete(ApiUrlManagementDeploymentsDeviceId,
53✔
174
                        controller.AbortDeviceDeployments),
53✔
175
                rest.Delete(ApiUrlManagementDeploymentsDeviceHistory,
53✔
176
                        controller.DeleteDeviceDeploymentsHistory),
53✔
177
                rest.Get(ApiUrlManagementDeploymentsDeviceId,
53✔
178
                        controller.ListDeviceDeployments),
53✔
179
                rest.Get(ApiUrlManagementDeploymentsDeviceList,
53✔
180
                        controller.GetDeploymentDeviceList),
53✔
181

53✔
182
                // Configuration deployments (internal)
53✔
183
                rest.Post(ApiUrlInternalDeviceConfigurationDeployments,
53✔
184
                        controller.PostDeviceConfigurationDeployment),
53✔
185

53✔
186
                // Devices
53✔
187
                rest.Get(ApiUrlDevicesDeploymentsNext, controller.GetDeploymentForDevice),
53✔
188
                rest.Post(ApiUrlDevicesDeploymentsNext, controller.GetDeploymentForDevice),
53✔
189
                rest.Put(ApiUrlDevicesDeploymentStatus,
53✔
190
                        controller.PutDeploymentStatusForDevice),
53✔
191
                rest.Put(ApiUrlDevicesDeploymentsLog,
53✔
192
                        controller.PutDeploymentLogForDevice),
53✔
193
                rest.Get(ApiUrlDevicesDownloadConfig,
53✔
194
                        controller.DownloadConfiguration),
53✔
195

53✔
196
                // Health Check
53✔
197
                rest.Get(ApiUrlInternalAlive, controller.AliveHandler),
53✔
198
                rest.Get(ApiUrlInternalHealth, controller.HealthHandler),
53✔
199
        }
53✔
200
}
201

202
func NewLimitsResourceRoutes(controller *DeploymentsApiHandlers) []*rest.Route {
13✔
203

13✔
204
        if controller == nil {
13✔
UNCOV
205
                return []*rest.Route{}
×
UNCOV
206
        }
×
207

208
        return []*rest.Route{
13✔
209
                // limits
13✔
210
                rest.Get(ApiUrlManagementLimitsName, controller.GetLimit),
13✔
211
        }
13✔
212
}
213

214
func TenantRoutes(controller *DeploymentsApiHandlers) []*rest.Route {
13✔
215
        if controller == nil {
13✔
UNCOV
216
                return []*rest.Route{}
×
UNCOV
217
        }
×
218

219
        return []*rest.Route{
13✔
220
                rest.Post(ApiUrlInternalTenants, controller.ProvisionTenantsHandler),
13✔
221
                rest.Get(ApiUrlInternalTenantDeployments, controller.DeploymentsPerTenantHandler),
13✔
222
                rest.Get(ApiUrlInternalTenantDeploymentsDevices,
13✔
223
                        controller.ListDeviceDeploymentsByIDsInternal),
13✔
224
                rest.Get(ApiUrlInternalTenantDeploymentsDevice,
13✔
225
                        controller.ListDeviceDeploymentsInternal),
13✔
226
                rest.Delete(ApiUrlInternalTenantDeploymentsDevice,
13✔
227
                        controller.AbortDeviceDeploymentsInternal),
13✔
228
                rest.Post(ApiUrlInternalTenantArtifacts, controller.NewImageForTenantHandler),
13✔
229

13✔
230
                // per-tenant storage settings
13✔
231
                rest.Get(ApiUrlInternalTenantStorageSettings, controller.GetTenantStorageSettingsHandler),
13✔
232
                rest.Put(ApiUrlInternalTenantStorageSettings, controller.PutTenantStorageSettingsHandler),
13✔
233
        }
13✔
234
}
235

236
func ReleasesRoutes(controller *DeploymentsApiHandlers) []*rest.Route {
13✔
237
        if controller == nil {
13✔
UNCOV
238
                return []*rest.Route{}
×
UNCOV
239
        }
×
240

241
        return []*rest.Route{
13✔
242
                rest.Get(ApiUrlManagementReleases, controller.GetReleases),
13✔
243
                rest.Get(ApiUrlManagementReleasesList, controller.ListReleases),
13✔
244
        }
13✔
245
}
246

247
func FMTConfigURL(scheme, hostname, deploymentID, deviceType, deviceID string) string {
25✔
248
        repl := strings.NewReplacer(
25✔
249
                "#"+ParamDeploymentID, url.PathEscape(deploymentID),
25✔
250
                "#"+ParamDeviceType, url.PathEscape(deviceType),
25✔
251
                "#"+ParamDeviceID, url.PathEscape(deviceID),
25✔
252
        )
25✔
253
        return scheme + "://" + hostname + repl.Replace(ApiUrlDevicesDownloadConfig)
25✔
254
}
25✔
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