@nosana/node 1.1.54-rc → 1.1.55-rc
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/package.json +1 -1
- package/dist/src/NodeManager/node/resource/image/imageManager.d.ts +10 -1
- package/dist/src/NodeManager/node/resource/image/imageManager.js +17 -11
- package/dist/src/NodeManager/node/resource/resourceManager.d.ts +22 -1
- package/dist/src/NodeManager/node/resource/resourceManager.js +19 -1
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
package/dist/package.json
CHANGED
|
@@ -1,12 +1,21 @@
|
|
|
1
|
+
import { DockerAuth } from '@nosana/sdk';
|
|
1
2
|
import { ContainerOrchestrationInterface } from '../../../provider/containerOrchestration/interface.js';
|
|
2
3
|
import { NodeRepository } from '../../../repository/NodeRepository.js';
|
|
4
|
+
/**
|
|
5
|
+
* An image the market requires, and the registry credentials it takes to pull
|
|
6
|
+
* it. Public images carry none.
|
|
7
|
+
*/
|
|
8
|
+
export type RequiredImage = {
|
|
9
|
+
name: string;
|
|
10
|
+
auth?: DockerAuth;
|
|
11
|
+
};
|
|
3
12
|
export declare class ImageManager {
|
|
4
13
|
private containerOrchestration;
|
|
5
14
|
private repository;
|
|
6
15
|
private fetched;
|
|
7
16
|
private market_required_images;
|
|
8
17
|
constructor(containerOrchestration: ContainerOrchestrationInterface, repository: NodeRepository);
|
|
9
|
-
pullMarketRequiredImages(required_images:
|
|
18
|
+
pullMarketRequiredImages(required_images: RequiredImage[]): Promise<void>;
|
|
10
19
|
pruneImages(): Promise<void>;
|
|
11
20
|
resyncImagesDB(): Promise<void>;
|
|
12
21
|
setImage(image: string, isPrivate?: boolean): Promise<void>;
|
|
@@ -11,18 +11,24 @@ export class ImageManager {
|
|
|
11
11
|
}
|
|
12
12
|
async pullMarketRequiredImages(required_images) {
|
|
13
13
|
this.fetched = true;
|
|
14
|
-
this.market_required_images = required_images;
|
|
15
|
-
for (const
|
|
16
|
-
if (!(await this.containerOrchestration.hasImage(
|
|
17
|
-
await this.containerOrchestration.pullImage(
|
|
18
|
-
}
|
|
19
|
-
if (!this.repository.getImageResource(image)) {
|
|
20
|
-
this.repository.updateImageResource(image, {
|
|
21
|
-
required: true,
|
|
22
|
-
lastUsed: new Date(),
|
|
23
|
-
usage: 1,
|
|
24
|
-
});
|
|
14
|
+
this.market_required_images = required_images.map(({ name }) => name);
|
|
15
|
+
for (const { name, auth } of required_images) {
|
|
16
|
+
if (!(await this.containerOrchestration.hasImage(name))) {
|
|
17
|
+
await this.containerOrchestration.pullImage(name, auth);
|
|
25
18
|
}
|
|
19
|
+
// Written whether or not the image is already known: an image a job
|
|
20
|
+
// pulled first has an entry that says nothing about the market requiring
|
|
21
|
+
// it, and `pruneImages` deletes anything not marked required. `isPrivate`
|
|
22
|
+
// carries the same weight it does for a job image — a credentialed image
|
|
23
|
+
// is dropped rather than left cached — and only takes effect once the
|
|
24
|
+
// market stops requiring this one.
|
|
25
|
+
const known = this.repository.getImageResource(name);
|
|
26
|
+
this.repository.updateImageResource(name, {
|
|
27
|
+
required: true,
|
|
28
|
+
isPrivate: !!auth,
|
|
29
|
+
lastUsed: known?.lastUsed ?? new Date(),
|
|
30
|
+
usage: known?.usage ?? 1,
|
|
31
|
+
});
|
|
26
32
|
}
|
|
27
33
|
}
|
|
28
34
|
async pruneImages() {
|
|
@@ -2,7 +2,7 @@ import { Market, RequiredResource } from '@nosana/sdk';
|
|
|
2
2
|
import { Resource } from '@nosana/sdk/dist/types/resources.js';
|
|
3
3
|
import { ContainerOrchestrationInterface } from '../../provider/containerOrchestration/interface.js';
|
|
4
4
|
import { NodeRepository } from '../../repository/NodeRepository.js';
|
|
5
|
-
import { ImageManager } from './image/imageManager.js';
|
|
5
|
+
import { ImageManager, RequiredImage } from './image/imageManager.js';
|
|
6
6
|
import { JobContext, VolumeManager } from './volume/volumeManager.js';
|
|
7
7
|
/**
|
|
8
8
|
* The market endpoint reports an HF resource's model as `url`, the field it
|
|
@@ -14,6 +14,27 @@ import { JobContext, VolumeManager } from './volume/volumeManager.js';
|
|
|
14
14
|
* boundary, but the same manager serves job resources.
|
|
15
15
|
*/
|
|
16
16
|
export declare function normalizeMarketResources(resources: RequiredResource[]): RequiredResource[];
|
|
17
|
+
/**
|
|
18
|
+
* A required image as the market endpoint reports it. It reported bare image
|
|
19
|
+
* names before it could carry registry credentials, and the node and the host
|
|
20
|
+
* manager release independently, so a node has to read both shapes: the string
|
|
21
|
+
* form outlives the field it was replaced by.
|
|
22
|
+
*/
|
|
23
|
+
export type MarketRequiredImage = string | {
|
|
24
|
+
name: string;
|
|
25
|
+
server?: string;
|
|
26
|
+
username?: string;
|
|
27
|
+
password?: string;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Translates market required images into the shape the pull path reads.
|
|
31
|
+
*
|
|
32
|
+
* Credentials ride along only when the market names an account to pull as. A
|
|
33
|
+
* `server` on its own names a registry without authenticating to it, and the
|
|
34
|
+
* node still pulls from it anonymously, so it is not enough on its own to make
|
|
35
|
+
* the image a private one.
|
|
36
|
+
*/
|
|
37
|
+
export declare function normalizeMarketImages(required_images: MarketRequiredImage[]): RequiredImage[];
|
|
17
38
|
export declare class ResourceManager {
|
|
18
39
|
private containerOrchestration;
|
|
19
40
|
private repository;
|
|
@@ -21,6 +21,24 @@ export function normalizeMarketResources(resources) {
|
|
|
21
21
|
return { ...hf, repo: hf.url };
|
|
22
22
|
});
|
|
23
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* Translates market required images into the shape the pull path reads.
|
|
26
|
+
*
|
|
27
|
+
* Credentials ride along only when the market names an account to pull as. A
|
|
28
|
+
* `server` on its own names a registry without authenticating to it, and the
|
|
29
|
+
* node still pulls from it anonymously, so it is not enough on its own to make
|
|
30
|
+
* the image a private one.
|
|
31
|
+
*/
|
|
32
|
+
export function normalizeMarketImages(required_images) {
|
|
33
|
+
return required_images.map((image) => {
|
|
34
|
+
if (typeof image === 'string')
|
|
35
|
+
return { name: image };
|
|
36
|
+
const { name, server, username, password } = image;
|
|
37
|
+
if (!username && !password)
|
|
38
|
+
return { name };
|
|
39
|
+
return { name, auth: { server, username, password } };
|
|
40
|
+
});
|
|
41
|
+
}
|
|
24
42
|
export class ResourceManager {
|
|
25
43
|
constructor(containerOrchestration, repository) {
|
|
26
44
|
this.containerOrchestration = containerOrchestration;
|
|
@@ -42,7 +60,7 @@ export class ResourceManager {
|
|
|
42
60
|
if (!data) {
|
|
43
61
|
return;
|
|
44
62
|
}
|
|
45
|
-
await this.images.pullMarketRequiredImages(data.required_images);
|
|
63
|
+
await this.images.pullMarketRequiredImages(normalizeMarketImages(data.required_images));
|
|
46
64
|
await this.volumes.pullMarketRequiredVolumes(normalizeMarketResources(data.required_remote_resources));
|
|
47
65
|
}
|
|
48
66
|
catch (error) {
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nosana/node",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.55-rc",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@nosana/node",
|
|
9
|
-
"version": "1.1.
|
|
9
|
+
"version": "1.1.55-rc",
|
|
10
10
|
"license": "ISC",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@coral-xyz/anchor": "^0.28.1-beta.1",
|