@@ -18,7 +18,8 @@ import * as path from 'path';
1818import { CliExitData } from './cli' ;
1919import {
2020 getInstance ,
21- Odo
21+ Odo ,
22+ OdoImpl
2223} from './odo' ;
2324import { Command } from './odo/command' ;
2425import {
@@ -44,6 +45,7 @@ import { vsCommand, VsCommandError } from './vscommand';
4445import { Cluster } from '@kubernetes/client-node/dist/config_types' ;
4546import { KubeConfig } from '@kubernetes/client-node' ;
4647import { Platform } from './util/platform' ;
48+ import * as validator from 'validator' ;
4749
4850type ExampleProject = SampleProject | StarterProject ;
4951type ComponentType = DevfileComponentType | ImageStreamTag | ExampleProject | Cluster | Registry ;
@@ -104,6 +106,7 @@ export class ComponentTypesView implements TreeDataProvider<ComponentType> {
104106 if ( isRegistry ( element ) ) {
105107 return {
106108 label : element . Name ,
109+ contextValue : ContextType . DEVFILE_REGISTRY ,
107110 tooltip : `Devfile Registry\nName: ${ element . Name } \nURL: ${ element . URL } ` ,
108111 collapsibleState : TreeItemCollapsibleState . Collapsed ,
109112 }
@@ -182,6 +185,21 @@ export class ComponentTypesView implements TreeDataProvider<ComponentType> {
182185 return data ;
183186 }
184187
188+ addRegistry ( newRegistry : Registry ) : void {
189+ this . registries . push ( newRegistry ) ;
190+ this . refresh ( false ) ;
191+ this . reveal ( newRegistry ) ;
192+
193+ }
194+
195+ removeRegistry ( targetRegistry : Registry ) : void {
196+ this . registries . splice (
197+ this . registries . findIndex ( ( registry ) => registry . Name === targetRegistry . Name ) ,
198+ 1
199+ ) ;
200+ this . refresh ( false ) ;
201+ }
202+
185203 private async getRegistries ( ) : Promise < Registry [ ] > {
186204 if ( ! this . registries ) {
187205 this . registries = await this . odo . getRegistries ( ) ;
@@ -239,8 +257,14 @@ export class ComponentTypesView implements TreeDataProvider<ComponentType> {
239257 return undefined ;
240258 }
241259
242- refresh ( ) : void {
243- this . registries = undefined ;
260+ reveal ( item : Registry ) : void {
261+ this . treeView . reveal ( item ) ;
262+ }
263+
264+ refresh ( cleanCache = true ) : void {
265+ if ( cleanCache ) {
266+ this . registries = undefined ;
267+ }
244268 this . onDidChangeTreeDataEmitter . fire ( ) ;
245269 }
246270
@@ -289,4 +313,69 @@ export class ComponentTypesView implements TreeDataProvider<ComponentType> {
289313 return 'Cannot find sample project repository url' ;
290314 }
291315 }
316+
317+ @vsCommand ( 'openshift.componentTypesView.registry.add' )
318+ public static async addRegistryCmd ( ) : Promise < void > {
319+ // ask for registry
320+ const regName = await window . showInputBox ( {
321+ prompt : 'Provide registry name to display in the view' ,
322+ placeHolder : 'Registry Name' ,
323+ validateInput : async ( value ) => {
324+ const trimmedValue = value . trim ( ) ;
325+ if ( trimmedValue . length === 0 ) {
326+ return 'Registry name cannot be empty'
327+ }
328+ if ( ! validator . matches ( trimmedValue , '^[a-zA-Z0-9]+$' ) ) {
329+ return 'Registry name can have only alphabet characters and numbers' ;
330+ }
331+ const registries = await ComponentTypesView . instance . getRegistries ( ) ;
332+ if ( registries . find ( ( registry ) => registry . Name === value ) ) {
333+ return `Registry name '${ value } ' is already used` ;
334+ }
335+ }
336+ } ) ;
337+
338+ if ( ! regName ) return null ;
339+
340+ const regURL = await window . showInputBox ( { ignoreFocusOut : true ,
341+ prompt : 'Provide registry URL to display in the view' ,
342+ placeHolder : 'Registry URL' ,
343+ validateInput : async ( value ) => {
344+ const trimmedValue = value . trim ( ) ;
345+ if ( ! validator . isURL ( trimmedValue ) ) {
346+ return 'Entered URL is invalid'
347+ }
348+ const registries = await ComponentTypesView . instance . getRegistries ( ) ;
349+ if ( registries . find ( ( registry ) => registry . URL === value ) ) {
350+ return `Registry with entered URL '${ value } ' already exists` ;
351+ }
352+ }
353+ } ) ;
354+
355+ if ( ! regURL ) return null ;
356+
357+ const secure = await window . showQuickPick ( [ 'Yes' , 'No' ] , {
358+ placeHolder : 'Is it a secure registry?'
359+ } ) ;
360+
361+ if ( ! secure ) return null ;
362+
363+ let token : string ;
364+ if ( secure === 'Yes' ) {
365+ token = await window . showInputBox ( { placeHolder : 'Token to access the registry' } ) ;
366+ if ( ! token ) return null ;
367+ }
368+
369+ const newRegistry = await OdoImpl . Instance . addRegistry ( regName , regURL , token ) ;
370+ ComponentTypesView . instance . addRegistry ( newRegistry ) ;
371+ }
372+
373+ @vsCommand ( 'openshift.componentTypesView.registry.remove' )
374+ public static async removeRegistry ( registry : Registry ) : Promise < void > {
375+ const yesNo = await window . showInformationMessage ( `Remove registry '${ registry . Name } '?` , 'Yes' , 'No' ) ;
376+ if ( yesNo === 'Yes' ) {
377+ await OdoImpl . Instance . removeRegistry ( registry . Name ) ;
378+ ComponentTypesView . instance . removeRegistry ( registry ) ;
379+ }
380+ }
292381}
0 commit comments