13
13
# limitations under the License.
14
14
15
15
import os
16
+ import sys
17
+ import json
16
18
import argparse
17
19
import logging
18
20
import datetime
19
21
import pytz
20
22
import tzlocal
21
- import sys
22
23
from lynkctx import LynkContext
23
24
24
25
25
26
def user_time (utc_time ):
27
+ """
28
+ Convert UTC time to local time and format it as a string.
29
+
30
+ Args:
31
+ utc_time (str): The UTC time in ISO format.
32
+
33
+ Returns:
34
+ str: The local time formatted as a string.
35
+ """
26
36
timestamp = datetime .datetime .fromisoformat (utc_time [:- 1 ])
27
37
local_timezone = tzlocal .get_localzone ()
28
38
local_time = timestamp .replace (tzinfo = pytz .UTC ).astimezone (local_timezone )
29
39
return local_time .strftime ('%Y-%m-%d %H:%M:%S %Z' )
30
40
31
41
32
42
def print_products (lynk_ctx ):
43
+ """
44
+ Print the products of the Lynk context.
45
+
46
+ Args:
47
+ lynk_ctx (LynkContext): The Lynk context object.
48
+ """
33
49
products = lynk_ctx .prods ()
34
50
35
51
# Calculate dynamic column widths
@@ -67,6 +83,12 @@ def print_products(lynk_ctx):
67
83
68
84
69
85
def print_versions (lynk_ctx ):
86
+ """
87
+ Print the versions of the Lynk context.
88
+
89
+ Args:
90
+ lynk_ctx (LynkContext): The Lynk context object.
91
+ """
70
92
versions = lynk_ctx .versions ()
71
93
if not versions :
72
94
print ('No versions found' )
@@ -122,20 +144,49 @@ def print_versions(lynk_ctx):
122
144
123
145
124
146
def download_sbom (lynk_ctx ):
147
+ """
148
+ Download SBOM from the lynk_ctx and save it to a file or print it to stdout.
149
+
150
+ Args:
151
+ lynk_ctx: The lynk context object.
152
+
153
+ Returns:
154
+ int: 0 if successful, 1 if failed to fetch SBOM.
155
+ """
125
156
sbom = lynk_ctx .download ()
126
157
if sbom is None :
127
158
print ('Failed to fetch SBOM' )
128
159
return 1
129
160
130
- sys .stdout .buffer .write (sbom .encode ("utf-8" , errors = 'ignore' ))
161
+ sbom_data = json .loads (sbom .encode ('utf-8' ))
162
+
163
+ if lynk_ctx .output_file :
164
+ with open (lynk_ctx .output_file , 'w' , encoding = 'utf-8' ) as f :
165
+ json .dump (sbom_data , f , indent = 4 , ensure_ascii = False )
166
+ else :
167
+ json .dump (sbom_data , sys .stdout , indent = 4 , ensure_ascii = False )
168
+
131
169
return 0
132
170
133
171
134
172
def upload_sbom (lynk_ctx , sbom_file ):
173
+ """
174
+ Upload SBOM to the lynk_ctx.
175
+
176
+ Args:
177
+ lynk_ctx: The lynk context object.
178
+ sbom_file: The path to the SBOM file.
179
+
180
+ Returns:
181
+ The result of the upload operation.
182
+ """
135
183
return lynk_ctx .upload (sbom_file )
136
184
137
185
138
186
def setup_args ():
187
+ """
188
+ Set up command line arguments for the script.
189
+ """
139
190
parser = argparse .ArgumentParser (description = 'Interlynk command line tool' )
140
191
parser .add_argument ('--verbose' , '-v' , action = 'count' , default = 0 )
141
192
@@ -183,17 +234,38 @@ def setup_args():
183
234
required = False ,
184
235
help = "Security token" )
185
236
237
+ download_parser .add_argument (
238
+ "--output" , help = "Output file" , required = False )
239
+
186
240
args = parser .parse_args ()
187
241
return args
188
242
189
243
190
244
def setup_log_level (args ):
245
+ """
246
+ Set up the log level based on the command line arguments.
247
+
248
+ Args:
249
+ args: The command line arguments.
250
+
251
+ Returns:
252
+ None.
253
+ """
191
254
if args .verbose == 0 :
192
255
logging .basicConfig (level = logging .ERROR )
193
256
logging .basicConfig (level = logging .DEBUG )
194
257
195
258
196
259
def setup_lynk_context (args ):
260
+ """
261
+ Set up the LynkContext object based on the command line arguments.
262
+
263
+ Args:
264
+ args: The command line arguments.
265
+
266
+ Returns:
267
+ LynkContext: The LynkContext object.
268
+ """
197
269
return LynkContext (
198
270
os .environ .get ('INTERLYNK_API_URL' ),
199
271
getattr (args , 'token' , None ) or os .environ .get (
@@ -203,11 +275,18 @@ def setup_lynk_context(args):
203
275
getattr (args , 'envId' , None ),
204
276
getattr (args , 'env' , None ),
205
277
getattr (args , 'verId' , None ),
206
- getattr (args , 'ver' , None )
278
+ getattr (args , 'ver' , None ),
279
+ getattr (args , 'output' , None )
207
280
)
208
281
209
282
210
283
def main () -> int :
284
+ """
285
+ Main function that serves as the entry point of the program.
286
+
287
+ Returns:
288
+ int: The exit code of the program.
289
+ """
211
290
args = setup_args ()
212
291
setup_log_level (args )
213
292
lynk_ctx = setup_lynk_context (args )
0 commit comments