2
2
3
3
import { Codefresh } from './codefresh.js' ;
4
4
import { autoDetectClient } from 'https://deno.land/x/[email protected] /mod.ts' ;
5
- import { AppsV1Api } from " https://deno.land/x/[email protected] /builtin/apps@v1/mod.ts" ;
5
+ import { AppsV1Api } from ' https://deno.land/x/[email protected] /builtin/apps@v1/mod.ts' ;
6
6
import { BatchV1Api } from 'https://deno.land/x/[email protected] /builtin/batch@v1/mod.ts' ;
7
7
import { CoreV1Api } from 'https://deno.land/x/[email protected] /builtin/core@v1/mod.ts' ;
8
8
import { StorageV1Api } from 'https://deno.land/x/[email protected] /builtin/storage.k8s.io@v1/mod.ts' ;
@@ -25,190 +25,229 @@ function selectRuntimeType() {
25
25
reTypes . forEach ( ( reType , index ) => {
26
26
console . log ( `${ index + 1 } . ${ reType } ` ) ;
27
27
} ) ;
28
- const typeSelected = prompt ( '\nWhich Type Of Runtime Are We Using? (Number):' ) ;
28
+
29
+ let typeSelected = Number ( prompt ( '\nWhich Type Of Runtime Are We Using? (Number):' ) ) ;
30
+ while ( isNaN ( typeSelected ) || typeSelected < 1 || typeSelected > reTypes . length ) {
31
+ console . log ( 'Invalid selection. Please enter a number corresponding to one of the listed runtime types.' ) ;
32
+ typeSelected = Number ( prompt ( '\nWhich Type Of Runtime Are We Using? (Number):' ) ) ;
33
+ }
34
+
29
35
return reTypes [ typeSelected - 1 ] ;
30
36
}
31
37
32
38
async function saveItems ( resources , dir ) {
33
- await Deno . mkdir ( `${ dirPath } /${ dir } /` , { recursive : true } ) ;
34
- return Promise . all ( resources . map ( ( item ) => {
35
- return Deno . writeTextFile ( `${ dirPath } /${ dir } /${ item . metadata . name } .yaml` , toYaml ( item , { skipInvalid : true } ) ) ;
36
- } ) ) ;
39
+ try {
40
+ await Deno . mkdir ( `${ dirPath } /${ dir } /` , { recursive : true } ) ;
41
+
42
+ const writePromises = resources . map ( async ( item ) => {
43
+ const filePath = `${ dirPath } /${ dir } /${ item . metadata . name } .yaml` ;
44
+ const fileContent = toYaml ( item , { skipInvalid : true } ) ;
45
+ await Deno . writeTextFile ( filePath , fileContent ) ;
46
+ } ) ;
47
+
48
+ await Promise . all ( writePromises ) ;
49
+ } catch ( error ) {
50
+ console . error ( `Error saving items to ${ dir } :` , error ) ;
51
+ }
37
52
}
38
53
39
- async function gatherClassic ( ) {
40
- const cf = new Codefresh ( ) ;
41
- await cf . init ( ) ;
42
- const reNames = await cf . getAllRuntimes ( ) ;
43
- console . log ( '' ) ;
44
- reNames . forEach ( ( re , index ) => {
45
- console . log ( `${ index + 1 } . ${ re } ` ) ;
46
- } ) ;
47
- const selection = prompt ( '\nWhich Classic Runtime Are We Working With? (Number): ' ) ;
48
- const reSpec = cf . runtimes [ selection - 1 ] ;
49
- const namespace = reSpec . runtimeScheduler . cluster . namespace ;
50
-
51
- console . log ( `\nGathering Data For ${ reSpec . metadata . name } .` ) ;
52
-
53
- const helmList = new Deno . Command ( 'helm' , { args : [ 'list' , '-n' , namespace , '-o' , 'json' ] } ) ;
54
- const output = await helmList . output ( ) ;
55
- const helmReleases = JSON . parse ( new TextDecoder ( ) . decode ( output . stdout ) ) ;
56
-
57
- const dataFetchers = {
58
- 'Cron' : ( ) => batchApi . namespace ( namespace ) . getCronJobList ( ) ,
59
- 'Jobs' : ( ) => batchApi . namespace ( namespace ) . getJobList ( ) ,
60
- 'Nodes' : ( ) => coreApi . getNodeList ( ) ,
61
- 'Volumes' : ( ) => coreApi . getPersistentVolumeList ( { labelSelector : 'io.codefresh.accountName' } ) ,
62
- 'Volumeclaims' : ( ) => coreApi . namespace ( namespace ) . getPersistentVolumeClaimList ( { labelSelector : 'io.codefresh.accountName' } ) ,
63
- 'Configmaps' : ( ) => coreApi . namespace ( namespace ) . getConfigMapList ( { labelSelector : 'app.kubernetes.io/name=cf-runtime' } ) ,
64
- 'Services' : ( ) => coreApi . namespace ( namespace ) . getServiceList ( ) ,
65
- 'Pods' : ( ) => coreApi . namespace ( namespace ) . getPodList ( ) ,
66
- 'Events' : ( ) => coreApi . namespace ( namespace ) . getEventList ( ) ,
67
- 'Storageclass' : ( ) => storageApi . getStorageClassList ( ) ,
68
- } ;
69
-
70
- for ( const [ dir , fetcher ] of Object . entries ( dataFetchers ) ) {
54
+ async function saveHelmReleases ( type , namespace ) {
55
+ try {
56
+ const helmList = new Deno . Command ( 'helm' , { args : [ 'list' , '-n' , namespace , '-o' , 'json' ] } ) ;
57
+ const output = await helmList . output ( ) ;
58
+ const helmReleases = JSON . parse ( new TextDecoder ( ) . decode ( output ) ) ;
59
+ await Deno . writeTextFile ( `${ dirPath } /${ type } -helmReleases.yaml` , toYaml ( helmReleases , { skipInvalid : true } ) ) ;
60
+ } catch ( error ) {
61
+ console . error ( `Error saving Helm releases for ${ type } :` , error ) ;
62
+ }
63
+ }
64
+
65
+
66
+ function dataFetchers ( type , namespace ) {
67
+ switch ( type ) {
68
+ case 'classic' :
69
+ return {
70
+ 'Cron' : ( ) => batchApi . namespace ( namespace ) . getCronJobList ( ) ,
71
+ 'Jobs' : ( ) => batchApi . namespace ( namespace ) . getJobList ( ) ,
72
+ 'Nodes' : ( ) => coreApi . getNodeList ( ) ,
73
+ 'Volumes' : ( ) => coreApi . getPersistentVolumeList ( { labelSelector : 'io.codefresh.accountName' } ) ,
74
+ 'Volumeclaims' : ( ) => coreApi . namespace ( namespace ) . getPersistentVolumeClaimList ( { labelSelector : 'io.codefresh.accountName' } ) ,
75
+ 'Configmaps' : ( ) => coreApi . namespace ( namespace ) . getConfigMapList ( { labelSelector : 'app.kubernetes.io/name=cf-runtime' } ) ,
76
+ 'Services' : ( ) => coreApi . namespace ( namespace ) . getServiceList ( ) ,
77
+ 'Pods' : ( ) => coreApi . namespace ( namespace ) . getPodList ( ) ,
78
+ 'Events' : ( ) => coreApi . namespace ( namespace ) . getEventList ( ) ,
79
+ 'Storageclass' : ( ) => storageApi . getStorageClassList ( ) ,
80
+ } ;
81
+ case 'gitops' :
82
+ return {
83
+ 'Apps' : ( ) => argoProj . namespace ( namespace ) . getApplicationList ( ) ,
84
+ 'Nodes' : ( ) => coreApi . getNodeList ( ) ,
85
+ 'Configmaps' : ( ) => coreApi . namespace ( namespace ) . getConfigMapList ( ) ,
86
+ 'Services' : ( ) => coreApi . namespace ( namespace ) . getServiceList ( ) ,
87
+ 'Pods' : ( ) => coreApi . namespace ( namespace ) . getPodList ( ) ,
88
+ 'Events' : ( ) => coreApi . namespace ( namespace ) . getEventList ( ) ,
89
+ } ;
90
+ case 'onprem' :
91
+ return {
92
+ 'Deployments' : ( ) => appsApi . namespace ( namespace ) . getDeploymentList ( ) ,
93
+ 'Daemonsets' : ( ) => appsApi . namespace ( namespace ) . getDaemonSetList ( ) ,
94
+ 'Nodes' : ( ) => coreApi . getNodeList ( ) ,
95
+ 'Volumes' : ( ) => coreApi . getPersistentVolumeList ( { labelSelector : 'io.codefresh.accountName' } ) ,
96
+ 'Volumeclaims' : ( ) => coreApi . namespace ( namespace ) . getPersistentVolumeClaimList ( { labelSelector : 'io.codefresh.accountName' } ) ,
97
+ 'Services' : ( ) => coreApi . namespace ( namespace ) . getServiceList ( ) ,
98
+ 'Pods' : ( ) => coreApi . namespace ( namespace ) . getPodList ( ) ,
99
+ 'Events' : ( ) => coreApi . namespace ( namespace ) . getEventList ( ) ,
100
+ 'Storageclass' : ( ) => storageApi . getStorageClassList ( ) ,
101
+ } ;
102
+ default :
103
+ console . error ( 'Invalid runtime type selected' ) ;
104
+ return ;
105
+ }
106
+ }
107
+
108
+ async function fetchAndSaveData ( type , namespace ) {
109
+ for ( const [ dir , fetcher ] of Object . entries ( dataFetchers ( type , namespace ) ) ) {
71
110
const resources = await fetcher ( ) ;
111
+ await saveItems ( resources . items , dir ) ;
112
+
72
113
if ( dir === 'Pods' ) {
73
- await saveItems ( resources . items , dir ) ;
74
114
await Promise . all ( resources . items . map ( async ( item ) => {
75
- const log = await coreApi . namespace ( namespace ) . getPodLog ( item . metadata . name , { container : item . spec . containers [ 0 ] . name } ) ;
76
- return Deno . writeTextFile ( `${ dirPath } /${ dir } /${ item . metadata . name } .log` , log ) ;
115
+ let log ;
116
+ try {
117
+ log = await coreApi . namespace ( namespace ) . getPodLog ( item . metadata . name , { container : item . spec . containers [ 0 ] . name } ) ;
118
+ } catch ( error ) {
119
+ console . error ( `Failed to get logs for ${ item . metadata . name } :` , error ) ;
120
+ log = error ;
121
+ }
122
+ await Deno . writeTextFile ( `${ dirPath } /${ dir } /${ item . metadata . name } .log` , log ) ;
77
123
} ) ) ;
78
- } else {
79
- await saveItems ( resources . items , dir ) ;
80
124
}
81
125
}
82
-
83
- Deno . writeTextFile ( `${ dirPath } /runtimeSpec.yaml` , toYaml ( reSpec , { skipInvalid : true } ) ) ;
84
- Deno . writeTextFile ( `${ dirPath } /classicReleases.yaml` , toYaml ( helmReleases , { skipInvalid : true } ) ) ;
126
+ await saveHelmReleases ( type , namespace ) ;
85
127
}
86
128
87
- async function gatherGitOps ( ) {
88
- const namespaceList = await coreApi . getNamespaceList ( ) ;
89
- console . log ( '' ) ;
90
- namespaceList . items . forEach ( ( ns , index ) => {
91
- console . log ( `${ index + 1 } . ${ ns . metadata . name } ` ) ;
92
- } ) ;
93
- const selection = prompt ( '\nWhich Namespace Is The GitOps Runtime Installed In? (Number): ' ) ;
94
- const namespace = namespaceList . items [ selection - 1 ] . metadata . name ;
129
+ async function gatherClassic ( ) {
130
+ try {
131
+ const cf = new Codefresh ( ) ;
132
+ await cf . init ( ) ;
133
+ const reNames = await cf . getAllRuntimes ( ) ;
134
+ console . log ( '' ) ;
135
+ reNames . forEach ( ( re , index ) => {
136
+ console . log ( `${ index + 1 } . ${ re } ` ) ;
137
+ } ) ;
138
+
139
+ let selection = Number ( prompt ( '\nWhich Classic Runtime Are We Working With? (Number): ' ) ) ;
140
+ while ( isNaN ( selection ) || selection < 1 || selection > reNames . length ) {
141
+ console . log ( 'Invalid selection. Please enter a number corresponding to one of the listed runtimes.' ) ;
142
+ selection = Number ( prompt ( '\nWhich Classic Runtime Are We Working With? (Number): ' ) ) ;
143
+ }
95
144
96
- const apps = await argoProj . namespace ( namespace ) . getApplicationList ( ) ;
97
- const isCodfresh = apps . items . some ( ( app ) => [ 'codefresh.io/entity' ] in app . metadata . labels ) ;
145
+ const reSpec = cf . runtimes [ selection - 1 ] ;
146
+ const namespace = reSpec . runtimeScheduler . cluster . namespace ;
98
147
99
- if ( ! isCodfresh ) {
100
- const continueData = confirm ( `\nCould not find a GitOps Runtime in ${ namespace } . Do you still want to continue?` ) ;
101
- if ( ! continueData ) {
102
- return ;
103
- }
148
+ console . log ( `\nGathering Data For ${ reSpec . metadata . name } .` ) ;
149
+
150
+ await fetchAndSaveData ( 'classic' , namespace ) ;
151
+
152
+ await Deno . writeTextFile ( `${ dirPath } /runtimeSpec.yaml` , toYaml ( reSpec , { skipInvalid : true } ) ) ;
153
+ } catch ( error ) {
154
+ console . error ( `Error gathering classic runtime data:` , error ) ;
104
155
}
156
+ }
105
157
106
- console . log ( `\nGathering Data In ${ namespace } For The GitOps Runtime.` ) ;
158
+ async function gatherGitOps ( ) {
159
+ try {
160
+ const namespaceList = await coreApi . getNamespaceList ( ) ;
161
+ console . log ( '' ) ;
162
+ namespaceList . items . forEach ( ( ns , index ) => {
163
+ console . log ( `${ index + 1 } . ${ ns . metadata . name } ` ) ;
164
+ } ) ;
165
+
166
+ let selection = Number ( prompt ( '\nWhich Namespace Is The GitOps Runtime Installed In? (Number): ' ) ) ;
167
+ while ( isNaN ( selection ) || selection < 1 || selection > namespaceList . items . length ) {
168
+ console . log ( 'Invalid selection. Please enter a number corresponding to one of the listed namespaces.' ) ;
169
+ selection = Number ( prompt ( '\nWhich Namespace Is The GitOps Runtime Installed In? (Number): ' ) ) ;
170
+ }
107
171
108
- const helmList = new Deno . Command ( 'helm' , { args : [ 'list' , '-n' , namespace , '-o' , 'json' ] } ) ;
109
- const output = await helmList . output ( ) ;
110
- const helmReleases = JSON . parse ( new TextDecoder ( ) . decode ( output . stdout ) ) ;
172
+ const namespace = namespaceList . items [ selection - 1 ] . metadata . name ;
111
173
112
- const dataFetchers = {
113
- 'Apps' : ( ) => argoProj . namespace ( namespace ) . getApplicationList ( ) ,
114
- 'Nodes' : ( ) => coreApi . getNodeList ( ) ,
115
- 'Configmaps' : ( ) => coreApi . namespace ( namespace ) . getConfigMapList ( ) ,
116
- 'Services' : ( ) => coreApi . namespace ( namespace ) . getServiceList ( ) ,
117
- 'Pods' : ( ) => coreApi . namespace ( namespace ) . getPodList ( ) ,
118
- 'Events' : ( ) => coreApi . namespace ( namespace ) . getEventList ( ) ,
119
- } ;
174
+ const apps = await argoProj . namespace ( namespace ) . getApplicationList ( ) ;
175
+ const isCodfresh = apps . items . some ( ( app ) => [ 'codefresh.io/entity' ] in app . metadata . labels ) ;
120
176
121
- for ( const [ dir , fetcher ] of Object . entries ( dataFetchers ) ) {
122
- const resources = await fetcher ( ) ;
123
- if ( dir === 'Pods' ) {
124
- await saveItems ( resources . items , dir ) ;
125
- await Promise . all ( resources . items . map ( async ( item ) => {
126
- const log = await coreApi . namespace ( namespace ) . getPodLog ( item . metadata . name , { container : item . spec . containers [ 0 ] . name } ) ;
127
- return Deno . writeTextFile ( `${ dirPath } /${ dir } /${ item . metadata . name } .log` , log ) ;
128
- } ) ) ;
129
- } else {
130
- await saveItems ( resources . items , dir ) ;
177
+ if ( ! isCodfresh ) {
178
+ const continueData = confirm ( `\nCould not find a GitOps Runtime in ${ namespace } . Do you still want to continue?` ) ;
179
+ if ( ! continueData ) {
180
+ Deno . exit ( ) ;
181
+ }
131
182
}
132
- }
133
183
134
- Deno . writeTextFile ( `${ dirPath } /gitopsReleases.yaml` , toYaml ( helmReleases , { skipInvalid : true } ) ) ;
184
+ console . log ( `\nGathering Data In ${ namespace } For The GitOps Runtime.` ) ;
185
+
186
+ await fetchAndSaveData ( 'gitops' , namespace ) ;
187
+ } catch ( error ) {
188
+ console . error ( `Error gathering GitOps runtime data:` , error ) ;
189
+ }
135
190
}
136
191
137
192
async function gatherOnPrem ( ) {
138
- const cf = new Codefresh ( ) ;
139
- await cf . init ( ) ;
140
- const accounts = await cf . getOnPremAccounts ( ) ;
141
- const runtimes = await cf . getOnPremRuntimes ( ) ;
142
-
143
- const namespaceList = await coreApi . getNamespaceList ( ) ;
144
- console . log ( '' ) ;
145
- namespaceList . items . forEach ( ( ns , index ) => {
146
- console . log ( `${ index + 1 } . ${ ns . metadata . name } ` ) ;
147
- } ) ;
148
- const selection = prompt ( '\nWhich Namespace Is Codefresh OnPrem Installed In? (Number): ' ) ;
149
- const namespace = namespaceList . items [ selection - 1 ] . metadata . name ;
150
-
151
- console . log ( `\nGathering Data For On Prem.` ) ;
152
-
153
- const helmList = new Deno . Command ( 'helm' , { args : [ 'list' , '-n' , namespace , '-o' , 'json' ] } ) ;
154
- const output = await helmList . output ( ) ;
155
- const helmReleases = JSON . parse ( new TextDecoder ( ) . decode ( output . stdout ) ) ;
156
-
157
- const dataFetchers = {
158
- 'Deployments' : ( ) => appsApi . namespace ( namespace ) . getDeploymentList ( ) ,
159
- 'Daemonsets' : ( ) => appsApi . namespace ( namespace ) . getDaemonSetList ( ) ,
160
- 'Nodes' : ( ) => coreApi . getNodeList ( ) ,
161
- 'Volumes' : ( ) => coreApi . getPersistentVolumeList ( { labelSelector : 'io.codefresh.accountName' } ) ,
162
- 'Volumeclaims' : ( ) => coreApi . namespace ( namespace ) . getPersistentVolumeClaimList ( { labelSelector : 'io.codefresh.accountName' } ) ,
163
- 'Services' : ( ) => coreApi . namespace ( namespace ) . getServiceList ( ) ,
164
- 'Pods' : ( ) => coreApi . namespace ( namespace ) . getPodList ( ) ,
165
- 'Events' : ( ) => coreApi . namespace ( namespace ) . getEventList ( ) ,
166
- 'Storageclass' : ( ) => storageApi . getStorageClassList ( ) ,
167
- } ;
168
-
169
- for ( const [ dir , fetcher ] of Object . entries ( dataFetchers ) ) {
170
- const resources = await fetcher ( ) ;
171
- if ( dir === 'Pods' ) {
172
- await saveItems ( resources . items , dir ) ;
173
- await Promise . all ( resources . items . map ( async ( item ) => {
174
- const log = await coreApi . namespace ( namespace ) . getPodLog ( item . metadata . name , { container : item . spec . containers [ 0 ] . name } ) ;
175
- return Deno . writeTextFile ( `${ dirPath } /${ dir } /${ item . metadata . name } .log` , log ) ;
176
- } ) ) ;
177
- } else {
178
- await saveItems ( resources . items , dir ) ;
193
+ try {
194
+ const cf = new Codefresh ( ) ;
195
+ await cf . init ( ) ;
196
+ const accounts = await cf . getOnPremAccounts ( ) ;
197
+ const runtimes = await cf . getOnPremRuntimes ( ) ;
198
+
199
+ const namespaceList = await coreApi . getNamespaceList ( ) ;
200
+ console . log ( '' ) ;
201
+ namespaceList . items . forEach ( ( ns , index ) => {
202
+ console . log ( `${ index + 1 } . ${ ns . metadata . name } ` ) ;
203
+ } ) ;
204
+
205
+ let selection = Number ( prompt ( '\nWhich Namespace Is Codefresh OnPrem Installed In? (Number): ' ) ) ;
206
+ while ( isNaN ( selection ) || selection < 1 || selection > namespaceList . items . length ) {
207
+ console . log ( 'Invalid selection. Please enter a number corresponding to one of the listed namespaces.' ) ;
208
+ selection = Number ( prompt ( '\nWhich Namespace Is Codefresh OnPrem Installed In? (Number): ' ) ) ;
179
209
}
180
- }
181
210
182
- Deno . writeTextFile ( `${ dirPath } /onPremReleases.yaml` , toYaml ( helmReleases , { skipInvalid : true } ) ) ;
183
- Deno . writeTextFile ( `${ dirPath } /onPremAccounts.yaml` , toYaml ( accounts , { skipInvalid : true } ) ) ;
184
- Deno . writeTextFile ( `${ dirPath } /onPremRuntimes.yaml` , toYaml ( runtimes , { skipInvalid : true } ) ) ;
211
+ const namespace = namespaceList . items [ selection - 1 ] . metadata . name ;
212
+
213
+ console . log ( `\nGathering Data For On Prem.` ) ;
214
+
215
+ await fetchAndSaveData ( 'onprem' , namespace ) ;
216
+
217
+ await Deno . writeTextFile ( `${ dirPath } /onPremAccounts.yaml` , toYaml ( accounts , { skipInvalid : true } ) ) ;
218
+ await Deno . writeTextFile ( `${ dirPath } /onPremRuntimes.yaml` , toYaml ( runtimes , { skipInvalid : true } ) ) ;
219
+ } catch ( error ) {
220
+ console . error ( `Error gathering On Prem data:` , error ) ;
221
+ }
185
222
}
186
223
187
224
async function main ( ) {
188
- const runtimeType = selectRuntimeType ( ) ;
225
+ try {
226
+ const runtimeType = selectRuntimeType ( ) ;
227
+
228
+ switch ( runtimeType ) {
229
+ case 'classic' :
230
+ await gatherClassic ( ) ;
231
+ break ;
232
+ case 'gitops' :
233
+ await gatherGitOps ( ) ;
234
+ break ;
235
+ case 'onprem' :
236
+ await gatherOnPrem ( ) ;
237
+ break ;
238
+ }
189
239
190
- switch ( runtimeType ) {
191
- case 'classic' :
192
- await gatherClassic ( ) ;
193
- break ;
194
- case 'gitops' :
195
- await gatherGitOps ( ) ;
196
- break ;
197
- case 'onprem' :
198
- await gatherOnPrem ( ) ;
199
- break ;
200
- default :
201
- console . log ( 'Invalid runtime type selected' ) ;
202
- return ;
203
- }
240
+ console . log ( `\nSaving data to ./codefresh-support-package-${ timestamp } .zip` ) ;
241
+ await compress ( dirPath , `./codefresh-support-package-${ timestamp } .zip` , { overwrite : true } ) ;
204
242
205
- console . log ( `\nSaving data to ./codefresh-support-package- ${ timestamp } .zip` ) ;
206
- await compress ( dirPath , `./codefresh-support-package- ${ timestamp } .zip` , { overwrite : true } ) ;
243
+ console . log ( '\nCleaning up temp directory' ) ;
244
+ await Deno . remove ( dirPath , { recursive : true } ) ;
207
245
208
- console . log ( '\nCleaning up temp directory' ) ;
209
- await Deno . remove ( dirPath , { recursive : true } ) ;
210
- console . log ( `\nPlease attach ./codefresh-support-package-${ timestamp } .zip to your support ticket.` ) ;
211
- console . log ( 'Before attaching, verify the contents and remove any sensitive information.' ) ;
246
+ console . log ( `\nPlease attach ./codefresh-support-package-${ timestamp } .zip to your support ticket.` ) ;
247
+ console . log ( 'Before attaching, verify the contents and remove any sensitive information.' ) ;
248
+ } catch ( error ) {
249
+ console . error ( `Error in main function:` , error ) ;
250
+ }
212
251
}
213
252
214
253
await main ( ) ;
0 commit comments