Skip to content

Commit 851ac72

Browse files
committed
Extract angular client part from data service to decouple from ngrx/data
1 parent bd0d645 commit 851ac72

File tree

8 files changed

+179
-133
lines changed

8 files changed

+179
-133
lines changed

packages/kubernetes-client-angular/projects/kubernetes-client-angular/README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ Ideal for SPA-like apps and CRDs.
2626
## Integration in Angular and NGRX
2727

2828
This package is an Angular library that integrates `@ngrx/data` for store management.
29+
Although, the `KubernetesClientService` can be used natively without store support.
2930

3031
## Getting started
3132

@@ -79,7 +80,7 @@ import { AppComponent } from './app.component'
7980
export class AppModule {}
8081
```
8182

82-
Optional but highly recommended: Create an extendable Service for each entity in `config-map.service.ts`:
83+
Optional but highly recommended: Create an extendable Service for each entity, for example in `config-map.service.ts`:
8384
```typescript
8485
import { Injectable } from '@angular/core'
8586
import { KubernetesCollectionService } from '@ccremer/kubernetes-client-angular'
@@ -181,7 +182,7 @@ export interface MyCustomResource extends KubeObject {
181182

182183
* The `Config` class returns a KubeConfig-like structure complete with cluster and user information.
183184
However, currently only a variant with a JWT token is supported, created with `Config.FromToken()` combined with `DefaultAuthorizer`.
184-
* `watch` operation isn't yet supported.
185+
* `watch` operation isn't yet supported (see also: https://github.com/angular/angular/issues/44143).
185186
* There is no validation to the passed in payloads or returned results.
186187
* Many Kubernetes resource types are missing, and they're not (yet?) generated from the Kubernetes API scheme.
187188
Implement your own or better yet, contribute to this package :)

packages/kubernetes-client-angular/projects/kubernetes-client-angular/README.md.njk

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ Ideal for SPA-like apps and CRDs.
2626
## Integration in Angular and NGRX
2727

2828
This package is an Angular library that integrates `@ngrx/data` for store management.
29+
Although, the `KubernetesClientService` can be used natively without store support.
2930

3031
## Getting started
3132

@@ -39,7 +40,7 @@ Setup the module with `@ngrx/data` in `app.module.ts`:
3940
{% include "projects/kubernetes-client-angular/examples/app.module.ts" -%}
4041
```
4142

42-
Optional but highly recommended: Create an extendable Service for each entity in `config-map.service.ts`:
43+
Optional but highly recommended: Create an extendable Service for each entity, for example in `config-map.service.ts`:
4344
```typescript
4445
{% include "projects/kubernetes-client-angular/examples/config-map.service.ts" -%}
4546
```
@@ -91,7 +92,7 @@ You can also provide your own resource type, as long as it fulfills the `KubeMet
9192

9293
* The `Config` class returns a KubeConfig-like structure complete with cluster and user information.
9394
However, currently only a variant with a JWT token is supported, created with `Config.FromToken()` combined with `DefaultAuthorizer`.
94-
* `watch` operation isn't yet supported.
95+
* `watch` operation isn't yet supported (see also: https://github.com/angular/angular/issues/44143).
9596
* There is no validation to the passed in payloads or returned results.
9697
* Many Kubernetes resource types are missing, and they're not (yet?) generated from the Kubernetes API scheme.
9798
Implement your own or better yet, contribute to this package :)

