-
Notifications
You must be signed in to change notification settings - Fork 16
/
products.go
141 lines (125 loc) · 4.39 KB
/
products.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
133
134
135
136
137
138
139
140
141
// Copyright (c) 2015 SUSE LLC. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package containersuseconnect
import (
"crypto/tls"
"encoding/json"
"io"
"io/ioutil"
"net/http"
)
// All the information we need from repositories as given by the registration
// server.
type Repository struct {
Name string `json:"name"`
Description string `json:"description"`
URL string `json:"url"`
Autorefresh bool `json:"autorefresh"`
Enabled bool `json:"enabled"`
}
// All the information we need from product as given by the registration
// server. It contains a slice of repositories in it.
type Product struct {
ProductType string `json:"product_type"`
Identifier string `json:"identifier"`
Version string `json:"version"`
Arch string `json:"arch"`
Repositories []Repository `json:"repositories"`
Extensions []Product `json:"extensions"`
Recommended bool `json:"recommended"`
Name string `json:"name"`
Description string `json:"description"`
}
// Parse the product as expected from the given reader. This function already
// checks whether the given reader is valid or not.
func parseProducts(reader io.Reader) ([]Product, error) {
var products []Product
data, err := ioutil.ReadAll(reader)
if err != nil {
return products,
loggedError("Can't read product information: %v", err.Error())
}
err = json.Unmarshal(data, &products)
if err != nil {
return products,
loggedError("Can't read product information: %v - %s", err.Error(), data)
}
return products, nil
}
// Request product information to the registration server. The `regCode`
// parameters is used to establish the connection with
// the registration server. The `installed` parameter contains the product to
// be requested.
// This function relies on [/connect/subscriptions/products](https://github.com/SUSE/connect/wiki/SCC-API-%28Implemented%29#product) API.
func requestProductsFromRegCode(data SUSEConnectData, regCode string,
installed InstalledProduct) ([]Product, error) {
var products []Product
var err error
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: data.Insecure},
Proxy: http.ProxyFromEnvironment,
}
client := &http.Client{Transport: tr}
req, err := http.NewRequest("GET", data.SccURL, nil)
if err != nil {
return products,
loggedError("Could not connect with registration server: %v\n", err)
}
values := req.URL.Query()
values.Add("identifier", installed.Identifier)
values.Add("version", installed.Version)
values.Add("arch", installed.Arch)
req.URL.RawQuery = values.Encode()
req.URL.Path = "/connect/subscriptions/products"
if data.SccURL == sccURLStr {
req.Header.Add("Authorization", `Token token=`+regCode)
}
resp, err := client.Do(req)
if err != nil {
return products, err
}
if resp.StatusCode != 200 {
return products,
loggedError("Unexpected error while retrieving products with regCode %s: %s", regCode, resp.Status)
}
return parseProducts(resp.Body)
}
// Request product information to the registration server. The `data` and the
// `credentials` parameters are used in order to establish the connection with
// the registration server. The `installed` parameter contains the product to
// be requested.
func RequestProducts(data SUSEConnectData, credentials Credentials,
installed InstalledProduct) ([]Product, error) {
var products []Product
var regCodes []string
var err error
if data.SccURL == sccURLStr {
regCodes, err = requestRegcodes(data, credentials)
if err != nil {
return products, err
}
} else {
// SMT does not have this API and does not need a regcode
regCodes = append(regCodes, "")
}
for _, regCode := range regCodes {
p, err := requestProductsFromRegCode(data, regCode, installed)
if err != nil {
var emptyProducts []Product
return emptyProducts, err
}
products = append(products, p...)
}
return products, nil
}