balena-preload
Version:
Preload balena OS images with a user application container
240 lines (239 loc) • 11.5 kB
TypeScript
import * as _ from 'lodash';
import * as EventEmitter from 'events';
import * as Docker from 'dockerode';
import * as streamModule from 'stream';
import type { Application, BalenaSDK, DeviceType, Pine, Release } from 'balena-sdk';
declare class BufferBackedWritableStream extends streamModule.Writable {
chunks: Buffer[];
_write(chunk: any, _enc: any, next: any): void;
getData(): Buffer<ArrayBuffer>;
}
type Layer = {
digest: any;
size: number;
};
type Manifest = {
manifest: {
layers: Layer[];
};
imageLocation: string;
};
type Image = {
is_stored_at__image_location: string;
image_size: string;
};
interface ImageInfo {
preloaded_builds: string[];
supervisor_version: string;
free_space: number;
config: {
deviceType: string;
};
balena_os_version: string;
}
export declare const CONTAINER_NAME = "balena-image-preloader";
export declare const applicationExpandOptions: {
readonly owns__release: {
readonly $select: readonly ["id", "commit", "end_timestamp", "composition"];
readonly $expand: {
readonly release_image: {
readonly $select: readonly ["id"];
readonly $expand: {
readonly image: {
readonly $select: readonly ["image_size", "is_stored_at__image_location"];
};
};
};
};
readonly $filter: {
readonly status: "success";
};
readonly $orderby: readonly [{
readonly end_timestamp: "desc";
}, {
readonly id: "desc";
}];
};
};
declare const createContainer: (docker: Docker, image: string, splashImage: string | undefined, dockerPort: number, proxy: string) => Promise<Docker.Container>;
declare const deviceTypeQuery: {
readonly $select: "slug";
readonly $expand: {
readonly is_of__cpu_architecture: {
readonly $select: "slug";
};
};
};
declare const getApplicationQuery: (releaseFilter: Pine.Filter<Release["Read"]>) => {
readonly $expand: {
readonly should_be_running__release: {
readonly $select: "commit";
};
readonly is_for__device_type: {
readonly $select: "slug";
readonly $expand: {
readonly is_of__cpu_architecture: {
readonly $select: "slug";
};
};
};
readonly owns__release: {
readonly $select: readonly ["id", "commit", "end_timestamp", "composition"];
readonly $expand: {
readonly release_image: {
readonly $select: readonly ["id"];
readonly $expand: {
readonly image: {
readonly $select: readonly ["image_size", "is_stored_at__image_location"];
};
};
};
};
readonly $filter: Pine.Filter<{
created_at: import("@balena/sbvr-types").Types["Date Time"]["Read"];
id: import("@balena/sbvr-types").Types["Integer"]["Read"];
belongs_to__application: {
__id: Application["Read"]["id"];
} | [Application["Read"]];
commit: import("@balena/sbvr-types").Types["Short Text"]["Read"];
composition: import("@balena/sbvr-types").Types["JSON"]["Read"];
status: import("@balena/sbvr-types").Types["Short Text"]["Read"];
source: import("@balena/sbvr-types").Types["Short Text"]["Read"];
build_log: import("@balena/sbvr-types").Types["Text"]["Read"] | null;
is_invalidated: import("@balena/sbvr-types").Types["Boolean"]["Read"];
start_timestamp: import("@balena/sbvr-types").Types["Date Time"]["Read"];
end_timestamp: import("@balena/sbvr-types").Types["Date Time"]["Read"] | null;
update_timestamp: import("@balena/sbvr-types").Types["Date Time"]["Read"];
release_version: import("@balena/sbvr-types").Types["Short Text"]["Read"] | null;
contract: import("@balena/sbvr-types").Types["JSON"]["Read"] | null;
is_passing_tests: import("@balena/sbvr-types").Types["Boolean"]["Read"];
is_finalized_at__date: import("@balena/sbvr-types").Types["Date Time"]["Read"] | null;
phase: "next" | "current" | "sunset" | "end-of-life" | null;
is_final: import("@balena/sbvr-types").Types["Boolean"]["Read"];
semver: import("@balena/sbvr-types").Types["Short Text"]["Read"];
semver_major: import("@balena/sbvr-types").Types["Integer"]["Read"];
semver_minor: import("@balena/sbvr-types").Types["Integer"]["Read"];
semver_patch: import("@balena/sbvr-types").Types["Integer"]["Read"];
semver_prerelease: import("@balena/sbvr-types").Types["Short Text"]["Read"];
semver_build: import("@balena/sbvr-types").Types["Short Text"]["Read"];
variant: import("@balena/sbvr-types").Types["Short Text"]["Read"];
revision: import("@balena/sbvr-types").Types["Integer"]["Read"] | null;
raw_version: import("@balena/sbvr-types").Types["Short Text"]["Read"];
version: import("@balena/sbvr-types").Types["JSON"]["Read"];
known_issue_list: import("@balena/sbvr-types").Types["Text"]["Read"] | null;
note: import("@balena/sbvr-types").Types["Text"]["Read"] | null;
invalidation_reason: import("@balena/sbvr-types").Types["Text"]["Read"] | null;
is_created_by__user: {
__id: import("balena-sdk").User["Read"]["id"];
} | [import("balena-sdk").User["Read"]] | [] | null;
release__has__tag_key?: Array<import("balena-sdk").ReleaseTag["Read"]>;
release_tag?: Array<import("balena-sdk").ReleaseTag["Read"]>;
release__has__asset_key?: Array<import("balena-sdk").ReleaseAsset["Read"]>;
release_asset?: Array<import("balena-sdk").ReleaseAsset["Read"]>;
image__is_part_of__release?: Array<import("balena-sdk").ImageIsPartOfRelease["Read"]>;
release_image?: Array<import("balena-sdk").ImageIsPartOfRelease["Read"]>;
contains__image?: Array<import("balena-sdk").ImageIsPartOfRelease["Read"]>;
should_be_running_on__application?: Array<Application["Read"]>;
should_be_running_on__device?: Array<import("balena-sdk").Device["Read"]>;
is_running_on__device?: Array<import("balena-sdk").Device["Read"]>;
is_pinned_to__device?: Array<import("balena-sdk").Device["Read"]>;
should_operate__device?: Array<import("balena-sdk").Device["Read"]>;
should_manage__device?: Array<import("balena-sdk").Device["Read"]>;
provides__device__installs__image?: Array<import("balena-sdk").ImageInstall["Read"]>;
provides__image_install?: Array<import("balena-sdk").ImageInstall["Read"]>;
}>;
readonly $orderby: readonly [{
readonly end_timestamp: "desc";
}, {
readonly id: "desc";
}];
};
};
};
export declare class Preloader extends EventEmitter {
docker: Docker;
appId: number | string | undefined;
commit: string | undefined;
image: string;
splashImage: string | undefined;
proxy: any;
dontCheckArch: boolean;
pinDevice: boolean;
certificates: string[];
additionalSpace: number | null;
application: any;
stdin: any;
stdout: streamModule.PassThrough;
stderr: streamModule.PassThrough;
bufferedStderr: BufferBackedWritableStream;
dockerPort: any;
container: Awaited<ReturnType<typeof createContainer>> | undefined;
state: any;
freeSpace: number | undefined;
preloadedBuilds: string[] | undefined;
supervisorVersion: string | undefined;
balenaOSVersion: string | undefined;
config: ImageInfo['config'] | undefined;
deviceTypes: Pine.OptionsToResponse<DeviceType['Read'], typeof deviceTypeQuery, undefined> | undefined;
balena: BalenaSDK;
constructor(balena: BalenaSDK | undefined, docker: Docker, appId: number | string | undefined, commit: string | undefined, image: string, splashImage: string | undefined, proxy: any, dontCheckArch: boolean, pinDevice?: boolean, certificates?: string[], additionalSpace?: number | null);
_build(): Promise<void>;
_fetchDeviceTypes(): Promise<void>;
_runWithSpinner<T>(name: string, fn: () => T | Promise<T>): Promise<T>;
_prepareErrorHandler(): void;
_runCommand(command: string, parameters: {
[name: string]: any;
}): Promise<unknown>;
_startSpinner(name: any): void;
_stopSpinner(name: any): void;
_progress(name: any, percentage: any): void;
_getStateVersion(): 1 | 2 | 3;
_getStateWithRegistration(stateVersion: number): Promise<void>;
_getStateFromTargetEndpoint(stateVersion: number): Promise<void>;
_getState(): Promise<void>;
_getImageInfo(): Promise<void>;
_getCommit(): any;
_getRelease(): any;
_getServicesFromApps(apps: any): any;
_getImages(): Image[];
_getImagesToPreload(): Image[];
registryRequest<RF extends 'json' | 'blob'>(url: {
registryUrl: string;
layerUrl: string;
} | string, registryToken: string | null, headers: Record<string, string>, responseFormat: RF, followRedirect: boolean): ReturnType<typeof this.balena.request.send<RF extends 'blob' ? Blob : RF extends 'json' ? Record<string, unknown> : never>>;
_getLayerSize(registryToken: any, registryUrl: any, layerUrl: any): Promise<number>;
_registryUrl(imageLocation: any): string;
_imageManifestUrl(imageLocation: any): string;
_layerUrl(imageLocation: any, layerDigest: any): string;
_getApplicationImagesManifests(imagesLocations: string[], registryToken: string): Promise<{
manifest: Manifest["manifest"];
imageLocation: string;
}[]>;
_getLayersSizes(manifests: Manifest[], registryToken: string): Promise<Map<any, any>>;
_getApplicationSize(): Promise<number>;
_getSize(): Promise<number>;
_getRequiredAdditionalSpace(): Promise<number>;
_supervisorLT7(): boolean;
_supervisorLT13(): boolean;
_getRegistryToken(images: string[]): Promise<string>;
_fetchApplication(): Promise<void>;
_checkImage(image: string): Promise<void>;
_pluralize(count: number, thing: string): string;
_deviceTypeArch(slug: string): string;
prepare(): Promise<void>;
cleanup(): Promise<void>;
kill(): Promise<any>;
_ensureCanPreload(): void;
_getAppData(): (_.Omit<any, "image" | "environment" | "serviceId"> & {
appId: never;
env: any;
imageId: any;
})[] | (Pick<any, string | number | symbol> & {
pinDevice: boolean;
});
_getSplashImagePath(): "/splash/balena-logo.png" | "/splash/resin-logo.png";
preload(): Promise<void>;
setApplication(application: NonNullable<Pine.OptionsToResponse<Application['Read'], ReturnType<typeof getApplicationQuery>, number>>): void;
setAppIdAndCommit(appIdOrSlug: string | number, commit: string): Promise<void>;
}
export {};