packages/kubernetes-client-angular/projects/kubernetes-client-angular/src/lib/kubernetes-authorizer.interceptor.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ export class KubernetesAuthorizerInterceptor implements HttpInterceptor {
1414
intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
1515
const url = request.url
1616
const base = this.config?.basePath ?? ''
17-
console.log('url', url, 'token', this.authorizer.getToken())
1817
if (url.startsWith(`${base}/api/`) || url.startsWith(`${base}/apis/`)) {
1918
return next.handle(
2019
request.clone({
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
import { Injectable, Optional } from '@angular/core'
2+
import { HttpClient } from '@angular/common/http'
3+
import { KubernetesUrlGeneratorService } from './kubernetes-url-generator.service'
4+
import { DataServiceConfig } from './config'
5+
import { KubeObject, Status } from '@ccremer/kubernetes-client/types/core'
6+
import { map, Observable } from 'rxjs'
7+
import { toURLSearchParams } from '@ccremer/kubernetes-client/api'
8+
import {
9+
DeleteOptions,
10+
GetOptions,
11+
ListOptions,
12+
MutationOptions,
13+
PatchOptions,
14+
} from '@ccremer/kubernetes-client/api/options'
15+
import { KubeList } from '@ccremer/kubernetes-client/types/core/KubeList'
16+
17+
@Injectable()
18+
export class KubernetesClientService {
19+
constructor(
20+
protected client: HttpClient,
21+
protected urlGenerator: KubernetesUrlGeneratorService,
22+
@Optional() protected config?: DataServiceConfig
23+
) {}
24+
25+
protected hideManagedFields<T extends KubeObject>(stream: Observable<T>, hide?: boolean): Observable<T> {
26+
if (!hide) return stream
27+
return stream.pipe(
28+
map((entity) => {
29+
delete entity.metadata?.managedFields
30+
return entity
31+
})
32+
)
33+
}
34+
35+
get<K extends KubeObject>(
36+
apiVersion: string,
37+
kind: string,
38+
name?: string,
39+
namespace?: string,
40+
options?: GetOptions
41+
): Observable<K> {
42+
const endpoint = this.urlGenerator.buildEndpoint(
43+
'GET',
44+
apiVersion,
45+
kind,
46+
namespace,
47+
name,
48+
toURLSearchParams(options)
49+
)
50+
return this.hideManagedFields(this.client.get<K>(endpoint, { responseType: 'json' }), options?.hideManagedFields)
51+
}
52+
53+
list<K extends KubeObject>(
54+
apiVersion: string,
55+
kind: string,
56+
namespace?: string,
57+
options?: ListOptions
58+
): Observable<KubeList<K>> {
59+
const endpoint = this.urlGenerator.buildEndpoint(
60+
'GET',
61+
apiVersion,
62+
kind,
63+
namespace,
64+
undefined,
65+
toURLSearchParams(options)
66+
)
67+
return this.client.get<KubeList<K>>(endpoint, { responseType: 'json' }).pipe(
68+
map((list) => {
69+
if (!options?.hideManagedFields) return list
70+
list.items = list.items.map((item) => {
71+
delete item.metadata?.managedFields
72+
return item
73+
})
74+
return list
75+
})
76+
)
77+
}
78+
79+
create<K extends KubeObject>(body: K, options?: MutationOptions): Observable<K> {
80+
const endpoint = this.urlGenerator.buildEndpoint(
81+
'POST',
82+
body.apiVersion,
83+
body.kind,
84+
body.metadata?.namespace,
85+
body.metadata?.name,
86+
toURLSearchParams(options)
87+
)
88+
return this.hideManagedFields(
89+
this.client.post<K>(endpoint, body, { responseType: 'json' }),
90+
options?.hideManagedFields
91+
)
92+
}
93+
94+
update<K extends KubeObject>(body: K, options?: MutationOptions): Observable<K> {
95+
const endpoint = this.urlGenerator.buildEndpoint(
96+
'POST',
97+
body.apiVersion,
98+
body.kind,
99+
body.metadata?.namespace,
100+
body.metadata?.name,
101+
toURLSearchParams(options)
102+
)
103+
return this.hideManagedFields(
104+
this.client.put<K>(endpoint, body, { responseType: 'json' }),
105+
options?.hideManagedFields
106+
)
107+
}
108+
109+
patch<K extends KubeObject>(body: K, options?: PatchOptions): Observable<K> {
110+
const endpoint = this.urlGenerator.buildEndpoint(
111+
'POST',
112+
body.apiVersion,
113+
body.kind,
114+
body.metadata?.namespace,
115+
body.metadata?.name,
116+
toURLSearchParams(options)
117+
)
118+
return this.hideManagedFields(
119+
this.client.patch<K>(endpoint, body, {
120+
responseType: 'json',
121+
headers: { 'content-type': 'application/merge-patch+json' },
122+
}),
123+
options?.hideManagedFields
124+
)
125+
}
126+
127+
delete(
128+
apiVersion: string,
129+
kind: string,
130+
name?: string,
131+
namespace?: string,
132+
options?: DeleteOptions
133+
): Observable<Status> {
134+
const endpoint = this.urlGenerator.buildEndpoint(
135+
'DELETE',
136+
apiVersion,
137+
kind,
138+
namespace,
139+
name,
140+
toURLSearchParams(options)
141+
)
142+
return this.client.delete<Status>(endpoint, { responseType: 'json' })
143+
}
144+
}

packages/kubernetes-client-angular/projects/kubernetes-client-angular/src/lib/kubernetes-data-service-factory.service.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { EntityCollectionDataService } from '@ngrx/data'
44
import { KubernetesDataService } from './kubernetes-data.service'
55
import { KubernetesUrlGeneratorService } from './kubernetes-url-generator.service'
66
import { DataServiceConfig } from './config'
7+
import { KubernetesClientService } from './kubernetes-client.service'
78
import { HttpClient } from '@angular/common/http'
89

910
/**
@@ -18,8 +19,12 @@ export class KubernetesDataServiceFactory {
1819
) {}
1920

2021
create<T extends KubeObject>(entityName: string): EntityCollectionDataService<T> {
21-
const overrideConfig = this.config?.overrides ? this.config.overrides[entityName] : this.config?.default
22-
return new KubernetesDataService<T>(entityName, this.httpClient, this.urlGenerator, overrideConfig)
22+
const overrideConfig = getDataServiceConfigOrDefault(entityName, this.config)
23+
return new KubernetesDataService<T>(
24+
entityName,
25+
new KubernetesClientService(this.httpClient, this.urlGenerator, overrideConfig),
26+
overrideConfig
27+
)
2328
}
2429
}
2530

0 commit comments

Comments
 (0)