Skip to content

Commit

Permalink
ask for pull secret if start require it
Browse files Browse the repository at this point in the history
Signed-off-by: Yevhen Vydolob <[email protected]>
  • Loading branch information
evidolob committed Mar 21, 2023
1 parent 2bb4005 commit a7169f6
Show file tree
Hide file tree
Showing 8 changed files with 133 additions and 48 deletions.
9 changes: 0 additions & 9 deletions src/crc-cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,12 +168,3 @@ export function daemonStop() {
daemonProcess.kill();
}
}

export async function needSetup(): Promise<boolean> {
try {
await execPromise(getCrcCli(), ['setup', '--check-only']);
return false;
} catch (e) {
return true;
}
}
13 changes: 13 additions & 0 deletions src/crc-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,19 @@ interface PresetQuickPickItem extends extensionApi.QuickPickItem {
data: Preset;
}

export let isNeedSetup = false;

export async function needSetup(): Promise<boolean> {
try {
await execPromise(getCrcCli(), ['setup', '--check-only']);
isNeedSetup = false;
return false;
} catch (e) {
isNeedSetup = true;
return true;
}
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
export async function setUpCrc(logger: extensionApi.Logger, askForPreset = false): Promise<boolean> {
if (askForPreset) {
Expand Down
103 changes: 103 additions & 0 deletions src/crc-start.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/**********************************************************************
* Copyright (C) 2023 Red Hat, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
***********************************************************************/

import * as extensionApi from '@podman-desktop/api';
import { isNeedSetup, needSetup, setUpCrc } from './crc-setup';
import { crcStatus } from './crc-status';
import { commander } from './daemon-commander';
import { crcLogProvider } from './log-provider';

interface ImagePullSecret {
auths: { auth: string; credsStore: string }[];
}

const missingPullSecret = 'Failed to ask for pull secret';

export async function startCrc(logger: extensionApi.Logger): Promise<void> {
try {
// call crc setup to prepare bundle, before start
if (isNeedSetup) {
try {
crcStatus.setSetupRunning(true);
await setUpCrc(logger);
await needSetup();
} catch (error) {
logger.error(error);
return;
} finally {
crcStatus.setSetupRunning(false);
}
}
crcLogProvider.startSendingLogs(logger);
const result = await commander.start();
console.error('StartResult:' + JSON.stringify(result));
} catch (err) {
if (typeof err.message === 'string') {
// check that crc missing pull secret
if (err.message.startsWith(missingPullSecret)) {
// ask user to provide pull secret
if (await askAndStorePullSecret(logger)) {
// if pull secret provided try to start again
return startCrc(logger);
}
return;
} else if (err.name === 'RequestError' && err.code === 'ECONNRESET') {
// look like crc start normally, but we receive empty response from socket, so 'got' generate an error
return;
}
}

console.error(err);
}
}

async function askAndStorePullSecret(logger: extensionApi.Logger): Promise<boolean> {
const pullSecret = await extensionApi.window.showInputBox({
prompt: 'Provide a pull secret',
// prompt: 'To pull container images from the registry, a pull secret is necessary.',
ignoreFocusOut: true,
});

if (!pullSecret) {
return false;
}
try {
const s: ImagePullSecret = JSON.parse(pullSecret);
if (s.auths && s.auths.length > 0) {
for (const a of s.auths) {
if (!a.auth && !a.credsStore) {
throw `${JSON.stringify(s)} JSON-object requires either 'auth' or 'credsStore' field`;
}
}
} else {
throw 'missing "auths" JSON-object field';
}
} catch (err) {
// not valid json
extensionApi.window.showErrorMessage(`Pull secret is not valid:\n '${err}',\n please try again`);
return false;
}
try {
await commander.pullSecretStore(pullSecret);
return true;
} catch (error) {
console.error(error);
logger.error(error);
}
return false;
}
2 changes: 1 addition & 1 deletion src/crc-status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export class CrcStatus {
}

get status(): Status {
return this.status;
return this._status;
}

setErrorStatus(): void {
Expand Down
7 changes: 4 additions & 3 deletions src/daemon-commander.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,14 +139,15 @@ export class DaemonCommander {
async pullSecretStore(value: unknown): Promise<string> {
const url = this.apiPath + '/pull-secret';

await got.post(url, {
json: value,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const response = await (got as any).post(url, {
body: value,
throwHttpErrors: false,
retry: {
limit: 0,
},
});
return 'OK';
return response.body;
}

async pullSecretAvailable() {
Expand Down
40 changes: 7 additions & 33 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,15 @@ import * as os from 'node:os';
import * as fs from 'node:fs';
import type { Status } from './daemon-commander';
import { commander } from './daemon-commander';
import { LogProvider } from './log-provider';
import { crcLogProvider } from './log-provider';
import { isWindows, productName } from './util';
import { daemonStart, daemonStop, getCrcVersion, needSetup } from './crc-cli';
import { daemonStart, daemonStop, getCrcVersion } from './crc-cli';
import { getCrcDetectionChecks } from './detection-checks';
import { CrcInstall } from './install/crc-install';
import { setUpCrc } from './crc-setup';
import { crcStatus } from './crc-status';

const crcLogProvider = new LogProvider(commander);

let isNeedSetup = false;
import { crcStatus } from './crc-status';
import { startCrc } from './crc-start';
import { isNeedSetup, needSetup } from './crc-setup';

export async function activate(extensionContext: extensionApi.ExtensionContext): Promise<void> {
const crcInstaller = new CrcInstall();
Expand All @@ -44,13 +42,11 @@ export async function activate(extensionContext: extensionApi.ExtensionContext):

if (crcVersion) {
status = 'installed';
}

isNeedSetup = await needSetup();
if (crcVersion) {
connectToCrc();
}

await needSetup();

detectionChecks.push(...getCrcDetectionChecks(crcVersion));

// create CRC provider
Expand Down Expand Up @@ -202,28 +198,6 @@ function presetChanged(provider: extensionApi.Provider, extensionContext: extens
}
}

async function startCrc(logger: extensionApi.Logger): Promise<void> {
try {
// call crc setup to prepare bundle, before start
if (isNeedSetup) {
try {
crcStatus.setSetupRunning(true);
await setUpCrc(logger);
isNeedSetup = false;
} catch (error) {
logger.error(error);
return;
} finally {
crcStatus.setSetupRunning(false);
}
}
crcLogProvider.startSendingLogs(logger);
await commander.start();
} catch (err) {
console.error(err);
}
}

async function stopCrc(): Promise<void> {
console.log('extension:crc: receive the call stop');
try {
Expand Down
4 changes: 2 additions & 2 deletions src/install/crc-install.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ import * as os from 'node:os';
import type { CrcReleaseInfo, Installer } from './base-install';
import { WinInstall } from './win-install';

import { getCrcVersion, needSetup } from '../crc-cli';
import { getCrcVersion } from '../crc-cli';
import { getCrcDetectionChecks } from '../detection-checks';
import { MacOsInstall } from './mac-install';
import { setUpCrc } from '../crc-setup';
import { needSetup, setUpCrc } from '../crc-setup';

const crcLatestReleaseUrl =
'https://developers.redhat.com/content-gateway/rest/mirror/pub/openshift-v4/clients/crc/latest/release-info.json';
Expand Down
3 changes: 3 additions & 0 deletions src/log-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import type { Logger } from '@podman-desktop/api';
import type { DaemonCommander } from './daemon-commander';
import { commander } from './daemon-commander';

export class LogProvider {
private timeout: NodeJS.Timeout;
Expand All @@ -41,3 +42,5 @@ export class LogProvider {
clearInterval(this.timeout);
}
}

export const crcLogProvider = new LogProvider(commander);

0 comments on commit a7169f6

Please sign in to comment.