github.com/argoproj/argo-cd@v1.8.7/ui/src/app/shared/services/applications-service.ts (about)

     1  import * as deepMerge from 'deepmerge';
     2  import {Observable} from 'rxjs';
     3  
     4  import * as models from '../models';
     5  import requests from './requests';
     6  
     7  interface QueryOptions {
     8      fields: string[];
     9      exclude?: boolean;
    10      selector?: string;
    11  }
    12  
    13  function optionsToSearch(options?: QueryOptions) {
    14      if (options) {
    15          return {fields: (options.exclude ? '-' : '') + options.fields.join(','), selector: options.selector || ''};
    16      }
    17      return {};
    18  }
    19  
    20  export class ApplicationsService {
    21      public list(projects: string[], options?: QueryOptions): Promise<models.ApplicationList> {
    22          return requests
    23              .get('/applications')
    24              .query({project: projects, ...optionsToSearch(options)})
    25              .then(res => res.body as models.ApplicationList)
    26              .then(list => {
    27                  list.items = (list.items || []).map(app => this.parseAppFields(app));
    28                  return list;
    29              });
    30      }
    31  
    32      public get(name: string, refresh?: 'normal' | 'hard'): Promise<models.Application> {
    33          const query: {[key: string]: string} = {};
    34          if (refresh) {
    35              query.refresh = refresh;
    36          }
    37          return requests
    38              .get(`/applications/${name}`)
    39              .query(query)
    40              .then(res => this.parseAppFields(res.body));
    41      }
    42  
    43      public getApplicationSyncWindowState(name: string): Promise<models.ApplicationSyncWindowState> {
    44          return requests
    45              .get(`/applications/${name}/syncwindows`)
    46              .query({name})
    47              .then(res => res.body as models.ApplicationSyncWindowState);
    48      }
    49  
    50      public revisionMetadata(name: string, revision: string): Promise<models.RevisionMetadata> {
    51          return requests.get(`/applications/${name}/revisions/${revision || 'HEAD'}/metadata`).then(res => res.body as models.RevisionMetadata);
    52      }
    53  
    54      public resourceTree(name: string): Promise<models.ApplicationTree> {
    55          return requests.get(`/applications/${name}/resource-tree`).then(res => res.body as models.ApplicationTree);
    56      }
    57  
    58      public watchResourceTree(name: string): Observable<models.ApplicationTree> {
    59          return requests.loadEventSource(`/stream/applications/${name}/resource-tree`).map(data => JSON.parse(data).result as models.ApplicationTree);
    60      }
    61  
    62      public managedResources(name: string, options: {id?: models.ResourceID; fields?: string[]} = {}): Promise<models.ResourceDiff[]> {
    63          return requests
    64              .get(`/applications/${name}/managed-resources`)
    65              .query({...options.id, fields: (options.fields || []).join(',')})
    66              .then(res => (res.body.items as any[]) || [])
    67              .then(items => {
    68                  items.forEach(item => {
    69                      if (item.liveState) {
    70                          item.liveState = JSON.parse(item.liveState);
    71                      }
    72                      if (item.targetState) {
    73                          item.targetState = JSON.parse(item.targetState);
    74                      }
    75                      if (item.predictedLiveState) {
    76                          item.predictedLiveState = JSON.parse(item.predictedLiveState);
    77                      }
    78                      if (item.normalizedLiveState) {
    79                          item.normalizedLiveState = JSON.parse(item.normalizedLiveState);
    80                      }
    81                  });
    82                  return items as models.ResourceDiff[];
    83              });
    84      }
    85  
    86      public getManifest(name: string, revision: string): Promise<models.ManifestResponse> {
    87          return requests
    88              .get(`/applications/${name}/manifests`)
    89              .query({name, revision})
    90              .then(res => res.body as models.ManifestResponse);
    91      }
    92  
    93      public updateSpec(appName: string, spec: models.ApplicationSpec): Promise<models.ApplicationSpec> {
    94          return requests
    95              .put(`/applications/${appName}/spec`)
    96              .send(spec)
    97              .then(res => res.body as models.ApplicationSpec);
    98      }
    99  
   100      public update(app: models.Application): Promise<models.Application> {
   101          return requests
   102              .put(`/applications/${app.metadata.name}`)
   103              .send(app)
   104              .then(res => this.parseAppFields(res.body));
   105      }
   106  
   107      public create(app: models.Application): Promise<models.Application> {
   108          return requests
   109              .post(`/applications`)
   110              .send(app)
   111              .then(res => this.parseAppFields(res.body));
   112      }
   113  
   114      public delete(name: string, cascade: boolean): Promise<boolean> {
   115          return requests
   116              .delete(`/applications/${name}`)
   117              .query({cascade})
   118              .send({})
   119              .then(() => true);
   120      }
   121  
   122      public watch(query?: {name?: string; resourceVersion?: string}, options?: QueryOptions): Observable<models.ApplicationWatchEvent> {
   123          const search = new URLSearchParams();
   124          if (query) {
   125              if (query.name) {
   126                  search.set('name', query.name);
   127              }
   128              if (query.resourceVersion) {
   129                  search.set('resourceVersion', query.resourceVersion);
   130              }
   131          }
   132          if (options) {
   133              const searchOptions = optionsToSearch(options);
   134              search.set('fields', searchOptions.fields);
   135              search.set('selector', searchOptions.selector);
   136          }
   137          const searchStr = search.toString();
   138          const url = `/stream/applications${(searchStr && '?' + searchStr) || ''}`;
   139          return requests
   140              .loadEventSource(url)
   141              .repeat()
   142              .retry()
   143              .map(data => JSON.parse(data).result as models.ApplicationWatchEvent)
   144              .map(watchEvent => {
   145                  watchEvent.application = this.parseAppFields(watchEvent.application);
   146                  return watchEvent;
   147              });
   148      }
   149  
   150      public sync(name: string, revision: string, prune: boolean, dryRun: boolean, strategy: models.SyncStrategy, resources: models.SyncOperationResource[]): Promise<boolean> {
   151          return requests
   152              .post(`/applications/${name}/sync`)
   153              .send({revision, prune: !!prune, dryRun: !!dryRun, strategy, resources})
   154              .then(() => true);
   155      }
   156  
   157      public rollback(name: string, id: number): Promise<boolean> {
   158          return requests
   159              .post(`/applications/${name}/rollback`)
   160              .send({id})
   161              .then(() => true);
   162      }
   163  
   164      public getContainerLogs(applicationName: string, namespace: string, podName: string, containerName: string): Observable<models.LogEntry> {
   165          const entries = requests
   166              .loadEventSource(`/applications/${applicationName}/pods/${podName}/logs?container=${containerName}&follow=true&namespace=${namespace}`)
   167              .map(data => JSON.parse(data).result as models.LogEntry);
   168          return new Observable(observer => {
   169              const subscription = entries.subscribe(
   170                  entry => {
   171                      if (entry.last) {
   172                          observer.complete();
   173                          subscription.unsubscribe();
   174                      } else {
   175                          observer.next(entry);
   176                      }
   177                  },
   178                  err => observer.error(err),
   179                  () => observer.complete()
   180              );
   181              return () => subscription.unsubscribe();
   182          });
   183      }
   184  
   185      public getResource(name: string, resource: models.ResourceNode): Promise<models.State> {
   186          return requests
   187              .get(`/applications/${name}/resource`)
   188              .query({
   189                  name: resource.name,
   190                  namespace: resource.namespace,
   191                  resourceName: resource.name,
   192                  version: resource.version,
   193                  kind: resource.kind,
   194                  group: resource.group
   195              })
   196              .then(res => res.body as {manifest: string})
   197              .then(res => JSON.parse(res.manifest) as models.State);
   198      }
   199  
   200      public getResourceActions(name: string, resource: models.ResourceNode): Promise<models.ResourceAction[]> {
   201          return requests
   202              .get(`/applications/${name}/resource/actions`)
   203              .query({
   204                  namespace: resource.namespace,
   205                  resourceName: resource.name,
   206                  version: resource.version,
   207                  kind: resource.kind,
   208                  group: resource.group
   209              })
   210              .then(res => (res.body.actions as models.ResourceAction[]) || []);
   211      }
   212  
   213      public runResourceAction(name: string, resource: models.ResourceNode, action: string): Promise<models.ResourceAction[]> {
   214          return requests
   215              .post(`/applications/${name}/resource/actions`)
   216              .query({
   217                  namespace: resource.namespace,
   218                  resourceName: resource.name,
   219                  version: resource.version,
   220                  kind: resource.kind,
   221                  group: resource.group
   222              })
   223              .send(JSON.stringify(action))
   224              .then(res => (res.body.actions as models.ResourceAction[]) || []);
   225      }
   226  
   227      public patchResource(name: string, resource: models.ResourceNode, patch: string, patchType: string): Promise<models.State> {
   228          return requests
   229              .post(`/applications/${name}/resource`)
   230              .query({
   231                  name: resource.name,
   232                  namespace: resource.namespace,
   233                  resourceName: resource.name,
   234                  version: resource.version,
   235                  kind: resource.kind,
   236                  group: resource.group,
   237                  patchType
   238              })
   239              .send(JSON.stringify(patch))
   240              .then(res => res.body as {manifest: string})
   241              .then(res => JSON.parse(res.manifest) as models.State);
   242      }
   243  
   244      public deleteResource(applicationName: string, resource: models.ResourceNode, force: boolean): Promise<any> {
   245          return requests
   246              .delete(`/applications/${applicationName}/resource`)
   247              .query({
   248                  name: resource.name,
   249                  namespace: resource.namespace,
   250                  resourceName: resource.name,
   251                  version: resource.version,
   252                  kind: resource.kind,
   253                  group: resource.group,
   254                  force
   255              })
   256              .send()
   257              .then(() => true);
   258      }
   259  
   260      public events(applicationName: string): Promise<models.Event[]> {
   261          return requests
   262              .get(`/applications/${applicationName}/events`)
   263              .send()
   264              .then(res => (res.body as models.EventList).items || []);
   265      }
   266  
   267      public resourceEvents(
   268          applicationName: string,
   269          resource: {
   270              namespace: string;
   271              name: string;
   272              uid: string;
   273          }
   274      ): Promise<models.Event[]> {
   275          return requests
   276              .get(`/applications/${applicationName}/events`)
   277              .query({
   278                  resourceUID: resource.uid,
   279                  resourceNamespace: resource.namespace,
   280                  resourceName: resource.name
   281              })
   282              .send()
   283              .then(res => (res.body as models.EventList).items || []);
   284      }
   285  
   286      public terminateOperation(applicationName: string): Promise<boolean> {
   287          return requests
   288              .delete(`/applications/${applicationName}/operation`)
   289              .send()
   290              .then(() => true);
   291      }
   292  
   293      private parseAppFields(data: any): models.Application {
   294          data = deepMerge(
   295              {
   296                  apiVersion: 'argoproj.io/v1alpha1',
   297                  kind: 'Application',
   298                  spec: {
   299                      project: 'default'
   300                  },
   301                  status: {
   302                      resources: [],
   303                      summary: {}
   304                  }
   305              },
   306              data
   307          );
   308  
   309          return data as models.Application;
   310      }
   311  }