@@ -7,9 +7,11 @@ import (
77 "io"
88 "log"
99 "net/http"
10+ "net/url"
1011 "os"
1112 "path/filepath"
1213 "slices"
14+ "strings"
1315 "time"
1416)
1517
@@ -47,13 +49,14 @@ type PatchedUsnsInputOutput struct {
4749
4850func main () {
4951 var config struct {
52+ APIUrl string
5053 Distro string
5154 LastUSNsJSON string
5255 LastUSNsJSONFilepath string
5356 Output string
5457 PackagesJSON string
5558 PackagesJSONFilepath string
56- APIUrl string
59+ Pages int
5760 }
5861
5962 flag .StringVar (& config .LastUSNsJSON ,
@@ -67,7 +70,7 @@ func main() {
6770 flag .StringVar (& config .APIUrl ,
6871 "api-url" ,
6972 JSON_API_URL ,
70- "URL of the Ubuntu security notices JSON API" )
73+ "URL of the Ubuntu security notices JSON API (https or file:// for a local JSON file) " )
7174 flag .StringVar (& config .PackagesJSON ,
7275 "packages" ,
7376 "" ,
@@ -84,12 +87,19 @@ func main() {
8487 "output" ,
8588 "" ,
8689 "Path to output JSON file" )
90+ flag .IntVar (& config .Pages ,
91+ "pages" ,
92+ 1 ,
93+ "Number of pages to fetch from the API (default: 1)" )
8794
8895 flag .Parse ()
8996
9097 if ! slices .Contains (supportedDistros , config .Distro ) {
9198 log .Fatalf ("--distro flag has to be one of the following values: %v" , supportedDistros )
9299 }
100+ if config .Pages < 1 {
101+ log .Fatalf ("--pages must be at least 1, got %d" , config .Pages )
102+ }
93103
94104 lastPatchedUSNs := []PatchedUsnsInputOutput {}
95105 if config .LastUSNsJSON != "" {
@@ -132,9 +142,23 @@ func main() {
132142 }
133143 }
134144
135- newUSNs , err := getNewUSNsFromJSONApi (config .APIUrl , lastPatchedUSNs , config .Distro )
136- if err != nil {
137- log .Fatal (err )
145+ var newUSNs []USN
146+ var err error
147+ if path , ok := fileURLPath (config .APIUrl ); ok {
148+ newUSNs , err = getNewUSNsFromFilepath (path )
149+ if err != nil {
150+ log .Fatal (err )
151+ }
152+ } else {
153+ newUSNs , err = getNewUSNsFromJSONApi (config .APIUrl , lastPatchedUSNs , config .Distro , config .Pages )
154+ if err != nil {
155+ log .Fatal (err )
156+ }
157+ }
158+
159+ fmt .Println ("Recent USNs found:" )
160+ for _ , usn := range newUSNs {
161+ fmt .Printf ("%s with name %s\n " , usn .ID , usn .Title )
138162 }
139163
140164 filteredUSNs := filterUSNsByPackages (newUSNs , packages , config .Distro )
@@ -225,20 +249,48 @@ func transformUSNsForOutput(usns []USN, distro string) []PatchedUsnsInputOutput
225249 return output
226250}
227251
228- func getNewUSNsFromJSONApi (jsonApiUrl string , lastPatchedUSNs []PatchedUsnsInputOutput , distro string ) ([]USN , error ) {
252+ func fileURLPath (rawURL string ) (string , bool ) {
253+ u , err := url .Parse (strings .TrimSpace (rawURL ))
254+ if err != nil || u .Scheme != "file" {
255+ return "" , false
256+ }
257+ path := u .Path
258+ if u .Host != "" {
259+ path = u .Host + path
260+ }
261+ return path , true
262+ }
263+
264+ func getNewUSNsFromFilepath (path string ) ([]USN , error ) {
265+ fileContent , err := os .ReadFile (path )
266+ if err != nil {
267+ return nil , err
268+ }
269+
270+ var data struct {
271+ Notices []USN `json:"notices"`
272+ }
273+ if err = json .Unmarshal (fileContent , & data ); err != nil {
274+ return nil , err
275+ }
276+ return data .Notices , nil
277+ }
278+
279+ const pageSize = 20
280+
281+ func getNewUSNsFromJSONApi (jsonApiUrl string , lastPatchedUSNs []PatchedUsnsInputOutput , distro string , numPages int ) ([]USN , error ) {
229282 var allUSNs []USN
230283
231- offsets := [] int { 0 , 20 }
232- for _ , offset := range offsets {
233- paginatedUrl := fmt .Sprintf ("%s?release=%s&limit=%d&offset=%d" , jsonApiUrl , distro , 20 , offset )
284+ for page := 0 ; page < numPages ; page ++ {
285+ offset := page * pageSize
286+ paginatedUrl := fmt .Sprintf ("%s?release=%s&limit=%d&offset=%d" , jsonApiUrl , distro , pageSize , offset )
234287 usns , err := fetchUSNPage (paginatedUrl )
235288 if err != nil {
236289 return nil , err
237290 }
238291 allUSNs = append (allUSNs , usns ... )
239292 }
240293
241- fmt .Println ("Looking for new USNs..." )
242294 var newUSNs []USN
243295 for _ , usn := range allUSNs {
244296
@@ -254,14 +306,6 @@ func getNewUSNsFromJSONApi(jsonApiUrl string, lastPatchedUSNs []PatchedUsnsInput
254306 })
255307 }
256308
257- if len (newUSNs ) > 0 {
258- for _ , usn := range newUSNs {
259- fmt .Printf ("New USN found: %s with name %s\n " , usn .ID , usn .Title )
260- }
261- } else {
262- fmt .Println ("No new USNs found" )
263- }
264-
265309 return newUSNs , nil
266310}
267311
0 commit comments