22
33import { Codefresh } from './codefresh.js' ;
44import { 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' ; 66import { BatchV1Api } from 'https://deno.land/x/[email protected] /builtin/batch@v1/mod.ts' ; 77import { CoreV1Api } from 'https://deno.land/x/[email protected] /builtin/core@v1/mod.ts' ; 88import { StorageV1Api } from 'https://deno.land/x/[email protected] /builtin/storage.k8s.io@v1/mod.ts' ; @@ -25,190 +25,229 @@ function selectRuntimeType() {
2525 reTypes . forEach ( ( reType , index ) => {
2626 console . log ( `${ index + 1 } . ${ reType } ` ) ;
2727 } ) ;
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+
2935 return reTypes [ typeSelected - 1 ] ;
3036}
3137
3238async 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+ }
3752}
3853
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 ) ) ) {
71110 const resources = await fetcher ( ) ;
111+ await saveItems ( resources . items , dir ) ;
112+
72113 if ( dir === 'Pods' ) {
73- await saveItems ( resources . items , dir ) ;
74114 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 ) ;
77123 } ) ) ;
78- } else {
79- await saveItems ( resources . items , dir ) ;
80124 }
81125 }
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 ) ;
85127}
86128
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+ }
95144
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 ;
98147
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 ) ;
104155 }
156+ }
105157
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+ }
107171
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 ;
111173
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 ) ;
120176
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+ }
131182 }
132- }
133183
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+ }
135190}
136191
137192async 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): ' ) ) ;
179209 }
180- }
181210
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+ }
185222}
186223
187224async 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+ }
189239
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 } ) ;
204242
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 } ) ;
207245
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+ }
212251}
213252
214253await main ( ) ;
0 commit comments